Skip to content

feat(studio): Add view in the Interfaces list-view panel creates a kanban, calendar or other list view - #27870

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-gkc8sq
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-gkc8sq

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

Requested by Bill · project thread

维护者速读

  • 改了什么:Studio 界面支柱里,对象的列表视图属性面板多了「添加视图」按钮。点开就是控制台已有的新建视图对话框:先选视图类型(表格、看板、日历、画廊……,来自 spec 的列表视图类型),再按字段标签选该类型必填的字段(看板的分组字段、日历的开始日期和标题字段),再填名称和键。视图直接完整地存进本包草稿,随后属性面板和画布都切到这个新视图,面板上有「返回 …」回到导航入口原来打开的视图。
  • 为什么改:以前面板只能编辑入口打开的那一个视图(通常是默认表格),Studio 里没有任何办法新建看板、日历等视图(Setup and Studio: suggestions from the 18.3.0 RC browser walkthrough: Setup naming and machine values, invitation and user onboarding, permission-set authoring, dialog focus, Studio first run, validation and flow builders, and publish-panel wording #27521 第 31 行)。
  • 风险与回滚:只改前端;新视图从不设为默认视图,导航入口不改,默认表格一个字节都不写;用的是控制台加视图入口同一个构建器(buildNewViewSpec + viewEnvelope),所以草稿里不会出现半成品视图;键已被占用时什么都不写、对话框不关、提示原因。回滚即 revert 本 PR。
  • 先看:ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx(createView、面板里的「添加视图」与「返回」)、ObjectListViewInspector.addView-27836.test.tsx、StudioDesignSurface.tsx(打开对话框前先发出面板里未保存的修改)。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/ObjectListViewInspector.addView-27836.test.tsx,预期 1 个文件 4 条全部通过(看板、日历、返回入口视图、键重名被拒)。
  • 需要你做的:无,席位落地。

Fixes #27836

Clause-②: no
Metadata-protocol: none

What changes

Measured first, on main at 9ae6384e. The Interfaces pillar's list-view panel (ObjectListViewInspector) edits exactly one view: the one the open nav entry lands on (listViewTargetOf), usually the object's default grid. Nothing in Studio creates a view of another type. Once a view exists, the panel already edits any list view's columns, filter and sort, and a kanban's card section (KanbanCardSection); a calendar, gallery, timeline, gantt, map, chart or tree has no section of its own (see Acceptance notes). The canvas already renders whatever view the panel holds (StudioCanvasListViewContext feeds object-view's listViews), so a kanban or calendar view in the panel shows as a board or calendar on the canvas.

"Add view" is a button at the top of the panel. It opens the console's existing CreateViewDialog, unchanged:

  • the type grid is the dialog's total record over ListViewVisualization, which @object-ui/core derives from the spec's view type enum, so no list is kept here;
  • the dialog asks the chosen type's required fields first and keeps Create disabled until each is picked; its field pickers here read the same fields as the panel's own pickers (the object's fields minus the platform's hidden system columns), shown by label;
  • then a label and a key.

On Create, the new hook method useObjectListViewDraft().createView(payload):

  1. builds the body the console's add-view door builds: buildNewViewSpec (with the panel's seed columns as the fallback, which mirrors them into kanban.columns as the spec requires) wrapped by viewEnvelope (OBJECT.KEY, viewKind: 'list', the label, config.data bound to the object);
  2. refuses a name a view already holds, published (client.list('view')) or drafted in any package (client.listDrafts({ type: 'view' })), writing nothing, as the pillar's New dashboard / report / page create does;
  3. saves it to the package draft with If-None-Match: *, so the door also refuses one drafted between that read and the save;
  4. then the panel and the canvas show it. The choice is stamped with the nav entry it was made on, so it expires by construction when another leaf opens. "Back to …" shows the entry's view again.

The view is born complete, so the draft never holds a half-made view and the held-input rule has nothing to hold. It is never the object's default (isDefault is not written), and the nav entry is not changed: the running app lists every view of the object in its view switcher. A refusal (taken key, or the door's own refusal) keeps the dialog open with the author's input, as CreateViewDialog's contract asks, and a toast says why in the designer locale.

