diff --git a/containers/libreportal/frontend/components/config-redirect/feature.json b/containers/libreportal/frontend/components/config-redirect/feature.json deleted file mode 100644 index 42bdcd1..0000000 --- a/containers/libreportal/frontend/components/config-redirect/feature.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "config-redirect", - "routes": ["/config", "/config*"], - "handler": "handleConfigRedirect", - "navId": "nav-config", - "order": 45, - "note": "Legacy /config* -> /admin redirect. No module; routes to the legacy handler." -} diff --git a/containers/libreportal/frontend/components/manifest.dev.json b/containers/libreportal/frontend/components/manifest.dev.json index f264f1d..15f4c82 100644 --- a/containers/libreportal/frontend/components/manifest.dev.json +++ b/containers/libreportal/frontend/components/manifest.dev.json @@ -46,15 +46,6 @@ "order": 40 } }, - { - "id": "config-redirect", - "routes": [ - "/config", - "/config*" - ], - "handler": "handleConfigRedirect", - "navId": "nav-config" - }, { "id": "tasks", "routes": [ @@ -95,24 +86,6 @@ "label": "Backups", "order": 50 } - }, - { - "id": "peers", - "routes": [ - "/peers", - "/peers*" - ], - "handler": "handlePeers", - "navId": "nav-config" - }, - { - "id": "ssh", - "routes": [ - "/ssh", - "/ssh*" - ], - "handler": "handleSsh", - "navId": "nav-config" } ] } diff --git a/containers/libreportal/frontend/components/peers/feature.json b/containers/libreportal/frontend/components/peers/feature.json deleted file mode 100644 index 623622d..0000000 --- a/containers/libreportal/frontend/components/peers/feature.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "peers", - "routes": ["/peers", "/peers*"], - "handler": "handlePeers", - "navId": "nav-config", - "order": 70, - "note": "Legacy /peers* -> /admin/tools/peers redirect. No module; routes to the legacy handler." -} diff --git a/containers/libreportal/frontend/components/ssh/feature.json b/containers/libreportal/frontend/components/ssh/feature.json deleted file mode 100644 index 64b5e02..0000000 --- a/containers/libreportal/frontend/components/ssh/feature.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "ssh", - "routes": ["/ssh", "/ssh*"], - "handler": "handleSsh", - "navId": "nav-config", - "order": 80, - "note": "Legacy /ssh* -> /admin/tools/ssh-access redirect. No module; routes to the legacy handler." -} diff --git a/containers/libreportal/frontend/core/kernel/spa.js b/containers/libreportal/frontend/core/kernel/spa.js index 40064d9..b1a8ca0 100755 --- a/containers/libreportal/frontend/core/kernel/spa.js +++ b/containers/libreportal/frontend/core/kernel/spa.js @@ -71,16 +71,12 @@ class LibrePortalSPAClean { this.routes.set('/app*', () => this.handleAppDetail()); this.routes.set('/admin', () => this.handleAdmin()); // Admin area (path-based: /admin/config/, /admin/tools/) 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('/peers', () => this.handlePeers()); // legacy → /admin/tools/peers - this.routes.set('/peers*', () => this.handlePeers()); - this.routes.set('/ssh', () => this.handleSsh()); // legacy → /admin/tools/ssh-access - this.routes.set('/ssh*', () => this.handleSsh()); + // Legacy /config, /peers, /ssh are handled by _legacyRedirect() at the top + // of navigate() (rewrites to the canonical /admin/* path). //console.log('📍 Routes registered:', Array.from(this.routes.keys())); } @@ -223,7 +219,19 @@ class LibrePortalSPAClean { async navigate(path, addToHistory = true) { // console.log('🚀 SPA: navigate called with:', path, 'addToHistory:', addToHistory); - + + // Legacy URL redirects (the old /ssh, /peers, /config short URLs → the Admin + // area). Rewritten here, at the top of navigate() and BEFORE the isLoading + // guard, so the canonical /admin/* path is what mounts + shows in the address + // bar. This replaces the former config-redirect/peers/ssh redirect + // components (whose handlers re-entered navigate() and were silently no-op'd + // by the guard below). + const redirected = this._legacyRedirect(path); + if (redirected && redirected !== path) { + path = redirected; + try { history.replaceState({ route: path }, '', path); } catch (_) {} + } + if (this.isLoading) { // console.log('⏳ Navigation already in progress, ignoring:', path); return; @@ -379,14 +387,22 @@ class LibrePortalSPAClean { } } - async handlePeers() { - // Legacy /peers → Peers under the Admin area. - this.navigate('/admin/tools/peers', true); - } - - async handleSsh() { - // Legacy /ssh → SSH Access under the Admin area. - this.navigate('/admin/tools/ssh-access', true); + // Map a legacy short URL (/ssh, /peers, /config[?=cat]) to its canonical + // /admin/* path, or return null if it isn't a legacy redirect. Used at the top + // of navigate(). Replaces the old config-redirect/peers/ssh handlers. + _legacyRedirect(path) { + const full = path || ''; + const p = full.split('?')[0]; + if (p === '/ssh' || p.startsWith('/ssh/')) return '/admin/tools/ssh-access'; + if (p === '/peers' || p.startsWith('/peers/')) return '/admin/tools/peers'; + if (p === '/config' || p.startsWith('/config/') || full.startsWith('/config?')) { + let cat = 'overview'; + if (full.includes('?=')) cat = full.split('?=')[1] || 'overview'; + else if (full.includes('?')) cat = new URLSearchParams(full.split('?')[1]).get('config') || 'overview'; + else { const seg = p.replace(/^\/config\/?/, ''); if (seg) cat = seg; } + return (typeof window.adminPath === 'function') ? window.adminPath(cat) : '/admin'; + } + return null; } async handleApps() { @@ -520,17 +536,6 @@ class LibrePortalSPAClean { } // Legacy /config and /config?= → 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...');