mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-11 01:55:43 +00:00
b73648651d
Admin page and Go /api/branding schema v1 with logo/contact fields, RustDesk-safe heartbeat projections, i18n, and handler tests. Thanks: INSOLVE (Honorary); Marco Jakobs (@jacotec); MyNameisStitch (@MyNameisStitch); Redspin (@playerumpknow)
463 lines
26 KiB
HTML
463 lines
26 KiB
HTML
<% const sidebarServerTab = typeof currentTab !== 'undefined' && currentTab ? currentTab : 'overview'; %>
|
|
<% const sidebarCommercialTab = typeof currentTab !== 'undefined' && currentTab ? currentTab : 'overview'; %>
|
|
<!-- Sidebar Navigation — TeamViewer-style icon rail + flyout -->
|
|
<aside class="sidebar" id="sidebar" data-collapsed="true">
|
|
<!-- Icon rail (always visible) -->
|
|
<div class="sidebar-rail">
|
|
<!-- Logo -->
|
|
<div class="sidebar-rail-logo">
|
|
<a href="/" class="sidebar-logo" title="<%= appName %>">
|
|
<% if (branding.logoType === 'text' && branding.logoText) { %>
|
|
<span class="brand-text-logo"><%= branding.logoText %><% if (branding.logoTextAccent) { %><span class="brand-text-accent"><%= branding.logoTextAccent %></span><% } %></span>
|
|
<% } else if (branding.logoType === 'svg' && branding.logoSvg) { %>
|
|
<span class="sidebar-logo-svg"><%- branding.logoSvg %></span>
|
|
<% } else if (branding.logoType === 'image' && branding.logoUrl) { %>
|
|
<img src="<%= branding.logoUrl %>" alt="<%= appName %>" class="sidebar-logo-img">
|
|
<% } else { %>
|
|
<span class="material-icons"><%= branding.logoIcon || 'dns' %></span>
|
|
<% } %>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Category icons -->
|
|
<nav class="sidebar-rail-nav">
|
|
<button class="sidebar-rail-btn <%= ['dashboard','devices','registrations','client-branding'].includes(currentPage) ? 'active' : '' %>"
|
|
data-category="main" title="<%= _('nav.main') %>">
|
|
<span class="material-icons">home</span>
|
|
</button>
|
|
<button class="sidebar-rail-btn <%= ['inventory','tickets','help-requests','automation','network','activity','cdap','fleet','scaling','cross-platform','chat'].includes(currentPage) ? 'active' : '' %>"
|
|
data-category="management" title="<%= _('nav.management') || 'Management' %>">
|
|
<span class="material-icons">business_center</span>
|
|
</button>
|
|
<button class="sidebar-rail-btn <%= ['reports','keys','generator','remote','toolkit','cdap-studio'].includes(currentPage) ? 'active' : '' %>"
|
|
data-category="tools" title="<%= _('nav.tools') %>">
|
|
<span class="material-icons">build</span>
|
|
</button>
|
|
<% if (isSuperAdmin || hasPermission('server.config') || hasPermission('user.view') || hasPermission('enrollment.manage') || hasPermission('enrollment.approve') || hasPermission('audit.view')) { %>
|
|
<button class="sidebar-rail-btn <%= ['tokens','organizations','policies','attestation','dataguard','users','security-audit','permissions','languages','resource-control'].includes(currentPage) ? 'active' : '' %>"
|
|
data-category="system" title="<%= _('nav.system') %>">
|
|
<span class="material-icons">admin_panel_settings</span>
|
|
</button>
|
|
<% } %>
|
|
<% if (hasPermission('server.config')) { %>
|
|
<button class="sidebar-rail-btn <%= currentPage === 'server-management' ? 'active' : '' %>"
|
|
data-category="server-mgmt" title="<%= _('nav.server_management') || 'Server Management' %>">
|
|
<span class="material-icons">dns</span>
|
|
</button>
|
|
<% } %>
|
|
<% if (hasPermission('billing.view')) { %>
|
|
<button class="sidebar-rail-btn sidebar-rail-btn--alpha <%= currentPage === 'commercialization' ? 'active' : '' %>"
|
|
data-category="commercialization" title="<%= _('commercialization.alpha_tooltip') || _('nav.commercialization') || 'Commercialization' %>">
|
|
<span class="material-icons">payments</span>
|
|
<span class="rail-stage-badge" aria-hidden="true"><%= _('commercialization.alpha_badge') || 'ALPHA' %></span>
|
|
</button>
|
|
<% } %>
|
|
<% if (hasPermission('server.attestation')) { %>
|
|
<a href="/server-attestation" class="sidebar-rail-btn <%= currentPage === 'server-attestation' ? 'active' : '' %>"
|
|
title="<%= _('nav.server_attestation') || 'Server Attestation' %>">
|
|
<span class="material-icons">verified</span>
|
|
</a>
|
|
<% } %>
|
|
<a href="/settings" class="sidebar-rail-btn <%= currentPage === 'settings' ? 'active' : '' %>"
|
|
title="<%= _('nav.settings') %>">
|
|
<span class="material-icons">settings</span>
|
|
</a>
|
|
</nav>
|
|
|
|
<!-- Bottom rail icons -->
|
|
<div class="sidebar-rail-bottom">
|
|
<button class="sidebar-rail-btn" id="sidebar-help-btn" title="<%= _('nav.help') || 'Help' %>">
|
|
<span class="material-icons">help_outline</span>
|
|
</button>
|
|
<button class="sidebar-rail-btn" id="sidebar-expand-btn" title="<%= _('nav.expand_sidebar') || 'Expand' %>">
|
|
<span class="material-icons">chevron_right</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Flyout panel (shows on category click/hover) -->
|
|
<div class="sidebar-flyout" id="sidebar-flyout">
|
|
<div class="sidebar-flyout-header">
|
|
<span class="sidebar-flyout-title" id="sidebar-flyout-title"></span>
|
|
</div>
|
|
|
|
<!-- Commercialization category links -->
|
|
<div class="sidebar-flyout-panel" data-panel="commercialization">
|
|
<% if (hasPermission('billing.view')) { %>
|
|
<a href="/commercialization?tab=overview" class="sidebar-link <%= currentPage === 'commercialization' && sidebarCommercialTab === 'overview' ? 'active' : '' %>">
|
|
<span class="material-icons">dashboard</span>
|
|
<span class="sidebar-link-text"><%= _('commercialization.tabs.overview') %></span>
|
|
</a>
|
|
<a href="/commercialization?tab=packages" class="sidebar-link <%= currentPage === 'commercialization' && sidebarCommercialTab === 'packages' ? 'active' : '' %>">
|
|
<span class="material-icons">inventory_2</span>
|
|
<span class="sidebar-link-text"><%= _('commercialization.tabs.packages') %></span>
|
|
</a>
|
|
<a href="/commercialization?tab=sessions" class="sidebar-link <%= currentPage === 'commercialization' && sidebarCommercialTab === 'sessions' ? 'active' : '' %>">
|
|
<span class="material-icons">schedule</span>
|
|
<span class="sidebar-link-text"><%= _('commercialization.tabs.sessions') %></span>
|
|
</a>
|
|
<a href="/commercialization?tab=reports" class="sidebar-link <%= currentPage === 'commercialization' && sidebarCommercialTab === 'reports' ? 'active' : '' %>">
|
|
<span class="material-icons">description</span>
|
|
<span class="sidebar-link-text"><%= _('commercialization.tabs.reports') %></span>
|
|
</a>
|
|
<a href="/commercialization?tab=settings" class="sidebar-link <%= currentPage === 'commercialization' && sidebarCommercialTab === 'settings' ? 'active' : '' %>">
|
|
<span class="material-icons">tune</span>
|
|
<span class="sidebar-link-text"><%= _('commercialization.tabs.settings') %></span>
|
|
</a>
|
|
<% } %>
|
|
</div>
|
|
|
|
<!-- Main category links -->
|
|
<div class="sidebar-flyout-panel" data-panel="main">
|
|
<a href="/" class="sidebar-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
|
<span class="material-icons">dashboard</span>
|
|
<span class="sidebar-link-text"><%= _('nav.dashboard') %></span>
|
|
</a>
|
|
<% if (hasPermission('device.view')) { %>
|
|
<a href="/devices" class="sidebar-link <%= currentPage === 'devices' ? 'active' : '' %>">
|
|
<span class="material-icons">devices</span>
|
|
<span class="sidebar-link-text"><%= _('nav.devices') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('enrollment.approve')) { %>
|
|
<a href="/registrations" class="sidebar-link <%= currentPage === 'registrations' ? 'active' : '' %>">
|
|
<span class="material-icons">how_to_reg</span>
|
|
<span class="sidebar-link-text"><%= _('nav.registrations') %></span>
|
|
<span class="badge-sidebar" id="reg-sidebar-badge" style="display: none;">0</span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('branding.edit')) { %>
|
|
<a href="/client-branding" class="sidebar-link <%= currentPage === 'client-branding' ? 'active' : '' %>">
|
|
<span class="material-icons">branding_watermark</span>
|
|
<span class="sidebar-link-text"><%= _('nav.client_branding') %></span>
|
|
</a>
|
|
<% } %>
|
|
</div>
|
|
|
|
<!-- Management category links -->
|
|
<div class="sidebar-flyout-panel" data-panel="management">
|
|
<% if (hasPermission('device.view')) { %>
|
|
<a href="/inventory" class="sidebar-link <%= currentPage === 'inventory' ? 'active' : '' %>">
|
|
<span class="material-icons">inventory_2</span>
|
|
<span class="sidebar-link-text"><%= _('nav.inventory') %></span>
|
|
</a>
|
|
<a href="/tickets" class="sidebar-link <%= currentPage === 'tickets' ? 'active' : '' %>">
|
|
<span class="material-icons">confirmation_number</span>
|
|
<span class="sidebar-link-text"><%= _('nav.tickets') %></span>
|
|
</a>
|
|
<a href="/help-requests" class="sidebar-link <%= currentPage === 'help-requests' ? 'active' : '' %>">
|
|
<span class="material-icons">support_agent</span>
|
|
<span class="sidebar-link-text"><%= _('nav.help_requests') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('server.config')) { %>
|
|
<a href="/automation" class="sidebar-link <%= currentPage === 'automation' ? 'active' : '' %>">
|
|
<span class="material-icons">smart_toy</span>
|
|
<span class="sidebar-link-text"><%= _('nav.automation') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('device.view')) { %>
|
|
<a href="/network" class="sidebar-link <%= currentPage === 'network' ? 'active' : '' %>">
|
|
<span class="material-icons">lan</span>
|
|
<span class="sidebar-link-text"><%= _('nav.network') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('audit.view')) { %>
|
|
<a href="/activity" class="sidebar-link <%= currentPage === 'activity' ? 'active' : '' %>">
|
|
<span class="material-icons">timeline</span>
|
|
<span class="sidebar-link-text"><%= _('nav.activity') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('cdap.view')) { %>
|
|
<a href="/cdap" class="sidebar-link <%= currentPage === 'cdap' ? 'active' : '' %>">
|
|
<span class="material-icons">developer_board</span>
|
|
<span class="sidebar-link-text"><%= _('nav.cdap') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('org.manage_devices')) { %>
|
|
<a href="/fleet" class="sidebar-link <%= currentPage === 'fleet' ? 'active' : '' %>">
|
|
<span class="material-icons">hub</span>
|
|
<span class="sidebar-link-text"><%= _('nav.fleet') || 'Fleet' %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('server.config')) { %>
|
|
<a href="/scaling" class="sidebar-link <%= currentPage === 'scaling' ? 'active' : '' %>">
|
|
<span class="material-icons">cell_tower</span>
|
|
<span class="sidebar-link-text"><%= _('nav.scaling') || 'Scaling' %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('device.view')) { %>
|
|
<a href="/cross-platform" class="sidebar-link <%= currentPage === 'cross-platform' ? 'active' : '' %>">
|
|
<span class="material-icons">devices</span>
|
|
<span class="sidebar-link-text"><%= _('nav.cross_platform') || 'Cross-Platform' %></span>
|
|
</a>
|
|
<% } %>
|
|
<a href="/chat" class="sidebar-link <%= currentPage === 'chat' ? 'active' : '' %>">
|
|
<span class="material-icons">chat</span>
|
|
<span class="sidebar-link-text"><%= _('nav.chat') %></span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Tools category links -->
|
|
<div class="sidebar-flyout-panel" data-panel="tools">
|
|
<% if (hasPermission('audit.view')) { %>
|
|
<a href="/reports" class="sidebar-link <%= currentPage === 'reports' ? 'active' : '' %>">
|
|
<span class="material-icons">assessment</span>
|
|
<span class="sidebar-link-text"><%= _('nav.reports') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('server.config')) { %>
|
|
<a href="/keys" class="sidebar-link <%= currentPage === 'keys' ? 'active' : '' %>">
|
|
<span class="material-icons">vpn_key</span>
|
|
<span class="sidebar-link-text"><%= _('nav.keys') %></span>
|
|
</a>
|
|
<a href="/generator" class="sidebar-link <%= currentPage === 'generator' ? 'active' : '' %>" title="<%= _('generator.alpha_tooltip') || _('nav.generator') %>">
|
|
<span class="material-icons">build</span>
|
|
<span class="sidebar-link-text"><%= _('nav.generator') %></span>
|
|
<span class="badge-sidebar badge-sidebar--alpha"><%= _('generator.alpha_badge') || 'ALPHA' %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('device.connect')) { %>
|
|
<a href="/remote" class="sidebar-link <%= currentPage === 'remote' ? 'active' : '' %>" target="_blank" rel="noopener noreferrer" title="<%= _('nav.remote_open_tab') || _('nav.remote') %>">
|
|
<span class="material-icons">connected_tv</span>
|
|
<span class="sidebar-link-text"><%= _('nav.remote') || 'Remote Desktop' %></span>
|
|
<span class="material-icons sidebar-link-external" aria-hidden="true">open_in_new</span>
|
|
</a>
|
|
<a href="/toolkit" class="sidebar-link <%= currentPage === 'toolkit' ? 'active' : '' %>">
|
|
<span class="material-icons">handyman</span>
|
|
<span class="sidebar-link-text"><%= _('nav.toolkit') || 'Toolkit' %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('cdap.view')) { %>
|
|
<a href="/cdap-studio" class="sidebar-link <%= currentPage === 'cdap-studio' ? 'active' : '' %>">
|
|
<span class="material-icons">account_tree</span>
|
|
<span class="sidebar-link-text"><%= _('nav.sdk_studio') || 'SDK Studio' %></span>
|
|
</a>
|
|
<% } %>
|
|
</div>
|
|
|
|
<!-- System category links -->
|
|
<div class="sidebar-flyout-panel" data-panel="system">
|
|
<% if (hasPermission('enrollment.manage')) { %>
|
|
<a href="/tokens" class="sidebar-link <%= currentPage === 'tokens' ? 'active' : '' %>">
|
|
<span class="material-icons">token</span>
|
|
<span class="sidebar-link-text"><%= _('nav.tokens') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('org.create') || hasPermission('org.edit') || hasPermission('org.manage_users')) { %>
|
|
<a href="/organizations" class="sidebar-link <%= currentPage === 'organizations' ? 'active' : '' %>">
|
|
<span class="material-icons">corporate_fare</span>
|
|
<span class="sidebar-link-text"><%= _('nav.organizations') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('server.config')) { %>
|
|
<a href="/policies" class="sidebar-link <%= currentPage === 'policies' ? 'active' : '' %>">
|
|
<span class="material-icons">policy</span>
|
|
<span class="sidebar-link-text"><%= _('nav.policies') || 'Policies' %></span>
|
|
</a>
|
|
<a href="/attestation" class="sidebar-link <%= currentPage === 'attestation' ? 'active' : '' %>">
|
|
<span class="material-icons">fingerprint</span>
|
|
<span class="sidebar-link-text"><%= _('nav.attestation') || 'Attestation' %></span>
|
|
</a>
|
|
<a href="/dataguard" class="sidebar-link <%= currentPage === 'dataguard' ? 'active' : '' %>">
|
|
<span class="material-icons">shield</span>
|
|
<span class="sidebar-link-text"><%= _('nav.dataguard') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('user.view')) { %>
|
|
<a href="/users" class="sidebar-link <%= currentPage === 'users' ? 'active' : '' %>">
|
|
<span class="material-icons">group</span>
|
|
<span class="sidebar-link-text"><%= _('nav.users') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('audit.view')) { %>
|
|
<a href="/security-audit" class="sidebar-link <%= currentPage === 'security-audit' ? 'active' : '' %>">
|
|
<span class="material-icons">security</span>
|
|
<span class="sidebar-link-text"><%= _('nav.security_audit') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (isSuperAdmin) { %>
|
|
<a href="/permissions" class="sidebar-link <%= currentPage === 'permissions' ? 'active' : '' %>">
|
|
<span class="material-icons">admin_panel_settings</span>
|
|
<span class="sidebar-link-text"><%= _('nav.permissions') %></span>
|
|
</a>
|
|
<% } %>
|
|
<% if (hasPermission('server.config')) { %>
|
|
<a href="/languages" class="sidebar-link <%= currentPage === 'languages' ? 'active' : '' %>">
|
|
<span class="material-icons">translate</span>
|
|
<span class="sidebar-link-text"><%= _('nav.languages') %></span>
|
|
</a>
|
|
<a href="/resource-control" class="sidebar-link <%= currentPage === 'resource-control' ? 'active' : '' %>">
|
|
<span class="material-icons">tune</span>
|
|
<span class="sidebar-link-text"><%= _('nav.resource_control') %></span>
|
|
</a>
|
|
<% } %>
|
|
</div>
|
|
|
|
<!-- Server Management category links (BETA) -->
|
|
<% if (hasPermission('server.config')) { %>
|
|
<div class="sidebar-flyout-panel" data-panel="server-mgmt">
|
|
<a href="/server-management?tab=overview" class="sidebar-link <%= currentPage === 'server-management' && sidebarServerTab === 'overview' ? 'active' : '' %>">
|
|
<span class="material-icons">monitoring</span>
|
|
<span class="sidebar-link-text"><%= _('server_mgmt.tab_overview') || 'Overview' %></span>
|
|
</a>
|
|
<a href="/server-management?tab=terminal" class="sidebar-link <%= currentPage === 'server-management' && sidebarServerTab === 'terminal' ? 'active' : '' %>">
|
|
<span class="material-icons">terminal</span>
|
|
<span class="sidebar-link-text"><%= _('server_mgmt.tab_terminal') || 'Terminal' %></span>
|
|
</a>
|
|
<a href="/server-management?tab=files" class="sidebar-link <%= currentPage === 'server-management' && sidebarServerTab === 'files' ? 'active' : '' %>">
|
|
<span class="material-icons">folder_open</span>
|
|
<span class="sidebar-link-text"><%= _('server_mgmt.tab_files') || 'Files' %></span>
|
|
</a>
|
|
<a href="/server-management?tab=services" class="sidebar-link <%= currentPage === 'server-management' && sidebarServerTab === 'services' ? 'active' : '' %>">
|
|
<span class="material-icons">miscellaneous_services</span>
|
|
<span class="sidebar-link-text"><%= _('server_mgmt.tab_services') || 'Services' %></span>
|
|
<span class="badge-sidebar" style="background:linear-gradient(135deg,#ff7b72,#d29922);color:#fff;flex-shrink:0;margin-left:auto;">BETA</span>
|
|
</a>
|
|
</div>
|
|
<% } %>
|
|
|
|
<!-- Sidebar footer - User -->
|
|
<div class="sidebar-footer">
|
|
<div class="sidebar-user" id="user-menu-trigger">
|
|
<div class="sidebar-user-avatar">
|
|
<%= user && user.username ? user.username.charAt(0).toUpperCase() : 'A' %>
|
|
</div>
|
|
<div class="sidebar-user-info">
|
|
<div class="sidebar-user-name"><%= user ? user.username : 'Admin' %></div>
|
|
<%
|
|
var _roleKey = user && user.role ? ('users.role_' + user.role) : 'users.role_admin';
|
|
var _roleLabel = _(_roleKey);
|
|
if (!_roleLabel || _roleLabel === _roleKey) {
|
|
_roleLabel = user && user.role
|
|
? user.role.replace(/_/g, ' ').replace(/\b\w/g, function(c){ return c.toUpperCase(); })
|
|
: 'Administrator';
|
|
}
|
|
%>
|
|
<div class="sidebar-user-role"><%= _roleLabel %></div>
|
|
</div>
|
|
</div>
|
|
<% if ((branding && branding.footerText) || (branding && branding.showPoweredBy !== 'false')) { %>
|
|
<div class="sidebar-attribution">
|
|
<% if (branding.footerText) { %><span class="sidebar-attribution-text"><%= branding.footerText %></span><% } %>
|
|
<% if (branding.showPoweredBy !== 'false') { %><span class="sidebar-attribution-powered"><%= _('branding.powered_by') %> BetterDesk</span><% } %>
|
|
</div>
|
|
<% } %>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
<script nonce="<%= cspNonce %>">
|
|
// Sidebar rail navigation + flyout logic
|
|
(function() {
|
|
var sidebar = document.getElementById('sidebar');
|
|
var flyout = document.getElementById('sidebar-flyout');
|
|
var flyoutTitle = document.getElementById('sidebar-flyout-title');
|
|
var expandBtn = document.getElementById('sidebar-expand-btn');
|
|
var nav = flyout;
|
|
var STORAGE_COLLAPSED = 'bd_sidebar_collapsed';
|
|
var STORAGE_SCROLL = 'bd_sidebar_scroll';
|
|
var activeCategory = null;
|
|
|
|
// Determine initial state
|
|
var savedCollapsed = localStorage.getItem(STORAGE_COLLAPSED);
|
|
var isCollapsed = savedCollapsed === null ? true : savedCollapsed === 'true';
|
|
sidebar.dataset.collapsed = String(isCollapsed);
|
|
document.documentElement.style.setProperty('--sidebar-current-width',
|
|
isCollapsed ? 'var(--sidebar-width-collapsed)' : 'var(--sidebar-width)');
|
|
|
|
// Auto-show the panel for the current page's category
|
|
var activeRail = sidebar.querySelector('.sidebar-rail-btn.active[data-category]');
|
|
if (activeRail) {
|
|
activeCategory = activeRail.dataset.category;
|
|
showPanel(activeCategory);
|
|
} else if (['settings', 'server-attestation'].includes('<%= currentPage %>')) {
|
|
// Direct rail links — no flyout sub-menu, keep sidebar collapsed
|
|
isCollapsed = true;
|
|
sidebar.dataset.collapsed = 'true';
|
|
document.documentElement.style.setProperty('--sidebar-current-width', 'var(--sidebar-width-collapsed)');
|
|
if (flyout) delete flyout.dataset.activeCategory;
|
|
}
|
|
|
|
function showPanel(category) {
|
|
// Hide all panels
|
|
flyout.querySelectorAll('.sidebar-flyout-panel').forEach(function(p) {
|
|
p.classList.remove('visible');
|
|
});
|
|
// Show target
|
|
var panel = flyout.querySelector('[data-panel="' + category + '"]');
|
|
if (panel) panel.classList.add('visible');
|
|
|
|
// Update rail active state
|
|
sidebar.querySelectorAll('.sidebar-rail-btn[data-category]').forEach(function(b) {
|
|
b.classList.toggle('selected', b.dataset.category === category);
|
|
});
|
|
|
|
// Title mapping
|
|
var titles = {
|
|
commercialization: '<%= _("nav.commercialization") || "Commercialization" %>',
|
|
main: '<%= _("nav.main") %>',
|
|
management: '<%= _("nav.management") || "Management" %>',
|
|
tools: '<%= _("nav.tools") %>',
|
|
system: '<%= _("nav.system") %>',
|
|
'server-mgmt': '<%= _("nav.server_management") || "Server Management" %>'
|
|
};
|
|
if (flyoutTitle) flyoutTitle.textContent = titles[category] || '';
|
|
if (flyout) flyout.dataset.activeCategory = category;
|
|
activeCategory = category;
|
|
}
|
|
|
|
// Rail button clicks
|
|
sidebar.querySelectorAll('.sidebar-rail-btn[data-category]').forEach(function(btn) {
|
|
btn.addEventListener('click', function() {
|
|
var cat = btn.dataset.category;
|
|
if (!isCollapsed && activeCategory === cat) {
|
|
toggleCollapse();
|
|
} else {
|
|
showPanel(cat);
|
|
if (isCollapsed) toggleCollapse();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Expand/collapse toggle
|
|
function toggleCollapse() {
|
|
isCollapsed = !isCollapsed;
|
|
sidebar.dataset.collapsed = String(isCollapsed);
|
|
document.documentElement.style.setProperty('--sidebar-current-width',
|
|
isCollapsed ? 'var(--sidebar-width-collapsed)' : 'var(--sidebar-width)');
|
|
localStorage.setItem(STORAGE_COLLAPSED, String(isCollapsed));
|
|
if (expandBtn) {
|
|
expandBtn.querySelector('.material-icons').textContent =
|
|
isCollapsed ? 'chevron_right' : 'chevron_left';
|
|
}
|
|
}
|
|
|
|
if (expandBtn) {
|
|
expandBtn.addEventListener('click', toggleCollapse);
|
|
expandBtn.querySelector('.material-icons').textContent =
|
|
isCollapsed ? 'chevron_right' : 'chevron_left';
|
|
}
|
|
|
|
// Scroll preservation
|
|
if (nav) {
|
|
try {
|
|
var saved = sessionStorage.getItem(STORAGE_SCROLL);
|
|
if (saved) nav.scrollTop = parseInt(saved, 10) || 0;
|
|
} catch(e) {}
|
|
var activeLink = nav.querySelector('.sidebar-link.active');
|
|
if (activeLink) {
|
|
var rect = activeLink.getBoundingClientRect();
|
|
var navRect = nav.getBoundingClientRect();
|
|
if (rect.top < navRect.top || rect.bottom > navRect.bottom) {
|
|
activeLink.scrollIntoView({ block: 'center' });
|
|
}
|
|
}
|
|
window.addEventListener('beforeunload', function() {
|
|
try { sessionStorage.setItem(STORAGE_SCROLL, String(nav.scrollTop)); } catch(e) {}
|
|
});
|
|
}
|
|
|
|
// Theme follows branding / data-theme-mode (do not force dark)
|
|
})();
|
|
</script>
|