Reshape the dashboard's Backup status grid into a click-to-pick UI:
- Removed the inline Back-up / Restore buttons from the System config
tile. Same shape as an app tile now; LibrePortal app icon instead of
the server-stack glyph.
- Grid is 2 columns (was auto-fill min 220px). Tiles are wider, read
better, and the System tile no longer needs to span a full row to fit
inline buttons.
- Click any tile (System or app) → opens a new "Back up" modal:
* System config first (key=__system__, LibrePortal icon)
* Every installed app, alphabetical
* Checkbox per row + 'Select all' / 'Clear' shortcuts
* The tile clicked is pre-ticked
- Confirm queues backup tasks:
* Everything ticked → single `libreportal backup all` (which also
runs `backup system`) — one task instead of N
* Subset → one task per ticked item (`backup system`
and/or `backup app create <slug>`)
Restore for System config used to live on the dashboard's inline
'Restore' button. It's now reachable via the Backups tab — system
snapshots appear in the snapshot list with the standard per-row
Restore action — same path apps already use. No new UI required;
just one fewer dashboard button.
Signed-off-by: librelad <librelad@digitalangels.vip>
- Add .backup-system-card { margin-top: 20px } — the card stands alone below the
two-column cards row (which has no bottom margin), so it was butting against it.
- Add a server-stack icon to the card header (matches the nebula stroke-icon style).
- DEVELOPMENT.md: document the dashboard "System config" card + its last-backup
status (tag system=config → `system` in the dashboard JSON), the CLI/auto paths,
and that the libreportal app is excluded from the per-app grid.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
When a location uses SSH key auth, show a key card: paste an existing private
key, or 'Generate keypair', then the card displays the public key to copy into
the remote server's authorized_keys (with Copy/Delete). Wires to the
ssh-key-set/generate/delete CLI; key mutations refresh locations.json so the
card reflects state immediately. applySshAuthVisibility toggles the card vs the
password field by auth mode. Private key only ever flows in (base64); only the
public key is ever shown.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
- Remove the per-tab 'How LibrePortal connects…' description lines; the tab
labels already say what each panel is, and the paragraphs read as misplaced
titles.
- Give the tab panels even, comfortable padding (tabs-content padding zeroed so
the panel owns it) instead of the cramped 2px sides.
- Round the tab strip's top corners (.tabs-list) so the strip + content read as
one card — .tabs-content already rounds the bottom, leaving the top square.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Reuse the shared .tabs-wrapper/.tab-button/.tab-panel components (same as an
app's Config/Tasks tabs) for the location editor instead of bespoke tab CSS:
emoji + label buttons, equal-width strip, accent active state. Panels toggle
via the .active class like the rest of the UI; only the panel padding is
trimmed so it nests inside the backup row.
Also drop the now-dead 'No advanced options' empty state — every type has at
least Engine + append-only in the Advanced tab.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The expanded location row was one long form. Split it into tabs so it opens
showing only the Connection fields. Retention moves from a stacked section
into its own tab, and the advanced overrides (URI/SSH port/append-only) get
their own tab instead of the inline disclosure from the previous pass.
Field grouping is metadata-driven: locFieldGroups partitions a type's fields
into Connection vs Advanced via the configs.json "advanced" flag (with
LOC_ADVANCED_SUFFIXES as the legacy fallback). Type changes rebuild both the
Connection and Advanced panels since advanced fields are type-dependent too.
Save still reads every field across all panels (hidden tabs stay in the DOM).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The Locations editor now renders field metadata from configs.json
(window.configData) instead of relying on the hardcoded BACKUP_LOC_FIELD_DEFS,
which drops to a fallback. Fields flagged advanced (URI override, SSH port,
append-only) move out of the main grid into a full-width "Advanced"
disclosure that's collapsed by default, so the common case stays simple.
Also load the unified config once on the backup page into window.configData
(metadata) + a flat window.systemConfigs (values). Previously systemConfigs
was only populated after a save — and with the full nested JSON, while the
code reads it as a flat map — so default-engine lookups and save-time change
detection silently misbehaved on first load. Both are now correct.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Give the per-location Save changes / Delete location row some breathing room
from the bottom of the expanded card.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Two follow-ups to the button restyle:
- On the nebula theme, primary/danger CTAs are translucent (rgba accent/danger
fill + white text + border), not the solid generic .btn-primary. The earlier
change only added the backup classes to the generic groups, so on nebula the
Add location / Save changes / Delete buttons fell back to a solid fill with
dark text. Add .backup-primary-btn and .backup-danger-btn to the
[data-theme="nebula"] groups too, so they match the config-page buttons.
- The per-location action row used justify-content: space-between, throwing the
two buttons to opposite edges. Switch to flex-start with a gap (like
.config-actions) and put Save changes (primary) before Delete location.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The backup pages' primary buttons (Add location, Save changes) and Delete
location button used a local gradient + glow in backup.css, so they didn't
match the flat solid-accent buttons on the config page. Add .backup-primary-btn
and .backup-danger-btn to the shared nebula button groups in themes.css
(.btn-primary / .btn-uninstall) so they get the same solid accent/danger fill
and hover with !important across themes, and drop the local gradient/shadow/lift
from backup.css. Top-right and bottom-of-page backup buttons now match config.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Drop the Export button from the config-backup warning banner — it's now just the alert + dismiss (x). On the Configuration tab the top-right primary action becomes an 'Export' dropdown (first item: Repository Passwords, reusing the existing export-passwords action) so more export types can be added later. Other tabs keep Backup all apps / Add location. Menu opens from the trigger and closes on outside click, item click, or tab switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Add a large amber alert-triangle icon to the 'keep your config backed up offline' banner and a close (x) button in its top-right. Dismissal is stored in localStorage (libreportal:backup-config-warning-dismissed) — a per-browser UI nudge, not server config — and hides both the banner and its divider until cleared.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Make the expanded location editor read like /config: Connection and Retention now use the section header + .domains-divider layout, and Connection gets a description. Move the retention 'Backup style' guidance into a tooltip and drop the always-visible hint line below it. Move the Enabled toggle out of the Connection fields into the collapsed location row header so a location can be enabled/disabled without expanding it; setLocationEnabled persists the change via the same config_update routing as saveSection.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys,
Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun
VPN routing, and a web dashboard to manage it all.
Free & open forever to self-host; optional paid hosted services fund it.
See PROMISE.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>