From b3f0331f157a9311d29950f8537c3d71fb4ffdc9 Mon Sep 17 00:00:00 2001 From: Alex Korin Date: Wed, 29 Apr 2026 20:59:34 +0100 Subject: [PATCH] refactor(frontend): migrate Monitoring view to design-system tokens (#554) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slice 2 of the #554 sweep. Migrates the /monitoring view (Health tab) from raw status colors to semantic tokens. Migrations (all clear status semantics): - Service-active badge (green) - 5 summary cards: healthy / degraded / unhealthy / critical (extra) - Active alerts banner background and heading - Per-alert priority icon (urgent vs warning) - "N issues" count for unhealthy agents - getStatusBgClass / getStatusTextClass / getStatusBadgeClass — all 5 statuses route through status-success / status-warning / status-danger (with 200/700 shades for the "critical" emphasis tier) Deferred (10 raw blue refs remain): - "Auto-refresh" toggle button — selected-state highlight, needs an `action-primary` or `state-selected` token (per #554 caveat) - "Check All" admin primary action button - Per-row "trigger health check" hover/focus styling These are the same categories deferred in #569 (operator queue slice 1). A future PR can introduce `action-*` tokens to cover them across the whole codebase. Tests: - Adds /monitoring smoke spec to e2e/smoke.spec.js (5 → 6 tests) Visual regression baselines for /monitoring will land in a follow-up PR once the cross-platform snapshot capture path is in place (Linux runner font rendering ≠ macOS, so locally captured PNGs would always fail in CI). Refs #554 Co-Authored-By: Claude Opus 4.7 (1M context) --- src/frontend/e2e/smoke.spec.js | 8 +++++ src/frontend/src/views/Monitoring.vue | 52 +++++++++++++-------------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/frontend/e2e/smoke.spec.js b/src/frontend/e2e/smoke.spec.js index aff8e90c2..a8d8224c8 100644 --- a/src/frontend/e2e/smoke.spec.js +++ b/src/frontend/e2e/smoke.spec.js @@ -26,4 +26,12 @@ test.describe('smoke', () => { await page.goto('/templates') await expect(page.getByText(/template/i).first()).toBeVisible({ timeout: 10000 }) }) + + test('monitoring page loads', async ({ page }) => { + await page.goto('/monitoring') + // Header, summary cards, or empty state — any of these confirms the route mounted. + await expect( + page.getByText(/monitoring|fleet|healthy|degraded|no agents/i).first() + ).toBeVisible({ timeout: 10000 }) + }) }) diff --git a/src/frontend/src/views/Monitoring.vue b/src/frontend/src/views/Monitoring.vue index cc2e392b4..47977d813 100644 --- a/src/frontend/src/views/Monitoring.vue +++ b/src/frontend/src/views/Monitoring.vue @@ -17,9 +17,9 @@ - + {{ monitoringStore.enabled ? 'Monitoring Active' : 'Monitoring Disabled' }} @@ -64,28 +64,28 @@
{{ monitoringStore.summary.total_agents }}
Total Agents
-
-
{{ monitoringStore.summary.healthy }}
+
+
{{ monitoringStore.summary.healthy }}
Healthy
-
-
{{ monitoringStore.summary.degraded }}
+
+
{{ monitoringStore.summary.degraded }}
Degraded
-
-
{{ monitoringStore.summary.unhealthy }}
+
+
{{ monitoringStore.summary.unhealthy }}
Unhealthy
-
-
{{ monitoringStore.summary.critical }}
+
+
{{ monitoringStore.summary.critical }}
Critical
-
+
-

+

Active Alerts ({{ monitoringStore.alerts.length }})

@@ -99,7 +99,7 @@
{{ alert.agent_name }} @@ -175,7 +175,7 @@
-
+
{{ agent.issues.length }} issue{{ agent.issues.length > 1 ? 's' : '' }}
@@ -373,30 +373,30 @@ function getStatusIcon(status) { function getStatusBgClass(status) { switch (status) { - case 'healthy': return 'bg-green-100 dark:bg-green-900/30' - case 'degraded': return 'bg-yellow-100 dark:bg-yellow-900/30' - case 'unhealthy': return 'bg-red-100 dark:bg-red-900/30' - case 'critical': return 'bg-red-200 dark:bg-red-900/50' + case 'healthy': return 'bg-status-success-100 dark:bg-status-success-900/30' + case 'degraded': return 'bg-status-warning-100 dark:bg-status-warning-900/30' + case 'unhealthy': return 'bg-status-danger-100 dark:bg-status-danger-900/30' + case 'critical': return 'bg-status-danger-200 dark:bg-status-danger-900/50' default: return 'bg-gray-100 dark:bg-gray-700' } } function getStatusTextClass(status) { switch (status) { - case 'healthy': return 'text-green-600 dark:text-green-400' - case 'degraded': return 'text-yellow-600 dark:text-yellow-400' - case 'unhealthy': return 'text-red-600 dark:text-red-400' - case 'critical': return 'text-red-700 dark:text-red-500' + case 'healthy': return 'text-status-success-600 dark:text-status-success-400' + case 'degraded': return 'text-status-warning-600 dark:text-status-warning-400' + case 'unhealthy': return 'text-status-danger-600 dark:text-status-danger-400' + case 'critical': return 'text-status-danger-700 dark:text-status-danger-500' default: return 'text-gray-500 dark:text-gray-400' } } function getStatusBadgeClass(status) { switch (status) { - case 'healthy': return 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300' - case 'degraded': return 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-700 dark:text-yellow-300' - case 'unhealthy': return 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300' - case 'critical': return 'bg-red-200 dark:bg-red-900/50 text-red-800 dark:text-red-200' + case 'healthy': return 'bg-status-success-100 dark:bg-status-success-900/30 text-status-success-700 dark:text-status-success-300' + case 'degraded': return 'bg-status-warning-100 dark:bg-status-warning-900/30 text-status-warning-700 dark:text-status-warning-300' + case 'unhealthy': return 'bg-status-danger-100 dark:bg-status-danger-900/30 text-status-danger-700 dark:text-status-danger-300' + case 'critical': return 'bg-status-danger-200 dark:bg-status-danger-900/50 text-status-danger-800 dark:text-status-danger-200' default: return 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400' } }