From 9de093725f559b9c0bc845eaed0d02a0f3cb8fe4 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Sun, 19 Apr 2026 19:18:18 +0100 Subject: [PATCH] Clarify dashboard workload and trend states Refs #1429 --- .../features/dashboardOverview/KPIStrip.tsx | 3 +++ .../features/dashboardOverview/TrendCharts.tsx | 16 ++++++++++++++-- .../__tests__/KPIStrip.test.tsx | 18 ++++++++++-------- .../__tests__/TrendCharts.test.tsx | 16 +++++++++++++++- .../__tests__/dashboardKpiPresentation.test.ts | 1 + .../src/utils/dashboardKpiPresentation.ts | 2 ++ 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/frontend-modern/src/features/dashboardOverview/KPIStrip.tsx b/frontend-modern/src/features/dashboardOverview/KPIStrip.tsx index af3877c91..541c0e838 100644 --- a/frontend-modern/src/features/dashboardOverview/KPIStrip.tsx +++ b/frontend-modern/src/features/dashboardOverview/KPIStrip.tsx @@ -85,6 +85,9 @@ export function KPIStrip(props: KPIStripProps) {

{props.workloads.total}

+

+ {workloadsPresentation.supportingText} +

{props.workloads.running} diff --git a/frontend-modern/src/features/dashboardOverview/TrendCharts.tsx b/frontend-modern/src/features/dashboardOverview/TrendCharts.tsx index 581465d66..26816aeb8 100644 --- a/frontend-modern/src/features/dashboardOverview/TrendCharts.tsx +++ b/frontend-modern/src/features/dashboardOverview/TrendCharts.tsx @@ -40,6 +40,14 @@ function normalizeRange(range: HistoryTimeRange): SummaryTimeRange { export function TrendCharts(props: TrendChartsProps) { const selectedRange = createMemo(() => normalizeRange(props.trendRange())); + const emptyStateTitle = createMemo(() => + props.overview.infrastructure.total > 0 ? 'History is warming up' : 'No infrastructure trends yet', + ); + const emptyStateBody = createMemo(() => + props.overview.infrastructure.total > 0 + ? 'Pulse needs a couple of CPU and memory samples from connected infrastructure before these charts render.' + : 'These charts appear after connected systems start reporting infrastructure CPU and memory history.', + ); const cpuSeries = createMemo(() => { const resources = props.overview.infrastructure.topCPU.slice(0, 5); @@ -125,8 +133,12 @@ export function TrendCharts(props: TrendChartsProps) { -

- {props.trends.infrastructure.emptyMessage} +
+

{emptyStateTitle()}

+

{emptyStateBody()}

+

+ {props.trends.infrastructure.emptyMessage} +

diff --git a/frontend-modern/src/features/dashboardOverview/__tests__/KPIStrip.test.tsx b/frontend-modern/src/features/dashboardOverview/__tests__/KPIStrip.test.tsx index fdd98efc9..0b65fe14d 100644 --- a/frontend-modern/src/features/dashboardOverview/__tests__/KPIStrip.test.tsx +++ b/frontend-modern/src/features/dashboardOverview/__tests__/KPIStrip.test.tsx @@ -3,18 +3,20 @@ import { render, screen } from '@solidjs/testing-library'; import { KPIStrip } from '../KPIStrip'; describe('KPIStrip', () => { - it('renders alert summary counts', () => { + it('keeps the workloads card explicitly discoverable for containers, VMs, and pods', () => { render(() => ( )); - expect(screen.getByText('Alerts')).toBeInTheDocument(); - expect(screen.getByText('5')).toBeInTheDocument(); - expect(screen.getByText(/critical ·/)).toBeInTheDocument(); + const workloadsLink = screen.getByRole('link', { name: /workloads/i }); + expect(workloadsLink.getAttribute('href')).toBe('/workloads'); + expect(screen.getByText('VMs, containers, and pods')).toBeInTheDocument(); + expect(screen.getByText('28')).toBeInTheDocument(); + expect(screen.getByText(/running/i)).toBeInTheDocument(); }); }); diff --git a/frontend-modern/src/features/dashboardOverview/__tests__/TrendCharts.test.tsx b/frontend-modern/src/features/dashboardOverview/__tests__/TrendCharts.test.tsx index 371db1704..7b832d523 100644 --- a/frontend-modern/src/features/dashboardOverview/__tests__/TrendCharts.test.tsx +++ b/frontend-modern/src/features/dashboardOverview/__tests__/TrendCharts.test.tsx @@ -61,6 +61,15 @@ describe('TrendCharts', () => { const [range, setRange] = createSignal('1h'); render(() => ( { emptyMessage: 'Gathering first sample…', }, })} - overview={makeOverview()} trendRange={range} setTrendRange={setRange} /> )); + expect(screen.getByText('History is warming up')).toBeTruthy(); + expect( + screen.getByText( + 'Pulse needs a couple of CPU and memory samples from connected infrastructure before these charts render.', + ), + ).toBeTruthy(); expect(screen.getByText('Gathering first sample…')).toBeTruthy(); }); }); diff --git a/frontend-modern/src/utils/__tests__/dashboardKpiPresentation.test.ts b/frontend-modern/src/utils/__tests__/dashboardKpiPresentation.test.ts index 69a8bc081..fbc567a6f 100644 --- a/frontend-modern/src/utils/__tests__/dashboardKpiPresentation.test.ts +++ b/frontend-modern/src/utils/__tests__/dashboardKpiPresentation.test.ts @@ -8,6 +8,7 @@ describe('dashboardKpiPresentation', () => { }); expect(getDashboardKpiPresentation('workloads')).toMatchObject({ label: 'Workloads', + supportingText: 'VMs, containers, and pods', }); expect(getDashboardKpiPresentation('storage')).toMatchObject({ label: 'Storage', diff --git a/frontend-modern/src/utils/dashboardKpiPresentation.ts b/frontend-modern/src/utils/dashboardKpiPresentation.ts index 8e0dcfaab..877cd3e7e 100644 --- a/frontend-modern/src/utils/dashboardKpiPresentation.ts +++ b/frontend-modern/src/utils/dashboardKpiPresentation.ts @@ -8,6 +8,7 @@ export type DashboardKpiKey = 'infrastructure' | 'workloads' | 'storage' | 'aler export interface DashboardKpiPresentation { label: string; + supportingText?: string; cardClassName: string; iconClassName: string; icon: Component<{ class?: string }>; @@ -23,6 +24,7 @@ const DASHBOARD_KPI_PRESENTATION: Record