From 1692ba0e9db57b18eebd0199800f9447a04094f3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Apr 2026 18:37:18 +0000 Subject: [PATCH] Fix tile/modal status inconsistency and add BIP110/Bitcoin Core mutual-exclusivity messaging Agent-Logs-Url: https://github.com/naturallaw777/staging_alpha/sessions/7238843b-8bbf-4f02-b932-defb5b6ace35 Co-authored-by: naturallaw777 <99053422+naturallaw777@users.noreply.github.com> --- app/sovran_systemsos_web/static/app.js | 39 +++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/app/sovran_systemsos_web/static/app.js b/app/sovran_systemsos_web/static/app.js index 36a6943..ff246ce 100644 --- a/app/sovran_systemsos_web/static/app.js +++ b/app/sovran_systemsos_web/static/app.js @@ -401,8 +401,14 @@ async function openServiceDetailModal(unit, name) { } // Section B: Status - var sc = statusClass(data.health || data.status); - var st = statusText(data.health || data.status, data.enabled); + // When a feature override is present, use the feature's enabled state so the + // modal matches what the dashboard tile shows (feature toggle is authoritative). + var effectiveEnabled = data.feature ? data.feature.enabled : data.enabled; + var effectiveHealth = data.feature && !data.feature.enabled + ? "disabled" + : (data.health || data.status); + var sc = statusClass(effectiveHealth); + var st = statusText(effectiveHealth, effectiveEnabled); html += '
' + '
Status
' + '
' + @@ -596,9 +602,34 @@ async function openServiceDetailModal(unit, name) { var addonStatusCls = feat.enabled ? "addon-status--on" : "addon-status--off"; var addonBtnLabel = feat.enabled ? "Disable Feature" : "Enable Feature"; var addonBtnCls = feat.enabled ? "btn btn-close-modal" : "btn btn-primary"; + + // Section title: use a more specific label for mutually-exclusive Bitcoin node features + var addonSectionTitle = (feat.id === "bip110" || feat.id === "bitcoin-core") + ? "\u20BF Bitcoin Node Selection" + : "\uD83D\uDD27 Addon Feature"; + + // Description: prefer the feature's own description over a generic fallback + var addonDesc = feat.description + ? feat.description + : "This is an optional addon feature. You can enable or disable it at any time."; + + // Conflicts warning: list mutually-exclusive feature names when present + var conflictsHtml = ""; + if (feat.conflicts_with && feat.conflicts_with.length > 0) { + var conflictNames = feat.conflicts_with.map(function(cid) { + if (_featuresData && Array.isArray(_featuresData.features)) { + var cf = _featuresData.features.find(function(f) { return f.id === cid; }); + if (cf) return cf.name; + } + return cid; + }); + conflictsHtml = '
\u26A0 Mutually exclusive with: ' + escHtml(conflictNames.join(", ")) + '
'; + } + html += '
' + - '
🔧 Addon Feature
' + - '

This is an optional addon feature. You can enable or disable it at any time.

' + + '
' + addonSectionTitle + '
' + + '

' + escHtml(addonDesc) + '

' + + conflictsHtml + '
' + '' + addonStatusLabel + '' + '' +