From cd21fca749ac48388782e741f32091a1cbccdf82 Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Mon, 17 Aug 2026 11:47:01 -0400 Subject: [PATCH] Give the wizard an ending: big checkmark plus a way out, and refresh it when the onboard lands With nothing blocking but optional keys unfilled the banner rendered an empty string, so a finished onboard showed a blank panel beside a Join button still greyed at Running. --- Plugin/unraid/Varaverk.page | 8 +++- Plugin/unraid/pages/setup.php | 77 ++++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/Plugin/unraid/Varaverk.page b/Plugin/unraid/Varaverk.page index 54266d1..7c32b22 100644 --- a/Plugin/unraid/Varaverk.page +++ b/Plugin/unraid/Varaverk.page @@ -277,8 +277,14 @@ function vvPtWatchJob(id, mountEl) { : (s.status === 'never_run' ? 'did not start ⚠' : `${s.status} (exit ${s.exit ?? '?'})`); mountEl.innerHTML = `${lbl}` + ` log`; - // Only the Partnership tab defines a reload; the wizard has nothing to refresh. if (typeof _vvPtReload === 'function') _vvPtReload(); + // The wizard does have something to refresh, and saying it did not is why the mirror's + // Join button stayed greyed at "Running" after the run finished. Worse, the mirror's own + // job takes about three seconds — it only notifies the owner — while the Phase 2 it + // triggers runs for minutes on the far side. So "this job is done" is not "the + // partnership is done", and a single reload here would still show an unfinished wizard. + // vvOnJobDone polls until the checklist actually turns. + if (typeof vvOnJobDone === 'function') vvOnJobDone(id, s); }) .catch(() => {}); }; diff --git a/Plugin/unraid/pages/setup.php b/Plugin/unraid/pages/setup.php index 64c6064..32621cf 100644 --- a/Plugin/unraid/pages/setup.php +++ b/Plugin/unraid/pages/setup.php @@ -540,20 +540,43 @@ function vvRenderDone(d) { if (!el) return; const partner = vvDetectedIdentity?.role === 'partner'; - if (d.complete) { - const next = partner - ? `Next: install this server's SSH key on ${vvEscHtml(vvDetectedIdentity.primary || 'the primary')} ` - + `and join, both on the Partnership tab.` - : 'Next: review the schedule, then onboard a partner when you have one.'; - el.innerHTML = `
- ✓ Setup complete — every required item is done.
- ${next}
`; + const blocking = (d.items || []).filter(i => !i.ok && i.blocking); + const onboarded = (d.items || []).some(i => i.id === 'partnership' && i.ok); + const optional = (d.items || []).filter(i => !i.ok && !i.blocking); + + // Three states, not two. The old code returned '' when nothing was blocking but `complete` was + // still false — which is exactly the moment a partnership finishes, because `complete` also + // wants the optional media-server keys deferred or filled. So the wizard went blank at the end + // of a successful onboard, beside a Join button still greyed at "running", and there was + // nothing on screen to say it was over. People wait at a blank screen. + if (d.complete || !blocking.length) { + const heading = onboarded + ? 'Partnership established — this server is onboarded.' + : 'Setup complete — every required item is done.'; + const leftover = optional.length + ? `
+ ${optional.length} optional item${optional.length > 1 ? 's' : ''} still open + (${optional.map(i => vvEscHtml(i.label)).join(', ')}) — fill them in whenever, or + dismiss with “Not now”. Nothing is waiting on them.
` + : ''; + el.innerHTML = `
+
+ +
+
${heading}
+
You can leave this page.
+
+
+ + +
+
${leftover}
`; return; } - const blocking = (d.items || []).filter(i => !i.ok && i.blocking); - if (!blocking.length) { el.innerHTML = ''; return; } el.innerHTML = `
${blocking.length} required item${blocking.length > 1 ? 's' : ''} left: @@ -561,6 +584,38 @@ function vvRenderDone(d) { Anything marked optional can be dismissed with “Not now”.
`; } +// Called by vvPtWatchJob when a job it was watching finishes. +// +// On the mirror, "the onboard job finished" means the owner has been notified — three seconds of +// work — and the Phase 2 it kicked off then runs for minutes on the other machine. Reloading once +// here would redraw the same unfinished wizard and stop, which is how the panel ended up frozen +// with a greyed Running button and no way to tell it had actually succeeded. +// +// So: reload immediately, and if the partnership is still not green keep asking. Bounded at five +// minutes because a Phase 2 that has not landed by then has failed and the operator should be +// looking at the log, not at a spinner. +let _vvPartnerPoll = null; +function vvOnJobDone(id, status) { + if (!String(id).includes('partnership_onboard')) { vvLoadChecklist(); return; } + if (_vvPartnerPoll) clearInterval(_vvPartnerPoll); + const deadline = Date.now() + 5 * 60 * 1000; + const check = () => { + fetch('/plugins/varaverk/api/checklist.php?_=' + Date.now()) + .then(r => r.json()) + .then(d => { + const done = (d.items || []).some(i => i.id === 'partnership' && i.ok); + if (done || Date.now() > deadline) { + clearInterval(_vvPartnerPoll); _vvPartnerPoll = null; + vvLoadChecklist(); + } + }) + .catch(() => {}); + }; + vvLoadChecklist(); + check(); + _vvPartnerPoll = setInterval(check, 6000); +} + function vvLoadChecklist() { fetch('/plugins/varaverk/api/checklist.php?_=' + Date.now()) .then(r => r.json()).then(d => {