use crate::data::{
Date, Element, ElementQuery, FromVimwikiElement, GqlPageFilter,
GraphqlDatabaseError, Page, PageQuery, Region,
};
use entity::*;
use entity_async_graphql::*;
use vimwiki::{self as v, Located};
#[gql_ent]
#[derive(Debug)]
pub enum Placeholder {
Title(PlaceholderTitle),
NoHtml(PlaceholderNoHtml),
Template(PlaceholderTemplate),
Date(PlaceholderDate),
Other(PlaceholderOther),
}
impl Placeholder {
pub fn region(&self) -> &Region {
match self {
Self::Title(x) => x.region(),
Self::NoHtml(x) => x.region(),
Self::Template(x) => x.region(),
Self::Date(x) => x.region(),
Self::Other(x) => x.region(),
}
}
pub fn page_id(&self) -> Id {
match self {
Self::Title(x) => x.page_id(),
Self::NoHtml(x) => x.page_id(),
Self::Template(x) => x.page_id(),
Self::Date(x) => x.page_id(),
Self::Other(x) => x.page_id(),
}
}
pub fn parent_id(&self) -> Option<Id> {
match self {
Self::Title(x) => x.parent_id(),
Self::NoHtml(x) => x.parent_id(),
Self::Template(x) => x.parent_id(),
Self::Date(x) => x.parent_id(),
Self::Other(x) => x.parent_id(),
}
}
}
impl<'a> FromVimwikiElement<'a> for Placeholder {
type Element = Located<v::Placeholder<'a>>;
fn from_vimwiki_element(
page_id: Id,
parent_id: Option<Id>,
element: Self::Element,
) -> Result<Self, GraphqlDatabaseError> {
let region = Region::from(element.region());
match element.into_inner() {
v::Placeholder::Title(title) => GraphqlDatabaseError::wrap(
PlaceholderTitle::build()
.region(region)
.title(title.to_string())
.page(page_id)
.parent(parent_id)
.finish_and_commit(),
)
.map(Self::from),
v::Placeholder::NoHtml => GraphqlDatabaseError::wrap(
PlaceholderNoHtml::build()
.region(region)
.page(page_id)
.parent(parent_id)
.finish_and_commit(),
)
.map(Self::from),
v::Placeholder::Template(template) => GraphqlDatabaseError::wrap(
PlaceholderTemplate::build()
.region(region)
.template(template.to_string())
.page(page_id)
.parent(parent_id)
.finish_and_commit(),
)
.map(Self::from),
v::Placeholder::Date(date) => GraphqlDatabaseError::wrap(
PlaceholderDate::build()
.region(region)
.date(Date::from(date))
.page(page_id)
.parent(parent_id)
.finish_and_commit(),
)
.map(Self::from),
v::Placeholder::Other { name, value } => {
GraphqlDatabaseError::wrap(
PlaceholderOther::build()
.region(region)
.name(name.to_string())
.value(value.to_string())
.page(page_id)
.parent(parent_id)
.finish_and_commit(),
)
.map(Self::from)
}
}
}
}
#[gql_ent]
pub struct PlaceholderTitle {
#[ent(field(graphql(filter_untyped)))]
region: Region,
title: String,
#[ent(edge)]
page: Page,
#[ent(edge(policy = "shallow", wrap, graphql(filter_untyped)))]
parent: Option<Element>,
}
#[gql_ent]
pub struct PlaceholderNoHtml {
#[ent(field(graphql(filter_untyped)))]
region: Region,
#[ent(edge)]
page: Page,
#[ent(edge(policy = "shallow", wrap, graphql(filter_untyped)))]
parent: Option<Element>,
}
#[gql_ent]
pub struct PlaceholderTemplate {
#[ent(field(graphql(filter_untyped)))]
region: Region,
template: String,
#[ent(edge)]
page: Page,
#[ent(edge(policy = "shallow", wrap, graphql(filter_untyped)))]
parent: Option<Element>,
}
#[gql_ent]
pub struct PlaceholderDate {
#[ent(field(graphql(filter_untyped)))]
region: Region,
#[ent(field(graphql(filter_untyped)))]
date: Date,
#[ent(edge)]
page: Page,
#[ent(edge(policy = "shallow", wrap, graphql(filter_untyped)))]
parent: Option<Element>,
}
#[gql_ent]
pub struct PlaceholderOther {
#[ent(field(graphql(filter_untyped)))]
region: Region,
name: String,
value: String,
#[ent(edge)]
page: Page,
#[ent(edge(policy = "shallow", wrap, graphql(filter_untyped)))]
parent: Option<Element>,
}
#[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 element = vimwiki_placeholder!(r#"%title some title"#);
let region = Region::from(element.region());
let ent =
Placeholder::from_vimwiki_element(999, Some(123), element)
.expect("Failed to convert from element");
assert_eq!(ent.region(), ®ion);
assert_eq!(ent.page_id(), 999);
assert_eq!(ent.parent_id(), Some(123));
assert!(matches!(ent, Placeholder::Title(_)));
let element = vimwiki_placeholder!(r#"%nohtml"#);
let region = Region::from(element.region());
let ent =
Placeholder::from_vimwiki_element(999, Some(123), element)
.expect("Failed to convert from element");
assert_eq!(ent.region(), ®ion);
assert_eq!(ent.page_id(), 999);
assert_eq!(ent.parent_id(), Some(123));
assert!(matches!(ent, Placeholder::NoHtml(_)));
let element = vimwiki_placeholder!(r#"%template some template"#);
let region = Region::from(element.region());
let ent =
Placeholder::from_vimwiki_element(999, Some(123), element)
.expect("Failed to convert from element");
assert_eq!(ent.region(), ®ion);
assert_eq!(ent.page_id(), 999);
assert_eq!(ent.parent_id(), Some(123));
assert!(matches!(ent, Placeholder::Template(_)));
let element = vimwiki_placeholder!(r#"%date 2017-07-08"#);
let region = Region::from(element.region());
let ent =
Placeholder::from_vimwiki_element(999, Some(123), element)
.expect("Failed to convert from element");
assert_eq!(ent.region(), ®ion);
assert_eq!(ent.page_id(), 999);
assert_eq!(ent.parent_id(), Some(123));
assert!(matches!(ent, Placeholder::Date(_)));
let element = vimwiki_placeholder!(r#"%other text"#);
let region = Region::from(element.region());
let ent =
Placeholder::from_vimwiki_element(999, Some(123), element)
.expect("Failed to convert from element");
assert_eq!(ent.region(), ®ion);
assert_eq!(ent.page_id(), 999);
assert_eq!(ent.parent_id(), Some(123));
assert!(matches!(ent, Placeholder::Other(_)));
});
}
}