Skip to content

Commit 5ab3d2d

Browse files
committed
feat(panel): add categories management UI
1 parent 6b67b19 commit 5ab3d2d

8 files changed

Lines changed: 717 additions & 2 deletions

File tree

crates/rustmail_panel/src/components/categories.rs

Lines changed: 585 additions & 0 deletions
Large diffs are not rendered by default.

crates/rustmail_panel/src/components/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod api_keys;
2+
pub mod categories;
23
pub mod configuration;
34
pub mod forbidden;
45
pub mod home;

crates/rustmail_panel/src/components/navbar.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn rustmail_navbar(props: &RustmailNavbarProps) -> Html {
3535
let home_active = current_path == "/panel";
3636
let config_active = current_path == "/panel/configuration";
3737
let apikeys_active = current_path == "/panel/apikeys";
38+
let categories_active = current_path == "/panel/categories";
3839
let tickets_active = current_path.starts_with("/panel/tickets");
3940
let admin_active = current_path == "/admin";
4041

@@ -45,6 +46,9 @@ pub fn rustmail_navbar(props: &RustmailNavbarProps) -> Html {
4546
let has_manage_permissions = props
4647
.permissions
4748
.contains(&PanelPermission::ManagePermissions);
49+
let has_manage_categories = props
50+
.permissions
51+
.contains(&PanelPermission::ManageCategories);
4852

4953
html! {
5054
<nav class="fixed top-0 left-0 w-full z-50 bg-gradient-to-r from-slate-900 to-black border-b border-slate-800">
@@ -162,6 +166,31 @@ pub fn rustmail_navbar(props: &RustmailNavbarProps) -> Html {
162166
html! {}
163167
}}
164168

169+
{ if has_manage_categories {
170+
html! {
171+
<button
172+
onclick={{
173+
let navigator = navigator.clone();
174+
move |_| if let Some(nav) = &navigator {
175+
nav.push(&PanelRoute::Categories);
176+
}
177+
}}
178+
class={classes!(
179+
"rounded-md", "px-3", "py-2", "text-sm", "transition",
180+
if categories_active {
181+
"bg-white/10 text-white"
182+
} else {
183+
"text-gray-300 hover:bg-white/10 hover:text-white"
184+
}
185+
)}
186+
>
187+
{i18n.t("navbar.categories")}
188+
</button>
189+
}
190+
} else {
191+
html! {}
192+
}}
193+
165194
{ if has_manage_permissions {
166195
html! {
167196
<a
@@ -339,6 +368,35 @@ pub fn rustmail_navbar(props: &RustmailNavbarProps) -> Html {
339368
html! {}
340369
}}
341370

371+
{ if has_manage_categories {
372+
html! {
373+
<button
374+
onclick={{
375+
let navigator = navigator.clone();
376+
let mobile_menu_open = mobile_menu_open.clone();
377+
move |_| {
378+
if let Some(nav) = &navigator {
379+
nav.push(&PanelRoute::Categories);
380+
}
381+
mobile_menu_open.set(false);
382+
}
383+
}}
384+
class={classes!(
385+
"block", "w-full", "text-left", "rounded-md", "px-3", "py-2", "text-sm", "transition",
386+
if categories_active {
387+
"bg-white/10 text-white"
388+
} else {
389+
"text-gray-300 hover:bg-white/10 hover:text-white"
390+
}
391+
)}
392+
>
393+
{i18n.t("navbar.categories")}
394+
</button>
395+
}
396+
} else {
397+
html! {}
398+
}}
399+
342400
{ if has_manage_permissions {
343401
html! {
344402
<a

crates/rustmail_panel/src/i18n/en/en.json

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"config": "Configuration",
1313
"apikeys": "API Keys",
1414
"tickets": "Tickets",
15+
"categories": "Categories",
1516
"administration": "Administration",
1617
"logout": "Logout"
1718
},
@@ -267,7 +268,37 @@
267268
"manage_config": "Manage Config",
268269
"manage_tickets": "Manage Tickets",
269270
"manage_api_keys": "Manage API Keys",
270-
"manage_permissions": "Manage Permissions"
271+
"manage_permissions": "Manage Permissions",
272+
"manage_categories": "Manage Categories"
273+
}
274+
},
275+
"categories": {
276+
"title": "Ticket Categories",
277+
"create": "+ Create Category",
278+
"loading": "Loading categories...",
279+
"no_categories": "No categories defined yet. Create your first one!",
280+
"settings": "Global Settings",
281+
"feature_enabled": "Category selection enabled",
282+
"feature_enabled_help": "When enabled, users opening a ticket via DM will be prompted to choose a category.",
283+
"timeout_label": "Selection timeout (seconds)",
284+
"timeout_help": "If the user doesn't pick within this delay, the ticket falls back to the default inbox. Minimum 30 seconds.",
285+
"state_enabled": "Enabled",
286+
"state_disabled": "Disabled",
287+
"delete": "Delete",
288+
"discord_category_id": "Discord Category ID",
289+
"error_name_required": "Name is required",
290+
"error_discord_id_required": "Discord category ID is required",
291+
"error_create": "Failed to create category",
292+
"modal": {
293+
"title": "Create Category",
294+
"name": "Name",
295+
"name_placeholder": "Connection Issue",
296+
"description": "Description (optional)",
297+
"emoji": "Emoji (optional)",
298+
"discord_category_id": "Discord Category ID",
299+
"cancel": "Cancel",
300+
"create": "Create",
301+
"creating": "Creating..."
271302
}
272303
},
273304
"forbidden": {

crates/rustmail_panel/src/i18n/fr/fr.json

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"config": "Configuration",
1313
"apikeys": "Clés API",
1414
"tickets": "Tickets",
15+
"categories": "Catégories",
1516
"administration": "Administration",
1617
"logout": "Se déconnecter"
1718
},
@@ -268,7 +269,37 @@
268269
"manage_config": "Gérer la Config",
269270
"manage_tickets": "Gérer les Tickets",
270271
"manage_api_keys": "Gérer les Clés API",
271-
"manage_permissions": "Gérer les Permissions"
272+
"manage_permissions": "Gérer les Permissions",
273+
"manage_categories": "Gérer les Catégories"
274+
}
275+
},
276+
"categories": {
277+
"title": "Catégories de tickets",
278+
"create": "+ Créer une catégorie",
279+
"loading": "Chargement des catégories...",
280+
"no_categories": "Aucune catégorie définie. Créez la première !",
281+
"settings": "Paramètres globaux",
282+
"feature_enabled": "Sélection de catégorie activée",
283+
"feature_enabled_help": "Si activée, les utilisateurs qui ouvrent un ticket via DM seront invités à choisir une catégorie.",
284+
"timeout_label": "Délai de sélection (secondes)",
285+
"timeout_help": "Si l'utilisateur ne choisit pas dans ce délai, le ticket est envoyé dans la boîte de réception par défaut. Minimum 30 secondes.",
286+
"state_enabled": "Activée",
287+
"state_disabled": "Désactivée",
288+
"delete": "Supprimer",
289+
"discord_category_id": "ID de catégorie Discord",
290+
"error_name_required": "Le nom est requis",
291+
"error_discord_id_required": "L'ID de catégorie Discord est requis",
292+
"error_create": "Impossible de créer la catégorie",
293+
"modal": {
294+
"title": "Créer une catégorie",
295+
"name": "Nom",
296+
"name_placeholder": "Problème de connexion",
297+
"description": "Description (optionnel)",
298+
"emoji": "Emoji (optionnel)",
299+
"discord_category_id": "ID de catégorie Discord",
300+
"cancel": "Annuler",
301+
"create": "Créer",
302+
"creating": "Création..."
272303
}
273304
},
274305
"forbidden": {

crates/rustmail_panel/src/pages/administration.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ pub fn administration() -> Html {
318318
("manage_tickets", i18n.t("panel.administration.permissions.manage_tickets")),
319319
("manage_api_keys", i18n.t("panel.administration.permissions.manage_api_keys")),
320320
("manage_permissions", i18n.t("panel.administration.permissions.manage_permissions")),
321+
("manage_categories", i18n.t("panel.administration.permissions.manage_categories")),
321322
].iter().map(|(value, label)| {
322323
let is_checked = selected_permissions.contains(&value.to_string());
323324
let selected_permissions_clone = selected_permissions.clone();
@@ -518,6 +519,7 @@ pub fn administration() -> Html {
518519
("manage_tickets", i18n.t("panel.administration.permissions.manage_tickets")),
519520
("manage_api_keys", i18n.t("panel.administration.permissions.manage_api_keys")),
520521
("manage_permissions", i18n.t("panel.administration.permissions.manage_permissions")),
522+
("manage_categories", i18n.t("panel.administration.permissions.manage_categories")),
521523
];
522524
let current_perms: Vec<String> = perms_list.iter().map(|(_, p)| {
523525
match p {
@@ -527,6 +529,7 @@ pub fn administration() -> Html {
527529
PanelPermission::ManageTickets => "manage_tickets",
528530
PanelPermission::ManageApiKeys => "manage_api_keys",
529531
PanelPermission::ManagePermissions => "manage_permissions",
532+
PanelPermission::ManageCategories => "manage_categories",
530533
}.to_string()
531534
}).collect();
532535

crates/rustmail_panel/src/pages/panel.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::components::api_keys::ApiKeysPage;
2+
use crate::components::categories::CategoriesPage;
23
use crate::components::configuration::ConfigurationPage;
34
use crate::components::home::Home;
45
use crate::components::navbar::RustmailNavbar;
@@ -26,6 +27,8 @@ pub enum PanelRoute {
2627
Configuration,
2728
#[at("/panel/apikeys")]
2829
ApiKeys,
30+
#[at("/panel/categories")]
31+
Categories,
2932
#[at("/panel/tickets")]
3033
TicketsList,
3134
#[at("/panel/tickets/:id")]
@@ -134,6 +137,7 @@ fn switch(route: PanelRoute, navigator: Option<Navigator>) -> Html {
134137
PanelRoute::Home => html! { <Home /> },
135138
PanelRoute::Configuration => html! { <ConfigurationPage /> },
136139
PanelRoute::ApiKeys => html! { <ApiKeysPage /> },
140+
PanelRoute::Categories => html! { <CategoriesPage /> },
137141
PanelRoute::TicketsList => html! { <TicketsList /> },
138142
PanelRoute::TicketDetails { id } => {
139143
let nav = navigator.clone();

crates/rustmail_panel/src/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub enum PanelPermission {
99
ManageTickets,
1010
ManageApiKeys,
1111
ManagePermissions,
12+
ManageCategories,
1213
}
1314

1415
impl PanelPermission {
@@ -20,6 +21,7 @@ impl PanelPermission {
2021
PanelPermission::ManageTickets => "Manage Tickets",
2122
PanelPermission::ManageApiKeys => "Manage API Keys",
2223
PanelPermission::ManagePermissions => "Manage Permissions",
24+
PanelPermission::ManageCategories => "Manage Categories",
2325
}
2426
}
2527
}

0 commit comments

Comments
 (0)