@micha.bigler/ui-core-micha 2.26.4 → 2.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +2 -1
- package/WORK_ORDERS.md +5 -0
- package/dist/components/PasswordChangeForm.js +14 -4
- package/dist/components/PasswordSetForm.js +10 -2
- package/dist/components/charts/TimeSeriesChart.js +44 -4
- package/dist/i18n/authTranslations.js +93 -0
- package/dist/i18n/notificationsTranslations.js +8 -0
- package/dist/notifications/NotificationSettings.js +48 -3
- package/dist/notifications/api.js +5 -0
- package/package.json +1 -1
- package/src/components/PasswordChangeForm.jsx +26 -1
- package/src/components/PasswordSetForm.jsx +18 -1
- package/src/components/charts/TimeSeriesChart.jsx +47 -5
- package/src/i18n/authTranslations.ts +94 -0
- package/src/i18n/notificationsTranslations.ts +8 -0
- package/src/notifications/NotificationSettings.jsx +95 -0
- package/src/notifications/api.js +6 -0
- package/tests/NotificationSettings.test.jsx +105 -0
- package/tests/PasswordChangeForm.test.jsx +70 -0
- package/tests/PasswordSetForm.test.jsx +70 -0
- package/tests/TimeSeriesChart.test.jsx +81 -9
- package/tests/authErrorCodeRendering.test.jsx +77 -0
- package/tests/authTranslations.test.js +52 -0
- package/work-orders/AUTH-1.md +74 -0
- package/work-orders/AUTH-2.md +74 -0
- package/work-orders/CHART-3.md +163 -0
- package/work-orders/CHART-4.md +203 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# WORK ORDER CHART-4 (ui-core-micha) — TimeSeriesChart renders no chart body (zero height)
|
|
2
|
+
|
|
3
|
+
**EXECUTION DIRECTIVE.** If you are the implementer reading this as your own spec, this section is not
|
|
4
|
+
addressed to you — it tells the Orchestrator how to invoke you; you ARE that invocation, do not shell
|
|
5
|
+
out to `codex exec`. Orchestrator: implement through `codex exec` in the background, invoked **directly
|
|
6
|
+
via Bash** (never the `debugger`/`*_coder` Agent wrappers) with **both** flags `--skip-git-repo-check`
|
|
7
|
+
and `--dangerously-bypass-approvals-and-sandbox`, prompt passed as a positional argument from this
|
|
8
|
+
file. Fall back to direct Claude implementation only on Codex quota / rate-limit / non-zero exit.
|
|
9
|
+
**Known at WO authoring time: the Codex workspace is out of credits for this session — the fallback
|
|
10
|
+
applies immediately, do not spend time retrying `codex exec` first.**
|
|
11
|
+
|
|
12
|
+
Bug-fix WO on CHART-2/CHART-3. Found live in jg-ferien's "Aktivität" screen (ACT-3/ACT-5 consumer)
|
|
13
|
+
immediately after CHART-3 shipped and jg's pin was bumped: the toolbar, series checkboxes, and MUI
|
|
14
|
+
X-Charts **legend** now all render correctly (proving CHART-3's fix works and real data is present),
|
|
15
|
+
but the chart canvas itself — bars and axes — is entirely absent. The card ends right after the
|
|
16
|
+
legend row with visible empty space beneath it.
|
|
17
|
+
|
|
18
|
+
## TIER
|
|
19
|
+
Tier 2 — shared-core UI consumed by every app that adopts `TimeSeriesChart`.
|
|
20
|
+
Independent `reviewer` + `ui_reviewer` mandatory.
|
|
21
|
+
|
|
22
|
+
## WHY
|
|
23
|
+
|
|
24
|
+
`TimeSeriesChart` composes `ChartFrame` + `BarChart` but never supplies either with a height:
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
<ChartFrame title={title} subtitle={subtitle} toolbar={toolbar} loading={loading} error={error} isEmpty={isDataEmpty}>
|
|
28
|
+
{!isDataEmpty && (
|
|
29
|
+
<BarChart xAxisLabel={xAxisLabel} yAxisLabel={yAxisLabel} xAxis={[{ data: data?.xLabels || [] }]}
|
|
30
|
+
series={visibleSeries.map(...)} palette={visiblePalette} />
|
|
31
|
+
)}
|
|
32
|
+
</ChartFrame>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Neither `minHeight`/`aspect` (ChartFrame's own sizing props) nor `minHeight`/`aspect`/a raw MUI
|
|
36
|
+
`height` (BarChart's) are passed. `ChartFrame`'s inner content `Box` has `display: flex, alignItems:
|
|
37
|
+
center, justifyContent: center` with no defined height — with `alignItems: center` (not `stretch`),
|
|
38
|
+
a flex child gets its own intrinsic height, not the parent's. `BarChart`'s own wrapping `Box` (`sx:
|
|
39
|
+
{width:'100%', minHeight, aspectRatio}`) therefore also has no height when neither prop is supplied.
|
|
40
|
+
MUI X-Charts' internal responsive container measures its actual parent height via `ResizeObserver` to
|
|
41
|
+
size the SVG — with a zero-height parent, the chart canvas (bars, axes) renders at zero size. The
|
|
42
|
+
**legend** is a separate MUI X-Charts sub-component sized by its own content (text + swatches), so it
|
|
43
|
+
renders regardless of container height — which is exactly why the legend was the only visible sign
|
|
44
|
+
of a mounted chart in the live screenshot.
|
|
45
|
+
|
|
46
|
+
This gap was invisible until now because CHART-3's own bug (`visibleKeys` never populating) kept
|
|
47
|
+
`isDataEmpty` permanently `true`, so `BarChart` never actually mounted in any live deployment before
|
|
48
|
+
today. It also went uncaught by CHART-2's and CHART-3's own tests: both `tests/BarChart.test.jsx` and
|
|
49
|
+
`tests/TimeSeriesChart.test.jsx` mock `@mui/x-charts/BarChart` itself (`vi.mock('@mui/x-charts/BarChart', ...)`
|
|
50
|
+
per CHART-2's own required-tests convention), so no test in this repo has ever mounted the *real* MUI
|
|
51
|
+
chart and observed its rendered size. The working reference is `dev/entries.jsx`'s `BarChartEntry`
|
|
52
|
+
(DX-1 harness), which explicitly sets `minHeight={360}` on `ChartFrame` and `height={320}` directly
|
|
53
|
+
on `BarChart` — i.e. every other real consumer of these primitives in this repo already knows it must
|
|
54
|
+
supply a height; `TimeSeriesChart`, as a preset built on top, was supposed to supply this itself
|
|
55
|
+
(hosts don't see `ChartFrame`/`BarChart` directly through the preset) and doesn't.
|
|
56
|
+
|
|
57
|
+
## SCOPE
|
|
58
|
+
|
|
59
|
+
**Give `TimeSeriesChart` a sensible built-in height for the chart it composes**, matching the
|
|
60
|
+
DX-1-proven working pattern:
|
|
61
|
+
1. Pass `minHeight` to `ChartFrame` (sizes the loading/error/empty states too, not just the chart).
|
|
62
|
+
2. Pass a height down to `BarChart` so the actual MUI chart canvas gets a real, non-zero pixel size —
|
|
63
|
+
either `BarChart`'s own `minHeight`/`aspect` wrapper props, or a raw `height` forwarded via
|
|
64
|
+
`BarChart`'s `...chartProps` pass-through to `MuiBarChart` (the mechanism `dev/entries.jsx` uses
|
|
65
|
+
directly against `BarChart`, confirmed working there). Pick whichever actually renders a non-zero
|
|
66
|
+
chart canvas when verified (see REQUIRED TESTS) — do not assume `aspectRatio` CSS alone reliably
|
|
67
|
+
drives MUI X-Charts' `ResizeObserver` sizing without checking; the raw `height` prop is the
|
|
68
|
+
confirmed-working mechanism in this repo's own reference usage and is the safer default if there
|
|
69
|
+
is any doubt.
|
|
70
|
+
3. Pick one fixed value (e.g. `320`/`360`, matching `dev/entries.jsx`'s own numbers) as a preset
|
|
71
|
+
default — this is a preset, not a raw primitive; the host does not choose chart height, matching
|
|
72
|
+
`TimeSeriesChart`'s existing "no new props" presentational contract. Do not add a new prop for
|
|
73
|
+
this unless a reviewer specifically asks for one.
|
|
74
|
+
|
|
75
|
+
**This WO's real fix is the test gap, not just the pixels.** The reason this shipped broken twice is
|
|
76
|
+
that every test in this file mocks the real MUI chart component. Required test 1 below must exercise
|
|
77
|
+
the **unmocked** `@mui/x-charts/BarChart` and assert a real rendered size — a mocked-chart test would
|
|
78
|
+
be exactly the kind of vacuous coverage that let this ship.
|
|
79
|
+
|
|
80
|
+
## NON-GOALS / DO NOT TOUCH
|
|
81
|
+
- Do not change the range picker, series toggles, `chartsTranslations`, or the CHART-3 `visibleKeys`
|
|
82
|
+
sync logic — this WO is scoped to sizing only.
|
|
83
|
+
- Do not change `ChartFrame`'s or `BarChart`'s own prop contracts (`minHeight`/`aspect` already exist
|
|
84
|
+
on both) — only how `TimeSeriesChart` calls them.
|
|
85
|
+
- Do not add a new prop to `TimeSeriesChart`'s public API for this — see SCOPE point 3.
|
|
86
|
+
|
|
87
|
+
## RISKS
|
|
88
|
+
- Every host that has adopted `TimeSeriesChart` is affected (currently jg-ferien via ACT-3/ACT-5) —
|
|
89
|
+
this changes rendering behaviour for all of them, in the correct direction (chart canvas now
|
|
90
|
+
actually visible).
|
|
91
|
+
- Getting this wrong a second time (e.g. an `aspectRatio`-only fix that still doesn't reliably drive
|
|
92
|
+
MUI X-Charts' internal measurement) ships a third silent failure in the same component. The
|
|
93
|
+
required unmocked-render test exists specifically to catch that before it reaches a live app again.
|
|
94
|
+
|
|
95
|
+
## REQUIRED TESTS TO WRITE
|
|
96
|
+
Extend `tests/TimeSeriesChart.test.jsx`. Do NOT run the full suite.
|
|
97
|
+
|
|
98
|
+
1. **The real bug's mechanism, not a jsdom layout measurement.** An initial attempt at this WO wrote
|
|
99
|
+
an *unmocked* test (real `@mui/x-charts/BarChart`, no `vi.mock`) asserting the rendered chart
|
|
100
|
+
surface's `viewBox` height was non-zero — verified, in practice, to be **vacuous**: it stayed green
|
|
101
|
+
even with the pre-fix code (no `height` prop anywhere), because jsdom's `ResizeObserver`/layout
|
|
102
|
+
handling does not reproduce the real-browser zero-height-parent behaviour this bug depends on. Do
|
|
103
|
+
not repeat that approach. Instead, keep the existing `chartSpy` mock convention (`vi.hoisted` +
|
|
104
|
+
`vi.mock('@mui/x-charts/BarChart', ...)`, already at `tests/TimeSeriesChart.test.jsx:9-10`) and
|
|
105
|
+
assert directly on the props the real `MuiBarChart` receives: `chartSpy.mock.calls.at(-1)[0].height`
|
|
106
|
+
must be a real, non-zero number. This is what actually distinguishes fixed from broken — confirmed
|
|
107
|
+
by reverting the fix and re-running: the prop assertion fails pre-fix (`props.height` is
|
|
108
|
+
`undefined`), the unmocked viewBox assertion does not.
|
|
109
|
+
2. **Non-vacuity**: this test must fail against the current (pre-fix) code — verify before considering
|
|
110
|
+
the fix complete (see note above — already verified once for the prop-assertion approach).
|
|
111
|
+
3. Existing mocked-`BarChart` tests (range/toggle/empty-state behaviour) stay as they are.
|
|
112
|
+
|
|
113
|
+
## CONTEXT PACKAGE — verified current state (Orchestrator, Implementation map)
|
|
114
|
+
|
|
115
|
+
Work from this package; do not explore broadly from scratch — open only the named files to verify.
|
|
116
|
+
|
|
117
|
+
**File to change: `src/components/charts/TimeSeriesChart.jsx`.**
|
|
118
|
+
|
|
119
|
+
Current return statement (verified, full slice, `:150-169`):
|
|
120
|
+
```jsx
|
|
121
|
+
return (
|
|
122
|
+
<ChartFrame
|
|
123
|
+
title={title}
|
|
124
|
+
subtitle={subtitle}
|
|
125
|
+
toolbar={toolbar}
|
|
126
|
+
loading={loading}
|
|
127
|
+
error={error}
|
|
128
|
+
isEmpty={isDataEmpty}
|
|
129
|
+
>
|
|
130
|
+
{!isDataEmpty && (
|
|
131
|
+
<BarChart
|
|
132
|
+
xAxisLabel={xAxisLabel}
|
|
133
|
+
yAxisLabel={yAxisLabel}
|
|
134
|
+
xAxis={[{ data: data?.xLabels || [] }]}
|
|
135
|
+
series={visibleSeries.map((series) => ({ data: series.data, label: series.label }))}
|
|
136
|
+
palette={visiblePalette}
|
|
137
|
+
/>
|
|
138
|
+
)}
|
|
139
|
+
</ChartFrame>
|
|
140
|
+
);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Reference (working) pattern — `dev/entries.jsx:35-39`:**
|
|
144
|
+
```jsx
|
|
145
|
+
function BarChartEntry() {
|
|
146
|
+
return (
|
|
147
|
+
<ChartFrame title="Monthly cases" subtitle="Standalone BarChart entry" minHeight={360}>
|
|
148
|
+
<BarChart {...barChartFixture} xAxisLabel="Month" yAxisLabel="Cases" height={320} />
|
|
149
|
+
</ChartFrame>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
Note `height={320}` on `BarChart` here is NOT `BarChart`'s own `minHeight`/`aspect` wrapper prop — it
|
|
154
|
+
lands in `BarChart`'s `...chartProps` rest spread (`BarChart.jsx:24,34`) and is forwarded straight to
|
|
155
|
+
`MuiBarChart`'s own native `height` prop, which MUI X-Charts uses as a fixed pixel height instead of
|
|
156
|
+
measuring the parent via `ResizeObserver`. This is the confirmed-working mechanism in this repo.
|
|
157
|
+
|
|
158
|
+
**`ChartFrame.jsx:86-99`** — the content `Box`: `sx={{ width:'100%', minHeight, aspectRatio: aspect,
|
|
159
|
+
display:'flex', alignItems:'center', justifyContent:'center' }}`. `alignItems:'center'` means a flex
|
|
160
|
+
child (here, `BarChart`'s own `Box`) is NOT stretched to fill this Box's height — it keeps its own
|
|
161
|
+
intrinsic height. Passing `minHeight` to `ChartFrame` sizes this outer Box correctly for the
|
|
162
|
+
loading/error/empty `Alert`/`CircularProgress` states (which have no fixed height of their own and
|
|
163
|
+
DO benefit from the flex-centered parent height), but does **not**, by itself, give `BarChart`'s
|
|
164
|
+
child `Box` any height — that must come from `BarChart` itself (its own `minHeight`/`aspect`, or the
|
|
165
|
+
raw `height` chartProp per the reference pattern above).
|
|
166
|
+
|
|
167
|
+
**`BarChart.jsx:15-44`** — full file, already shown above in this WO's WHY section — `minHeight`/
|
|
168
|
+
`aspect` are explicit named props (`:22-23`) applied to `BarChart`'s own wrapping `Box` (`:32`);
|
|
169
|
+
anything else lands in `...chartProps` (`:24`) and is spread onto `MuiBarChart` directly (`:34`),
|
|
170
|
+
which is how a raw `height` reaches the underlying MUI component.
|
|
171
|
+
|
|
172
|
+
**Test file: `tests/TimeSeriesChart.test.jsx`** — already mocks `@mui/x-charts/BarChart` via
|
|
173
|
+
`vi.hoisted` + `vi.mock` (`:9-10`) and every existing test reads `chartSpy.mock.calls.at(-1)[0]` to
|
|
174
|
+
assert exact props (e.g. the `series`/`colors` assertions at `:87-89,94-99`). Add the new test in the
|
|
175
|
+
same style, asserting `props.height` — see REQUIRED TESTS above for why an unmocked render test does
|
|
176
|
+
NOT work here.
|
|
177
|
+
|
|
178
|
+
## TARGET REPO
|
|
179
|
+
`C:\Users\biglmi\Documents\webapps\ui-core-micha`. Branch `main`. Publish per the repo's release
|
|
180
|
+
flow (patch bump — bug fix, no interface change).
|
|
181
|
+
|
|
182
|
+
## TEST SCOPE FOR THE GATE (orchestrator)
|
|
183
|
+
`tests/TimeSeriesChart.test.jsx`. Not the full suite.
|
|
184
|
+
|
|
185
|
+
## MINI-HANDOVER (pastable)
|
|
186
|
+
|
|
187
|
+
> Repo: `C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`).
|
|
188
|
+
> Work order: `work-orders/CHART-4.md` — read it fully, then follow the `orchestrate-codex` skill.
|
|
189
|
+
> **Codex workspace is out of credits this session — go straight to the direct-Claude fallback, do
|
|
190
|
+
> not attempt `codex exec` first.**
|
|
191
|
+
>
|
|
192
|
+
> Second bug in `TimeSeriesChart` (after CHART-3): the chart legend renders but the actual bars/axes
|
|
193
|
+
> never appear because neither `ChartFrame` nor `BarChart` ever receive a height — MUI X-Charts'
|
|
194
|
+
> responsive container measures a zero-height parent and draws nothing. `dev/entries.jsx`'s
|
|
195
|
+
> `BarChartEntry` is the proof this is fixable: `minHeight={360}` on `ChartFrame` + `height={320}`
|
|
196
|
+
> forwarded straight to `BarChart` (MUI's own native height prop, not the wrapper's `minHeight`/
|
|
197
|
+
> `aspect`). The required regression test must NOT mock `@mui/x-charts/BarChart` — every existing test
|
|
198
|
+
> in this component mocks it, which is exactly how two sizing/rendering bugs shipped undetected.
|
|
199
|
+
|
|
200
|
+
## PROGRESS CONTRACT
|
|
201
|
+
Emit `PLAN: <steps>` up front, then a single-line `PROGRESS: [<n>/<total>] <action>` before every
|
|
202
|
+
relevant action and `PROGRESS: [<n>/<total>] done` on completion, spaced so no gap exceeds ~2 min,
|
|
203
|
+
stdout unbuffered, and exactly one final `RESULT: DONE|BLOCKED <reason>`.
|