Skip to content

feat(chart): a matrix can read its cells from records (schema 2.124.0, stacked on #1734) - #1747

Closed
rubenvdlinde wants to merge 10 commits into
developmentfrom
feat/matrix-cell-records
Closed

rubenvdlinde wants to merge 10 commits into
developmentfrom
feat/matrix-cell-records

Conversation

@rubenvdlinde

@rubenvdlinde rubenvdlinde commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #1734 (bar-list and matrix chart kinds). This branch contains #1734's commits; review only the last commits, or after #1734 merges, the diff against development. Schema order: #1731 → #1734 → #1736 → #1746 (2.123.0) → this PR (2.124.0) → #1743.

What

The matrix chart kind can read a matrix the app keeps as data, instead of a copy written into the manifest. A manifest copy shows every install the same matrix and drifts from the version the app computes with, and nobody notices. New chart prop cellSource (schema 2.124.0), generic for any app:

  • One record per cell: list register / schema with a token-resolved filter and lay the records out by rowField / columnField, with valueField as the cell.
  • The matrix inside ONE record (cellsPath): read the first record filter finds, or fallbackFilter if it finds none (e.g. { active: true }). Take its array at cellsPath and narrow it with cellFilter, which accepts tokens, e.g. one slice of a matrix over three axes. Take the axis order from rowOrderPath / columnOrderPath on that record.
  • Common to both modes:
    • Labels come from rowLabels / columnLabels maps or rowLabelField / columnLabelField.
    • Order comes from rowOrder / columnOrder lists, else rowOrderField / columnOrderField, else natural order.
    • valueLabels maps a stored value to its text, and colorMap may key on either.
    • Nothing is listed while a filter token is unresolved: a record without matrixVersion shows no matrix, by design, so it never shows a matrix it was not calculated with. fallbackFilter applies only when the filter finds no record.
    • highlight matches the row and column keys.
  • Reuses fetchReferenceObjects for the list. The layout lives in the new utils matrixCells.pivotCells and cellsFromRecord.

The case: board DqHandhaving. Each municipality keeps its enforcement (LHS) matrix in dossiq's lhsMatrix record. The record is picked by version and carries cells[] entries { behaviour, severity, actorType, intervention } plus behaviourAxis / severityAxis. The recommendation stores the matrixVersion and actorType it was computed with. Config: cellSource: { register: "dossiq", schema: "lhsMatrix", filter: { version: "@object.matrixVersion" }, fallbackFilter: { active: true }, cellsPath: "cells", cellFilter: { actorType: "@object.actorType" }, rowField: "behaviour", columnField: "severity", valueField: "intervention", rowOrderPath: "behaviourAxis", columnOrderPath: "severityAxis" } with highlight: { row: "@object.behaviour", column: "@object.severity" }.

A matrix without cellSource draws as before.

Verified

  • tests/utils/matrixCells.spec.js and tests/components/CnChartWidgetMatrixCells.spec.js. The per-record mode's component specs fail 2 of 3 without it; the one-record specs fail 4 without that mode.
  • Chart, dashboard and schema specs: 726 passed. Schema version test and hash ledger are set for 2.124.0.
  • eslint, stylelint, check:jsdoc, check:docs: all exit 0. Docs regenerated. Full jest, build and e2e are left to CI.

OpenSpec: openspec/changes/matrix-cell-records.

🤖 Generated with Claude Code

Assisted-by: ClaudeCode:claude-opus-5-5
Assisted-by: ClaudeCode:claude-opus-5-5
Assisted-by: ClaudeCode:claude-opus-5-5
Assisted-by: ClaudeCode:claude-opus-5-5
…and-heatmap

# Conflicts:
#	src/schemas/app-manifest-v2.schema.json
#	tests/schemas/app-manifest-v2.schema.hashes.json
#	tests/schemas/app-manifest-v2.schema.spec.js
CnChartWidget draws chartKind "bar-list" (label, track at its share of
barMax or the largest value, value, drilldown rows, footnote) and
"matrix" (a series per row, tinted cells, text cells through colorMap,
highlight outlines the record's cell), without ApexCharts. valueFormat
gains "number" with suffix; endpointSource gains rowsPath. In the board
look dashboard card heads draw no divider. Boards DqDashboard,
DqTermijnen, DqDoorlooptijd, DqProcesanalyse, DqHandhaving.

Assisted-by: ClaudeCode:claude-opus-5-5
Assisted-by: ClaudeCode:claude-opus-5-5
…and-heatmap

# Conflicts:
#	src/schemas/app-manifest-v2.schema.json
#	tests/schemas/app-manifest-v2.schema.hashes.json
#	tests/schemas/app-manifest-v2.schema.spec.js
cellSource lists records that each hold one cell from a register (filter
tokens resolved, e.g. @object.matrixVersion) and lays them out by
rowField / columnField with valueField as the cell, with labels, order and
valueLabels. highlight matches the cell keys. Generic for any app that
keeps a matrix as data; board DqHandhaving.

Assisted-by: ClaudeCode:claude-opus-5-5
…4.0)

With cellsPath, cellSource reads ONE record (filter, else fallbackFilter),
takes its cells array, narrows it by cellFilter (tokens allowed) and orders
the axes from rowOrderPath / columnOrderPath on that record. The
one-record-per-cell mode stays. Schema 2.124.0 types cellSource.

Assisted-by: ClaudeCode:claude-opus-5-5
@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Landed in batch 8 via #1771.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant