Organize navigation into a responsive grouped sidebar

This commit is contained in:
2026-10-05 18:55:48 -04:00
parent e9d0b2ee30
commit a5f9956615
4 changed files with 210 additions and 198 deletions
+52
View File
@@ -0,0 +1,52 @@
import type { UserRole } from './auth.js';
export interface NavigationItem { label: string; href: string; shortcut?: string; matches?: (path: string) => boolean }
export interface NavigationGroup { id: string; label: string; admin?: boolean; items: NavigationItem[] }
export const navigationGroups: NavigationGroup[] = [
{ id: 'fleet', label: 'Fleet', items: [
{ label: 'Overview', href: '/', shortcut: 'f', matches: path => path === '/' || path.startsWith('/servers/') },
{ label: 'Collections', href: '/collections' },
{ label: 'Hosts', href: '/hosts', shortcut: 'o', matches: path => path === '/hosts' || /^\/hosts\/(?!operations(?:\/|$))/.test(path) },
{ label: 'Capacity', href: '/capacity' }
] },
{ id: 'library', label: 'Library', items: [
{ label: 'Scripts', href: '/scripts', shortcut: 's' },
{ label: 'Configs', href: '/configs', shortcut: 'c' },
{ label: 'Plugins', href: '/plugins', shortcut: 'p' },
{ label: 'Game Files', href: '/game-files' }
] },
{ id: 'operations', label: 'Operations', items: [
{ label: 'Provisioning', href: '/provisioning', shortcut: 'd', matches: path => /^\/(provisioning|deployments)(\/|$)/.test(path) },
{ label: 'Betas', href: '/betas', shortcut: 'b' },
{ label: 'Campaigns', href: '/campaigns', shortcut: 'a' },
{ label: 'Maintenance', href: '/maintenance', shortcut: 'w', matches: path => /^\/(maintenance|watchdog)(\/|$)/.test(path) },
{ label: 'Host operation history', href: '/hosts/operations' }
] },
{ id: 'analytics', label: 'Analytics', items: [
{ label: 'Metrics', href: '/metrics', shortcut: 'm' },
{ label: 'Leaderboard', href: '/leaderboard', shortcut: 'l' },
{ label: 'Match History', href: '/matches' }
] },
{ id: 'administration', label: 'Administration', admin: true, items: [
{ label: 'Settings', href: '/settings', shortcut: 'h', matches: path => path === '/settings' },
{ label: 'Keys', href: '/server-keys', shortcut: 'k' },
{ label: 'Users', href: '/settings/users' }
] }
];
export function visibleNavigation(role: UserRole): NavigationGroup[] {
return navigationGroups.filter(group => !group.admin || role === 'admin');
}
export function navigationItemActive(item: NavigationItem, path: string): boolean {
return item.matches ? item.matches(path) : path === item.href || path.startsWith(item.href + '/');
}
export function navigationLocation(path: string, role: UserRole) {
for (const group of visibleNavigation(role)) {
const item = group.items.find(item => navigationItemActive(item, path));
if (item) return { group, item };
}
return null;
}