Merge pull request #358 from naturallaw777/arena/019fadc2-sovran-systemsos
Improve service version details and naming
This commit is contained in:
@@ -2576,6 +2576,15 @@ def _get_service_version(unit: str) -> str | None:
|
||||
)
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
m = _NIX_STORE_VERSION_RE.search(result.stdout)
|
||||
# Some wrapped systemd commands contain an escaped or nested
|
||||
# store path that the strict package-path expression misses. Fall
|
||||
# back to scanning each store path segment for the version token.
|
||||
if not m:
|
||||
for store_path in re.findall(r"/nix/store/[a-z0-9]{32}-[^\\s/\\\"]+", result.stdout):
|
||||
candidates = re.findall(r"(?:^|-)(\\d+\\.\\d+(?:\\.\\d+)*(?:[+-][a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*)?)$", store_path)
|
||||
if candidates:
|
||||
m = type("_VersionMatch", (), {"group": lambda self, n: candidates[-1]})()
|
||||
break
|
||||
if m:
|
||||
ver = m.group(1)
|
||||
# Strip a single trailing period (defensive; shouldn't appear in store paths)
|
||||
|
||||
@@ -256,6 +256,80 @@
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Version lives in the detail modal so compact tiles stay visually stable. */
|
||||
.svc-detail-version-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin: -6px 0 20px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid rgba(109, 191, 139, 0.28);
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, rgba(109, 191, 139, 0.12), rgba(109, 191, 139, 0.04));
|
||||
}
|
||||
|
||||
.svc-detail-version-icon {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 8px;
|
||||
background: rgba(109, 191, 139, 0.18);
|
||||
color: var(--accent-color);
|
||||
font-size: 1.35rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.svc-detail-version-label {
|
||||
color: var(--text-dim);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.svc-detail-version-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.svc-detail-version-state {
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 999px;
|
||||
color: var(--accent-color);
|
||||
background: rgba(109, 191, 139, 0.14);
|
||||
font-size: 0.62rem;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.svc-detail-version-card--unavailable,
|
||||
.svc-detail-version-card--not-applicable {
|
||||
border-color: rgba(229, 165, 10, 0.3);
|
||||
background: rgba(229, 165, 10, 0.07);
|
||||
}
|
||||
|
||||
.svc-detail-version-card--unavailable .svc-detail-version-icon,
|
||||
.svc-detail-version-card--not-applicable .svc-detail-version-icon {
|
||||
color: var(--yellow);
|
||||
background: rgba(229, 165, 10, 0.14);
|
||||
}
|
||||
|
||||
.svc-detail-version-card--unavailable .svc-detail-version-state,
|
||||
.svc-detail-version-card--not-applicable .svc-detail-version-state {
|
||||
color: var(--yellow);
|
||||
background: rgba(229, 165, 10, 0.14);
|
||||
}
|
||||
|
||||
.svc-detail-version-value {
|
||||
margin-top: 2px;
|
||||
color: var(--text-primary);
|
||||
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* ── Service detail: Domain ──────────────────────────────────────── */
|
||||
|
||||
.svc-detail-domain-value {
|
||||
|
||||
@@ -659,6 +659,29 @@ async function openServiceDetailModal(unit, name, icon) {
|
||||
'</div>' +
|
||||
'</div>');
|
||||
|
||||
// Keep package versions in the detail modal rather than the compact tile.
|
||||
// The API uses `version` for regular services and `bitcoin_version` for
|
||||
// older Bitcoin payloads, so accept both while the backend is upgraded.
|
||||
var serviceVersion = data.version || data.bitcoin_version || '';
|
||||
// These services are wrappers, setup helpers, or application stacks rather
|
||||
// than a single versioned daemon represented by the tile's systemd unit.
|
||||
var versionNotApplicable = [
|
||||
'phpfpm-wordpress.service', 'phpfpm-nextcloud.service',
|
||||
'albyhub.service', 'nwc-wallets.service',
|
||||
'zeus-connect-setup.service', 'sparrow-autoconnect.service'
|
||||
].indexOf(unit) !== -1;
|
||||
var versionState = serviceVersion ? 'detected' : (versionNotApplicable ? 'not-applicable' : 'unavailable');
|
||||
var versionText = serviceVersion || (versionNotApplicable
|
||||
? 'This service does not expose a single package version'
|
||||
: (effectiveEnabled ? 'Version could not be detected' : 'Start the service to detect its version'));
|
||||
var versionBadge = serviceVersion ? 'Detected' : (versionNotApplicable ? 'Not applicable' : 'Not detected');
|
||||
addSetup('<div class="svc-detail-version-card svc-detail-version-card--' + versionState + '">' +
|
||||
'<div class="svc-detail-version-icon">⌁</div>' +
|
||||
'<div class="svc-detail-version-copy"><div class="svc-detail-version-label">Installed version ' +
|
||||
'<span class="svc-detail-version-state">' + versionBadge + '</span></div>' +
|
||||
'<div class="svc-detail-version-value">' + escHtml(versionText) + '</div></div>' +
|
||||
'</div>');
|
||||
|
||||
// Section B2: BIP-110 live status (bip110 tile only)
|
||||
if (icon === 'bip110' && data.bip110) {
|
||||
var bip110 = data.bip110;
|
||||
|
||||
@@ -156,13 +156,10 @@ function buildTile(svc) {
|
||||
var pct = Math.round((svc.sync_progress || 0) * 100);
|
||||
var id = tileId(svc);
|
||||
var eta = _calcBtcEta(id, svc.sync_progress || 0);
|
||||
var ver = svc.version || svc.bitcoin_version || '';
|
||||
var versionLabel = ver ? '<div class="tile-version">' + escHtml(ver) + '</div>' : '';
|
||||
tile.innerHTML =
|
||||
'<img class="tile-icon" src="/static/icons/' + escHtml(svc.icon) + '.svg" alt="' + escHtml(svc.name) + '" onerror="this.style.display=\'none\';this.nextElementSibling.style.display=\'flex\'">' +
|
||||
'<div class="tile-icon-fallback" style="display:none">?</div>' +
|
||||
'<div class="tile-name">' + escHtml(svc.name) + '</div>' +
|
||||
versionLabel +
|
||||
'<div class="tile-sync-container">' +
|
||||
'<div class="tile-sync-label">\u23F3 Syncing Timechain</div>' +
|
||||
'<div class="tile-sync-bar-row">' +
|
||||
@@ -178,10 +175,8 @@ function buildTile(svc) {
|
||||
return tile;
|
||||
}
|
||||
|
||||
var ver = svc.version || svc.bitcoin_version || '';
|
||||
var versionLabel = ver ? '<div class="tile-version">' + escHtml(ver) + '</div>' : '';
|
||||
var bip110Badge = (svc.icon === 'bip110') ? _renderBip110Badge(svc.bip110) : '';
|
||||
tile.innerHTML = '<img class="tile-icon" src="/static/icons/' + escHtml(svc.icon) + '.svg" alt="' + escHtml(svc.name) + '" onerror="this.style.display=\'none\';this.nextElementSibling.style.display=\'flex\'"><div class="tile-icon-fallback" style="display:none">?</div><div class="tile-name">' + escHtml(svc.name) + '</div>' + versionLabel + bip110Badge + '<div class="tile-status"><span class="status-dot ' + sc + '"></span><span class="status-text">' + st + '</span></div>';
|
||||
tile.innerHTML = '<img class="tile-icon" src="/static/icons/' + escHtml(svc.icon) + '.svg" alt="' + escHtml(svc.name) + '" onerror="this.style.display=\'none\';this.nextElementSibling.style.display=\'flex\'"><div class="tile-icon-fallback" style="display:none">?</div><div class="tile-name">' + escHtml(svc.name) + '</div>' + bip110Badge + '<div class="tile-status"><span class="status-dot ' + sc + '"></span><span class="status-text">' + st + '</span></div>';
|
||||
|
||||
tile.style.cursor = "pointer";
|
||||
tile.addEventListener("click", function() {
|
||||
@@ -235,22 +230,6 @@ function updateTiles(services) {
|
||||
if (fill) fill.style.width = pct + "%";
|
||||
if (pctEl) pctEl.textContent = pct + "%";
|
||||
if (etaEl) etaEl.textContent = etaText;
|
||||
// Update or insert version label
|
||||
var syncVer = svc.version || svc.bitcoin_version || '';
|
||||
if (syncVer) {
|
||||
var syncVerEl = tile.querySelector(".tile-version");
|
||||
if (syncVerEl) {
|
||||
syncVerEl.textContent = syncVer;
|
||||
} else {
|
||||
var syncNameEl = tile.querySelector(".tile-name");
|
||||
if (syncNameEl) {
|
||||
var newSyncVerEl = document.createElement("div");
|
||||
newSyncVerEl.className = "tile-version";
|
||||
newSyncVerEl.textContent = syncVer;
|
||||
syncNameEl.insertAdjacentElement("afterend", newSyncVerEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// IBD finished or not syncing — if tile had sync layout rebuild it normally
|
||||
if (tile.querySelector(".tile-sync-container")) {
|
||||
@@ -265,22 +244,6 @@ function updateTiles(services) {
|
||||
var text = tile.querySelector(".status-text");
|
||||
if (dot) dot.className = "status-dot " + sc;
|
||||
if (text) text.textContent = st;
|
||||
// Update or insert version label for all service tiles
|
||||
var tileVer = svc.version || svc.bitcoin_version || '';
|
||||
if (tileVer) {
|
||||
var verEl = tile.querySelector(".tile-version");
|
||||
if (verEl) {
|
||||
verEl.textContent = tileVer;
|
||||
} else {
|
||||
var nameEl = tile.querySelector(".tile-name");
|
||||
if (nameEl) {
|
||||
var newVerEl = document.createElement("div");
|
||||
newVerEl.className = "tile-version";
|
||||
newVerEl.textContent = tileVer;
|
||||
nameEl.insertAdjacentElement("afterend", newVerEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update BIP-110 badge for bip110 tiles
|
||||
if (svc.icon === 'bip110') {
|
||||
var badgeHtml = _renderBip110Badge(svc.bip110);
|
||||
@@ -290,8 +253,8 @@ function updateTiles(services) {
|
||||
var newBadge = _firstElementFromHtml(badgeHtml);
|
||||
if (newBadge) { badgeEl.replaceWith(newBadge); } else { badgeEl.remove(); }
|
||||
} else if (badgeHtml) {
|
||||
// Insert badge after version label (or after tile-name if no version)
|
||||
var anchorEl = tile.querySelector(".tile-version") || tile.querySelector(".tile-name");
|
||||
// Insert badge after the service name
|
||||
var anchorEl = tile.querySelector(".tile-name");
|
||||
if (anchorEl) {
|
||||
var newBadgeEl = _firstElementFromHtml(badgeHtml);
|
||||
if (newBadgeEl) anchorEl.insertAdjacentElement("afterend", newBadgeEl);
|
||||
|
||||
@@ -79,7 +79,7 @@ let
|
||||
{ label = "Test Username"; file = "/var/lib/secrets/matrix-test-username"; }
|
||||
{ label = "Test Password"; file = "/var/lib/secrets/matrix-test-password"; }
|
||||
]; }
|
||||
{ name = "Element-Call"; unit = "livekit.service"; type = "system"; icon = "element-calling"; enabled = cfg.features.element-calling; category = "communication"; credentials = []; }
|
||||
{ name = "LiveKit (Element Call)"; unit = "livekit.service"; type = "system"; icon = "element-calling"; enabled = cfg.features.element-calling; category = "communication"; credentials = []; }
|
||||
]
|
||||
# ── Self-Hosted Apps (server+desktop only) ─────────────────
|
||||
++ lib.optionals cfg.roles.server_plus_desktop [
|
||||
|
||||
Reference in New Issue
Block a user