Repository navigation
Commit 1013ef1
fix(app-shell): a draft-only object's nav entry opens its drafted default list view in Studio Interfaces (#30315)
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} -->
_Requested by **Yibo Wang** · [project
thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwB7gJBqvTiMpqqBp2Jkh3F7S)_
Fixes #30177
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:Studio 界面里,一个还只是草稿的对象,从导航入口打开时现在会打开作者草拟的那个默认列表视图(例如「All
deals」),视图下拉里不再多出一个并不存在的「Default view」,第一次编辑也写进这个视图本身。
- 为什么改:之前入口只按已发布的元数据找默认视图,草稿对象不在其中,于是打开不存在的
`OBJECT.default`;作者一编辑,包里就多出第二个默认列表视图,而且它的列是空的。
- 风险与回滚:只改 Studio
面板选哪个视图,不动接口、数据和规格。已发布对象的行为不变;包的草稿列表读回来之前,面板对「尚未标记默认的对象」多转一下加载圈。回滚即还原本
PR。
-
先看:`ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx`
里 `useObjectListViewDraft` 的 `entryTarget` / `holding` 两段,以及新函数
`draftedListViewsOf`。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/studio-design/ObjectListViewInspector.draftOnlyObject-12508.test.tsx`,预期
8 个测试全部通过,其中 objectstack#30177 一组断言入口打开
`acmetrial_deal.all`、切换器只列这一项、第一次编辑只写这一个视图。
- 需要你做的:无,席位落地。
## What changes
In Studio › Interfaces, the list-view panel of an `object` nav entry
with no `viewName` edits the object's default list view.
`useObjectListViewDraft` resolved that view (`listViewTargetOf`) from
the shell's merged `listViews` only. A draft-only object is absent from
the shell's metadata, so the entry opened `OBJECT.default`, which does
not exist; the header's view switcher listed that "Default view" beside
the view the author had drafted with `isDefault: true`; and the first
edit created `OBJECT.default` with `isDefault: true`, a second default
list view in the package (seeded with no columns).
- The entry's default is now resolved against the merged views **and**
this package's drafted list views of the object (`draftedListViewsOf`,
over the draft-overlaid view list the switcher already reads; no new
request). A flagged merged view still wins; a flagged drafted view comes
next; `OBJECT.default` stays the fallback.
- That draft read is asynchronous. Until it answers, an entry whose
default no merged view flags is held (`holding`): no buffer is loaded
and nothing is listed, so no edit can be made against the fallback name
before the drafted default is known. A failed or refused draft read
lists nothing drafted, and the entry falls back to `OBJECT.default` as
before.
- This applies to every object, not only draft-only ones. The draft-only
set (`draftOnlyObjects`) is itself read asynchronously and can be stale
across a publish, and a published object whose package drafts its first
default view had the same phantom; resolving against the drafted views
avoids both without depending on that set.
Changeset: `@object-ui/app-shell` patch.
## Tests
New top-level `describe` in the existing hook harness
`ObjectListViewInspector.draftOnlyObject-12508.test.tsx` (real hook,
real `MetadataClient` over an in-memory server; the server now also
serves the drafts ledger, the draft-overlaid view list, `?state=draft`
reads and records PUTs):
- draft-only object + drafted `acmetrial_deal.all` (`isDefault: true`) +
entry with no `viewName` → the panel targets and loads
`acmetrial_deal.all`; the switcher lists only it; the first edit (made
as the panel makes it) PUTs `view/acmetrial_deal.all` and no other view
carries `isDefault`;
- while the draft-overlaid view list is held, nothing is loaded or
listed and no `acmetrial_deal.default` request is sent; once it answers,
the entry is `acmetrial_deal.all`;
- CONTROL: a published object with no flagged view still targets
`OBJECT.default`;
- CONTROL: a draft-only object with no drafted view still targets
`OBJECT.default`, and the first edit creates it flagged default.
<details><summary>Ablation (fix committed first;
scripts/ablation-replace.mjs, restored to the HEAD blob, git diff HEAD
empty)</summary>
- Draft read removed (`{ ...publishedViews,
...draftedListViewsOf(objectName, draftViewRows) }` → `publishedViews`):
2 failed, 6 passed. The first pin reads `viewId`
`acmetrial_deal.default` where `acmetrial_deal.all` is expected; the
hold pin's settled target is `acmetrial_deal.default`.
- Hold removed (`holding` forced `false`): 1 failed, 7 passed.
`loadedFor` reads `listView:acmetrial_deal.default` while the drafts are
unread.
</details>
<details><summary>Test runs</summary>
- At `d0d0f1e6` (before merging `main`): every app-shell test file
importing `ObjectListViewInspector` or `StudioDesignSurface`, 210 files,
`--maxWorkers=2`, under the verify lock: `Test Files 210 passed (210)`,
`Tests 1344 passed (1344)`, VERDICT command-exit 0.
- At `bfd2fbff` (after merging `main` `959c26be`, rebuilt): the 33
list-view, Interfaces-pillar and draft-only files of that set: `Test
Files 33 passed (33)`, `Tests 183 passed (183)`, VERDICT 0. `pnpm
--filter @object-ui/app-shell run type-check`: VERDICT 0.
- eslint on the two touched source/test files from the package dir: 0
errors (22 warnings, all pre-existing patterns on lines this PR does not
touch).
</details>
<details><summary>Gates at bfd2fbf</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (3 paths vs merge base `959c26be1`): 35
commands, run serially under one verify lock (VERDICT command-exit 0),
every one exit 0, including `node scripts/check-sdui-manifest.mjs` and
`pnpm --dir ui exec vitest run scripts/` (`Test Files 170 passed | 2
skipped (172)`, `Tests 4985 passed | 2 skipped`). `--ran` with the
recorded exit codes: 35 derived, 35 run, 0 NOT-MEASURED (a derived
zero). The record is the project's `ui-orders/30177-gates-ran.list`.
</details>
Not run locally: the full ui suite (CI's Test UI shards run it).
`origin/main` moved after the merge; its only overlap with this PR's
area is four added lines in `StudioDesignSurface.tsx`, a file this PR
does not edit.
## Verification
Dev boot of `examples/app-crm` (`objectstack dev --seed-admin --fresh`)
after a full build, console Vite pointed at it, Playwright Chromium,
signed in as the dev admin. Seeded over the REST door as the card
describes: writable package `com.acme.trial`, then with `?mode=draft`
the object `acmetrial_deal`, the list view `acmetrial_deal.all` (`label:
All deals`, `isDefault: true`) and the app `acmetrial_app` whose one nav
entry is the object with no `viewName`. Opened the entry in Studio ›
Interfaces.
| | Before (main's `ObjectListViewInspector.tsx`, Vite restarted with
`--force`, served module checked) | After (this branch) |
|:--|:--|:--|
| Panel opens | `acmetrial_deal.default`, "There is no list view
"Default view" yet", 0 columns | `acmetrial_deal.all`, "Unpublished
draft", columns Name, Stage |
| Switcher lists | Default view ✓, All deals | All deals ✓ |
| First edit (Add field → Amount) PUTs | `view/acmetrial_deal.default`,
`isDefault: true`, columns `[amount]` | `view/acmetrial_deal.all`,
`isDefault: true`, columns `[name, stage, amount]` |
| Package's view drafts afterwards | `acmetrial_deal.all` and
`acmetrial_deal.default`, both `isDefault: true` | `acmetrial_deal.all`
|
Shots (2x, 1440 wide) and the request readings are in the project's
`ui-orders/30177-shots/` folder (`before-switcher.png`,
`before-edited.png`, `after-switcher.png`, `after-edited.png`); this
repository has no place to commit them, per `ui/AGENTS.md` Housekeeping.
## Acceptance notes
- **Create View / first-edit column seed for a draft-only object, not
fixed here.** `seedColumns` is `defaultListColumnsFromObject(objectDef,
5)` and `objectDef` comes from the shell's merged objects, which do not
hold a draft-only object, so the seed is empty: the before leg's first
edit wrote `columns: [amount]` only, and New view's fallback columns are
empty the same way. Seeding from the object's draft fields is a
different read (the object's draft definition, not the view drafts this
PR reuses), so it stays out of this PR per the dispatch and is reported
to the seat for its own card.
- While the package's view drafts are unread, the header title of an
object with no flagged merged view still names the fallback view
("Default view") for that moment; the switcher lists nothing and the
panel shows its loading state, so nothing can be edited.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01WGufzigMc8dMgZMjwQtjCq)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent c8e6d38 commit 1013ef1
3 files changed
Lines changed: 190 additions & 14 deletions
File tree
- .changeset
- ui/packages/app-shell/src/views/studio-design
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
35 | 40 | | |
36 | 41 | | |
37 | 42 | | |
| |||
40 | 45 | | |
41 | 46 | | |
42 | 47 | | |
| 48 | + | |
| 49 | + | |
43 | 50 | | |
| 51 | + | |
| 52 | + | |
44 | 53 | | |
| 54 | + | |
| 55 | + | |
45 | 56 | | |
46 | 57 | | |
47 | 58 | | |
| |||
55 | 66 | | |
56 | 67 | | |
57 | 68 | | |
58 | | - | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
59 | 82 | | |
60 | 83 | | |
61 | 84 | | |
62 | 85 | | |
63 | 86 | | |
64 | 87 | | |
65 | | - | |
| 88 | + | |
66 | 89 | | |
67 | 90 | | |
68 | 91 | | |
| |||
131 | 154 | | |
132 | 155 | | |
133 | 156 | | |
| 157 | + | |
134 | 158 | | |
| 159 | + | |
135 | 160 | | |
| 161 | + | |
136 | 162 | | |
137 | 163 | | |
138 | 164 | | |
| |||
169 | 195 | | |
170 | 196 | | |
171 | 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
22 | | - | |
23 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
24 | 28 | | |
25 | 29 | | |
26 | 30 | | |
| |||
161 | 165 | | |
162 | 166 | | |
163 | 167 | | |
164 | | - | |
| 168 | + | |
| 169 | + | |
165 | 170 | | |
166 | 171 | | |
167 | 172 | | |
| |||
296 | 301 | | |
297 | 302 | | |
298 | 303 | | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
299 | 317 | | |
300 | 318 | | |
301 | 319 | | |
| |||
475 | 493 | | |
476 | 494 | | |
477 | 495 | | |
478 | | - | |
479 | 496 | | |
480 | 497 | | |
481 | 498 | | |
| |||
490 | 507 | | |
491 | 508 | | |
492 | 509 | | |
493 | | - | |
494 | | - | |
495 | 510 | | |
496 | 511 | | |
497 | 512 | | |
| |||
518 | 533 | | |
519 | 534 | | |
520 | 535 | | |
521 | | - | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
522 | 551 | | |
523 | 552 | | |
524 | 553 | | |
| |||
527 | 556 | | |
528 | 557 | | |
529 | 558 | | |
530 | | - | |
| 559 | + | |
| 560 | + | |
531 | 561 | | |
532 | 562 | | |
533 | 563 | | |
| |||
571 | 601 | | |
572 | 602 | | |
573 | 603 | | |
574 | | - | |
| 604 | + | |
575 | 605 | | |
576 | 606 | | |
577 | 607 | | |
| |||
667 | 697 | | |
668 | 698 | | |
669 | 699 | | |
670 | | - | |
| 700 | + | |
671 | 701 | | |
672 | 702 | | |
673 | 703 | | |
| |||
0 commit comments