fix(web): metrics dashboard SoC chart text freezes on first-load value#4308
fix(web): metrics dashboard SoC chart text freezes on first-load value#4308chalfontchubby wants to merge 2 commits into
Conversation
The battery SoC doughnut chart's center text (percentage and kWh figures) is drawn by a Chart.js afterDraw plugin registered once in mdInitSOCChart. That plugin closed over the pct/d values from the moment the chart was first created. On each 30s refresh, mdUpdateSOCChart only mutates the existing chart's data array and calls .update() - it never recreates the chart (mdRenderAll only calls mdInitSOCChart again if mdSocChart doesn't exist yet) - so the doughnut ring's fill proportion updated correctly but the on-screen number text stayed frozen at the first-load reading, while every other card on the page (Health, Cost, API, Solar) re-renders fresh from the latest data on every refresh. Fixes springfall2008#4151. The afterDraw plugin now reads chart.data.datasets[0].data[0] for the percentage (already correctly updated by mdUpdateSOCChart) and the MD_DATA global for the kWh figures (already correctly reassigned on every refresh), instead of the stale closed-over values. No JS execution/browser test infra exists in this codebase, so this can't run the embedded JavaScript and check actual canvas output. Added a structural test instead, checking the generated JS source itself reads from chart.data/MD_DATA rather than the closure parameters, to catch a regression back to the same bug shape. 🤖 Implemented with Claude Code, disclosed per repo convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes the Metrics Dashboard battery SoC doughnut chart center text not updating on periodic refresh by removing stale closure-captured values in the Chart.js afterDraw plugin and instead reading live values from the chart dataset and current MD_DATA. Adds a regression test that inspects the generated JS source to ensure the live-data reads are present, and wires the test into the unit test runner.
Changes:
- Update the Chart.js
afterDrawplugin to read the live percentage fromchart.data.datasets[0].data[0]and kWh figures fromMD_DATA. - Add a unit test that validates the generated dashboard JS references live data sources (rather than closure variables).
- Register the new test in
apps/predbat/unit_test.py.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apps/predbat/web_metrics_dashboard.py | Updates the SoC chart center-text drawing logic to read live values on refresh. |
| apps/predbat/unit_test.py | Registers the new metrics-dashboard SoC refresh regression test. |
| apps/predbat/tests/test_metrics_dashboard_soc_refresh.py | Adds a source-based regression test to prevent reintroducing the stale-closure bug shape. |
| assert "chart.data.datasets[0].data[0]" in plugin_block, "afterDraw should read the live percentage from the chart's own current data, not a closed-over value" | ||
| assert "MD_DATA.battery_soc_kwh" in plugin_block, "afterDraw should read the live kWh figure from the MD_DATA global, not a closed-over value" |
There was a problem hiding this comment.
Fixed — added assertions that the pre-fix stale-closure reads (mdFmt(pct,, d.battery_soc_kwh, d.battery_max_kwh) are gone from the plugin block, not just that the new reads are present. Verified it actually catches a partial revert: temporarily reintroduced just the pct half of the original bug and confirmed the new assertion fails where the old test wouldn't have.
…the new reads present Copilot review on springfall2008#4308: the test only checked the new live-data reads (chart.data.datasets[0].data[0], MD_DATA.battery_soc_kwh) were present, not that the old closed-over reads (pct, d.battery_soc_kwh/battery_max_kwh) were actually removed - a partial revert of either half would still pass. Verified by temporarily reintroducing just the pct half of the original bug: the new assertion catches it, the old test wouldn't have. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
Fixes #4151. The battery SoC doughnut chart's center text (percentage and kWh figures) is drawn by a Chart.js
afterDrawplugin registered once inmdInitSOCChart. That plugin closed over thepct/dvalues from the moment the chart was first created. On each 30s refresh,mdUpdateSOCChartonly mutates the existing chart's data array and calls.update()- it never recreates the chart (mdRenderAllonly callsmdInitSOCChartagain ifmdSocChartdoesn't exist yet) - so the doughnut ring's fill proportion updated correctly but the on-screen number text stayed frozen at the first-load reading, while every other card on the page (Health, Cost, API, Solar) re-renders fresh from the latest data on every refresh.Split out from #4288, which originally bundled this with two unrelated fixes.
Changes
apps/predbat/web_metrics_dashboard.py: theafterDrawplugin now readschart.data.datasets[0].data[0]for the percentage (already correctly updated bymdUpdateSOCChart) and theMD_DATAglobal for the kWh figures (already correctly reassigned on every refresh), instead of the stale closed-over values.apps/predbat/tests/test_metrics_dashboard_soc_refresh.py: no JS execution/browser test infra exists in this codebase, so this checks the generated JS source itself reads fromchart.data/MD_DATArather than the closure parameters, to catch a regression back to the same bug shape.Test plan
./run_all --test metrics_dashboard_soc_refresh- new test passes./run_all --quick- full quick suite passes (611 tests, 0 failures)./run_pre_commit- clean (ruff, black, cspell, markdownlint)🤖 Implemented with Claude Code, disclosed per repo convention.