refactor: sidebar nav items modules dynamiques selon is_enabled

Les items CORE (dashboard, proxmox, updates, settings, modules) sont
toujours affichés. Les modules optionnels (terminal, files, services,
logs) n'apparaissent dans la sidebar que si leur module est activé
en base de données — conformément à l'instruction.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
enzo 2026-03-22 02:55:39 +01:00
parent c9ba6755b8
commit 91cf788221

View file

@ -319,20 +319,48 @@ document.addEventListener('alpine:init', () => {
})
// ── Composant: sidebar ──────────────────────────────────────────────────
// Items CORE : toujours visibles.
// Items modules : visibles seulement si le module est activé en DB.
const _coreNavItems = [
{ id: 'dashboard', iconClass: 'lnid-dashboard-square-1', iconColor: '#6c8ef4', labelKey: 'nav.dashboard', href: '/dashboard.html' },
{ id: 'proxmox', iconClass: 'lnid-server-1', iconColor: '#22c55e', labelKey: 'nav.proxmox', href: '/proxmox.html' },
{ id: 'updates', iconClass: 'lnid-arrow-upward', iconColor: '#f59e0b', labelKey: 'nav.updates', href: '/updates.html' },
{ id: 'settings', iconClass: 'lnid-gear-1', iconColor: '#94a3b8', labelKey: 'nav.settings', href: '/settings.html' },
{ id: 'modules', iconClass: 'lnid-puzzle', iconColor: '#f472b6', labelKey: 'nav.modules', href: '/modules.html' },
]
// Définition des items de navigation pour les modules optionnels.
// Un module dont l'id n'est pas ici n'aura pas d'entrée dans la sidebar.
const _moduleNavDef = {
terminal: { iconClass: 'lnid-terminal', iconColor: '#a78bfa', labelKey: 'nav.terminal', href: '/terminal.html' },
files: { iconClass: 'lnid-folder-1', iconColor: '#84cc16', labelKey: 'nav.files', href: '/files.html' },
services: { iconClass: 'lnid-gear-2', iconColor: '#fb923c', labelKey: 'nav.services', href: '/services.html' },
logs: { iconClass: 'lnid-scroll-angular-1', iconColor: '#38bdf8', labelKey: 'nav.logs', href: '/logs.html' },
}
Alpine.data('sidebar', () => ({
get collapsed() { return Alpine.store('ui').sidebarCollapsed },
get currentPage() { return Alpine.store('ui').currentPage },
navItems: [
{ id: 'dashboard', iconClass: 'lnid-dashboard-square-1', iconColor: '#6c8ef4', labelKey: 'nav.dashboard', href: '/dashboard.html' },
{ id: 'proxmox', iconClass: 'lnid-server-1', iconColor: '#22c55e', labelKey: 'nav.proxmox', href: '/proxmox.html' },
{ id: 'updates', iconClass: 'lnid-arrow-upward', iconColor: '#f59e0b', labelKey: 'nav.updates', href: '/updates.html' },
{ id: 'terminal', iconClass: 'lnid-terminal', iconColor: '#a78bfa', labelKey: 'nav.terminal', href: '/terminal.html' },
{ id: 'services', iconClass: 'lnid-gear-2', iconColor: '#fb923c', labelKey: 'nav.services', href: '/services.html' },
{ id: 'logs', iconClass: 'lnid-scroll-angular-1', iconColor: '#38bdf8', labelKey: 'nav.logs', href: '/logs.html' },
{ id: 'settings', iconClass: 'lnid-gear-1', iconColor: '#94a3b8', labelKey: 'nav.settings', href: '/settings.html' },
{ id: 'modules', iconClass: 'lnid-puzzle', iconColor: '#f472b6', labelKey: 'nav.modules', href: '/modules.html' },
],
// Commence avec les items CORE ; init() ajoute les modules activés
navItems: [..._coreNavItems],
async init() {
try {
const res = await apiFetch('/api/modules')
if (!res.ok) return
const modules = await res.json() || []
const moduleItems = modules
.filter(m => m.is_enabled && !m.is_core && _moduleNavDef[m.id])
.map(m => ({ id: m.id, ..._moduleNavDef[m.id] }))
// Insérer les modules entre Updates et Settings
const insertAt = this.navItems.findIndex(i => i.id === 'settings')
this.navItems = [
...this.navItems.slice(0, insertAt),
...moduleItems,
...this.navItems.slice(insertAt),
]
} catch(e) {}
},
iconStyle(item) {
return this.isActive(item.id) ? '' : `color: ${item.iconColor}`