Merge claude/1

This commit is contained in:
librelad 2026-06-01 11:12:11 +01:00
commit ef344081e5
5 changed files with 24 additions and 38 deletions

View File

@ -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 = '<div class="error">Peers page template failed to load.</div>';
return;
}
if (typeof PeersPage !== 'undefined') {
window.peersPage = new PeersPage('config-section');
await window.peersPage.init();
} else {
configSection.innerHTML = '<div class="error">PeersPage controller not loaded.</div>';
}
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.

View File

@ -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);
}

View File

@ -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/<sub>), 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 = '<div class="updater-empty">Loading backup center…</div>';
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 = '<div class="updater-empty">Failed to load the backup center.</div>';
} finally {

View File

@ -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) {

View File

@ -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();