summaryrefslogtreecommitdiff
path: root/web/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/app.js')
-rw-r--r--web/app.js42
1 files changed, 42 insertions, 0 deletions
diff --git a/web/app.js b/web/app.js
index bca41fa..a7c18b6 100644
--- a/web/app.js
+++ b/web/app.js
@@ -339,6 +339,46 @@ export function setTaskFilterTab(tab) {
localStorage.setItem('taskFilterTab', tab);
}
+// ── Tab badge counts ───────────────────────────────────────────────────────────
+
+/**
+ * Computes badge counts for the 'interrupted', 'ready', and 'running' tabs.
+ * Returns { interrupted: N, ready: N, running: N }.
+ */
+export function computeTabBadgeCounts(tasks) {
+ let interrupted = 0;
+ let ready = 0;
+ let running = 0;
+ for (const t of tasks) {
+ if (INTERRUPTED_STATES.has(t.state)) interrupted++;
+ if (t.state === 'READY') ready++;
+ if (t.state === 'RUNNING') running++;
+ }
+ return { interrupted, ready, running };
+}
+
+/**
+ * Updates the badge count spans inside the tab buttons for
+ * 'interrupted', 'ready', and 'running'.
+ * Badge is hidden (display:none) when count is zero.
+ */
+export function updateTabBadges(tasks, doc = (typeof document !== 'undefined' ? document : null)) {
+ if (!doc) return;
+ const counts = computeTabBadgeCounts(tasks);
+ for (const [tab, count] of Object.entries(counts)) {
+ const btn = doc.querySelector(`.tab[data-tab="${tab}"]`);
+ if (!btn) continue;
+ let badge = btn.querySelector('.tab-count-badge');
+ if (!badge) {
+ badge = doc.createElement('span');
+ badge.className = 'tab-count-badge';
+ btn.appendChild(badge);
+ }
+ badge.textContent = String(count);
+ badge.hidden = count === 0;
+ }
+}
+
// ── Stats computations ─────────────────────────────────────────────────────────
/**
@@ -961,6 +1001,8 @@ async function poll() {
const tasks = await fetchTasks();
if (isUserEditing()) return;
+ updateTabBadges(tasks);
+
const activeTab = getActiveTab();
switch (activeTab) {
case 'queue':