diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-16 00:41:44 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-16 00:41:44 +0000 |
| commit | 908fb8650ce1f295b6047fe95a75ec4aa235b7dc (patch) | |
| tree | 8f97498c91e167d9c94b998175121041e6879398 /web/app.js | |
| parent | b91636be171bc8e43a3dba1b54f78e2048356ab1 (diff) | |
fix: restore running tab rendering and throttle history fetch
- poll() now calls renderActiveTab(cache) on early-return so switching
tabs always renders immediately instead of leaving the panel blank
- renderRunningView unchanged check now requires running.length > 0,
fixing the empty-state message never appearing when no tasks run
- Extract renderActiveTab() to avoid duplicating the tab switch logic
- Throttle execution history fetch to once per 60s (was every poll)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'web/app.js')
| -rw-r--r-- | web/app.js | 79 |
1 files changed, 44 insertions, 35 deletions
@@ -1079,6 +1079,7 @@ let taskCache = new Map(); let lastServerUpdate = null; let pollTimeout = null; let lastUserInteraction = Date.now(); +let lastHistoryFetch = 0; function getActiveTab() { const active = document.querySelector('.tab.active'); @@ -1096,13 +1097,52 @@ async function fetchHealth() { return res.json(); } +function renderActiveTab(allTasks) { + const activeTab = getActiveTab(); + switch (activeTab) { + case 'queue': + renderQueuePanel(allTasks); + break; + case 'interrupted': + renderInterruptedPanel(allTasks); + break; + case 'ready': + renderReadyPanel(allTasks); + break; + case 'running': + renderRunningView(allTasks); + if (Date.now() - lastHistoryFetch > 60_000) { + lastHistoryFetch = Date.now(); + fetchRecentExecutions(BASE_PATH, fetch) + .then(execs => renderRunningHistory(execs)) + .catch(() => { + const histEl = document.querySelector('.running-history'); + if (histEl) histEl.innerHTML = '<p class="task-meta">Could not load execution history.</p>'; + }); + } + break; + case 'all': + renderAllPanel(allTasks); + break; + case 'stats': + fetchRecentExecutions(BASE_PATH, fetch) + .then(execs => renderStatsPanel(allTasks, execs)) + .catch(() => {}); + break; + case 'settings': + renderSettingsPanel(); + break; + } +} + async function poll() { try { const health = await fetchHealth(); const serverUpdate = health.last_updated; - // If server says nothing changed, we skip fetching tasks. + // If server says nothing changed, skip fetching but still render (e.g. tab was just switched). if (lastServerUpdate && serverUpdate <= lastServerUpdate && taskCache.size > 0) { + renderActiveTab(Array.from(taskCache.values())); return; } @@ -1118,39 +1158,7 @@ async function poll() { const allTasks = Array.from(taskCache.values()); updateTabBadges(allTasks); - - const activeTab = getActiveTab(); - switch (activeTab) { - case 'queue': - renderQueuePanel(allTasks); - break; - case 'interrupted': - renderInterruptedPanel(allTasks); - break; - case 'ready': - renderReadyPanel(allTasks); - break; - case 'running': - renderRunningView(allTasks); - fetchRecentExecutions(BASE_PATH, fetch) - .then(execs => renderRunningHistory(execs)) - .catch(() => { - const histEl = document.querySelector('.running-history'); - if (histEl) histEl.innerHTML = '<p class="task-meta">Could not load execution history.</p>'; - }); - break; - case 'all': - renderAllPanel(allTasks); - break; - case 'stats': - fetchRecentExecutions(BASE_PATH, fetch) - .then(execs => renderStatsPanel(allTasks, execs)) - .catch(() => {}); - break; - case 'settings': - renderSettingsPanel(); - break; - } + renderActiveTab(allTasks); } catch (err) { console.error('Polling failed:', err); const panel = document.querySelector('[data-panel="queue"] .panel-task-list'); @@ -2106,7 +2114,8 @@ function renderRunningView(tasks) { // Update elapsed spans in place if the same tasks are still running. const existingCards = currentEl.querySelectorAll('[data-task-id]'); const existingIds = new Set([...existingCards].map(c => c.dataset.taskId)); - const unchanged = running.length === existingCards.length && + const unchanged = running.length > 0 && + running.length === existingCards.length && running.every(t => existingIds.has(t.id)); if (unchanged) { |
