use {
crate::async_graphql::{self, dataloader::DataLoader, Context, FieldResult},
crate::Database,
async_graphql::InputObject,
serde::{Deserialize, Serialize},
slug::slugify,
sqlx::types::Uuid,
};
#[derive(Debug, Clone, Serialize, Deserialize, async_graphql::SimpleObject)]
pub struct Menu {
pub id: Uuid,
pub name: String,
pub slug: String,
pub items: Vec<MenuItem>,
}
#[derive(Debug, Clone, InputObject, Serialize, Deserialize)]
pub struct MenuUpdate {
pub id: Uuid,
pub name: Option<String>,
pub items: Option<Vec<MenuItemInput>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, async_graphql::SimpleObject)]
pub struct MenuItem {
pub label: String,
pub path: String,
#[serde(alias = "children")]
pub items: Option<Vec<MenuItem>>,
}
#[derive(Debug, Clone, InputObject, Serialize, Deserialize)]
pub struct MenuItemInput {
pub label: String,
pub path: String,
#[serde(alias = "children")]
pub items: Option<Vec<MenuItemInput>>,
}
impl From<MenuItemInput> for MenuItem {
fn from(value: MenuItemInput) -> Self {
MenuItem {
label: value.label,
path: value.path,
items: value.items.map(|v| v.into_iter().map(Into::into).collect()),
}
}
}
impl Menu {
pub async fn menu_by_slug(&self, context: &Context<'_>, slug: String) -> FieldResult<Menu> {
let db = context.data::<DataLoader<Database>>()?.loader();
let menu = db.get_menu_by_slug(slugify(&slug)).await?;
Ok(menu)
}
}