From 164f782a951aafcf20b23c0ce78910d2db5bde79 Mon Sep 17 00:00:00 2001 From: librelad Date: Mon, 1 Jun 2026 11:12:11 +0100 Subject: [PATCH] fix(webui): address Migrate-refactor review findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Restore empty-state 'Open Locations' now deep-links to the backup center's Locations sub-tab: the embedded center honors /overview/backups/ and switchTab()s to it after mount (was landing on Dashboard). - PeersPage.notify + MigratePage.notify use the real window.notificationSystem (were calling a never-defined window.showNotification → console-only). - Remove the now-dead Admin config-manager peers branch (Peers left Admin). - Trim the dead migrate.json/peers fetch + hostnameToPeerName from BackupPage (no consumer after the migrate removal). Co-Authored-By: Claude Opus 4.8 --- .../admin/config/js/config-manager.js | 20 ++----------------- .../components/admin/peers/js/peers-page.js | 2 +- .../apps/overview/js/overview-manager.js | 16 ++++++++++++--- .../apps/overview/migrate/js/migrate-page.js | 7 ++++--- .../backup/core/js/backup-fetch-client.js | 17 ++++------------ 5 files changed, 24 insertions(+), 38 deletions(-) diff --git a/containers/libreportal/frontend/components/admin/config/js/config-manager.js b/containers/libreportal/frontend/components/admin/config/js/config-manager.js index ce88a87..b342a0f 100755 --- a/containers/libreportal/frontend/components/admin/config/js/config-manager.js +++ b/containers/libreportal/frontend/components/admin/config/js/config-manager.js @@ -72,24 +72,8 @@ if (typeof window.ConfigManager === 'undefined') { // instances (kind=backup-channel for shared-backup migrate, or // kind=direct-ssh-direct for live SSH pulls). Same shape as SSH Access: // we inject its content template, then init PeersPage. - if (category === 'peers') { - try { this.sidebar.populateSidebar(); } catch (e) {} - await lazyLoad('/components/admin/peers/js/peers-page.js'); - try { - const html = await fetch('/components/admin/peers/html/peers-content.html').then(r => r.text()); - configSection.innerHTML = html; - } catch (e) { - configSection.innerHTML = '
Peers page template failed to load.
'; - return; - } - if (typeof PeersPage !== 'undefined') { - window.peersPage = new PeersPage('config-section'); - await window.peersPage.init(); - } else { - configSection.innerHTML = '
PeersPage controller not loaded.
'; - } - return; - } + // Peers moved out of Admin → Overview › Migrate › Peers; /admin/tools/peers + // redirects there, so this branch is intentionally gone. // System is an admin tool page that internally routes between index / // metric / per-app / storage sub-views based on the URL sub-path. diff --git a/containers/libreportal/frontend/components/admin/peers/js/peers-page.js b/containers/libreportal/frontend/components/admin/peers/js/peers-page.js index 6e96106..3bd8545 100644 --- a/containers/libreportal/frontend/components/admin/peers/js/peers-page.js +++ b/containers/libreportal/frontend/components/admin/peers/js/peers-page.js @@ -431,7 +431,7 @@ class PeersPage { } notify(message, kind) { - if (typeof window.showNotification === 'function') window.showNotification(message, kind); + if (window.notificationSystem && window.notificationSystem.show) window.notificationSystem.show(message, kind || 'info'); else if (kind === 'error') console.error(message); else console.log(message); } diff --git a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js index 7c938fb..d87c4d3 100644 --- a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js +++ b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js @@ -428,17 +428,26 @@ class OverviewManager { // configuration sections (its sidebar restyled as a nested tab strip). On a // revisit we refresh rather than re-mount, to keep its sub-tab + expand state. mountBackupCenter(pane) { + // Honor an optional sub-tab deep-link (/overview/backups/), e.g. the + // Restore empty-state's "Open Locations" button. + const seg = window.location.pathname.replace(/^\/overview\/backups\/?/, '').split('/')[0]; + const sub = ['dashboard', 'backups', 'locations', 'configuration'].includes(seg) ? seg : null; // Detect a prior mount by the embedded fragment in THIS pane — not by // #backup-section, which the per-app Backups tab also defines. if (pane.querySelector('.backup-layout') && window.overviewBackupPage) { - try { window.overviewBackupPage.refreshAll().then(() => window.overviewBackupPage.render()).catch(() => {}); } catch (_) {} + try { + window.overviewBackupPage.refreshAll().then(() => { + window.overviewBackupPage.render(); + if (sub) window.overviewBackupPage.switchTab(sub); + }).catch(() => {}); + } catch (_) {} return; } pane.innerHTML = '
Loading backup center…
'; - this._loadBackupCenter(pane); + this._loadBackupCenter(pane, sub); } - async _loadBackupCenter(pane) { + async _loadBackupCenter(pane, sub) { if (this._backupLoading) return; this._backupLoading = true; try { @@ -456,6 +465,7 @@ class OverviewManager { try { if (window.overviewBackupPage) window.overviewBackupPage.dispose(); } catch (_) {} window.overviewBackupPage = new BackupPage({ embedded: true }); await window.overviewBackupPage.init(); + if (sub) { try { window.overviewBackupPage.switchTab(sub); } catch (_) {} } } catch (_) { pane.innerHTML = '
Failed to load the backup center.
'; } finally { diff --git a/containers/libreportal/frontend/components/apps/overview/migrate/js/migrate-page.js b/containers/libreportal/frontend/components/apps/overview/migrate/js/migrate-page.js index 5d2804b..fd40b80 100644 --- a/containers/libreportal/frontend/components/apps/overview/migrate/js/migrate-page.js +++ b/containers/libreportal/frontend/components/apps/overview/migrate/js/migrate-page.js @@ -68,7 +68,7 @@ class MigratePage { } const locBtn = e.target.closest('[data-action="go-to-locations"]'); if (locBtn && this.root()?.contains(locBtn)) { - if (window.navigateToRoute) window.navigateToRoute('/overview/backups'); + if (window.navigateToRoute) window.navigateToRoute('/overview/backups/locations'); return; } if (e.target.closest('#ov-migrate-confirm')) { this.confirmMigrate(); return; } @@ -107,8 +107,9 @@ class MigratePage { closeModal() { document.getElementById('ov-migrate-modal')?.classList.remove('open'); } notify(msg, type) { - const n = (window.LP && window.LP.services && window.LP.services.notify) || window.notify; - if (n && n.show) n.show(msg, type || 'info'); + if (window.notificationSystem && window.notificationSystem.show) window.notificationSystem.show(msg, type || 'info'); + else if (type === 'error') console.error(msg); + else console.log(msg); } async runTask(command, type, app) { diff --git a/containers/libreportal/frontend/components/backup/core/js/backup-fetch-client.js b/containers/libreportal/frontend/components/backup/core/js/backup-fetch-client.js index f27c56b..b13c01f 100644 --- a/containers/libreportal/frontend/components/backup/core/js/backup-fetch-client.js +++ b/containers/libreportal/frontend/components/backup/core/js/backup-fetch-client.js @@ -2,26 +2,17 @@ Object.assign(BackupPage.prototype, { async refreshAll() { const ts = Date.now(); - const [dashboard, locations, , schema, migrate, peersData] = await Promise.all([ + const [dashboard, locations, , schema] = await Promise.all([ this.fetchJson(`/data/backup/generated/dashboard.json?t=${ts}`), this.fetchJson(`/data/backup/generated/locations.json?t=${ts}`), this.loadSystemConfigs(), - this.fetchJson(`/data/backup/generated/schema.json?t=${ts}`), - this.fetchJson(`/data/backup/generated/migrate.json?t=${ts}`), - this.fetchJson(`/data/peers/generated/peers.json?t=${ts}`) + this.fetchJson(`/data/backup/generated/schema.json?t=${ts}`) ]); this.dashboard = dashboard; this.locations = locations; this.locSchema = schema; - this.migrate = migrate; - // Build hostname → friendly-name lookup once so renderMigrate can show - // "homelab (host: homelab.lan)" instead of bare hostnames. - this.hostnameToPeerName = {}; - for (const p of (peersData?.peers || [])) { - if (p.kind === 'backup-channel' && p.config?.hostname) { - this.hostnameToPeerName[p.config.hostname] = p.name; - } - } + // (migrate.json + peers lookup moved to MigratePage when Migrate left the + // backup center — nothing here consumes them anymore.) this.snapshotsByLoc = {}; if (!this.engines.length) await this.loadEngines();