From 6da5577b275c3908940039146ef50ceff4278579 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Wed, 8 Oct 2025 23:55:33 -0400 Subject: [PATCH] wiz status page --- src/services/wizard/index.ts | 31 +++++++++++++++----------- static/js/status.js | 43 +++++++++++++++++++++++++++++++----- static/status.html | 28 +++++++++++++---------- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/services/wizard/index.ts b/src/services/wizard/index.ts index ce44bb3d..7ea31c8b 100644 --- a/src/services/wizard/index.ts +++ b/src/services/wizard/index.ts @@ -148,23 +148,28 @@ export class Wizard { relay_url_CustomCheck: relay => relay !== '', }) if (err != null) { throw new Error(err.message) } - if (this.IsInitialized() || this.pendingConfig !== null) { - throw new Error("already initialized") - } const pendingConfig = { sourceName: req.source_name, relayUrl: req.relay_url, automateLiquidity: req.automate_liquidity, pushBackupsToNostr: req.push_backups_to_nostr } - - // Also update the application name in the database - try { - const appsList = await this.storage.applicationStorage.GetApplications() - const defaultNames = ['wallet', 'wallet-test', this.settings.defaultAppName] - const existingDefaultApp = appsList.find(app => defaultNames.includes(app.name)) - if (existingDefaultApp) { - await this.storage.applicationStorage.UpdateApplication(existingDefaultApp, { name: req.source_name, avatar_url: (req as any).avatar_url || existingDefaultApp.avatar_url }) + + // If already initialized, treat as idempotent update: persist name/avatar and env settings, do not block. + if (this.IsInitialized()) { + try { + const appsList = await this.storage.applicationStorage.GetApplications() + const defaultNames = ['wallet', 'wallet-test', this.settings.defaultAppName] + const existingDefaultApp = appsList.find(app => defaultNames.includes(app.name)) || appsList[0] + if (existingDefaultApp) { + await this.storage.applicationStorage.UpdateApplication(existingDefaultApp, { name: req.source_name, avatar_url: (req as any).avatar_url || (existingDefaultApp as any).avatar_url }) + } + } catch (e) { + this.log(`Error updating app info: ${(e as Error).message}`) } - } catch (e) { - this.log(`Error updating app name: ${(e as Error).message}`) + this.updateEnvFile(pendingConfig) + return } + // First-time configuration flow + if (this.pendingConfig !== null) { + throw new Error("already initializing") + } this.updateEnvFile(pendingConfig) this.configQueue.forEach(q => q.res(true)) this.configQueue = [] diff --git a/static/js/status.js b/static/js/status.js index 24143e78..46e3b702 100644 --- a/static/js/status.js +++ b/static/js/status.js @@ -1,4 +1,27 @@ $(() => { + const postConfig = async (updates) => { + try { + const stateRes = await fetch('/wizard/service_state') + if (stateRes.status !== 200) return false + const s = await stateRes.json() + const body = { + source_name: updates.source_name ?? (s.source_name || s.provider_name || ''), + relay_url: updates.relay_url ?? (s.relay_url || (s.relays && s.relays[0]) || ''), + automate_liquidity: s.automate_liquidity || false, + push_backups_to_nostr: s.push_backups_to_nostr || false, + avatar_url: s.avatar_url || '' + } + const res = await fetch('/wizard/config', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body) + }) + if (res.status !== 200) return false + const j = await res.json().catch(() => ({})) + if (j && j.status && j.status !== 'OK') return false + return true + } catch { return false } + } $("#show-reset").click(() => { $("#reset-content").text('Reset the administrator account if you lost access via the Dashboard.'); $("#reset-box").show(); @@ -18,9 +41,13 @@ $(() => { }); $("#save-show-nodey").click(() => { var targetInputVal = $('input[name="show-nodey"]').val() - $('#show-nodey-text').text(targetInputVal) - $('.show-nodey').hide() - $('#show-nodey-text').show() + postConfig({ source_name: targetInputVal }).then(ok => { + if (ok) { + $('#show-nodey-text').text(targetInputVal) + } + $('.show-nodey').hide() + $('#show-nodey-text').show() + }) }) $("#cancel-show-nodey").click(() => { $('.show-nodey').hide() @@ -38,9 +65,13 @@ $(() => { }); $("#save-show-nostr").click(() => { var targetInputVal = $('input[name="show-nostr"]').val() - $('#show-nostr-text').text(targetInputVal) - $('.show-nostr').hide() - $('#show-nostr-text').show() + postConfig({ relay_url: targetInputVal }).then(ok => { + if (ok) { + $('#show-nostr-text').text(targetInputVal) + } + $('.show-nostr').hide() + $('#show-nostr-text').show() + }) }) $("#cancel-show-nostr").click(() => { $('.show-nostr').hide() diff --git a/static/status.html b/static/status.html index 44210dc6..5fd8836e 100644 --- a/static/status.html +++ b/static/status.html @@ -19,7 +19,7 @@
Lightning Pub logo - Lightning Pub logo + Lightning Pub logo
@@ -157,20 +157,24 @@ } const j = await res.json() console.log(j) - if (j.status !== 'OK') { - document.getElementById('errorText').innerText = "failed to get state info" + j.reason - return - } - document.getElementById("show-nodey-text").innerHTML = j.provider_name - document.getElementById("show-nostr-text").innerHTML = j.relays[0] - document.getElementById("adminNpub").innerText = j.admin_npub - document.getElementById("relayStatus").innerHTML = ` ${j.relay_connected ? 'Connected' : 'Disconnected'}` - document.getElementById("lndStatus").innerHTML = ` ${j.lnd_state}` + // Map fields from service state + const name = j.source_name || j.provider_name || 'Unknown' + const relayUrl = j.relay_url || (j.relays && j.relays[0]) || '' + const admin = j.admin_npub || '' + const lndStateNum = typeof j.lnd_state === 'number' ? j.lnd_state : 0 + const lndText = lndStateNum === 2 ? 'ONLINE' : (lndStateNum === 1 ? 'SYNCING' : 'OFFLINE') + const lndDot = lndStateNum === 2 ? 'green-dot' : (lndStateNum === 1 ? 'yellow-dot' : 'red-dot') + const relayConnected = !!relayUrl + document.getElementById("show-nodey-text").innerHTML = name + document.getElementById("show-nostr-text").innerHTML = relayUrl || '—' + document.getElementById("adminNpub").innerText = admin + document.getElementById("relayStatus").innerHTML = ` ${relayConnected ? 'Connected' : 'Disconnected'}` + document.getElementById("lndStatus").innerHTML = ` ${lndText}` document.getElementById("watchdog-status").innerHTML = ` ${j.watchdog_ok ? 'No Alerts' : 'ALERT!!'}` document.getElementById("inviteLinkHttp").href = `https://my.shockwallet.app/#/sources?addSource=${j.nprofile}` document.getElementById("inviteLinkHttp").innerHTML = `https://my.shockwallet.app/#/sources?addSource=${j.nprofile}` - document.querySelector('input[name="show-nodey"]').placeholder = j.provider_name; - document.title = j.provider_name; + document.querySelector('input[name="show-nodey"]').placeholder = name; + document.title = name; } try { fetchInfo()