ed399cec6c
fix-issue/next-issue had unresolved placeholders (<dein Testkommando>, <owner>/<repo>) and no explicit branch-creation step, so a run that skipped the CLAUDE.md convention could commit straight to main. Adds a CI-gate before setting ai-review (actions_run_read against the existing .gitea/workflows/ci.yml) instead of trusting self-reported test results, plus a /work-queue command to chain next-issue -> fix-issue. dev.bundle is Vaadin-regenerated and was tracked+dirty, so every autofix commit would have swept in unrelated binary diffs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0114SVTvBYjLBt3TTxhzJttd
57 lines
6.2 KiB
Markdown
57 lines
6.2 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Commands
|
||
|
||
```bash
|
||
./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, via `e2e/PlaywrightTestBase`. Slow (~1 min). Playwright downloads its browsers into `~/.cache/ms-playwright` on 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.:
|
||
```bash
|
||
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 options `Map` to JSON via Jackson and calls `renderChart` client-side, and exposes point-click events back to the server via `@ClientCallable`.
|
||
- `AxisChart` (abstract) — builds `series`/`xaxis.categories` options for line/bar.
|
||
- `LineChart`, `BarChart` extend `AxisChart`; `PieChart` extends `ApexChart` directly (`series`/`labels` instead of axis-based).
|
||
- `DialectTheme` — single source of chart styling (categorical color palette, grid/legend/stroke option fragments). Every chart's `setData(...)` starts from `DialectTheme.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](https://gridstack.js.org) 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 `GridStackItem`s 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-ready` bearbeiten.
|
||
- 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-blocked` setzen.
|
||
- PR-Beschreibung MUSS `Closes #<nr>` enthalten.
|
||
- Keine Änderungen an kritischen Pfaden ohne Freigabe: `pom.xml`, `mvnw`/`mvnw.cmd`,
|
||
`.mvn/`, `.gitea/workflows/`, `.gitignore`.
|