feat(admin): one-click sources sync — admin-only button triggers git clone/pull + re-import + KB overview refresh with polled live status

This commit is contained in:
2026-08-25 21:39:38 -04:00
parent 0654b304e1
commit 52136fe307
13 changed files with 1621 additions and 2 deletions
+27 -1
View File
@@ -37,6 +37,20 @@
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
<span class="new-chat-label">New chat</span>
</button>
<!-- Phase 32: the admin-only "Sync sources" button (TODO.md:5) —
SHIPS hidden (anonymous-safe), header.js reveals it for the
admin on the SAME cached whoami that reveals #nav-sources /
#nav-tuning (one fetch, no extra whoami call). sources.js
drives the §7.4 "never stale" lifecycle: idle → "Syncing…"
(disabled + spinning icon + 2 s GET /api/sync/status poll) →
last result ("Synced HH:MM" + counts in #sync-result) or the
role="alert" error banner. #sync-result is the aria-live
announcer for the last result. -->
<button type="button" class="sync-btn" id="sync-btn" hidden aria-label="Sync sources">
<svg class="sync-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>
<span class="sync-label" id="sync-label">Sync sources</span>
</button>
<span class="sync-result" id="sync-result" role="status" aria-live="polite"></span>
<a href="/login.html?next=/sources.html" class="auth-link" id="sign-in-link" hidden>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M10 4h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-8"/><path d="M4 12h11"/><path d="m12 9 3 3-3 3"/></svg>
<span class="auth-label">Sign in</span>
@@ -50,11 +64,23 @@
<main id="main" class="app-main" tabindex="-1">
<div class="container sources-shell">
<!-- Phase 32: the sync failure banner — the chat error-banner
markup style (kb-banner + is-error), role="alert" so a failed
sync is announced. sources.js fills #sync-error-text and
un-hides it on a failed run (the button re-enables,
retry-ready); a new sync hides it again. -->
<div class="kb-banner is-error" id="sync-error-banner" role="alert" hidden>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.6 22.2 20.4H1.8Z"/><path d="M12 9.5v4.6"/><path d="M12 17.4h.01"/></svg>
<span id="sync-error-text"></span>
</div>
<div class="page-head">
<h1>Knowledge base</h1>
<p class="page-sub">
Every <code>*.md</code> file indexed from <code>~/Homelab</code> and
<code>~/Deployments</code>. Re-run the import to refresh.
<code>~/Deployments</code>. Re-run the import to refresh — or hit
<strong>Sync sources</strong> in the header to clone the repos and
re-import.
</p>
</div>