DashboardView and GridStackView rendered the same three charts from the
same hardcoded data, so every chart factory method existed twice. The
dashboard is now the GridStackLayout variant at @Route(""):
- GridStackView deleted, its grid/toolbar/chart factories moved into
DashboardView, which keeps the point-click notifications the old
dashboard had.
- Charts size to their widget (100%/100%) instead of a fixed 400px.
- MainLayout has one dashboard entry; nav.gridstack/page.gridstack keys
dropped from all three bundles.
- Storage key is "dashboard" (was "gridstack-demo"), so a saved layout
from the old route is not reused.
- GridStackViewTest renamed to DashboardViewTest, plus a test asserting
the three charts render.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0124BiJikbhbiEsNfJxdWM69
6.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
./mvnw spring-boot:run # run app (default goal) — http://localhost:8080, ~30s first start
./mvnw compile # compile only
./mvnw package # production build → target/*.jar
java -jar target/*.jar # run production jar
./mvnw test # run all tests
Tests live in two flavours, both run by surefire (*Test):
views/*Test— browserless (browserless-test-spring): the Vaadin UI is built server-side and asserted on the component tree, no browser. Fast (seconds).e2e/*PlaywrightTest— real headless Chromium (com.microsoft.playwright:playwright) against the app on a random port, viae2e/PlaywrightTestBase. Slow (~1 min). Playwright downloads its browsers into~/.cache/ms-playwrighton first run; if that fails (offline runner, missing system libs) the tests are skipped via a JUnit assumption instead of failing the build.
E2E assertions match the English captions: German is the unsuffixed fallback bundle (translations.properties), so de is not a provided locale and Vaadin serves translations_en.properties for a German browser. PlaywrightTestBase pins the context locale to en-US to make that explicit.
Java 25 toolchain required (pom.xml sets java.version=25). If the default JDK on PATH is older (check java -version), point JAVA_HOME at a Java 25 install for the Maven build, e.g.:
JAVA_HOME="/path/to/jdk-25" ./mvnw compile
Port 8080 conflicts: a prior spring-boot:run left running in the background is the usual cause (Vaadin dev mode keeps a second process/thread alive under a different PID than the launching Maven process — killing the Maven process alone may not free the port). Find and stop the actual listener before restarting.
Architecture
Vaadin Flow (server-side Java UI, no hand-written HTML/JS for views) on Spring Boot 4.1, using the Aura theme (not Lumo — no @Theme annotation; Aura is wired via @StyleSheet(Aura.STYLESHEET) in Application.java).
Charts are ApexCharts, not Vaadin Charts. The bridge lives in components/:
ApexChart(abstract,@Tag("apex-chart")) — owns the JS module (frontend/components/apex-chart.ts, a Lit element rendering into light DOM), serializes an optionsMapto JSON via Jackson and callsrenderChartclient-side, and exposes point-click events back to the server via@ClientCallable.AxisChart(abstract) — buildsseries/xaxis.categoriesoptions for line/bar.LineChart,BarChartextendAxisChart;PieChartextendsApexChartdirectly (series/labelsinstead of axis-based).DialectTheme— single source of chart styling (categorical color palette, grid/legend/stroke option fragments). Every chart'ssetData(...)starts fromDialectTheme.baseOptions(chartType)and merges in its data. Add new chart types here, not by duplicating option maps.
Since apex-chart.ts renders into light DOM (createRenderRoot() returns this), global CSS can reach into the chart markup — but series/legend/grid colors are driven entirely by the options JSON, not CSS, because ApexCharts renders its own SVG/canvas.
GridStackLayout/GridStackItem (components/) wrap gridstack.js 13.1.0 for draggable/resizable grids. Unlike ApexChart, the bridge (frontend/components/grid-stack.ts) is a plain HTMLElement, not a Lit component — its children are server-rendered GridStackItems living in light DOM, and a Lit render root would fight gridstack for ownership of them. A MutationObserver calls makeWidget/removeWidget as Flow adds/removes children, so there's no explicit add/remove protocol to the client. Every GridStackItem needs a stable gs-id (auto-generated if not given) — GridStackLayout.setStorageKey(...) persists drag/resize state to browser localStorage keyed on it and restores by matching ids, so items lose their saved position if their id changes between reloads. Item styling (.grid-stack-item-content) extends the --dialect-* alias layer in styles.css, same as .dialect-card.
Views (views/): MainLayout (@Layout, applies to all routes) is the AppLayout shell — navbar + SideNav drawer, with one SideNavItem per route. Routes: DashboardView (@Route("")) puts each chart in a Card (components/Card.java) inside a GridStackItem of a GridStackLayout, so widgets are draggable/resizable and the layout is persisted to localStorage; charts use width: 100% / height: 100% to fill their widget rather than a fixed pixel height; FormView (@Route("formular")) demonstrates form controls bound via Binder; TableView (@Route("tabelle")) demonstrates a Grid over dummy data with a live text filter (GridListDataView.addFilter, TextField in ValueChangeMode.EAGER). New views should reuse Card to wrap their content rather than adding components directly, and get a matching SideNavItem in MainLayout.
Styling: src/main/resources/META-INF/resources/styles.css is the one project-level stylesheet (loaded via @StyleSheet("styles.css") in Application.java). It defines --dialect-* design tokens (Dialect design system: primary orange #E86C00, cool-gray background, card radius/shadow) and aliases them onto Aura's own CSS custom properties (--aura-accent-color-*, --aura-background-color-*, --aura-orange, --aura-yellow) rather than fighting the theme. Aura tokens use OKLCH + relative-color syntax and accept plain hex overrides. When restyling, prefer extending this alias layer over hardcoding new colors in components.
UI copy/data (chart labels, notifications) is in German.
AI-Autofix – Regeln
- Nur Issues mit Label
ai-readybearbeiten. - Branch-Namensschema:
ai/issue-<nr>-<kurz-slug>. - Kein Fix ohne grüne Tests. Test-Befehl:
./mvnw test. - Bei Unklarheit / Scope > ~200 Zeilen Diff: NICHT fixen,
stattdessen Issue kommentieren ("needs human") und Label
ai-blockedsetzen. - PR-Beschreibung MUSS
Closes #<nr>enthalten. - Keine Änderungen an <kritische Pfade, z.B. build config, Migrations> ohne Freigabe.