From 89c22c6091c6d6106fb306e5804341c1364335d5 Mon Sep 17 00:00:00 2001 From: timmy Date: Wed, 5 Aug 2026 22:48:47 +0000 Subject: [PATCH] fix: render repo mix before populating counts (#48) --- frontend/index.html | 50 ++++++++++++++++++++----------------------- tests/test_widgets.py | 11 ++++++++++ 2 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 tests/test_widgets.py diff --git a/frontend/index.html b/frontend/index.html index 5b6c917..aeed274 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -106,7 +106,16 @@ textarea { resize: vertical; min-height: 120px; }

Live Widgets

-
+
+
+

Live clock

+
+
+
+

Repo mix

+
Loading…
+
+
@@ -358,33 +367,20 @@ textarea { resize: vertical; min-height: 120px; } tickWidgets(); /* Widgets */ - const widgetOrder = ['countdown','repoAtAGlance']; - const widgetRegistry = { - countdown: () => ({ title: 'Live clock', html: '
' }), - repoAtAGlance: async () => { - const el = qs('#repo-mix'); - if (!el) return { title:'Repo mix', html:'
Unavailable
' }; - try { - const res = await fetch('/api/v1/context', { headers: { Accept: 'application/json' } }); - const data = await res.json(); - const repos = data.repos || []; - const issues = (data.issues||[]).filter(i=>i.state==='open'); - const prs = data.pull_requests || []; - el.innerHTML = '
Repos
' + repos.length + '
Open issues
' + issues.length + '
Open PRs
' + prs.length + '
'; - } catch (e) { el.innerHTML = '
Widget unavailable.
'; } - return { title:'Repo mix', html:'
Loading…
' }; - }, - }; - const widgetsEl = qs('#widgets'); - function paintWidgets() { - widgetsEl.innerHTML = ''; - widgetOrder.forEach(async k => { - const w = await widgetRegistry[k](); - const node = document.createElement('div'); node.className='widget'; node.innerHTML = '

' + escapeHtml(w.title) + '

' + w.html; - widgetsEl.appendChild(node); - }); + async function updateRepoMix() { + const el = qs('#repo-mix'); + try { + const res = await fetch('/api/v1/context', { headers: { Accept: 'application/json' } }); + const data = await res.json(); + const repos = data.repos || []; + const issues = (data.issues||[]).filter(i=>i.state==='open'); + const prs = data.pull_requests || []; + el.innerHTML = '
Repos
' + repos.length + '
Open issues
' + issues.length + '
Open PRs
' + prs.length + '
'; + } catch (e) { + el.innerHTML = '
Widget unavailable.
'; + } } - paintWidgets(); + updateRepoMix(); function widgetTick() { const el=qs('#widget-clock'); if(el) el.textContent = fmt(new Date()); } setInterval(widgetTick, 1000); diff --git a/tests/test_widgets.py b/tests/test_widgets.py new file mode 100644 index 0000000..adeca85 --- /dev/null +++ b/tests/test_widgets.py @@ -0,0 +1,11 @@ +import pytest + +from src.views import dashboard + + +@pytest.mark.anyio +async def test_dashboard_renders_repo_mix_placeholder_before_javascript_runs(): + html = await dashboard() + server_rendered_html = html.split("