The Backups tab's Configuration sub-tab showed only the warning banner and
an orphaned divider -- the actual config form (retention presets, engine,
keep-policies, Save/Reset) never appeared.
Root cause: a duplicate id. The Fleet Overview, the app grid and per-app
detail all render the shared apps-unified-layout, which keeps a hidden
#config-tab > #config-section in the DOM. The Backups Configuration sub-tab
created its OWN #config-section, and configManager.renderConfig() resolved
the target with getElementById('config-section') -- which returns the FIRST
(hidden) node in document order. So the 21KB form painted into the invisible
per-app container while the backup tab's container stayed empty. Because the
/backup routes now redirect into /apps/overview/backups, this fired every
time -- the form had effectively never been visible.
Fix:
- renderConfig(category, target) now accepts an explicit container (element
or id) and falls back to #config-section; the error-retry button re-targets
via configSection.id.
- The Backups Configuration sub-tab uses a unique id (#backup-config-section)
and passes it to renderConfig; retention-preset and engine-details
selectors are scoped to it.
Also: the Refresh button now spins + locks while refreshAll()+render() run,
so the click has visible feedback instead of appearing to do nothing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pages and panels showed inconsistent loading states: the Backup center
and several admin pages (System, SSH, admin Overview), the Overview
Migrate/Peers panels, the per-app updater section and the backup engine
details modal rendered a bare 'Loading…' text line (updater-empty /
backup-empty-state) with no spinner, while Services/Config/Tasks used a
boxed card + spinner.
Add one shared loader — window.lpLoadingBox(message) + .lp-loading CSS in
the core/loading subsystem (the boxed card + accent spinner the good tabs
already use) — and route those bare-text loaders through it. The system
metric graph keeps its absolute overlay but gains the same spinner.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
backup/ held 15 loose .js plus css/html at the component root. Split into
per-tab sub-systems mirroring the admin/apps layout:
backup/core/{js,css,html}/ schema, base BackupPage, fetch-client,
cron-schedule, backup.css, backup-content.html
backup/dashboard/js/ backup-dashboard
backup/snapshots/js/ backup-snapshots, backup-snapshot-actions
backup/locations/js/ backup-locations, backup-location-fields,
backup-location-modal, backup-ssh-key
backup/migrate/js/ backup-migrate
backup/configuration/js/ backup-configuration, backup-retention-presets,
backup-engine-details
Updated the scripts[] array + loadFragment in index.js, the backup.css href in
index.html, and the handleBackup() fallback paths in spa.js. No behaviour
change — files moved verbatim (prototype-augment clusters), all 17 referenced
paths verified to resolve, node --check clean.
Signed-off-by: librelad <librelad@digitalangels.vip>