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.
This commit is contained in:
Gmer4Lfe
2026-08-17 11:47:01 -04:00
parent ead5d38d7c
commit cd21fca749
2 changed files with 73 additions and 12 deletions
+66 -11
View File
@@ -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 = `<div style="margin-top:16px;padding:10px 12px;border-radius:3px;background:#0d1f0d;
border:1px solid #1a3a1a;color:#4caf50;font-size:12px;line-height:1.6;">
✓ Setup complete — every required item is done.<br>
<span style="color:#3a7a3a;">${next}</span></div>`;
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
? `<div style="color:#3a7a3a;font-size:11px;margin-top:6px;">
${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.</div>`
: '';
el.innerHTML = `<div style="margin-top:16px;padding:14px 16px;border-radius:4px;background:#0d1f0d;
border:1px solid #1a3a1a;">
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;">
<span style="font-size:30px;line-height:1;color:#4caf50;">✓</span>
<div style="flex:1;min-width:200px;">
<div style="color:#4caf50;font-size:14px;font-weight:600;">${heading}</div>
<div style="color:#3a7a3a;font-size:11px;margin-top:2px;">You can leave this page.</div>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;">
<button class="vv-pt-action-btn run" onclick="window.location.href='${_vvRedirect || '?tab=scheduler'}'"
style="font-size:12px;white-space:nowrap;">Go to Scheduler →</button>
<button class="vv-pt-action-btn info" onclick="window.location.href='?tab=monitor'"
style="font-size:12px;white-space:nowrap;">Monitor</button>
</div>
</div>${leftover}</div>`;
return;
}
const blocking = (d.items || []).filter(i => !i.ok && i.blocking);
if (!blocking.length) { el.innerHTML = ''; return; }
el.innerHTML = `<div style="margin-top:16px;padding:10px 12px;border-radius:3px;background:#1a1400;
border:1px solid #3a2e00;color:#a80;font-size:12px;line-height:1.6;">
${blocking.length} required item${blocking.length > 1 ? 's' : ''} left:
@@ -561,6 +584,38 @@ function vvRenderDone(d) {
<span style="color:#665;">Anything marked optional can be dismissed with “Not now”.</span></div>`;
}
// 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 => {