Opening the dialog first sends the panel's pending edit (the pillar's list-view autosave flush), because the view the panel shows changes once the new one is created and the autosave drops an edit begun on another target.

Tests

ObjectListViewInspector.addView-27836.test.tsx: the REAL hook, panel and Create View dialog over a REAL MetadataClient, whose transport judges every view PUT with the installed spec's view schema (422 on refusal):

  • a kanban: one PUT, to acme_task.pipeline_board in the package with If-None-Match: *, accepted by the spec, kanban.groupByField: 'status', no isDefault, no write to the default view; the panel then shows the board with its card section;
  • a calendar: calendar: { startDateField: 'due_date', titleField: 'title' }, picked by label, accepted; the panel shows it;
  • "Back to …" returns the panel to acme_task.default;
  • a taken key: no PUT, the dialog stays open, the toast names the key, the panel stays on the default view.

Acceptance notes

  • Editing a non-grid view's own settings is not built here. After creation, a kanban's card section is editable (it already was); a calendar's start-date and title fields, and the type-specific blocks of gallery, timeline, gantt, map, chart and tree, are set only by the dialog. The panel still edits their columns, filter and sort. Filed by the seat as Studio list-view inspector: edit a non-grid view's own settings (calendar start date and title, gallery, timeline, gantt, map, chart, tree) #27895.
  • A view created here is reopened in Studio only through a nav entry that names it. The panel shows the view it created until another leaf opens; there is no view switcher inside the panel. In the running app the view is in the object's view switcher once published. Filed by the seat as Studio list-view inspector: switch between an object's list views inside the panel, so a view made with Add view can be reopened #27896.
  • The dialog's own copy (type names, field prompts) comes from the console bundle (console.objectView.*, through useObjectTranslation), so it follows the app's language rather than the Studio's designer locale; the panel's new strings are in the studio bundle (en, zh).
  • Publishing: the view is an ordinary package draft (client.save('view', …, { mode: 'draft', packageId })), published with the package like every other Studio draft; not exercised in a browser here.
  • No docs page under content/docs/ describes this panel; none was changed.

Verification

Readings for this head are in the report comment on #27836 (tests, ablation, type-check, the derived gate list reconciled with --ran).

… chosen type and opens it

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

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

席位核对

ACCEPT · head a2a002b50d98e56eb6bbfbe3f489027ad7e6e47a · 2026-10-30T02:55Z

  • Shape: draft → main, Fixes #27836 on its own line, no other card number beside a closing keyword. Clause-②: no and Metadata-protocol: none match the claim; @object-ui/app-shell (private: true) plus three add-only studio keys (en, zh). No contract review owed.
  • Premise, measured: "Add view" in the list-view inspector reuses app-shell's own CreateViewDialog: view types come from the spec-derived ListViewVisualization, not a local list, and the type's required fields are picked by label up front. The view body is built with buildNewViewSpec + viewEnvelope. A taken name is refused after reading both the published list and drafts. The view is saved as a package draft with If-None-Match: *, then the panel and canvas switch to it with "Back to …". It writes no isDefault and changes no nav entry, so the default grid is unchanged.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure; mergeable_state clean. check-governed-merges --pr 27870: NOT governed (0 of 6 paths), 452 changed lines.
  • Accepted deviations: the PR's attribution line links the card thread, not the seat thread (same project, same requester). Publishing a created view was not exercised in a browser; it is an ordinary package draft.
  • Out of scope: editing a non-grid view's own settings → Studio list-view inspector: edit a non-grid view's own settings (calendar start date and title, gallery, timeline, gantt, map, chart, tree) #27895; a view switcher inside the panel → Studio list-view inspector: switch between an object's list views inside the panel, so a view made with Add view can be reopened #27896 (the seat added both numbers to the body). The dialog's copy following the app language rather than the Studio locale stays a note.
  • Landing: non-governed, all checks green, mergeable_state clean ⇒ the seat lands it (pr_ready + automerge_enable).

Generated by Claude Code

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/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio Interfaces: an Add view with a type choice (grid, kanban, calendar, …) in the list-view inspector (#27521 row 31)

1 participant