diff --git a/dashboard/src/index.md b/dashboard/src/index.md index df80e1e..e022303 100644 --- a/dashboard/src/index.md +++ b/dashboard/src/index.md @@ -239,6 +239,16 @@ function _workstreamsForMode(mode, rows) { const _savedChartMode = _MODE_VALUES.has(globalThis.__stateHubOverviewChartMode) ? globalThis.__stateHubOverviewChartMode : "active"; +const _chartModeState = Mutable(_savedChartMode); + +function _setChartMode(value) { + const mode = _modeValue(value); + globalThis.__stateHubOverviewChartMode = mode; + _chartModeState.value = mode; +} +``` + +```js const _modeSelect = html``; -_modeSelect.value = _savedChartMode; +_modeSelect.value = _modeValue(_chartModeState); _modeSelect.addEventListener("input", () => { - globalThis.__stateHubOverviewChartMode = _modeSelect.value; + _setChartMode(_modeSelect.value); }); _modeSelect.addEventListener("change", () => { - globalThis.__stateHubOverviewChartMode = _modeSelect.value; + _setChartMode(_modeSelect.value); }); - -// view() is the idiomatic Observable Framework reactive input: -// it displays the element AND returns a reactive value that re-runs dependent blocks. -const _chartMode = _modeValue(view(_modeSelect)); +display(_modeSelect); ``` ```js import * as Plot from "npm:@observablehq/plot"; -const _chartWsFiltered = _workstreamsForMode(_chartMode, wsAll); +const _chartModeValue = _modeValue(_chartModeState); +const _chartWsFiltered = _workstreamsForMode(_chartModeValue, wsAll); // Sort by domain, then repository, then most recently updated workstream. // The axis labels show each domain/repo group once. @@ -278,7 +286,7 @@ const chartWs = [..._chartWsFiltered].sort((a, b) => { // ── Status weight: bold for notable statuses in mixed-status modes ───────────── // Color is NOT used for status — avoids green-on-green when finished bars fill the row. -const _isTimeBased = !_STATUS_MODES.has(_chartMode) && !_HEALTH_MODES.has(_chartMode); +const _isTimeBased = !_STATUS_MODES.has(_chartModeValue) && !_HEALTH_MODES.has(_chartModeValue); function _wsWeight(s) { return (isClosedWorkstream(s) || normalizeWorkstreamStatus(s) === "blocked") ? "bold" : "normal"; } // ── y-axis: domain/repo label for first workstream per repository only ──────── @@ -330,7 +338,7 @@ if (chartWs.length === 0) { week: "No workstreams changed this week.", month: "No workstreams changed this month.", }; - display(html`

${_emptyMsg[_chartMode] ?? "No workstreams."}

`); + display(html`

${_emptyMsg[_chartModeValue] ?? "No workstreams."}

`); } else { display(Plot.plot({ y: { diff --git a/workplans/STATE-WP-0057-overview-workstream-stage-counts.md b/workplans/STATE-WP-0057-overview-workstream-stage-counts.md index a4396b2..b6e429c 100644 --- a/workplans/STATE-WP-0057-overview-workstream-stage-counts.md +++ b/workplans/STATE-WP-0057-overview-workstream-stage-counts.md @@ -243,8 +243,10 @@ accurate workstream counts for all mode groups. `_chartWsFiltered` was computed in the same cell as `view(_modeSelect)`. Moving `_chartWsFiltered = _workstreamsForMode(_chartMode, wsAll)` into the downstream chart cell restored filtering when operators choose a mode other - than `active`. Added a `change` listener alongside `input` for persisted mode - selection. `npm run test` and `npm run build` both passed after the fix. + than `active`. A second pass kept `_chartMode` as the raw reactive view value + and normalizes it inside the downstream chart cell before filtering and empty + state selection. Added a `change` listener alongside `input` for persisted + mode selection. `npm run test` and `npm run build` both passed after the fix. - Browser click-through remains pending because the Codex in-app browser bridge failed to start in this session with a Windows sandbox setup failure, and no local Playwright/Puppeteer package is installed for a headless fallback.