export const NAV_MODE_KEY = "sb_mode"; /* ────────────────────────────────────────────── NAVIGATION DATA — single source of truth ────────────────────────────────────────────── */ export const NAV_GROUPS = [ { id: "clients", label: "Clients", icon: "fa-display", iconColor: "text-sky-400", href: "/", linkId: "nav-clients", alwaysVisible: true, }, { id: "purgatory", label: "Purgatory", icon: "fa-user-clock", iconColor: "text-amber-400", href: "/purgatory", linkId: "enrollment-link", hasBadge: true, }, { id: "system", label: "System", icon: "fa-gear", iconColor: "text-slate-300", children: [ { href: "/logs", label: "Logs", icon: "fa-clipboard-list", iconColor: "text-amber-400", linkId: "logs-link", hidden: true }, { href: "/file-share", label: "File Share", icon: "fa-share-nodes", iconColor: "text-rose-400", linkId: "file-share-link", hidden: true }, { href: "/users", label: "Users", icon: "fa-users", iconColor: "text-indigo-400", linkId: "users-link", hidden: true }, { href: "/notifications", label: "Notifications", icon: "fa-bell", iconColor: "text-yellow-400", linkId: "notifications-link", hidden: true }, ], }, { id: "management", label: "Management", icon: "fa-folder-open", iconColor: "text-cyan-400", children: [ { href: "/scripts", label: "Scripts", icon: "fa-code", iconColor: "text-cyan-400", linkId: "scripts-link" }, { href: "/socks5-manager", label: "Proxies", icon: "fa-network-wired", iconColor: "text-sky-400", linkId: "socks5-link" }, { href: "/sol-publish", label: "Sol Publish", icon: "fa-link-slash", iconColor: "text-purple-400", linkId: "sol-publish-link", hidden: true }, ], }, { id: "build", label: "Build", icon: "fa-wrench", iconColor: "text-orange-400", children: [ { href: "/build", label: "Builder", icon: "fa-hammer", iconColor: "text-orange-400", linkId: "build-link", hidden: true }, { href: "/plugins", label: "Plugins", icon: "fa-puzzle-piece", iconColor: "text-violet-400", linkId: "plugins-link", hidden: true }, ], }, { id: "monitoring", label: "Monitoring", icon: "fa-chart-line", iconColor: "text-emerald-400", children: [ { href: "/metrics", label: "Metrics", icon: "fa-chart-line", iconColor: "text-emerald-400", linkId: "metrics-link" }, ], }, { id: "plugin_apps", label: "Plugin Apps", icon: "fa-plug", iconColor: "text-fuchsia-400", hidden: true, children: [], } ]; /* ────────────────────────────────────────────── TOPBAR — dropdown menus ────────────────────────────────────────────── */ export function dropdownItem(child) { const hiddenCls = child.hidden ? " hidden" : ""; const badgeHtml = child.hasBadge ? `` : ""; return ` ${child.label} ${badgeHtml} `; } function dropdownGroup(group) { if (group.href && !group.children) { // Simple link (Clients, Purgatory) const alwaysCls = group.alwaysVisible ? "" : " hidden"; const badgeHtml = group.hasBadge ? `` : ""; return ` ${group.label} ${badgeHtml} `; } // Dropdown group — wrapper always visible, children control visibility const items = group.children.map(dropdownItem).join(""); const groupHidden = group.hidden ? " hidden" : ""; return ` `; } function mountTopbar(host) { host.className = "sticky top-0 z-10 w-full px-5 py-3 bg-slate-950/80 backdrop-blur border-b border-slate-800"; const groupsHtml = NAV_GROUPS.map(dropdownGroup).join(""); host.innerHTML = `
Overlord
`; // Collect all link refs const refs = { toggle: null, panel: document.getElementById("nav-panel"), collapseBtn: null, navLinks: document.getElementById("nav-links"), navUtility: document.getElementById("nav-utility"), logoutBtn: document.getElementById("logout-btn"), notifyToggle: document.getElementById("notify-toggle"), notifyBadge: document.getElementById("notify-badge"), accountSettingsBtn: document.getElementById("account-settings-btn"), usernameDisplay: document.getElementById("username-display"), roleBadge: document.getElementById("role-badge"), enrollmentBadge: document.getElementById("enrollment-badge"), navHideBtn: document.getElementById("nav-hide-btn"), }; // Add individual link refs NAV_GROUPS.forEach((g) => { if (g.linkId) refs[g.linkId.replace(/-/g, "") + "Ref"] = document.getElementById(g.linkId); if (g.children) { g.children.forEach((c) => { const key = c.linkId.replace(/-/g, "") + "Ref"; refs[key] = document.getElementById(c.linkId); }); } }); // Convenience refs expected by nav.js refs.usersLink = document.getElementById("users-link"); refs.buildLink = document.getElementById("build-link"); refs.solPublishLink = document.getElementById("sol-publish-link"); refs.pluginsLink = document.getElementById("plugins-link"); refs.scriptsLink = document.getElementById("scripts-link"); refs.logsLink = document.getElementById("logs-link"); refs.notificationsLink = document.getElementById("notifications-link"); refs.enrollmentLink = document.getElementById("enrollment-link"); refs.fileShareLink = document.getElementById("file-share-link"); return refs; } /* ────────────────────────────────────────────── SIDEBAR — tree-style expandable ────────────────────────────────────────────── */ export function sidebarChild(child) { const hiddenCls = child.hidden ? " hidden" : ""; const badgeHtml = child.hasBadge ? `` : ""; return ` ${child.label} ${badgeHtml} `; } function sidebarGroup(group) { if (group.href && !group.children) { // Simple link (Clients, Purgatory) const alwaysCls = group.alwaysVisible ? "" : " hidden"; const badgeHtml = group.hasBadge ? `` : ""; return ` ${group.label} ${badgeHtml} `; } // Expandable group — wrapper always visible, children control visibility const childrenHtml = group.children.map(sidebarChild).join(""); const groupHidden = group.hidden ? " hidden" : ""; return `
${childrenHtml}
`; } function mountSidebar(host) { const groupsHtml = NAV_GROUPS.map(sidebarGroup).join(""); host.innerHTML = `
`; // Mobile topbar const mobileBar = document.createElement("div"); mobileBar.id = "sb-mobile-bar"; mobileBar.innerHTML = ` Overlord `; host.insertAdjacentElement("afterend", mobileBar); // Mobile backdrop const backdrop = document.createElement("div"); backdrop.id = "sb-backdrop"; document.body.appendChild(backdrop); // Collect refs const refs = { toggle: document.getElementById("nav-toggle"), collapseBtn: document.getElementById("sb-collapse-btn"), panel: host, navLinks: document.getElementById("nav-links"), navUtility: document.getElementById("nav-utility"), logoutBtn: document.getElementById("logout-btn"), notifyToggle: document.getElementById("notify-toggle"), notifyBadge: document.getElementById("notify-badge"), accountSettingsBtn: document.getElementById("account-settings-btn"), usernameDisplay: document.getElementById("username-display"), roleBadge: document.getElementById("role-badge"), enrollmentBadge: document.getElementById("enrollment-badge"), navHideBtn: document.getElementById("nav-hide-btn"), }; // Convenience refs expected by nav.js refs.usersLink = document.getElementById("users-link"); refs.buildLink = document.getElementById("build-link"); refs.solPublishLink = document.getElementById("sol-publish-link"); refs.pluginsLink = document.getElementById("plugins-link"); refs.scriptsLink = document.getElementById("scripts-link"); refs.logsLink = document.getElementById("logs-link"); refs.notificationsLink = document.getElementById("notifications-link"); refs.enrollmentLink = document.getElementById("enrollment-link"); refs.fileShareLink = document.getElementById("file-share-link"); return refs; } export function mountNav(host) { const mode = localStorage.getItem(NAV_MODE_KEY); if (mode === "sidebar") { return mountSidebar(host); } return mountTopbar(host); }