Bundle a small set of distro marks (Debian/Ubuntu/Fedora/Arch) plus a
generic Linux/Tux fallback under /icons/os/, and show the icon next to the
OS value, keyed off the cleaned distro name. Locally bundled — no external
calls — and unknown distros fall back to the generic glyph.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Introduces per-area identity hues as reusable tokens (--page-updates/backups/
ssh/system + -rgb companions) and a generic .admin-action-btn that takes its
colour from --page set on the card. The Overview buttons now read in their
area's hue — Updates blue, Backups emerald, SSH violet, System amber — with the
icon following via currentColor; "Update now" is the filled (primary) variant.
The tokens are the foundation to extend each area's identity (page headers,
accents) going forward, not just these buttons.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The admin ops/health board now lives at /admin/dashboard (adminPath
('overview') emits it; the topbar Admin link points there). Bare /admin
still resolves to the same board — no redirect, both paths render it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Update/Verify (refresh, shield-check), Manage backups (archive), Manage SSH
(key), View system stats (activity). Icons inherit the button's text colour —
no per-button colour, so the footer stays calm; the icon plus the card's status
dot do the distinguishing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
System is live stats, not configuration, so it shouldn't live under
/admin/config. adminPath('system') now emits /admin/system; the path
parser locates 'system' positionally; all nav targets, breadcrumbs and the
dashboard disk-card link point at /admin/system{,/storage,/metric/<k>}.
adminCategoryFromPath already resolves /admin/<x> to that category, so
ConfigManager still mounts AdminSystem unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The "View/Open storage breakdown" links in the System storage summary were
plain text links; restyle them as the same accent pill CTA (icon + label)
used on the Disk metric page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
"Live · binary ring backed" meant nothing to a user; show a per-metric
sentence describing what the chart is (e.g. "Root-filesystem usage over
time.") instead.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Move the Disk page's "View storage breakdown" button beneath the time-range
picker (actions stack in a column, right-aligned) instead of beside it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The plain text link read as unstyled; give it the same pill shape as the
Reclaim Space button (icon + label) in the accent colour, so it looks
intentional without borrowing Reclaim's caution-orange.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Add a "View storage breakdown →" button on the Disk metric page (disk
only) that opens /admin/config/system/storage — keeps the trend page and
the breakdown page focused but a click apart, instead of merging them.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The "LibrePortal X GB" sublabel under the disk percentage read as clutter;
remove it. The % and the coloured LibrePortal portion of the ring stay.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The System-page storage ring is an overview, so showing individual app
(compose-project) names was wrong — it now shows a single "Applications"
slice totalling all apps, alongside Images and Build cache. The per-app
breakdown stays on the full Storage page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Replace the disk gauge's concentric inner ring with a single ring whose
leading portion is coloured to mark the LibrePortal share of the disk
(one ring: total disk used overall, LibrePortal highlighted within it).
On the full-screen Disk metric page, add a flat reference line marking
LibrePortal's current share alongside the disk-usage trend. The gauge
gains a `segment` option; the chart line is a "now" value (no historical
LP series yet), so it's flat across the range.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
- Disk gauge (System page) gains an inner ring for the LibrePortal slice of
the disk, so it shows total disk used AND how much of that is us.
- System-page storage summary now shows the full LibrePortal breakdown
(apps + images + build cache), not just the Docker engine categories.
- Fix the chart colours: Images use the Reclaim orange, build cache the
deeper red (warm = reclaimable overhead), apps a cool palette.
- Images list: dark container, Clear All / Select all moved into the section
head (count text dropped), each image shows its app's icon.
- Storage by app restyled to the same Tasks-style list (app icons,
expandable folders), minus the selection controls.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Post-task UI refresh was scattered: every page added its own taskCompleted
listener and hard-coded which actions it cared about, so it was easy to add a
task and forget the refresh (stale UI), with no single place to see the wiring.
Adds TaskRefreshCoordinator (window.taskRefresh): one listener, with dedupe
(the SSE bus + synthetic fallbacks double-fire) and opt-in debounce (bursts
coalesce; per-task handlers run every time). Components now register a refresh
entry; window.taskRefresh.table() is the introspectable "what reloads when" map.
Migrated onto it: apps (install/uninstall/tool/config_update lifecycle +
restore/update/rebuild state), backups (backup/restore/delete), the update
badge, and the admin overview integrity badge. Gaps closed: restore/update/
rebuild now repaint app+service data. (start/stop/restart intentionally omitted —
no live status surface to refresh today; revisit if a running/stopped badge is
added. Storage reclaim/image-rm keep their own in-page refresh.)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
config_update re-deploys apps (ports, subdomains, Open URLs, routing) but the
WebUI only unlocked the nav on completion — leaving stale URLs/routing until a
manual reload. apps-manager now refreshes apps + services and repaints the
current view when a config_update task completes, via a reusable
refreshAppsAndView() helper (also the basis for the upcoming task-refresh
registry).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Replace the frontpage liquid-fill disk circle with a real donut split into
Apps · Docker · Other · Free, keeping disk % used in the centre. Apps come
from the per-app generator (root-device bytes), Docker from system df; both
are clamped within "used" so skew can't overflow. Live disk ticks redraw it,
and the card now clicks through to the full Storage breakdown.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The trends grid lost its disk chart; add it back as a 6th card plotting
root-filesystem % over time, alongside CPU/Memory/Network/Load/Swap. The
'disk' history series and metric-detail entry already existed, so the
expand-to-detail flow works unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Replaces the read-only "Largest images" top-10 table with a Tasks-style list of
ALL Docker images, with select-one / select-multiple / clear-all removal that
mirrors the Tasks page UX (row checkboxes, master select-all, a button that
morphs Clear All ↔ Delete Selected (N), an eo confirm modal).
Deletion routes through the task system, NOT a new web API: a new
`libreportal system image rm [--force] <ids>` CLI subcommand (validates each
ref, loops runFileOp docker image rm, reports a tally) is invoked via the
system_image_rm task action — same pattern as Reclaim. The web backend change
is read-only (uncap the existing /storage image list). In-use images are
skipped by default with an opt-in "force-remove" toggle (warned). The page
stays put, toasts, and refreshes on the task's completion event.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Put everything back in a single donut instead of an app-only one: a slice
per app plus Docker's images and build cache, with one legend listing them
all. Colours run continuously so app and Docker slices stay distinct, and
the Docker cards below reuse the same colours. The per-folder app
drill-down table stays. This is the "all the data, with app usage added"
view that was asked for.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The Storage page now leads with on-disk usage by app: the headline donut
is split by app (each a coloured slice, total app data in the centre),
and the "Storage by app" table is its legend — swatch + bar colours match
the slices, rows expand to the per-folder breakdown. Docker's engine
figures (images + build cache) drop to a secondary section below. This is
the integration that was asked for; the donut is your data, not Docker's
overhead.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Like named volumes, a container's writable layer is a near-zero scratch
number for LibrePortal (app data lives in bind mounts, shown per-app), so
sitting it next to per-app storage just confused things. Remove the
"Containers" slice/card and its backend summation, and reframe the Docker
breakdown as "Docker engine" overhead (images + build cache) — clearly
separate from your app data.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Extend the app-storage generator to record every bind mount's size and
in-container path, grouped into a per-app folder list. The "Storage by
app" rows are now expandable: click an app to see where its space goes
(e.g. /var/lib/mysql vs /data), with external-drive folders flagged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
LibrePortal apps keep data in bind mounts, so Docker named-volume
accounting is always ~empty and just reads as a confusing "0 B". Now that
per-app on-disk usage covers the real "what's filling my disk" question,
remove volumes end to end: the donut slice, category card, "Largest
volumes" table and the System-page count, plus the backend's volume
summation and top_volumes payload. Reclaim copy no longer references
volumes (it reassures about app data instead).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The old comment implied the key was still a REPLACE_ME placeholder. Reword to
describe current behaviour (signature required for release installs) plus how to
rotate the key.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>