Repository navigation
Commit d0097af
fix(app-shell): the Create View dialog binds a chart view to an ADR-0021 dataset of its object (objectui#11576) (#11580)
Fixes #11576
Clause-②: no
The console's Create View dialog now authors the spec's ADR-0021 chart
binding, `chart: { chartType, dataset, values, dimensions? }`, and
nothing else. Until now it wrote `chart: { chartType, xAxisField,
yAxisFields }`, which `@objectstack/spec` 17.6.0's strict
`ListChartConfigSchema` refuses by name. So the platform's view write
door refused every chart view the console created.
Shape: option A of the seat's answer on the card (comment `5973755839`,
amending claim `5973664751`), under triage `5973399361`.
## What users see today (ruling step 1, measured before any edit)
Measured at objectui `main` `0903617` (= this branch's base). The real
`ObjectDataPage` and the real dialog were mounted, with a real
`MetadataClient` whose fetch replays the platform's view gate (the
installed spec 17.6.0 `getMetadataTypeSchema('view')`) at the network
boundary:
- Picking Chart in "Save as view" and pressing Create sends `PUT
…/meta/view/crm_deal.KEY?mode=draft` with `config.chart = {chartType:
bar, xAxisField: stage, yAxisFields: [amount]}`.
- The gate refuses it. Its ViewItem arm reports `unrecognized_keys
[xAxisField, yAxisFields]` and `dataset` / `values` missing, and the
client throws a **422**.
- **The user sees nothing.** The dialog has already closed (its submit
does not await the save). The page stays on `/data`, with no navigation,
no toast and no alert. The only trace is
`console.error('[ObjectDataPage] Failed to save view:')`.
- `ObjectView.handleViewCreate` (the view tab bar's add button) has the
same catch-and-log shape.
That silent failure is a defect of its own and outlives this payload
change. It is **not** addressed here: the seat files it as its own card.
## What changed
- **`CreateViewDialog`.** The chart type's picks are now:
- `chartType`, unchanged;
- `dataset`: only the ADR-0021 datasets whose base `object` is the
view's object, never the whole catalog;
- `values`: one of the chosen dataset's measures, required, written as a
one-element list;
- `dimensions`: one of its dimensions, optional, shown only when the
dataset declares any, and omitted from the payload when empty.
- **How the dialog reads them.** It reads the catalog itself through
`useDatasetCatalog()` / `useDatasetSemantics()`, the pair the dashboard
widget editor binds with. A closed dialog, or one with no `objectDef`,
fetches nothing. A dataset, measure or dimension name counts only while
it is among the current options, so a stale or foreign name can neither
open Create nor reach the payload. Choosing another dataset clears the
measure and dimension picked from the last one.
- **An object with no dataset.** The chart card is disabled through the
dialog's existing "type unavailable" path. Its tooltip names the reason
("exposes no dataset") instead of the field wording, because a dataset
is not a field.
- **`xAxisField` / `yAxisFields` are gone from the dialog.** There is no
dual spelling.
- **Header comments corrected.** The "pure, no dataSource coupling"
sentence now says what the dialog reads and when. The spec-alignment
claim now points at the two pins that re-derive it for `chart`, and says
in writing that no test drives the other types' payloads through the
dialog against the spec (AGENTS.md #9).
- **`useDatasetCatalog`.** `DatasetCatalogEntry` gains an optional
`object`, the served document's base object; `toCatalogEntry` keeps it
when served. No other consumer reads it.
- **`@object-ui/i18n`.** The four axis keys
(`console.objectView.xAxisField`, `xAxisFieldHelp`, `yAxisField`,
`yAxisFieldHelp`) leave all ten packs; the dialog was their only reader.
Eight keys label the new picks: `dataset`, `datasetHelp`,
`chartMeasure`, `chartMeasureHelp`, `chartDimension`,
`chartDimensionHelp`, `viewTypeUnavailableDataset`, `noDatasetMeasure`.
Terms follow each pack's existing dashboard dataset vocabulary.
`objectView-config-keys-retired-4730.test.ts` owns this namespace's
arithmetic, so it moves with them: 123 retired, 102 surviving, 225
total.
- **Changeset.** One, patch, for `@object-ui/app-shell` and
`@object-ui/i18n`.
**Clause-② stays `no`.** `CreateViewDialogProps` is unchanged. Neither
`DatasetCatalogEntry` nor `useDatasetCatalog` (nor `CreateViewDialog`
itself) is exported from `packages/app-shell/src/index.ts`, and the
package's `exports` publishes only `.`.
## Pins
- `CreateViewDialog.chartBinding-11576.test.tsx`:
- the served dataset fixtures parse as spec `DatasetSchema` documents
(control);
- `toCatalogEntry` carries `object`;
- the picker offers the `crm_deal` dataset and never the `crm_account`
one;
- it offers the chosen dataset's own measures and dimensions;
- the chart card is disabled when the object exposes no dataset;
- no catalog is fetched while the dialog is closed;
- the payload is exactly the ADR-0021 block, with no legacy key;
- `dimensions` is omitted when the dataset declares none;
- **DOOR 1**, `ObjectDataPage.buildSaveAsViewSpec`: the payload parses
against the 17.6.0 `ListViewSchema`, and its envelope passes
`ViewItemSchema`;
- **the save-door probe, turned around**: the same replayed view gate
now answers **200** for the new payload, and the user lands on the new
draft (`…/view/crm_deal.KEY?preview=draft`).
- `ObjectView.createChartView-11576.test.tsx`:
- **DOOR 2**, `ObjectView.handleViewCreate`: a chart view is created
through the tab bar's add button with the real `ObjectView` and the real
dialog. The body handed to `metadataClient.save` passes `ListViewSchema`
(config) and `ViewItemSchema` (envelope), with no legacy key.
- **Renders on the object page**: that saved config, mounted as the
object's list view, reaches `ObjectChart` through the dataset branch
(`dataset` / `values` / `dimensions`; no `objectName` / `aggregate`).
## Evidence
**Red first, at base `0903617`:**
- The probe above answered 422, with the user seeing nothing.
- The two new pin files, run on the unmodified tree: `Tests 9 failed | 4
passed (13)`. Every failure is "no dataset / values picker exists", or
(the unavailable-card case) "the old dialog reads no catalog". The 4
passes are the 3 fixture controls and "no catalog while closed", which
the old dialog satisfies trivially.
**Ablation**, at `5db856f`, run by objectstack's
`scripts/ablation-replace.mjs` with an `EXIT INT TERM` restore trap:
- The mutation plants `subConfig.xAxisField = 'stage'` into the dialog's
payload: anchor 1 to 0, blob `a8cc632c` to `6b44f4a0`, "mutation
landed".
- Predicted before the run: 5 red, 9 green. Observed: `Tests 5 failed |
9 passed (14)`.
- Red, on the spec's own refusal: the payload case, the no-dimensions
case (`refused by the spec: unrecognized_keys`), DOOR 1
(`unrecognized_keys`), the 2xx door (`expected 422 to be 200`) and DOOR
2 (`ListViewSchema` refusal).
- Green: the fixture and catalog controls, the four picker cases, and
the render case.
- Restored by blob hash: `a8cc632c` == HEAD blob, `git diff HEAD` empty,
marker count 0.
**Green**, every run below at `5db856f` (`git rev-parse --short HEAD`):
- `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...'
build`: exit 0.
- `pnpm --filter @object-ui/app-shell --filter @object-ui/i18n
type-check`: both echoed `type-check: Done`. `tsc -p tsconfig.test.json
--listFilesOnly` counts both new pins (app-shell) and the 4730 pin
(i18n) in the checked program.
- Narrowed `pnpm exec vitest run --maxWorkers=2` over 140 files: every
`CreateViewDialog*`, `ObjectDataPage*` and `ObjectView*` suite in
app-shell, every suite naming the catalog reader, and the whole
`packages/i18n/` (all-locales parity included). Result: `Test Files 140
passed (140)`, `Tests 2012 passed | 13 skipped (2025)`. This is a
declared narrowing: the rest of app-shell's suites are CI's.
- Gates, all exit 0:
- `check:control-bytes` (`OK`);
- `check:new-line-citations` (`VERDICT … 0 new citation(s)`);
- `check:changeset-claims` (report-only);
- `check:pending-changeset-literals` (`No test source names a pending
changeset`);
- `check:i18n-keys` (every call-site key resolves against the en pack);
- `check:i18n-drift` (`No en value changed in this range`);
- `check:i18n-designer-parity`;
- `check:vi-mock-specifiers`, `check:vi-mock-inherit`,
`check:vi-mock-override-shape`;
- `check:test-path-roots`;
- `check:metadata-write-doors`;
- `check:unreferenced-sources`;
- `node scripts/check-changeset-presence.mjs` (`15 source file(s) of 2
released package(s) changed, and this change declares 1 changeset(s)`).
- Bundle gates, after a `@object-ui/console` build
(`check:eager-closure`, `check:eager-locale-catalogues`), exit 0:
- aggregate eager closure 3311.7 KB against a 3330.4 KB budget;
- all four per-chunk ceilings and chunk membership held;
- exactly one locale catalogue (en) eager.
- Lint, a proven narrowing:
- Population: the root `eslint.config.js` `files: ['**/*.{ts,tsx}']`
blocks; the packages carry no config of their own.
- Count: `--format json` linted 15 files with 0 errors.
- Invariance: the config sets no `parserOptions.project` /
`projectService` (no type-aware linting), and no rule under
`eslint-rules/` reads another file, so this diff cannot move a verdict
in an untouched file.
- Warnings: the two changed source files carry the same warnings as at
base (8 and 8, 1 and 1). The 9 others are `no-explicit-any` in the two
new test files.
## Acceptance notes
- `UnifiedViewConfig.chart` in `@object-ui/types`
(`packages/types/src/designer.ts`) still declares `chartType`,
`xAxisField`, `yAxisFields`, `aggregation`, `series`, `config` and
`filter`, and no `dataset` / `values`. It is exported from the package
index and has zero consumers in this repo. Noted, not changed here.
- Render-side legacy chart readers still read the inline axes, which the
17.6.0 write door now refuses at save, so only rows saved before the
cutover can reach them. Noted, not changed here; the ruling scopes the
removal to the dialog. The readers:
- `ObjectView`'s non-dataset chart branch (the "Translate here" block
over `xAxisField` / `yAxisFields` / `aggregation`);
- `ListView`'s `case 'chart'` fallback ("Legacy inline aggregate
(deprecated …) Kept as a fallback").
- The new picks' labels reach `t()` through `REQUIRED_FIELDS_BY_TYPE`'s
`i18nKey`, so `check:i18n-dead-keys` (report-only) lists six of them as
needs-review. That is the same tier the dialog's existing keys
(`chartType`, `groupByField`, `startDateField`, …) already sit in.
- Dataset and member labels come from `useDatasetCatalog`, which
resolves an author's `I18nLabel` in the designer locale (`en-US` or
`zh-CN`), as the dashboard and report editors show them. A de or ja
session therefore sees a dataset's English label where the author
declared one.
- No test drives the kanban, calendar, gallery, map or tree payloads
through this dialog against the spec. The corrected header says so
rather than claiming alignment.
Write route: `objectstack-fleet[bot]` through the fleet-write relay.
Session `https://claude.ai/code/session_01FjqrwXPfSMkSfkKYDSRkN2`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FjqrwXPfSMkSfkKYDSRkN2)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 2f54dca commit d0097af
16 files changed
Lines changed: 947 additions & 122 deletions
File tree
- .changeset
- packages
- app-shell/src/views
- metadata-admin/previews
- i18n/src
- __tests__
- locales
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
Lines changed: 323 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
0 commit comments