From 0dc85e8261f6d924977f70cdf0e0119cd73d81e6 Mon Sep 17 00:00:00 2001 From: iris Date: Wed, 10 Jun 2026 00:55:28 +0200 Subject: [PATCH] fix(frontend): flag gone-agent columns in the schedules table (#1586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The schedules table builds a column per target, including agents that have since been destroyed (their past schedules linger). Those columns showed identically to live agents, so the operator couldn't tell a schedule still targets something that no longer exists. Flag them: renderSchedulesTableHead now checks each agent column against the live roster (containersState) and, for any that isn't there (and isn't 'operator', which is always valid), greys + strikes through the column label and titles it 'no longer exists (gone)'. The rows stay visible + cancellable — the operator can see the stale targets and clear them rather than be surprised by phantom columns. Build green. --- frontend/packages/dashboard/src/dashboard.css | 8 ++++++++ frontend/packages/dashboard/src/schedules.js | 11 +++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index a0d0e04c..dc5dd382 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -1181,6 +1181,14 @@ footer .banner-thin { display: inline-block; padding: 0 4px 1px; } +/* Column for an agent no longer in the live roster — its past schedules + linger but the agent is gone. Greyed + struck through so the operator + can still see (and cancel) the stale entries rather than be surprised. */ +.schedules-table-agent-th--gone > div { + color: var(--muted); + text-decoration: line-through; + opacity: 0.75; +} .schedules-table-row-cancelled td { opacity: 0.55; } .schedules-table-body-cell { max-width: 30em; diff --git a/frontend/packages/dashboard/src/schedules.js b/frontend/packages/dashboard/src/schedules.js index 7b2eabb3..b396f4d8 100644 --- a/frontend/packages/dashboard/src/schedules.js +++ b/frontend/packages/dashboard/src/schedules.js @@ -619,9 +619,16 @@ function renderSchedulesTableHead(agents) { el('th', {}, 'owner'), el('th', { class: 'schedules-table-body-th' }, 'body'), ); + // 'operator' is always a valid target; every other column maps to a + // container, so flag any column whose agent is no longer in the live + // roster — its past schedules linger in the table but the agent is gone. + const liveNames = new Set(Array.from(containersState.values()).map((c) => c.name)); for (const a of agents) { - headerRow.append(el('th', { class: 'schedules-table-agent-th', title: a }, - el('div', {}, el('span', {}, a)))); + const gone = a !== 'operator' && !liveNames.has(a); + headerRow.append(el('th', { + class: 'schedules-table-agent-th' + (gone ? ' schedules-table-agent-th--gone' : ''), + title: gone ? a + ' — no longer exists (gone)' : a, + }, el('div', {}, el('span', {}, a)))); } headerRow.append(el('th', { class: 'schedules-table-actions-th' }, '')); thead.append(headerRow);