fix(webui): Services-tab Advanced toggle reveals rich detail again
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>
This commit is contained in:
parent
fb9c1ee14a
commit
75162af648
@ -282,8 +282,7 @@ class ServicesManager {
|
||||
_renderRichDetail(info) {
|
||||
if (!info || !info.detail) return '';
|
||||
const d = info.detail;
|
||||
const fmt = window.SystemFmt;
|
||||
if (!fmt) return '';
|
||||
const fmt = window.SystemFmt || SVC_FMT;
|
||||
const lim = d.limits || {};
|
||||
const memLimit = lim.memory || 0;
|
||||
const cpuLimit = lim.nano_cpus
|
||||
@ -350,7 +349,7 @@ class ServicesManager {
|
||||
const stats = info?.stats;
|
||||
const detail = info?.detail;
|
||||
const memLimit = detail?.limits?.memory || 0;
|
||||
const fmt = window.SystemFmt;
|
||||
const fmt = window.SystemFmt || SVC_FMT;
|
||||
const cpuEl = item.querySelector('[data-svc-live="cpu"]');
|
||||
const memEl = item.querySelector('[data-svc-live="mem"]');
|
||||
if (cpuEl) cpuEl.textContent = stats ? `${(stats.cpu_percent ?? 0).toFixed(1)}% CPU` : '—';
|
||||
@ -411,7 +410,7 @@ class ServicesManager {
|
||||
const stats = info.stats;
|
||||
const detail = info.detail;
|
||||
const memLimit = detail?.limits?.memory || 0;
|
||||
const fmt = window.SystemFmt;
|
||||
const fmt = window.SystemFmt || SVC_FMT;
|
||||
const cpuTxt = stats ? `${(stats.cpu_percent ?? 0).toFixed(1)}% CPU` : '—';
|
||||
const memUsed = stats?.memory?.used ?? 0;
|
||||
const memPct = memLimit > 0 ? (memUsed / memLimit) * 100 : (stats?.memory?.percent ?? 0);
|
||||
@ -804,6 +803,34 @@ class ServicesManager {
|
||||
|
||||
// Tiny helpers ----------------------------------------------------------
|
||||
|
||||
// Number/time formatters for the rich detail panel + live stat chips. Mirrors
|
||||
// the admin System page's window.SystemFmt, but owned here so the Services tab
|
||||
// renders its advanced detail even when that page module hasn't loaded — it's
|
||||
// lazy, so visiting /admin/system must NOT be a prerequisite for this tab.
|
||||
// Prefer window.SystemFmt when present so both surfaces share one implementation.
|
||||
const SVC_FMT = {
|
||||
bytes(n) {
|
||||
n = Number(n) || 0;
|
||||
const u = ['B', 'KB', 'MB', 'GB', 'TB']; let i = 0;
|
||||
while (n >= 1024 && i < u.length - 1) { n /= 1024; i++; }
|
||||
return `${n.toFixed(i ? 1 : 0)} ${u[i]}`;
|
||||
},
|
||||
rate(n) { return `${this.bytes(n)}/s`; },
|
||||
timeAgo(unixSec) {
|
||||
if (!unixSec) return '';
|
||||
const diff = Math.floor(Date.now() / 1000) - unixSec;
|
||||
if (diff < 60) return `${diff}s ago`;
|
||||
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
|
||||
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
|
||||
return `${Math.floor(diff / 86400)}d ago`;
|
||||
},
|
||||
timeAgoIso(iso) {
|
||||
if (!iso) return '';
|
||||
const t = Math.floor(new Date(iso).getTime() / 1000);
|
||||
return Number.isFinite(t) && t > 0 ? this.timeAgo(t) : '';
|
||||
},
|
||||
};
|
||||
|
||||
function escapeHtml(s) {
|
||||
return String(s ?? '')
|
||||
.replace(/&/g, '&')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user