use crate::data::{
Description, Element, ElementQuery, FromVimwikiElement, GqlPageFilter,
GraphqlDatabaseError, Page, PageQuery, Region, UriRef,
};
use entity::*;
use entity_async_graphql::*;
use serde::{Deserialize, Serialize};
use std::fmt;
use vimwiki::{self as v, Located};
#[gql_ent]
pub struct TransclusionLink {
#[ent(field(graphql(filter_untyped)))]
region: Region,
#[ent(field(graphql(filter_untyped)))]
uri_ref: UriRef,
#[ent(field(graphql(filter_untyped)))]
description: Option<Description>,
#[ent(field(graphql(filter_untyped)))]
properties: Vec<Property>,
#[ent(edge)]
page: Page,
#[ent(edge(policy = "shallow", wrap, graphql(filter_untyped)))]
parent: Option<Element>,
}
impl fmt::Display for TransclusionLink {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.description().as_ref() {
Some(desc) => write!(f, "{}", desc),
None => write!(f, "{}", self.uri_ref()),
}
}
}
impl<'a> FromVimwikiElement<'a> for TransclusionLink {
type Element = Located<v::Link<'a>>;
fn from_vimwiki_element(
page_id: Id,
parent_id: Option<Id>,
element: Self::Element,
) -> Result<Self, GraphqlDatabaseError> {
let region = Region::from(element.region());
let link = element.into_inner();
let v::LinkData {
uri_ref,
description,
properties,
} = link.into_data();
GraphqlDatabaseError::wrap(
Self::build()
.region(region)
.uri_ref(UriRef::from(uri_ref))
.description(description.map(Description::from))
.properties(
properties
.unwrap_or_default()
.into_iter()
.map(|(key, value)| Property {
key: key.to_string(),
value: value.to_string(),
})
.collect(),
)
.page(page_id)
.parent(parent_id)
.finish_and_commit(),
)
}
}
#[derive(
async_graphql::SimpleObject,
Clone,
Debug,
PartialEq,
Eq,
Serialize,
Deserialize,
ValueLike,
)]
pub struct Property {
key: String,
value: String,
}
#[cfg(test)]
mod tests {
use super::*;
use entity_inmemory::InmemoryDatabase;
use vimwiki::macros::*;
#[test]
fn should_fully_populate_from_vimwiki_element() {
global::with_db(InmemoryDatabase::default(), || {
let link = vimwiki_link!(
r#"{{https://example.com/pic.png|Some description|class="some class"}}"#
);
let region = Region::from(link.region());
let ent =
TransclusionLink::from_vimwiki_element(999, Some(123), link)
.expect("Failed to convert from element");
assert_eq!(ent.region(), ®ion);
assert_eq!(
ent.uri_ref(),
&"https://example.com/pic.png".parse::<UriRef>().unwrap()
);
assert_eq!(
ent.description(),
&Some(Description::Text(String::from("Some description")))
);
assert_eq!(
ent.properties(),
&vec![Property {
key: "class".to_string(),
value: "some class".to_string(),
}]
);
assert_eq!(ent.page_id(), 999);
assert_eq!(ent.parent_id(), Some(123));
});
}
}