Repository navigation
fix(plugin-dashboard): a dimensionless table renders a row of every measure and a dimensionless chart one mark per measure, as the spec states (objectui#11261) - #11278
Conversation
…easure and a dimensionless chart one mark per measure (objectui#11261) DatasetWidget classified every widget with no dimensions as a one-number tile, so a dimensionless table or bar/line/area/combo chart with two or more measures rendered values[0] and dropped the rest, although every door accepts it and the spec's metric-family arity refusal sends authors there for "several numbers in ONE widget". Only a metric-family type is now a tile by type. With no dimension and two or more measures, a table/pivot renders its one row of measures, and a bar/line/area/combo chart plots one mark per measure with the measures' labels on the category axis (the single row transposed under one series labelled with the existing dashboard.total key). One measure and no dimension stays a tile on every type, and every type the spec's text does not name keeps its tile too. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
…measure rendering (objectui#11261) Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Inputs read, and nothing else: card #11261 (body and all 3 comments: triage Check-runs on the head (the gate verdicts): 43 latest runs, all completed at 22:36Z after a 4-minute foreground wait: 40 ① Derived judgmentsItem 1 — the classification ( Item 1 — the transposition ( Item 1 — the flat-table branch. RIGHT. Item 2 — one measure and no dimension. RIGHT. With Item 4 — the query. RIGHT. Item 4 — the ablation leg, against what the new file pins. CONSISTENT. The new file holds 25 rows: 7 SUBJECT (table + pivot via Item 3 — the nine CONTROL rows for the unnamed types. RIGHT. Each asserts the measured state (the No accept set or public type moves. RIGHT. The diff touches ② Semver level
Clause-②: no. RIGHT, and consistent: the claim ③ Boundary flagsDeviation, the objectui#8894 file: one SUBJECT ("covers the dimensionless arm") moved from a dimensionless Q1 (the nine unnamed types) and Q2 (the dispatch's item 5 premise that the warning would afterwards fire only for metric-family tiles, measured false). Neither is answered on this card, and that is the ordered outcome: item 3 says a claim that finds them dropping measures "returns an open question" and invents no semantics. Carrying both to objectui#8894 at ACCEPT with The out-of-scope observation (a typeless widget with a dimension routes to The PR body at this head, sentence by sentence: the base-state description, the door and spec statements, the classification, the two rendering arms, the one-measure case, the nine-type list, the warning statement, the moved example, the pin table, the gates, the census line and the docs line are true or, for the local gate numbers and the objectstack census, the dev's claims outside this input set that nothing here contradicts. The docs line was checked: none of the four dashboard docs, the README or the SKILL at the head states the old "no dimensions is a tile" rule. One sentence is not true as written: in "Ablation", "all 18 CONTROL rows, all 9 objectui#8894 rows and all 11 sub-caption rows stayed green" — at this head Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #11261
Clause-②: no
What this changes
DatasetWidgetclassified every widget that declares nodimensionsas a one-number tile (isMetric = METRIC_TYPES.has(widgetType) || dimensions.length === 0). So the card's{ type: 'table', dataset: 'sales', values: ['revenue', 'cost', 'margin'] }renderedrevenuealone. Every door accepts that widget, and the spec's own metric-family arity refusal sends authors there. Its ADR-0087 entrydashboard-widget-metric-family-multi-measure-refused(replacement, read in the installed@objectstack/spec17.5.0) says: "type: 'table'renders a row of measures, and the chart families (bar/line/area/combo) render one mark per measure".Per triage
5918660676(the renderer delivers the stated behaviour; no spec narrowing):table/pivot, or a widget whose family (CHART_TYPE_MAP) isbar/line/area/combo(MEASURE_AXIS_CHART_FAMILIES).[]grand-total grouping.headerLabel(the widget's one measure-label channel). The value sits under one series labelled with the existingdashboard.totalkey, so no new string is minted. AcompareTothe widget asks for draws as one overlay series beside each measure. The dimensioned overlay path is byte-identical (same data keys and labels).table,pivot,bar,line,areaandcombo.pie,donut,funnel,scatter,column,horizontal-bar,radar,treemap,sankey): measured and unchanged. A dimensionless one with two measures is still a tile. It rendersvalues[0], and objectui#8894's warning still names the dropped measure. This goes back as an open question in the report, and no display semantics are invented for these types.isMetric, so it no longer fires for the widgets that now render every measure. One example inDatasetWidget.unrenderedMeasures-8894.test.tsxmoved. Its SUBJECT "covers the dimensionless arm" used a dimensionlessbar, which is no longer a tile, so it now uses apie, which still is. Its assertions are unchanged.Pins
DatasetWidget.dimensionlessMeasures-11261.test.tsxdraws real Recharts marks through the registry, using theDatasetWidget.chartConfigMarks-9203harness.table(andpivot) over revenue, cost, margin renders one row with all three, no footer, no warningbardraws two.recharts-bar-rectangle, with category ticksRevenue,Costcombo;line/areaplot across the two measure labelsbardraws 4 marks (2 + 2 overlay)metrictile with no dimension renders the tile markup and still warnstable/barqueries exactly{ dimensions: [], measures: values }(nototals)PR objectui#8887's two pins stay green: the drop on a metric-type tile, and the no-sub-caption byte-identity (
DatasetWidget.subCaption.test.tsx).Ablation (restore the old
isMetric)The fix was committed first.
node ../objectstack/scripts/ablation-replace.mjsthen ran in WRAP mode (the anchor must hit once, the write is verified on disk, and a trap restores it). It replaced the newisMetricline with the old one and ran the new file, the objectui#8894 file and the sub-caption file.9640acd2abcc->4bf0c16ab58b.9640acd2abcc, andgit diff HEADis empty (re-checked independently).Gates (at
7d54b7cfb)pnpm exec vitest run packages/plugin-dashboard/src/: 155 files passed, 1420 passed / 6 skipped. At basef61dab169it was 154 files, 1395 / 6; the difference is the new file's 25.pnpm --filter @object-ui/plugin-dashboard type-check, with the closure built first by turbo: exit 0.tsc -p tsconfig.test.json --listFilesincludes both touched test files.pnpm exec eslinton the 3 changed source and test files: 0 errors. The 11 warnings inDatasetWidget.tsxare the same 11, under the same rules, as at base. The new file has 0 errors and 0 warnings.node scripts/check-changeset-presence.mjs: exit 0.node scripts/check-control-bytes.mjs: exit 0.pnpm check:new-line-citations: 0 new citations.node scripts/markdown-test-inputs.mjs --auditran (exit 0), and so didpnpm exec vitest run scripts/__tests__/(177 files passed, 2 skipped; 5371 passed).DatasetWidget, plus PR objectui#11257's two door pins (types, app-shell): 6 files, 84 passed.Acceptance notes
git grepover itsorigin/mainat75519e1c0). objectui'sexamples/andapps/author none. So no shipped example changes rendering.grepovercontent/docs, the package README andskills/), so none became false. The changeset carries the user-facing description.chartType = CHART_TYPE_MAP[widgetType] ?? 'bar'sends a widget with notypeand a dimension to a bar chart, while the spec defaultstypetometric. A spec-parsed document always carries a type, so this reaches only an unparsed client draft. This change readsCHART_TYPE_MAPwithout that default, so it adds no path through it.Generated by Claude Code