From ea9d4f21d7cc645e11231e99273964a39b66738c Mon Sep 17 00:00:00 2001 From: naturallaw77 Date: Tue, 8 Sep 2026 22:08:20 +0000 Subject: [PATCH] Polish pass: sysops wording, QR size, NWC toolbar, logo, diagnostics placement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eight fixes from live testing: Systems Operational modal: - Drop the "test from your phone on mobile data" (hairpin NAT) sentence from the router note — too technical for the intended audience. - Node-only role: when BTCPay Server and Lightning Wallet Connections (LNURL) are both off, the router card becomes a simple "No router setup needed yet" note explaining that ports 80/443 only matter if one of those services is turned on. When one is enabled, the card shows the same port steps and live domain/port diagnostics as the Desktop + Server role (diagnostics now poll only enabled services). Service modals: - The Domain Diagnostic Checklist now shows only the domain-active step (Domain Configured). DNS and port diagnostics live in Systems Operational, which shows the full checklist. - Node-only role: BTCPay Server and Lightning Wallet Connections modals gain a "Ports to Forward in Your Router" section with the standard 80/443 wording and this computer's LAN address. - Domain setup and reconfigure dialogs no longer contain router port-forwarding instructions (already handled during Desktop + Server onboarding and shown in Systems Operational). Lightning Wallet Connections: - Refresh and New Wallet toolbar buttons now share one height and baseline (a leftover 12px top margin on Refresh was offsetting it). - The header status chip has a proper gap between the status dot and its label. Zeus Connect / QR codes: - QR codes render at the original 240px with the white frame and pixelated upscaling, restoring scannability. Brand: - The sidebar logo loads via /static/sovran-hub-icon.svg (same as the login page) instead of an inline symbol — the gradient-heavy symbol did not render reliably. The icon sprite is hidden with the browser-safe zero-size pattern instead of display:none. --- .../static/css/modals.css | 26 ++++++--- .../static/js/dashboard.js | 53 +++++++++++++------ .../static/js/features.js | 7 --- .../static/js/service-detail.js | 20 ++++++- app/sovran_systemsos_web/templates/index.html | 23 +------- 5 files changed, 79 insertions(+), 50 deletions(-) diff --git a/app/sovran_systemsos_web/static/css/modals.css b/app/sovran_systemsos_web/static/css/modals.css index 4816df5..503de8d 100644 --- a/app/sovran_systemsos_web/static/css/modals.css +++ b/app/sovran_systemsos_web/static/css/modals.css @@ -471,11 +471,13 @@ } .creds-qr-img { - width: 150px; - height: 150px; - padding: 10px; - background: #edf4ef; - border-radius: 14px; + width: 240px; + height: 240px; + border-radius: 12px; + border: 4px solid #fff; + background-color: #fff; + image-rendering: pixelated; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4); } .creds-qr-hint { @@ -912,6 +914,7 @@ .nwc-header-chip { display: inline-flex; align-items: center; + gap: 6px; font-family: var(--mono); font-size: 0.66rem; font-weight: 600; @@ -953,10 +956,22 @@ .nwc-toolbar-actions { margin-left: auto; display: flex; + align-items: center; gap: 9px; flex-wrap: wrap; } +/* Refresh + New Wallet share one height so the toolbar reads as one row */ +.nwc-toolbar-actions .matrix-form-back, +.nwc-toolbar-actions .matrix-action-btn { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 34px; + padding: 7px 16px; + font-size: 0.8rem; +} + .nwc-wallet-list { display: flex; flex-direction: column; } .nwc-wallet-card { @@ -1031,7 +1046,6 @@ overflow-wrap: anywhere; } -.nwc-toolbar-refresh, .nwc-domain-required-btn { margin-top: 12px; } .nwc-intro-header { margin-bottom: 14px; } diff --git a/app/sovran_systemsos_web/static/js/dashboard.js b/app/sovran_systemsos_web/static/js/dashboard.js index fc1e290..fa397fc 100644 --- a/app/sovran_systemsos_web/static/js/dashboard.js +++ b/app/sovran_systemsos_web/static/js/dashboard.js @@ -221,9 +221,19 @@ ''; } + function isNodeRole() { + return (typeof _currentRole !== "undefined" && _currentRole === "node"); + } + + function hasEnabledDomainService(services) { + return DOMAIN_UNITS.some(function (u) { + return services.some(function (s) { return s.unit === u && s.enabled; }); + }); + } + function whoUsesPorts() { - if (typeof _currentRole !== "undefined" && _currentRole === "node") { - return 'On this Bitcoin Node install, BTCPay Server and Lightning Wallet Connections (LNURL) are the domain services that use these ports.'; + if (isNodeRole()) { + return 'On this Bitcoin Node install, BTCPay Server and Lightning Wallet Connections (LNURL) are the domain services that use these ports.'; } return 'All your domain services share ports 80 and 443 — Matrix, BTCPay Server, VaultWarden, Nextcloud, WordPress, Haven Relay, Lightning Wallet Connections, and Element Calling.'; } @@ -253,14 +263,24 @@ step(3, "Turned off", "", off ? escHtml(offNames.join(", ")) : "None") + ''; - /* Router ports — repo wording (domain-prereqs.js / server.py) */ - html += '
' + - '
' + icon("g-wifi") + 'Router — Ports to Forward
' + - step(1, "Port 80", "TCP — HTTP (redirect to HTTPS)", fwd) + - step(2, "Port 443", "TCP — HTTPS", fwd) + - '
' + icon("g-alert") + 'One router task
' + - '
Set the internal and external port to the same number. You only need to do this once — all your services share these two ports. Test from your phone on mobile data (your home network may not support hairpin NAT / loopback).
' + - '
'; + /* Router ports — repo wording (domain-prereqs.js / server.py). + Node-only role: ports matter only once BTCPay Server or Lightning + Wallet Connections (LNURL) is turned on — until then, no router task. */ + if (isNodeRole() && !hasEnabledDomainService(services)) { + html += '
' + + '
' + icon("g-wifi") + 'Router
' + + '
' + icon("g-check") + 'No router setup needed yet
' + + '
Ports 80 and 443 only need to be forwarded on your router if you turn on BTCPay Server or Lightning Wallet Connections (LNURL). If you enable one of them, come back here — this card will show exactly what to do.
' + + '
'; + } else { + html += '
' + + '
' + icon("g-wifi") + 'Router — Ports to Forward
' + + step(1, "Port 80", "TCP — HTTP (redirect to HTTPS)", fwd) + + step(2, "Port 443", "TCP — HTTPS", fwd) + + '
' + icon("g-alert") + 'One router task
' + + '
Set the internal and external port to the same number. You only need to do this once — all your services share these two ports.
' + + '
'; + } /* Live domain diagnostics (sequential checklist from the backend — same data the domain-service modals show) */ @@ -269,10 +289,13 @@ '
Checking…
' + ''; - /* Who uses these ports */ - html += '
' + - '
' + icon("g-antenna") + 'Who uses these ports
' + - '
' + whoUsesPorts() + '
'; + /* Who uses these ports (redundant on a Node install with no domain + services on — the router note above already covers it) */ + if (!isNodeRole() || hasEnabledDomainService(services)) { + html += '
' + + '
' + icon("g-antenna") + 'Who uses these ports
' + + '
' + whoUsesPorts() + '
'; + } $sysBody.innerHTML = html; $sysModal.classList.add("open"); @@ -281,7 +304,7 @@ var checkCard = document.getElementById("sys-check-card"); var stepsEl = document.getElementById("sys-check-steps"); var units = DOMAIN_UNITS.filter(function (u) { - return services.some(function (s) { return s.unit === u; }); + return services.some(function (s) { return s.unit === u && s.enabled; }); }); if (!units.length || !checkCard || !stepsEl) return; checkCard.style.display = ""; diff --git a/app/sovran_systemsos_web/static/js/features.js b/app/sovran_systemsos_web/static/js/features.js index 8287ff6..99f2b0b 100644 --- a/app/sovran_systemsos_web/static/js/features.js +++ b/app/sovran_systemsos_web/static/js/features.js @@ -97,7 +97,6 @@ function openDomainSetupModal(feat, onSaved) { nwcWarning + renderDomainNeedsHtml({ serviceName: feat.name, hostExample: hostExample, purpose: purpose }) + renderNjallaStepsHtml({ hostExample: hostExample, pasteHint: "below" }) + - '
' + '

