Skip to content

feat(app-shell): Studio opens an off-nav list view on its object's page, lists only views no dropdown reaches, and reads form views as forms - #30401

Open
objectstack-fleet[bot] wants to merge 6 commits into
mainfrom
claude/project-thread-5r0o5c
Open

objectstack-fleet[bot] wants to merge 6 commits into
mainfrom
claude/project-thread-5r0o5c

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

domain:ui#2 · os-bill · session_01Utp6Cb5R6JDdfyvtj3dPR2

维护者速读

  • 改了什么:Studio 界面里,从「不在导航中 → 视图」打开列表视图,现在落到对象页(标题 对象 / 视图 ▾),条件格式化和视图表单分节一并搬到右侧面板;有导航入口的对象,其列表视图不再重复列在该分组;表单视图显示为「线索表单」这类可读名字,分组标题按内容写「表单视图 / 视图 / 表单视图与列表视图」,表单视图的「视图类型」读出 简单 / 标签页 / 向导,不再是「simple(未找到)」。
  • 为什么改:Studio Interfaces: choose an object's view from a dropdown at the top of the preview, in the object's title, the way the running list does #30046 Scope 6–8(裁定 A,6651738887)。同一个列表视图以前有两个页面、两套面板,导航里已能到达的视图又在「不在导航中」重复出现,表单视图名字是 crm_lead.form 这类内部名。
  • 风险与回滚:只动 Studio 前端(app-shell 与 studio 语言包三个新键),不动元数据、spec 或服务端。共用的视图检查器只在表单视图上换类型清单,列表视图那一侧不变并有测试钉住。回滚即 revert 本 PR。
  • 先看:StudioDesignSurface.tsx 的 pickOffNav / listViewDoorOf 与离线分组过滤,ListViewMoreSection.tsx(新),ViewVariantInspector.tsx 的 useTypeOptions。
  • 两分钟验证:打开示例 CRM 的 Studio → 界面:「不在导航中」只剩「表单视图」4 项;点「线索表单」,视图类型显示「简单」;访问 ?surface=view:crm_lead.pipeline 落到「线索 / 线索看板」。
  • 需要你做的:本 PR 新增三个 i18n 键(Clause-② widening),席位需安排 TIER_DEFAULT 评审;其余无。

Fixes #30046

Clause-②: yes (widening) — three new published @object-ui/i18n Studio keys: engine.studio.if.offNav.viewForms, engine.studio.if.offNav.viewMixed, engine.studio.if.offNav.formName (en + zh). No accept set narrowed.
Metadata-protocol: none — Studio UI only: no metadata key, spec schema, server route or stored shape is added or read differently; the view items are read through the existing /meta/view list (drafts overlaid) and written through the existing list-view draft path.

What changes

