The per-service rich detail panel (.service-rich: limits, healthcheck,
networks, mounts) and the live mem chip both did `const fmt =
window.SystemFmt` and bailed when it was absent. SystemFmt is defined by
the lazy admin System page module, so on the app Services tab it's usually
undefined — `_renderRichDetail` returned '' and the panel was never in the
DOM, so flipping Advanced revealed nothing.
Give the Services component its own SVC_FMT formatter (mirrors SystemFmt)
and use `window.SystemFmt || SVC_FMT` everywhere, dropping the hard bail.
The rich panel now renders whether or not /admin/system was ever visited.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
The Services tab restart button POSTed to a backend endpoint that (a)
checked the app's compose path from INSIDE the webui container, where
the host's containers root isn't mounted — so every restart failed with
'Compose file not found' — and (b) queued a raw 'docker compose restart'
that the host task processor would run as the manager user, which can't
talk to the rootless daemon anyway. Errors surfaced via a bare alert().
Per-service restart now follows the exact shape of the whole-app verbs:
- CLI: 'libreportal app restart <app> [service]' — the optional service
arg makes dockerRestartApp restart just that compose service, via
dockerCommandRun (right user in rootless mode) from the app dir on the
host, where the compose file actually lives. Service names validated
against compose-legal characters before touching a shell line.
- WebUI: the button dispatches a 'service_restart' task action through
the task router (mutations-via-tasks), runs in the background with the
standard task toast + link — no page switch — and failures use the
notification system instead of alert(). Because the task runs host-
side, restarting the WebUI's own libreportal-service now works too.
- Backend: the mutating restart endpoint and its now-unused helpers are
removed; service-routes.js is read-only surface (status + log tails).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
De-clutter each component into sub-system folders (apps: core/ port-manager/
services/ tools/ routing/; admin: config/ overview/ system/ ssh/ peers/) with
the standard js/ css/ html/ icons/ layout inside; single-page components
(backup/dashboard/tasks/updater) get js/ css/ html/. Single-feature icon sets
moved into their sub-system (vpn -> apps/core/icons, config/cpu/os ->
admin/{config,system}/icons); shared app + category icons stay in core/icons.
feature.json + index.js stay at each component root (the scanned descriptor +
entry). Every controller/CSS/fragment/icon path reference rewritten; verified
no stale refs, all JS valid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>