Enter the address for this service and paste the update command from Njal.la.

' + '' + '
' + @@ -144,8 +143,6 @@ function openDomainSetupModal(feat, onSaved) { $domainSetupModal.classList.add("open"); - // Fill the router port-forwarding box with this computer's LAN IP (best-effort) - renderRouterPortsBox("domain-router-box"); } function openDomainReconfigureModal(feat, existingDomain, onSaved) { @@ -193,9 +190,7 @@ function openDomainReconfigureModal(feat, existingDomain, onSaved) { '' + escHtml(externalIp) + '' + '
  • If the IP is wrong or the record is missing, update it
  • ' + '
  • If you changed the DDNS curl command, paste the updated one below
  • ' + - '
  • Confirm ports 80 and 443 (TCP) are still forwarded on your router to this computer — see the reminder below:
  • ' + '' + - '
    ' + '' + '
    ' + '

    ℹ Paste the full curl command from your Njal.la dashboard\'s Dynamic record

    ' + @@ -241,8 +236,6 @@ function openDomainReconfigureModal(feat, existingDomain, onSaved) { $domainSetupModal.classList.add("open"); - // Fill the router port-forwarding box with this computer's LAN IP (best-effort) - renderRouterPortsBox("domain-router-box"); } function closeDomainSetupModal() { diff --git a/app/sovran_systemsos_web/static/js/service-detail.js b/app/sovran_systemsos_web/static/js/service-detail.js index 0d6e095..41e4551 100644 --- a/app/sovran_systemsos_web/static/js/service-detail.js +++ b/app/sovran_systemsos_web/static/js/service-detail.js @@ -718,7 +718,11 @@ async function openServiceDetailModal(unit, name, icon) { // Section C: Domain diagnostics (domain services) if (data.needs_domain) { - var steps = data.domain_check_steps || []; + // The Hub shows only the domain-active step here; the full DNS and + // port diagnostics live in the Systems Operational modal. + var steps = (data.domain_check_steps || []).filter(function (s) { + return Number(s.step) === 1; + }); var stepsHtml = ""; steps.forEach(function(step) { var iconLabel = "—"; @@ -747,6 +751,17 @@ async function openServiceDetailModal(unit, name, icon) { domainActionHtml + ''); + // Node-only role: BTCPay Server and Lightning Wallet Connections are + // the domain services — surface the router task here. (Desktop + Server + // set this up during onboarding; Systems Operational shows it too.) + if (typeof _currentRole !== "undefined" && _currentRole === "node" && + (unit === "btcpayserver.service" || unit === "albyhub.service")) { + addSetup('
    ' + + '
    Ports to Forward in Your Router
    ' + + '
    ' + + '
    '); + } + if (data.router_ports && data.router_ports.length > 0) { var trimmedInternalIp = data.internal_ip ? String(data.internal_ip).trim() : ""; addSetup('
    ' + @@ -1004,6 +1019,9 @@ async function openServiceDetailModal(unit, name, icon) { $credsBody.innerHTML = html; if (isNwc) _nwcWireTabs(); _attachCopyHandlers($credsBody); + if (document.getElementById("svc-node-router-box")) { + renderRouterPortsBox("svc-node-router-box"); + } if (_isNwcServiceUnit(unit) && (effectiveEnabled || data.enabled)) { await _nwcInitWalletFlow(unit, name, icon); var nwcRtlBtn = document.getElementById("nwc-open-rtl-btn"); diff --git a/app/sovran_systemsos_web/templates/index.html b/app/sovran_systemsos_web/templates/index.html index dc4073a..3f9f57a 100644 --- a/app/sovran_systemsos_web/templates/index.html +++ b/app/sovran_systemsos_web/templates/index.html @@ -18,26 +18,7 @@ -
    - +
    The Hub
    Sovran_SystemsOS v{{ sovran_version }}