Compare commits
2 Commits
8315a58226
...
a511ed9e8d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a511ed9e8d | ||
|
|
fab6997cd7 |
@ -46,7 +46,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/config?=overview" class="dashboard-admin-link">
|
||||
<a href="/admin" class="dashboard-admin-link">
|
||||
Admin overview
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</a>
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
</svg>
|
||||
App Center
|
||||
</a>
|
||||
<a href="config.html" class="nav-item" id="nav-config">
|
||||
<a href="/admin" class="nav-item" id="nav-config">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>
|
||||
</svg>
|
||||
|
||||
@ -58,7 +58,7 @@ class AdminOverview {
|
||||
window.librePortalSPA?.navigate('/backup', true);
|
||||
} else if (where === 'ssh' || where === 'security') {
|
||||
const target = where === 'ssh' ? 'ssh-access' : 'security';
|
||||
window.history.pushState({}, '', `/config?=${target}`);
|
||||
window.history.pushState({}, '', window.adminPath(target));
|
||||
window.configCategory = target;
|
||||
window.configManager?.renderConfig?.(target);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class ConfigSidebar {
|
||||
overviewItem.setAttribute('data-category', 'overview');
|
||||
overviewItem.innerHTML = '<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" style="margin-right:8px;vertical-align:middle"><rect x="3" y="3" width="7" height="9"></rect><rect x="14" y="3" width="7" height="5"></rect><rect x="14" y="12" width="7" height="9"></rect><rect x="3" y="16" width="7" height="5"></rect></svg> Overview';
|
||||
overviewItem.addEventListener('click', function () {
|
||||
window.history.pushState({}, '', '/config?=overview');
|
||||
window.history.pushState({}, '', window.adminPath('overview'));
|
||||
document.querySelectorAll('.category').forEach(function (item) { item.classList.remove('active'); });
|
||||
this.classList.add('active');
|
||||
window.configCategory = 'overview';
|
||||
@ -76,8 +76,7 @@ class ConfigSidebar {
|
||||
|
||||
categoryItem.addEventListener('click', function() {
|
||||
// Update URL without full page reload
|
||||
const url = '/config?=' + category.id;
|
||||
window.history.pushState({}, '', url);
|
||||
window.history.pushState({}, '', window.adminPath(category.id));
|
||||
|
||||
// Update active state
|
||||
document.querySelectorAll('.category').forEach(function(item) {
|
||||
@ -109,7 +108,7 @@ class ConfigSidebar {
|
||||
sshItem.setAttribute('data-category', 'ssh-access');
|
||||
sshItem.innerHTML = '<img src="/icons/config/security.svg" alt="SSH Access" style="width: 20px; height: 20px; margin-right: 8px;"/> SSH Access';
|
||||
sshItem.addEventListener('click', function () {
|
||||
window.history.pushState({}, '', '/config?=ssh-access');
|
||||
window.history.pushState({}, '', window.adminPath('ssh-access'));
|
||||
document.querySelectorAll('.category').forEach(function (item) { item.classList.remove('active'); });
|
||||
this.classList.add('active');
|
||||
window.configCategory = 'ssh-access';
|
||||
|
||||
@ -17,7 +17,7 @@ class TopbarComponent {
|
||||
if (path.startsWith('/apps') || path === '/apps') {
|
||||
return 'apps';
|
||||
}
|
||||
if (path.startsWith('/config') || path === '/config') {
|
||||
if (path.startsWith('/admin') || path.startsWith('/config') || path.startsWith('/ssh')) {
|
||||
return 'config';
|
||||
}
|
||||
if (path.startsWith('/tasks') || path === '/tasks') {
|
||||
@ -266,14 +266,12 @@ class TopbarComponent {
|
||||
// PRIMARY: Use path-based detection only (most reliable)
|
||||
if (path.startsWith('/app') || path.startsWith('/apps')) {
|
||||
activeNavId = 'nav-app-center';
|
||||
} else if (path.startsWith('/config')) {
|
||||
activeNavId = 'nav-config';
|
||||
} else if (path.startsWith('/admin') || path.startsWith('/config') || path.startsWith('/ssh')) {
|
||||
activeNavId = 'nav-config'; // Admin area (config + SSH live here)
|
||||
} else if (path.startsWith('/tasks')) {
|
||||
activeNavId = 'nav-tasks';
|
||||
} else if (path.startsWith('/backup')) {
|
||||
activeNavId = 'nav-backup';
|
||||
} else if (path.startsWith('/ssh')) {
|
||||
activeNavId = 'nav-config'; // SSH Access lives under the Admin (config) area
|
||||
} else if (path === '/' || path === '/dashboard') {
|
||||
activeNavId = 'nav-dashboard';
|
||||
} else {
|
||||
@ -349,7 +347,7 @@ class TopbarComponent {
|
||||
|
||||
if (path.startsWith('/app') || path.startsWith('/apps')) {
|
||||
activeNavId = 'nav-app-center';
|
||||
} else if (path.startsWith('/config')) {
|
||||
} else if (path.startsWith('/admin') || path.startsWith('/config') || path.startsWith('/ssh')) {
|
||||
activeNavId = 'nav-config';
|
||||
} else if (path.startsWith('/tasks')) {
|
||||
activeNavId = 'nav-tasks';
|
||||
|
||||
@ -68,13 +68,15 @@ class LibrePortalSPAClean {
|
||||
this.routes.set('/apps', () => this.handleApps());
|
||||
this.routes.set('/app', () => this.handleAppDetail()); // Handle /app without query
|
||||
this.routes.set('/app*', () => this.handleAppDetail()); // Handle /app with query
|
||||
this.routes.set('/config', () => this.handleConfig()); // Handle /config without query
|
||||
this.routes.set('/config*', () => this.handleConfig()); // Handle /config with query
|
||||
this.routes.set('/admin', () => this.handleAdmin()); // Admin area (path-based: /admin/config/<x>, /admin/tools/<x>)
|
||||
this.routes.set('/admin*', () => this.handleAdmin());
|
||||
this.routes.set('/config', () => this.handleConfigRedirect()); // legacy → /admin
|
||||
this.routes.set('/config*', () => this.handleConfigRedirect());
|
||||
this.routes.set('/tasks', () => this.handleTasks()); // Handle /tasks without query
|
||||
this.routes.set('/tasks*', () => this.handleTasks()); // Handle /tasks with query
|
||||
this.routes.set('/backup', () => this.handleBackup());
|
||||
this.routes.set('/backup*', () => this.handleBackup());
|
||||
this.routes.set('/ssh', () => this.handleSsh());
|
||||
this.routes.set('/ssh', () => this.handleSsh()); // legacy → /admin/tools/ssh-access
|
||||
this.routes.set('/ssh*', () => this.handleSsh());
|
||||
|
||||
//console.log('📍 Routes registered:', Array.from(this.routes.keys()));
|
||||
@ -270,9 +272,8 @@ class LibrePortalSPAClean {
|
||||
}
|
||||
|
||||
async handleSsh() {
|
||||
// SSH Access now lives inside the Admin (config) area as a sidebar item.
|
||||
// Redirect old /ssh links to it.
|
||||
this.navigate('/config?=ssh-access', true);
|
||||
// Legacy /ssh → SSH Access under the Admin area.
|
||||
this.navigate('/admin/tools/ssh-access', true);
|
||||
}
|
||||
|
||||
async handleApps() {
|
||||
@ -363,43 +364,41 @@ class LibrePortalSPAClean {
|
||||
}
|
||||
}
|
||||
|
||||
async handleConfig() {
|
||||
//console.log('⚙️ Loading config...');
|
||||
|
||||
// Handle query parameters for config
|
||||
const path = window.location.pathname + window.location.search;
|
||||
if (path.includes('?=')) {
|
||||
const [basePath, query] = path.split('?=');
|
||||
window.configCategory = query || 'overview';
|
||||
} else if (path.includes('?')) {
|
||||
const url = new URL(path, window.location.origin);
|
||||
const searchParams = url.searchParams;
|
||||
window.configCategory = searchParams.get('config') || 'overview';
|
||||
} else {
|
||||
window.configCategory = 'overview';
|
||||
}
|
||||
|
||||
// Admin area. Path-based: /admin (overview), /admin/config/<category>,
|
||||
// /admin/tools/ssh-access. Reuses the config page shell + ConfigManager.
|
||||
async handleAdmin() {
|
||||
window.configCategory = window.adminCategoryFromPath(window.location.pathname);
|
||||
|
||||
try {
|
||||
const html = await this.fetchContent('/html/config-content.html');
|
||||
this.loadContent(html, 'Configuration');
|
||||
|
||||
// Config manager should already be initialized by SystemLoader
|
||||
this.loadContent(html, 'Admin');
|
||||
|
||||
if (window.configManager) {
|
||||
// Render the actual configuration
|
||||
if (typeof window.configManager.renderConfig === 'function') {
|
||||
await window.configManager.renderConfig(window.configCategory || 'overview');
|
||||
}
|
||||
//console.log('✅ Config loaded');
|
||||
} else {
|
||||
console.error('ConfigManager not available - SystemLoader should have initialized it');
|
||||
throw new Error('ConfigManager not initialized by SystemLoader');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Config load error:', error);
|
||||
this.showError('Failed to load configuration');
|
||||
console.error('❌ Admin load error:', error);
|
||||
this.showError('Failed to load the Admin area');
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy /config and /config?=<x> → the path-based /admin equivalent.
|
||||
async handleConfigRedirect() {
|
||||
const search = window.location.search || '';
|
||||
let cat = 'overview';
|
||||
if (search.includes('?=')) {
|
||||
cat = (window.location.pathname + search).split('?=')[1] || 'overview';
|
||||
} else {
|
||||
cat = new URLSearchParams(search).get('config') || 'overview';
|
||||
}
|
||||
this.navigate(window.adminPath(cat), true);
|
||||
}
|
||||
|
||||
async handleTasks() {
|
||||
//console.log('📋 Loading tasks...');
|
||||
|
||||
@ -476,7 +475,7 @@ class LibrePortalSPAClean {
|
||||
|
||||
if (path.startsWith('/app') || path.startsWith('/apps')) {
|
||||
activeId = 'nav-app-center';
|
||||
} else if (path.startsWith('/config')) {
|
||||
} else if (path.startsWith('/admin') || path.startsWith('/config') || path.startsWith('/ssh')) {
|
||||
activeId = 'nav-config';
|
||||
} else if (path.startsWith('/tasks')) {
|
||||
activeId = 'nav-tasks';
|
||||
@ -507,6 +506,21 @@ class LibrePortalSPAClean {
|
||||
}
|
||||
}
|
||||
|
||||
// Admin area path helpers (shared by the SPA, sidebar, overview, ssh page).
|
||||
// Map a category to its path-based URL, and parse a path back to a category.
|
||||
window.adminPath = function (category) {
|
||||
if (!category || category === 'overview') return '/admin';
|
||||
if (category === 'ssh-access') return '/admin/tools/ssh-access';
|
||||
return '/admin/config/' + category;
|
||||
};
|
||||
window.adminCategoryFromPath = function (pathname) {
|
||||
const segs = String(pathname || '').replace(/^\/admin\/?/, '').split('/').filter(Boolean);
|
||||
if (!segs.length || segs[0] === 'overview') return 'overview';
|
||||
if (segs[0] === 'config') return segs[1] || 'general';
|
||||
if (segs[0] === 'tools') return segs[1] || 'overview';
|
||||
return segs[0];
|
||||
};
|
||||
|
||||
// Global navigation function for click handlers
|
||||
window.navigateToRoute = function(href) {
|
||||
if (window.spaClean) {
|
||||
@ -522,8 +536,8 @@ window.navigateToRoute = function(href) {
|
||||
route = '/dashboard';
|
||||
} else if (route === 'apps') {
|
||||
route = '/apps';
|
||||
} else if (route === 'config') {
|
||||
route = '/config?=general';
|
||||
} else if (route === 'config' || route === 'admin') {
|
||||
route = '/admin';
|
||||
} else if (route === 'tasks') {
|
||||
route = '/tasks';
|
||||
} else if (!route.startsWith('/')) {
|
||||
|
||||
@ -150,8 +150,8 @@ async function initializeData() {
|
||||
} else if (currentPath === '/apps' || currentPath === '/app' || searchParams.has('apps') || searchParams.has('app')) {
|
||||
// Apps page: All apps + categories (no system configs needed)
|
||||
await loadAppsPageData();
|
||||
} else if (currentPath.startsWith('/config') || searchParams.has('config')) {
|
||||
// Config pages: System configs + apps + categories
|
||||
} else if (currentPath.startsWith('/admin') || currentPath.startsWith('/config') || currentPath.startsWith('/ssh') || searchParams.has('config')) {
|
||||
// Admin area (config + SSH): system configs + apps + categories
|
||||
await loadConfigDetailData();
|
||||
} else {
|
||||
// Default: Load all data for SPA
|
||||
|
||||
@ -264,7 +264,7 @@ class Router {
|
||||
// PRIMARY: Use path-based detection only (most reliable)
|
||||
if (pathname.startsWith('/app') || pathname.startsWith('/apps')) {
|
||||
activeNavId = 'nav-app-center';
|
||||
} else if (pathname.startsWith('/config')) {
|
||||
} else if (pathname.startsWith('/admin') || pathname.startsWith('/config') || pathname.startsWith('/ssh')) {
|
||||
activeNavId = 'nav-config';
|
||||
} else if (pathname.startsWith('/tasks')) {
|
||||
activeNavId = 'nav-tasks';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user