Repository navigation
Commit bc97f92
fix(app-shell): an interface page relays its source view's hiddenFields and fieldOrder (objectui#10638) (#10667)
Fixes #10638
Clause-②: no — an interface page begins honouring two declared per-view
keys it drops today; no export, schema or accept set moves.
Executes triage `5833520187` (bug · p2) under claim `5833614033`
(`domain:ui` seat 2, session `session_014mXUNuFomfj24w7s1pZzhN`). This
PR puts the source view's `hiddenFields` and `fieldOrder` into the list
schema `InterfaceListPage` hands `ListView`. It states the page config's
precedence and mirrors the objectui#7516 relay pin.
## What changed
- **The relay** (`packages/app-shell/src/views/InterfaceListPage.tsx`).
The schema literal now gets two conditional spreads beside `columns`:
`hiddenFields: view.hiddenFields` and `fieldOrder: view.fieldOrder`.
Each is present only when the view authored the key and the view
supplies the columns. The page composes nothing. `ListView`'s
`effectiveFields` memo already runs `columns` projects → `hiddenFields`
subtracts → `fieldOrder` sorts the survivors, and an unlisted survivor
sorts last.
- **The pin** (`InterfaceListPage.viewFieldKeysRelay-10638.test.tsx`).
`ListView` is stubbed and its `schema` prop is captured, the same
posture as `ObjectView.fieldOrderRelay-7516.test.tsx`. Three FIX cases:
the view's `hiddenFields` arrives verbatim; the view's `fieldOrder`
arrives verbatim; the whole composition arrives together. One PRECEDENCE
case and two CONTROLs: an empty view `columns`, and a view that authors
neither key.
- **The file header** (rounds 2 and 3). It now states `sourceView` as a
fallback: the view's columns (with its `hiddenFields` / `fieldOrder`)
and sort are inherited unless the page defines its own `columns` /
`sort`, and its base filter is always inherited with the page's
`filterBy` appended (ADR-0047 revised). The "never restated" wording it
replaces was false on base as well.
- **Changeset** `.changeset/10638-interface-page-view-field-keys.md`,
`'@object-ui/app-shell': patch`.
## The precedence (H2): the whole composition, from one source
`cfg` has no spelling of either key. `InterfacePageConfigSchema` is a
`strictObject`, and its alias map sends `fields` / `columnList` to
`columns` and neither key anywhere. So the two keys resolve **with** the
page's column list, as one unit, on the same three branches `columns`
already used:
1. **The page authors its own `columns`.** That list is used as it
stands, and neither view key applies. Released spec (`@objectstack/spec`
17.4.0): page `columns` are "Defined directly on the page (no view
inheritance)", and `sourceView` is "Still honored at runtime as a
fallback when the page has no own `columns`".
2. **Otherwise the view's non-empty `columns`.** The view's
`hiddenFields` and `fieldOrder` come with them.
3. **Otherwise object-derived defaults.** Neither key applies.
`ListViewSchema.columns` says an empty list "declares no projection, so
neither of them applies". This is spec source at objectstack
`origin/main` (objectstack#19598, `9dcdb77`), not yet in the released
17.4.0.
Why not "the page's `columns` projects, the view's keys subtract and
sort", as the order's H2 sketched? The composition is declared **per
view**. The `ListViewSchema` composition docblock says "Three keys on
this schema together build one field list"; this is spec source at
objectstack `origin/main` (objectstack#19598), not yet in the released
17.4.0. Mixing sources would also break design mode. The design-mode
column drag (`onColumnStateChange`) saves the order it shows as the
page's `columns`. A relayed view `fieldOrder` would then sort that list
straight back, so the drag would appear to do nothing. Ablation B below
shows the pin catches that wiring.
## Premises, measured on base `4a3d500fd` before the first edit
- **H1 holds.** The site is as the card describes: `resolveSourceView`
feeds a schema literal with 0 mentions of either key. Fixture: `columns:
['name','owner','stage']`, `hiddenFields: ['owner']`, `fieldOrder:
['stage','name']`.
- What `ListView` **receives** on base: the pin reads `Tests 3 failed |
3 passed (6)`, `expected undefined to deeply equal [ 'owner' ]` and `… [
'stage', 'name' ]`. `schema.columns` arrives as
`['name','owner','stage']`.
- What it **draws**, from a one-off probe that was not committed: the
real `InterfaceListPage` and the real `ListView`, with only
`object-grid` stubbed to record the column list it is handed. Base draws
`["name","owner","stage"]`. Head draws `["stage","name"]`.
- **H2.** The precedence is set out above. The PRECEDENCE case is green
on base by construction, because base relays neither key. What it
catches is an over-broad relay; see ablation B.
- **H3.** The relay only delivers the values; `ListView` is untouched.
- **H4.** The pin goes red on base and green on head, with per-hunk
ablations below.
- **H5.** No sentence needed reconciling:
- No interface-page doc and no `packages/app-shell/README.md` sentence
names which source-view keys the page honours.
- Of the pending changesets naming `InterfaceListPage`, only
`.changeset/7218-rowcolor-host-relay.md` names the edited file (per
`check:changeset-claims`). Its paragraph ("has shipped `rowColor:
view.rowColor` next to `grouping` and `pagination`") was re-read and is
still true.
## Verification of the change, round 1, on `b172bf0fb`
All runs went through the shared verify lock. Legs 2–4 ran in one hold,
each with a trap-protected restore proven by the blob hash matching HEAD
(`00977917bcae`) and `git diff HEAD` empty.
- **Head:** pin `Tests 6 passed (6)`. Probe draws `["stage","name"]`.
- **Base file swapped in** (`git show 4a3d500:…`; on disk the
`viewComposes` count is 0 and the blob equals the base blob
`f3e2e80e0509`): pin `Tests 3 failed | 3 passed (6)`, the three FIX
cases. Probe draws `["name","owner","stage"]`.
- **Ablation A:** the relay hunk deleted, both spread lines. Tool:
`ablation-replace.mjs` (objectstack), anchor `x1 → x0`, blob
`00977917bcae → 740fff063f76`; an in-run `grep -c` read `0` and `0`.
Predicted: three FIX cases red. Measured: `Tests 3 failed | 3 passed
(6)`, the three FIX cases. The probe draws `["name","owner","stage"]`.
- **Ablation B:** the precedence gate removed (`viewComposes && view.` →
`true && view.`, `--expect 2`, anchor `x2 → x0`, replacement `x0 → x2`),
so the keys are carried unconditionally. Predicted: PRECEDENCE and the
empty-`columns` CONTROL red. Measured: `Tests 2 failed | 4 passed (6)`,
exactly those two.
- **Dependency closure:** `turbo run build
--filter='@object-ui/app-shell^...' --concurrency=2`. `Tasks: 28
successful, 28 total`.
- **`@object-ui/app-shell` type-check:** `tsc --noEmit && tsc -p
tsconfig.test.json`, exit 0. `--listFilesOnly` on the test project lists
the new pin.
- **Tests that name `InterfaceListPage`** (23 files across 9 packages):
`Test Files 23 passed (23)`, `Tests 362 passed (362)`.
- **Lint, narrowed and proven:**
- Population from ESLint's own config: `isPathIgnored` is false for both
changed `.ts`/`.tsx` files.
- Count: 2 files, 0 errors. `InterfaceListPage.tsx` has 39 warnings on
head and 39 on base. The pin has 9 `no-explicit-any` warnings, the same
as its sibling `InterfaceListPage.mapConfig.test.tsx`.
- Invariance: no type-aware linting (`parserOptions.project` /
`projectService` unset), and no rule under `eslint-rules/` reads the
filesystem, so this diff cannot move a verdict on any untouched file.
- **Gates (lock-free), with each gate's own verdict line:**
- `check-changeset-presence` ✅ `2 source file(s) of 1 released
package(s) changed, and this change declares 1 changeset(s)`
- `check:new-line-citations` `VERDICT new-cross-file-line-citations: 0
new citation(s)`
- `check:control-bytes` ✅ OK
- `check-changeset-no-major` ✅
- `check-changeset-fixed` ✅
- `check:pending-changeset-literals` ✅
- `check:vi-mock-specifiers` / `-inherit` / `-override-shape` ✅ OK
- `check:test-path-roots` ✅ OK
- `check:changeset-claims`: report-only; the one paragraph it names was
re-read, as above
- `check-governed-queue-guard --test` on the three paths: `NOT GOVERNED`
## Round 2, on `2a26e30ec` (wording only, no code change)
The contract review passed the change and asked for three wording fixes:
1. **The file header clause** now states `sourceView` as the ADR-0047
(revised) fallback. The replaced text said "never restated", which was
false on base too.
2. **The changeset** now reads "carried that view's `columns`, `filter`,
`sort` (and its other keys)", so the list is no longer read as
exhaustive. The frontmatter is byte-identical: md5 of its first three
lines is `4e8ce55021fe3b14329c8b4cb3f9f354` before and after.
3. **This body** marks which spec quotes are released (17.4.0) and which
are spec source at objectstack `origin/main` (objectstack#19598).
Gates on `2a26e30ec`:
- `check-changeset-presence` ✅ `2 source file(s) of 1 released
package(s) changed, and this change declares 1 changeset(s)`
- `check-changeset-no-major` ✅
- `check:control-bytes` ✅ OK
- `check:new-line-citations` `VERDICT new-cross-file-line-citations: 0
new citation(s)`
- `@object-ui/app-shell` type-check: exit 0, after the closure build
(`Tasks: 28 successful, 28 total`, all cached)
Merge check: fresh `origin/main` `ed8251189` has not touched the three
files since base, and `git merge-tree` is clean, so no merge commit was
needed.
## Round 3, on `106a48803` (one comment clause)
The round-2 re-review found the header clause false on its filter leg:
the page always spreads the view's `filter` and appends its own
`filterBy` (`:437-440` at this head), so the page never displaces the
base filter. The clause now says so. Comment only; `check:control-bytes`
and `check:new-line-citations` pass, the app-shell type-check exits 0,
and `git merge-tree` against `origin/main` `f905090a1` is clean.
Not run locally; these are CI's: the full `pnpm test` farm, `Lint`, E2E,
and the repo-wide `pnpm lint`.
## Acceptance notes
- The page still takes the source view's `filter`, `sort`, `grouping`,
`rowColor`, `pagination`, `userFilters` and the other keys whether or
not it authors its own `columns`. This PR does not change that; it
scopes only the two new keys. Read from source, not measured.
- The object route (`ObjectView`) handles a `columns: []` view
differently. It fills in default columns, then relays that view's
`hiddenFields` / `fieldOrder`, so the keys subtract from and sort the
defaults there. This page applies neither key to its defaults. Carded by
the seat as objectui#10694.
---
_Generated by [Claude
Code](https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 69a6fc1 commit bc97f92
3 files changed
Lines changed: 266 additions & 3 deletions
File tree
- .changeset
- packages/app-shell/src/views
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
10 | | - | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
11 | 14 | | |
12 | 15 | | |
13 | 16 | | |
| |||
439 | 442 | | |
440 | 443 | | |
441 | 444 | | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
442 | 457 | | |
443 | 458 | | |
444 | | - | |
| 459 | + | |
445 | 460 | | |
446 | 461 | | |
447 | 462 | | |
| |||
459 | 474 | | |
460 | 475 | | |
461 | 476 | | |
| 477 | + | |
| 478 | + | |
462 | 479 | | |
463 | 480 | | |
464 | 481 | | |
| |||
Lines changed: 221 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 | + | |
0 commit comments