Files
electric-cherry/src/lib/navigation.ts
T

111 lines
3.3 KiB
TypeScript

import { canReadAdmin, 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: 'Servers',
href: '/',
shortcut: 'f',
matches: (path) => path === '/' || path.startsWith('/servers/')
},
{
label: 'Hosts',
href: '/hosts',
shortcut: 'o',
matches: (path) => path === '/hosts' || path.startsWith('/hosts/')
},
{ label: 'Capacity', href: '/capacity' },
{ label: 'Autoscaling', href: '/autoscaling' },
{ label: 'Collections', href: '/collections' }
]
},
{
id: 'releases',
label: 'Releases',
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' },
{ label: 'Betas', href: '/betas', shortcut: 'b' },
{ label: 'Campaigns', href: '/campaigns', shortcut: 'a' }
]
},
{
id: 'activity',
label: 'Activity',
items: [
{
label: 'Provisioning',
href: '/provisioning',
matches: (path) => /^\/(provisioning|deployments)(\/|$)/.test(path)
},
{
label: 'Maintenance',
href: '/maintenance',
shortcut: 'w',
matches: (path) => /^\/(maintenance|watchdog)(\/|$)/.test(path)
}
]
},
{
id: 'players',
label: 'Players',
items: [
{ label: 'Leaderboard', href: '/leaderboard', shortcut: 'l' },
{ label: 'Matches', href: '/matches' },
{ label: 'Bank', href: '/bank' },
{ label: 'Usage', href: '/metrics', shortcut: 'm' }
]
},
{
id: 'admin',
label: 'Admin',
admin: true,
items: [
{ label: 'Users', href: '/settings/users' },
{ label: 'Keys', href: '/server-keys', shortcut: 'k' },
{
label: 'Settings',
href: '/settings',
shortcut: 'h',
matches: (path) => path === '/settings'
}
]
}
];
export function visibleNavigation(role: UserRole): NavigationGroup[] {
return navigationGroups.filter((group) => !group.admin || canReadAdmin(role));
}
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;
}