menu: 2 kind of menus: user and admin

This commit is contained in:
Philippe Loctaux 2023-03-23 21:11:42 +01:00
parent 1facd2ffbf
commit 75f9b9dca3
8 changed files with 135 additions and 54 deletions

View file

@ -1,24 +1,39 @@
mod icons;
mod items; mod items;
mod template; mod template;
pub use items::Item; pub use items::{Admin, User};
pub use template::Template; pub use template::Template;
pub struct Menu { pub enum Menu {
pub selected: Item, User(User),
pub list: Vec<Item>, Admin(Admin),
} }
impl From<Item> for Menu { impl Menu {
fn from(value: Item) -> Self { pub fn selected(&self) -> &'static str {
Self { match self {
selected: value, Menu::User(user) => user.id(),
list: list(), Menu::Admin(admin) => admin.id(),
}
}
pub fn list(&self) -> Vec<Template> {
match self {
Menu::User(user) => user.list(),
Menu::Admin(admin) => admin.list(),
} }
} }
} }
/// Declare list of ordered menu items impl From<User> for Menu {
fn list() -> Vec<Item> { fn from(value: User) -> Self {
vec![Item::Home] Self::User(value)
}
}
impl From<Admin> for Menu {
fn from(value: Admin) -> Self {
Self::Admin(value)
}
} }

View file

@ -0,0 +1,3 @@
/// Find icons on https://tabler-icons.io
pub const HOME: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-home" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 12l-2 0l9 -9l9 9l-2 0"></path><path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7"></path><path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6"></path></svg>"#;
pub const LOGOUT: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-logout" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M14 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2"></path><path d="M7 12h14l-3 -3m0 6l3 -3"></path></svg>"#;

View file

@ -1,32 +1,5 @@
pub enum Item { mod admin;
Home, mod user;
}
impl Item { pub use admin::Admin;
pub fn id(&self) -> &'static str { pub use user::User;
match self {
Item::Home => "home",
}
}
pub fn label(&self) -> &'static str {
match self {
Item::Home => "Home",
}
}
pub fn link(&self) -> &'static str {
match self {
Item::Home => "/",
}
}
/// Find icons on https://tabler-icons.io
pub fn icon(&self) -> &'static str {
match self {
Item::Home => {
r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-home" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 12l-2 0l9 -9l9 9l-2 0"></path><path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7"></path><path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6"></path></svg>"#
}
}
}
}

View file

@ -0,0 +1,43 @@
use super::super::icons;
use crate::menu::Template;
const LIST: &[Admin] = &[Admin::ExitAdmin, Admin::AdminDashboard];
pub enum Admin {
ExitAdmin,
AdminDashboard,
}
impl Admin {
pub fn list(&self) -> Vec<Template> {
LIST.iter().map(Template::from).collect()
}
pub fn id(&self) -> &'static str {
match self {
Self::ExitAdmin => "exit_admin",
Self::AdminDashboard => "admin_dashboard",
}
}
pub fn label(&self) -> &'static str {
match self {
Self::ExitAdmin => "Exit admin panel",
Self::AdminDashboard => "Admin dashboard",
}
}
pub fn link(&self) -> &'static str {
match self {
Self::ExitAdmin => "/",
Self::AdminDashboard => "/admin",
}
}
pub fn icon(&self) -> &'static str {
match self {
Self::ExitAdmin => icons::LOGOUT,
Self::AdminDashboard => icons::HOME,
}
}
}

View file

@ -0,0 +1,38 @@
use super::super::icons;
use crate::menu::Template;
const LIST: &[User] = &[User::Home];
pub enum User {
Home,
}
impl User {
pub fn list(&self) -> Vec<Template> {
LIST.iter().map(Template::from).collect()
}
pub fn id(&self) -> &'static str {
match self {
User::Home => "home",
}
}
pub fn label(&self) -> &'static str {
match self {
User::Home => "Home",
}
}
pub fn link(&self) -> &'static str {
match self {
User::Home => "/",
}
}
pub fn icon(&self) -> &'static str {
match self {
User::Home => icons::HOME,
}
}
}

View file

@ -1,4 +1,4 @@
use super::Item; use super::{Admin, User};
use rocket::serde::Serialize; use rocket::serde::Serialize;
#[derive(Serialize)] #[derive(Serialize)]
@ -10,8 +10,19 @@ pub struct Template {
icon: &'static str, icon: &'static str,
} }
impl From<Item> for Template { impl From<&User> for Template {
fn from(value: Item) -> Self { fn from(value: &User) -> Self {
Self {
id: value.id(),
label: value.label(),
link: value.link(),
icon: value.icon(),
}
}
}
impl From<&Admin> for Template {
fn from(value: &Admin) -> Self {
Self { Self {
id: value.id(), id: value.id(),
label: value.label(), label: value.label(),

View file

@ -4,7 +4,7 @@ mod responder;
mod template; mod template;
use self::content::*; use self::content::*;
use crate::menu::{Item, Menu}; use crate::menu::Menu;
use erased_serde::Serialize; use erased_serde::Serialize;
pub use flash::FlashKind; pub use flash::FlashKind;
@ -42,10 +42,13 @@ impl Page {
/// Show menu with active item /// Show menu with active item
fn menu(&self) -> Option<Menu> { fn menu(&self) -> Option<Menu> {
use crate::menu::Admin as AdminMenu;
use crate::menu::User as UserMenu;
match self { match self {
Page::Error(_) => None, Page::Error(_) => None,
Page::Setup => None, Page::Setup => None,
Page::Homepage(_) => Some(Item::Home.into()), Page::Homepage(_) => Some(UserMenu::Home.into()),
Page::Authorize(_) => None, Page::Authorize(_) => None,
Page::Redirect(_) => None, Page::Redirect(_) => None,
} }

View file

@ -22,12 +22,7 @@ fn render(p: Page, flash: Option<(String, String)>) -> Template {
TemplateContent { TemplateContent {
title: p.page_title(), title: p.page_title(),
version: env!("CARGO_PKG_VERSION"), version: env!("CARGO_PKG_VERSION"),
menu: p.menu().map(|menu| { menu: p.menu().map(|menu| (menu.selected(), menu.list())),
(
menu.selected.id(),
menu.list.into_iter().map(MenuTemplate::from).collect(),
)
}),
flash, flash,
content: p.content(), content: p.content(),
}, },