Scope 6–8 of #30046, ruled as option A (6651738887). Scope 1–5 landed in #30175 and are untouched.

  • Scope 6 — a list view opens on its object's page from every door. Picking a list view under 不在导航中 → 视图, or following a link to the view itself (?surface=view:OBJECT.KEY), now lands on the object page with its header dropdown (object / view ▾) on that view: the object's nav entry when it has one, else the object itself with no entry (?surface=object:OBJECT&view=…, which a reload or a shared link opens again). The panel there gains ListViewMoreSection (new): the view's 条件格式化 (ConditionalFormattingEditor, whose CEL verdicts now hold the list-view autosave the way they held the view page's Save) and the spec authoring form's sections for a view, pruned of every key the panel already edits, so no setting has two controls. A form view, and a view a read-only base's pair adds (addedIn), still open as themselves. Studio on zh-CN still mixes languages and terms: view properties panel, flow nodes, publish sheet labels, and 仪表板 beside 仪表盘 #30039 owns translating those sections.
  • Scope 7 — the 视图 group lists what the dropdowns do not reach. A list view whose object has a nav entry is no longer listed, a view only drafted in the package included (withDraftViewBindings reads the drafted rows' object/viewKind from the draft-overlaid list, fail-soft). The list views of an object with no entry stay listed. The only-customized filter is unchanged.
  • Scope 8 — form views read as forms. A form view is listed by its label, else as the object's name plus 表单 ("Lead form", 「线索表单」, with · key for a non-default form); the group's heading says what it holds (表单视图, 视图, or 表单视图与列表视图). In ViewVariantInspector, a form view's 视图类型 reads the form-variant schema's type enum (simple / tabbed / wizard, labelled with the existing engine.inspector.pageBlock.option.formType.* keys) and defaults to simple; a list view's picker is byte-for-byte the same roster as before.
  • ObjectListViewInspector.tsx: the hook gains openView(surface, viewId); the panel appends ListViewMoreSection as an independent block after the sort block, with no existing section reordered (seat 4's [Decision] Selection-bar actions cannot be configured in Studio: should the view panel offer them? #30089 adds a section in the same render region). fix(app-shell): a draft-only object's nav entry opens its drafted default list view in Studio Interfaces #30315's listViewTargetOf hunks are not touched. StudioDesignSurface.tsx's restoreOriginal / publishNonce region (Studio: after 恢复原版 the rail keeps the customized mark and 仅看定制 (1) until a reload #30238) is not touched.

Tests

  • New InterfacesPillar.offNavListViews-30046.test.tsx (13 cases): Scope 7 filtering with controls (an object with no entry stays listed, a drafted view included), Scope 8 names and the three headings, Scope 6 object page landing, the panel's 条件格式化 and spec sections, a second pick on the same page, ?surface=object:…&view= and ?surface=view:… links with and without an entry, CONTROL that a form view still opens as itself, and the CEL hold (autosave blocked on a bad rule, saved once fixed).
  • New ViewVariantInspector.formViewType-30046.test.tsx (8 cases, en + zh): a form view reads its layout and offers only the form roster; a form view with no type reads Simple; CONTROL a list view still offers the list types; CONTROL an off-enum list type is still flagged.
  • packageSurfaces.test.ts: 3 cases for viewBindingOf / withDraftViewBindings.
  • InterfacesPillar.offNavItems-26889.test.tsx and InterfacesPillar.offNavDeepLink-28561.test.tsx: their off-nav view fixture is now a form view (web_form), since a list view of an object with an entry is no longer listed there; what they assert is unchanged.
  • Red first: with origin/main's five source files checked out, 17 of the new/changed cases fail (5 files); all pass on this branch.
  • Ablations (scripts/ablation-replace.mjs, each restored with blob == HEAD and an empty git diff HEAD): Scope 7 filter → 3 red; the list-view door → 5 red; the form-type roster pick → 2 red (both locales); the CEL hold term → 1 red.

Acceptance notes

  • Card Acceptance 5, browser checks on both package kinds (branch head before the main merge, which brought no ui change), screenshots in the project files under ui-seat2/card-30046/screenshots/:
    • Read-only example CRM (examples/app-crm): 不在导航中 lists only 表单视图 (4): 活动表单, 线索表单 · web_to_lead, 线索表单, 商机表单; the default landing panel carries 条件格式化 and 基础信息 below the sort block; ?surface=view:crm_lead.pipeline lands on 线索 / 线索看板 at surface=object:crm_lead&nav=nav_leads&view=crm_lead.pipeline; 线索表单 opens as a form view whose 视图类型 reads 简单.
    • Writable throwaway package (one object with a nav entry, one without, all views drafted): the heading reads 表单视图与列表视图 with Case表单 and Open cases only; the entry object's drafted All tasks / My tasks are absent from the group and present in its header dropdown; Open cases lands on Case / Open cases at surface=object:ws_case&view=ws_case.open, survives a reload, and its panel shows the view's CEL rule (CEL 有效).
  • Observed, not in this card's scope: the form view inspector's header still reads the item name (crm_lead.form), and its spec sections (Layout, Columns, Title) are English in zh, which is Studio on zh-CN still mixes languages and terms: view properties panel, flow nodes, publish sheet labels, and 仪表板 beside 仪表盘 #30039's.
  • Line budget: 1153 insertions, 41 deletions (1194 changed lines, about half of them tests), under the ~1200 stop.

Verification

On the final tree (head 9eff7192, origin/main 870ebce3 merged in), every exit code recorded to a file before any pipe:

  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack <14 changed paths>: 35 commands, all exit 0 (pnpm --dir ui exec vitest run scripts/: Test Files 170 passed | 2 skipped, Tests 4985 passed | 2 skipped). --ran reconciliation: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN.
  • node scripts/check-sdui-manifest.mjs: exit 0 (and --self-test exit 0).
  • pnpm --filter @object-ui/app-shell --filter @object-ui/i18n lint: exit 0, 0 errors (warnings only, existing patterns).
  • pnpm --dir ui run check:new-line-citations: exit 0. pnpm check:nul-bytes: exit 0.
  • pnpm exec turbo run type-check --filter=@object-ui/app-shell --filter=@object-ui/i18n --concurrency=2 (under os-verify-lock): 69/69 tasks, exit 0.
  • Targeted re-run after the merge: the five changed/new test files, Test Files 5 passed, Tests 50 passed.
  • Before the merge, every test file importing a changed module plus every InterfacesPillar.* and StudioDesignSurface.* test (167 files): 1220/1221, the one red being the zh lazy-catalogue race in the new inspector test, since fixed (top-level await loadStudioCatalogue('zh')) and green three runs in a row.

Generated by Claude Code

…s object's page; the group lists what the dropdown does not reach; a form view reads a real type

WIP: the three remaining scopes of the Interfaces view dropdown card, with
their tests; not yet run.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CXDf4Yt5PtKZFbtLVD
…e opened from 不在导航中; controls stay controls

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CXDf4Yt5PtKZFbtLVD
… first; changeset

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CXDf4Yt5PtKZFbtLVD
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#2 · os-bill · session_01Utp6Cb5R6JDdfyvtj3dPR2

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 9eff719240e8b21f3877c663e4f1b211ad4628f8
Local-runs: none

Reviewed 2026-11-05T09:45Z. Face: Clause-②: yes (widening) declaration only (changeset line). The diff touches no packages/spec/src/** and no governed rule text. It does not narrow anything.

① Derived judgments

  • @object-ui/i18n gains three keys. They are engine.studio.if.offNav.viewForms, engine.studio.if.offNav.viewMixed and engine.studio.if.offNav.formName ({object} placeholder). Each is added to both en.ts and zh.ts, and no existing key is renamed or removed. The keys are additive and widen the bundle's published key set. ✔
  • PackageSurface gains optional object? / viewKind? members, and viewBindingOf / withDraftViewBindings are new exports. They live in app-shell's internal studio-design/packageSurfaces.ts. The fields are optional and appear only on view rows, so every existing reader keeps its shape. ✔
  • ViewVariantInspector reads its 视图类型 options from getFormVariantSchema() for a form-family view. The source enum is the spec's FormViewSchema.type, read as served and not restated here. The list family keeps getListVariantSchema() unchanged. A form view with no type now reads the spec default simple, where it used to read grid. Nothing new is written: the value is only displayed until the author commits a pick. ✔
  • ListViewMoreSection drives the generic SchemaForm from the spec's list-variant JSONSchema plus getViewForm. It prunes the keys the panel already edits and keeps no per-key field list. repinned() restores the pruned keys from the body on every emit, so a form edit cannot move them. ✔
  • The list-view autosave is held while a conditional-formatting CEL verdict is non-zero. It reuses the existing engine.studio.held.inspectorInvalid clause, which adds to what the panel holds (it holds more edits, not fewer). It matches the Save hold on the view's own page (objectui#4527). ✔
  • New door: ?surface=object:OBJECT for an object that has no nav entry. This deep-link shape is new for the Studio and the mirror already wrote object: leaves. It only resolves when the package lists a list view of that object; otherwise the off-nav fallback applies as before. ✔

② Semver level

The changeset sets @object-ui/app-shell: patch and @object-ui/i18n: patch. Both are additive with no removal, which matches repo precedent for Clause-②: yes (widening) (for example .changeset/27193-recompute-home-amounts.md, 27195-…). The level is consistent with the declaration. ✔ Metadata-protocol: none is correct, since no server or protocol path is touched.

③ Boundary flags

Implemented-by: claude/project-thread-5r0o5c
Reviewed-by: session_01Utp6Cb5R6JDdfyvtj3dPR2

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#2 · os-bill · session_01Utp6Cb5R6JDdfyvtj3dPR2

维护者速读

  • 改了什么: Studio 界面里有三处改动。
    1. 从「不在导航中 → 视图」打开列表视图,或者直接访问 ?surface=view:对象.视图 链接,现在都会落到对象页(对象 / 视图 ▾),条件格式化和视图表单分节也一起搬进了右侧面板。
    2. 有导航入口的对象,它的列表视图不再在该分组里重复出现。
    3. 表单视图显示为「线索表单」这样的可读名字;分组标题按实际内容写成「表单视图」「视图」或「表单视图与列表视图」;表单视图的「视图类型」读出「简单 / 标签页 / 向导」,不再显示「simple(未找到)」。
  • 为什么改: Studio Interfaces: choose an object's view from a dropdown at the top of the preview, in the object's title, the way the running list does #30046 Scope 6–8(裁定 A,6651738887)。同一个列表视图原先有两个页面、两套面板;导航里已经能到达的视图又在「不在导航中」重复出现;表单视图显示的是 crm_lead.form 这样的内部名。
  • 风险与回滚: 改动只在 Studio 前端:app-shell 加三个新的 studio 语言包键。不动元数据、spec 和服务端。共用的视图检查器只在表单视图上换类型清单,列表视图那一侧不变,并有测试钉住。回滚办法是撤销本 PR。
  • 先看: StudioDesignSurface.tsx 里的 pickOffNav / listViewDoorOf;新文件 ListViewMoreSection.tsx;ViewVariantInspector.tsx 里的 useTypeOptions。
  • 两分钟验证: 打开示例 CRM 的 Studio → 界面。「不在导航中」应只剩「表单视图」4 项;点「线索表单」,视图类型应显示「简单」;访问 ?surface=view:crm_lead.pipeline,应落到「线索 / 线索看板」。
  • 需要您做的: 无。本 PR 不在受管面,共 1194 行,三个新 i18n 键的 TIER_DEFAULT 契约复核已经 PASS(6654816602)。席位会经合并队列落地。
  • 席位意见: ACCEPT。

席位核对 — ACCEPT · domain:ui#2 · head 9eff719240e8b21f3877c663e4f1b211ad4628f8

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 11:31
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 5, 2026 11:31
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 5, 2026
…-5r0o5c

ViewVariantInspector.tsx: main moved the list-view type labels to
viewTypeLabels.ts (imported as typeLabel); this branch's form-layout
labels (FORM_TYPE_LABELS, formTypeLabel) are kept beside that import.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CXDf4Yt5PtKZFbtLVD

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio Interfaces: choose an object's view from a dropdown at the top of the preview, in the object's title, the way the running list does

1 participant