fix(views): the five per-view-type configs speak the spec vocabulary (#2231 phase 3) - #2892
Merged
Merged
Conversation
…2231 phase 3) `kanban`/`calendar`/`gantt`/`gallery`/`timeline` on `ListViewSchema` were the last hand-written forks after #2882 — and the fork was not cosmetic. objectui named the same concepts differently from `@objectstack/spec/ui`, and several read-sites only understood one of the two dialects. Two of those gaps were live bugs. Kanban lanes ignored the spec key. `ListView` gated the Kanban tab on `groupByField || groupField` but rendered lanes off `groupField` alone, so a config authored with the spec key — what the product's own `CreateViewDialog` emits — offered the tab and then grouped by whatever `detectStatusField()` guessed. The spec's `columns` (fields shown on each card) was also spread onto the board verbatim, where `columns` means LANES, so `ObjectKanban` built lanes with undefined id/title. `columns` now maps to `cardFields`, and the vocabulary keys are stripped from the passthrough (matching plugin-view's adapter, which already did this). Timeline lost every spec key in app-shell. `ObjectView`'s `timeline` branch was a three-key whitelist while its `gallery`/`gantt` siblings had already been fixed to spread-first, so a stored `timeline: { startDateField, endDateField, groupByField, colorField, scale }` arrived with only `titleField` and an axis pinned to the `'due_date'` fallback. Also: plugin-view's `ObjectView` now reads `gallery.coverField` and `timeline.startDateField` (it understood only the legacy aliases), the dead `gallery.subtitleField` is removed (three producers computed it; `ObjectGallery` never read it), and `defaultKanbanFromObject` no longer emits the legacy key alongside the spec one — that dual-write existed only to work around the render bug. Schema side: the four remaining configs derive from the spec via `.partial()` — the product authors partial configs while spec marks `columns`/`titleField`/ `startDateField` required — and `gantt` needs no local schema at all. `.passthrough()` is preserved so renderer-ahead knobs (calendar's `allDayField`) still reach the renderer. The pre-#2231 names (`groupField`, `cardFields`, `imageField`, `dateField`) stay accepted as deprecated aliases so stored views keep validating; the spec key wins wherever both appear. `calendar.defaultView` stays local — no spec counterpart. The drift guard now pins the derivation per config, and five ListView regression tests cover the kanban bugs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3EDGLKNvbcpDTLzyiAd3Q
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
… $select Third instance of the same root cause as the kanban lane bug. The view-config field collector — which decides what `$select`/`$expand` asks the server for — listed only the legacy objectui keys (`groupField`, `groupBy`, `cardFields`), so a spec-authored config named its lane and card fields in a vocabulary the collector could not see. The board then rendered from rows that never carried those fields, which reads as an empty board rather than a config error. Adds the spec counterparts (`groupByField`, `summarizeField`, and `columns` — the kanban card fields) ahead of the aliases, in both collectors. Pinned by a test that asserts the queried field set contains the lane and card fields of a spec-authored kanban; it fails without this change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3EDGLKNvbcpDTLzyiAd3Q
Contributor
❌ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 of #2231, after #2622/#2636 (derive
ListViewSchema, retire the spec-bridge copy) and #2882 (reduce every remaining "Mirrors @objectstack/spec/ui X" sub-schema to a spec re-export).kanban/calendar/gantt/gallery/timelinewere the last hand-written forks — and this fork was not cosmetic. objectui named the same concepts differently from the protocol, and the read-sites disagreed about which dialect they spoke. Three of those disagreements were live rendering bugs, all reachable from a view created through the product's own UI:CreateViewDialogemits spec vocabulary (packages/app-shell/src/views/CreateViewDialog.tsx).The three bugs
1. Kanban lanes ignored the spec key.
ListViewgated the Kanban tab ongroupByField || groupFieldbut rendered lanes offgroupFieldalone. A spec-authored config offered the tab and then grouped by whateverdetectStatusField()guessed.The same block spread the whole config onto the component props last, so the spec's
columns(the fields shown on each card) landed onObjectKanban'scolumnsprop — which means lanes.ObjectKanbanthen took its object-array branch and mappedstring[]throughlocalizeColumn, producing lanes withundefinedid and title.Fixed: read the spec key first, map
columns→cardFields, strip the vocabulary keys from the passthrough.plugin-view's adapter already did this correctly; the three adapters now agree.2. The
$selectcollector was blind to the spec vocabulary. Same root cause, one layer earlier. The collector that decides what the view asks the server for listed onlygroupField/groupBy/cardFields, so a spec-authored config named its lane and card fields in a vocabulary the collector could not see — the board then rendered from rows that never carried them, which reads as an empty board rather than a config error. AddsgroupByField,summarizeFieldandcolumnsahead of the aliases, in both collectors.3. Timeline lost every spec key in app-shell.
ObjectView'stimelinebranch was a three-key whitelist while itsgalleryandganttsiblings had already been fixed to spread-first (their comments explain why). A storedtimeline: { startDateField, endDateField, groupByField, colorField, scale }arrived with onlytitleField, axis pinned to the'due_date'fallback.Also fixed
plugin-view'sObjectViewnow readsgallery.coverFieldandtimeline.startDateField— it understood only the legacy aliases.gallery.subtitleFieldremoved. Three producers computed it;ObjectGallerydeclared the prop and never read it — declared ≠ delivered.defaultKanbanFromObjectno longer writes the legacy key alongside the spec one. That dual-write existed only to work around bug 1 (its comment said so).Schema
The four remaining configs derive from the spec configs via
.partial()— the product authors partial configs (kanban: { groupByField }with nocolumns) while spec markscolumns/titleField/startDateFieldrequired, so requiring them would reject views the app itself creates. Same trade-offSpecListViewFieldsalready makes.ganttneeds no local schema at all and now flows in with the rest..passthrough()is preserved from the pre-#2231 shapes for the reason the spec itself puts it onGanttConfigSchema/TreeConfigSchema: renderers grow config knobs ahead of the protocol (calendar'sallDayField), and stripping them would silently disable a shipped capability.The pre-#2231 names stay accepted as deprecated aliases so stored view metadata keeps validating — the spec key is canonical and wins wherever both appear:
kanbangroupField,cardFieldsgroupByField/columnscalendardefaultViewgalleryimageFieldcoverFieldtimelinedateFieldstartDateFieldTests
list-view-spec-parity.test.tsgains a per-config derivation guard: every spec field present, local keys exactly the sanctioned set, spec vocabulary parses without stripping, aliases still accepted, and partial configs still valid.ListViewregression tests. Five pin the kanban render bugs via aComponentRegistrystub that captures the resolved props (spec key groups, alias still works, spec key wins over alias,columns→cardFieldswith no lane leak, unrecognized spec fields still pass through). The sixth asserts the queried field set contains a spec-authored kanban's lane and card fields — verified to fail without the collector fix, so it is not a vacuous test.Verification
@object-ui/typestsc --noEmit: 0 errors. Changed files lint-clean (0 errors).Follow-ups
Tracked in #2890 (phases 4–5): the top-level legacy vocabulary (
show*→userActions,fields→columns,filters→filter,objectName→data.provider:'object',aria/sharing→ spec sub-shapes), dropping the four aliases above once stored metadata is migrated, promotingcalendar.defaultViewinto the spec, and auditingObjectViewSchema/DetailViewSchema.objectstack#3761 (merged) promotes
ListColumn.prefixand the{ type, field }summaryform into the spec; when it releases,@object-ui/typesdrops its lastListColumnSchema.extend().🤖 Generated with Claude Code