feat: data service layer for chart widgets (#20) #34

Merged
pitfriedrich merged 1 commits from ai/issue-20-chart-data-service into main 2026-07-28 18:22:25 +00:00
Collaborator

Closes #20

What

Adds a thin data layer between the dashboard and its widgets, so the numbers no longer live as literals in the view.

New package com.example.data:

  • ChartSeries(nameKey, values, categoryKeys) — one named series plus its categories. Defensive copies, and the constructor rejects a mismatched value/category count.
  • KpiData(id, labelKey, deltaPercent, trend) — the numbers behind a KPI tile. valueKey() derives the pre-formatted display value's bundle key.
  • ChartDataService — interface with revenueByMonth(), revenueByRegion(), kpis().
  • InMemoryChartDataService@Service, returns exactly the numbers the view used to hold.

DashboardView takes the service via constructor injection, lays the KPI tiles out from kpis() (i * 3 reproduces the previous x positions), and feeds line/bar from one shared revenueByMonth() instead of two copies of the same list.

Design note: translation keys, not text

The records carry bundle keys (month.jan, kpi.revenueTotal), not display strings. Category and series labels are locale-dependent, and resolving them needs a UI — keeping that in the view is what makes the service testable as plain Java, per the acceptance criteria. The view resolves them with a small translate(List<String>) helper.

The grid id of a KPI tile now comes from KpiData.id() (kpi-revenue, kpi-orders, …) — unchanged values, so layouts already saved in localStorage still match.

Tests

  • New InMemoryChartDataServiceTest: no Spring context, no Vaadin UI — values/categories, unique kpi- ids, value-key derivation, immutability and the balance check.
  • Existing DashboardViewTest passes unchanged (same eight widgets, same tile geometry, same three charts), which is the "renders identically" check.

Unrelated fix included

DashboardChartPlaywrightTest.dataUpdate_keepsTheRenderedSvgInPlace was already red on main (verified by stashing this branch's changes). Since the KPI tiles landed, the first apex-chart in the DOM is a sparkline, which has no xaxis.categories; the test's axis-chart patch was therefore a structural change, and updateOptions(..., redrawPaths=true) legitimately recreated the SVG. The test now targets apex-chart:not(.dialect-sparkline). No production JS/Java changed for this.

./mvnw test green (30 tests, incl. Playwright e2e).

Closes #20 ## What Adds a thin data layer between the dashboard and its widgets, so the numbers no longer live as literals in the view. New package `com.example.data`: - **`ChartSeries(nameKey, values, categoryKeys)`** — one named series plus its categories. Defensive copies, and the constructor rejects a mismatched value/category count. - **`KpiData(id, labelKey, deltaPercent, trend)`** — the numbers behind a KPI tile. `valueKey()` derives the pre-formatted display value's bundle key. - **`ChartDataService`** — interface with `revenueByMonth()`, `revenueByRegion()`, `kpis()`. - **`InMemoryChartDataService`** — `@Service`, returns exactly the numbers the view used to hold. `DashboardView` takes the service via constructor injection, lays the KPI tiles out from `kpis()` (`i * 3` reproduces the previous x positions), and feeds line/bar from one shared `revenueByMonth()` instead of two copies of the same list. ## Design note: translation keys, not text The records carry **bundle keys** (`month.jan`, `kpi.revenueTotal`), not display strings. Category and series labels are locale-dependent, and resolving them needs a `UI` — keeping that in the view is what makes the service testable as plain Java, per the acceptance criteria. The view resolves them with a small `translate(List<String>)` helper. The grid id of a KPI tile now comes from `KpiData.id()` (`kpi-revenue`, `kpi-orders`, …) — unchanged values, so layouts already saved in `localStorage` still match. ## Tests - New `InMemoryChartDataServiceTest`: no Spring context, no Vaadin UI — values/categories, unique `kpi-` ids, value-key derivation, immutability and the balance check. - Existing `DashboardViewTest` passes unchanged (same eight widgets, same tile geometry, same three charts), which is the "renders identically" check. ## Unrelated fix included `DashboardChartPlaywrightTest.dataUpdate_keepsTheRenderedSvgInPlace` was **already red on `main`** (verified by stashing this branch's changes). Since the KPI tiles landed, the first `apex-chart` in the DOM is a sparkline, which has no `xaxis.categories`; the test's axis-chart patch was therefore a structural change, and `updateOptions(..., redrawPaths=true)` legitimately recreated the SVG. The test now targets `apex-chart:not(.dialect-sparkline)`. No production JS/Java changed for this. `./mvnw test` green (30 tests, incl. Playwright e2e).
claude-bot added 1 commit 2026-07-28 18:19:40 +00:00
fix: pull dashboard widget data from a ChartDataService (#20)
CI / build-and-test (pull_request) Successful in 2m32s
b341b2ed5d
Chart and KPI numbers were literals in DashboardView, duplicated between
the line and bar chart, and only existed at construction time. Add a thin
data layer as the seam for later refresh/filter work:

- ChartSeries / KpiData records, immutable, carrying translation keys
  rather than display text so the data layer stays free of a UI locale.
- ChartDataService interface plus an in-memory implementation returning
  the previous hardcoded numbers, so nothing changes visually.
- DashboardView injects the service, lays out the KPI tiles from its
  list (grid ids come from the data, so saved layouts still match), and
  resolves the keys against the bundle.

Also fixes DashboardChartPlaywrightTest, red on main since the KPI tiles
landed: it patched the first apex-chart, which is now a sparkline with no
xaxis.categories, so the axis-chart patch was a structural change and
legitimately redrew the SVG. It now targets an axis chart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0124BiJikbhbiEsNfJxdWM69
pitfriedrich merged commit 03872a9d0c into main 2026-07-28 18:22:25 +00:00
pitfriedrich deleted branch ai/issue-20-chart-data-service 2026-07-28 18:22:26 +00:00
Sign in to join this conversation.