Skip to content

fix(fields): permission-ref / position-ref cells draw the registry label, the name on title - #27970

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

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/project-thread-j9w213

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

Requested by Bill · project thread

Fixes #27861

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:用户详情页的「权限集」「岗位」两个页签,列表单元格从显示 API 名(如 organization_admin_no_bypass)改为显示目录里的标签(如 "Organization Admin"),鼠标悬停显示 API 名;目录里查不到的名字照原样显示。
  • 为什么改:管理员看不出一个用户到底持有哪些权限集,只能逐个点开;编辑表单早已显示标签,只读单元格没有。
  • 风险与回滚:只改只读显示,不改存储与写入;目录读取失败或未返回时退回显示 API 名。回滚即还原本 PR。
  • 先看:ui/packages/fields/src/widgets/RegistryRefCell.tsx(新的只读单元格)、ui/packages/fields/src/widgets/registryCatalog.ts(共享目录读取,每个数据源每种类型只请求一次)、ui/packages/plugin-detail/src/RelatedList.tsx(把字段的 widget 传给单元格类型解析的一行)。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/plugin-detail/src/__tests__/RelatedList.registryRefColumn.test.tsx,预期 3 个用例全绿;或在 showcase 里打开 Setup → Users → 任一用户 → Permission Sets,应看到权限集标签,悬停看到 API 名。
  • 需要你做的:无,席位落地。

What changes

sys_user_permission_set.permission_set and sys_user_position.position are by-name text columns declaring widget: 'permission-ref' / widget: 'position-ref'. The edit face (RegistryRefField in @object-ui/fields, not the form renderer the card names) already listed the registry with labels; no read cell did, so a user's Permission Sets and Positions tabs printed the api name.

  • A read face in @object-ui/fields (widgets/RegistryRefCell.tsx), registered under permission-ref / position-ref, which resolveCellRendererType now promotes a textual field declaring either widget to (WIDGET_CELL_RENDERER_TYPES, beside object-ref / recipient-picker). It draws the registry label with the stored name on title.
  • One read for the whole list (widgets/registryCatalog.ts): the catalog the edit picker lists, DataSource.listMetadataItems(type) (GET /api/v1/meta/:type), read once per data source and registry type and shared by every cell; a cell mounting after it settled draws the label on its first render. A failed read is not kept, so the next cell asks again. No new endpoint. RegistryRefField now imports its registryLister narrowing from that module instead of keeping its own copy; its behaviour is unchanged.
  • The fallback: a name the catalog does not hold, or holds without a label, draws as the name (same face as the text cell); so does every cell while the catalog loads, when it fails, or when no data source can list a registry.
  • The related list reaches it: RelatedList's makeCell resolved the cell key from type and format only, so the declared widget never reached the cell resolution there (the grid already passed it). It now passes widget too. Side effect named: a related-list column declaring object-ref also reaches its console face now; recipient-picker still draws its stored text there, because the related list passes no dependentValues.

Tests

  • ui/packages/fields/src/widgets/__tests__/RegistryRefCell.readFace.test.tsx — the widget picks the key; permission-ref and position-ref each draw the label with the name on title from ONE listMetadataItems call shared by several cells; a late mount draws the label at once with no second read; the fallback (an unknown name and an unlabelled one render the name); no data source, loading and a failed catalog draw the name, and a failed catalog is re-read; an empty value draws the shared No-value glyph and reads nothing.
  • ui/packages/plugin-detail/src/__tests__/RelatedList.registryRefColumn.test.tsx — the real RelatedList and data-table, one test per acceptance box: Permission Sets (label, api name on title, one catalog read for the column), Positions, and an unknown name rendering as the name.
  • Census pins updated for the two new registered keys: cellRenderers.objectLiteral-8596.test.tsx (fields) and summaryChip.badgeFitCensus-8464.test.tsx (plugin-detail, fit side 38 → 40).

Acceptance notes

  • The card's mechanism names ui/packages/components/src/renderers/form/form.tsx as the edit face; the picker is ui/packages/fields/src/widgets/RegistryRefField.tsx (form.tsx only lists the widget names it hands a data source). The catalog reused is that picker's.
  • The object-ref / recipient-picker faces live in @object-ui/app-shell, kept out of @object-ui/fields for the console's eager ui-components chunk; this card's ruling puts the registry-name face in @object-ui/fields. Its reader is the picker's own catalog call plus a small cache. CI's check:eager-closure step weighs it; this branch did not build the console locally.
  • Labels are whatever GET /meta/:type serves; the server already translates the security catalog's labels for that route, so the cell does no client translation.
  • The edit picker (RegistryRefField) still reads its catalog fresh per mount, uncached: a set authored in Studio is listed on the next form, as before.

Verification

All readings on head 8307533a (after merging origin/main), through the shared verification lock.

Targeted tests
  • pnpm --dir ui exec vitest run packages/fields/src/widgets/__tests__/RegistryRef packages/fields/src/__tests__/cellRenderers.objectLiteral-8596.test.tsx packages/fields/src/__tests__/widgetRefCells-12613.test.tsx packages/fields/src/__tests__/listCellRendererTypes-8734.test.tsx packages/fields/src/__tests__/fieldFaceSeam-13216.test.tsx packages/plugin-detail/src/__tests__/RelatedList.registryRefColumn.test.tsx packages/plugin-detail/src/__tests__/summaryChip.badgeFitCensus-8464.test.tsx packages/app-shell/src/views/widget-ref-cells/ — Test Files 10 passed (10), Tests 89 passed (89).
  • Before the merge: packages/fields/ + packages/plugin-detail/ whole — 624 files passed, 4 tests red in cellRenderers.objectLiteral-8596 (the census naming the two new keys, then fixed: 34/34); the cross-package pins (plugin-grid tests, plugin-list tests, app-shell widget-ref and pointer-card faces, plugin-tree/kanban/form, cli registered-types ratchet, components form wiring, two console services) — 396 files, 3659 tests passed.
  • pnpm --filter @object-ui/fields --filter @object-ui/plugin-detail run type-check — both Done (each runs tsc --noEmit && tsc -p tsconfig.test.json, the second covering the test files).
Ablations (one-off, restored, blob-verified)
  • RelatedList.tsx: dropping widget: def.widget from the cell resolution — RelatedList.registryRefColumn.test.tsx 3 failed (3); restored blob a15b2c84 = HEAD.
  • RegistryRefCell.tsx: drawing {name} in place of {label ?? name} — RegistryRefCell.readFace.test.tsx 5 failed / 4 passed (the four that pass are the name-fallback, no-source, loading and empty cases, which the mutation does not change); restored blob 7ff0f587 = HEAD.
Gates
  • dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, every exit 0 — including node scripts/check-sdui-manifest.mjs, pnpm check:nul-bytes, pnpm check:cross-package-test-inputs, pnpm check:test-source-alias, pnpm --dir ui exec vitest run scripts/ (169 files passed).
  • Also run: pnpm check:changeset-fixed exit 0; pnpm check:new-line-citations (ui) — 0 new citations.
  • Not run locally: the console build and its check:eager-closure budget, which CI's Build & E2E UI job runs.

Generated by Claude Code

@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tooling labels Oct 30, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

席位核对

ACCEPT · head 8307533a8934e5f809a3cfd15a47b8b5ccf27c1b · 2026-10-30T05:59Z

  • Shape: draft → main, Fixes #27861. Clause-②: no and Metadata-protocol: none. No new public export or i18n key: PositionRefCell and PermissionRefCell are registered under the widget keys but are not exported, and RegistryItemHeader is still re-exported from RegistryRefField. The changeset is patch on @object-ui/fields and @object-ui/plugin-detail.
  • Change, read (10 files, +487/−30 against origin/main):
    • A textual field that declares widget: 'permission-ref' or 'position-ref' now resolves to a read face that draws the registry label, with the stored name on title.
    • The labels come from the edit picker's own catalog (listMetadataItems). One request per data source and registry type is shared across every cell. A failed read is not kept.
    • An unknown or unlabelled name, a catalog that is still loading or failed, and a data source with no lister all draw the stored name.
    • The catalog helper moved from RegistryRefField.tsx into registryCatalog.ts unchanged, and the picker now imports it.
    • RelatedList makeCell now passes the declared widget to resolveCellRendererType, as the grid already does. This is the one line that lets a user's Permission Sets and Positions tabs reach the face. The claim's file surface was amended for it.
  • Evidence (report 6515926624):
    • On the head, 10 targeted files pass 89 tests.
    • Before the merge, all of fields and plugin-detail ran 624 files, and the one census pin that names the new keys was updated.
    • Cross-package pins: 396 files, 3659 tests passed.
    • Two ablations turn red as expected: the widget pass-through (3/3 red), and label → name (5 red, with the 4 fallback cases staying green). Both restore cleanly.
    • Both packages type-check. Derived gates: 34/34 exit 0.
  • Side effect, declared: an object-ref column in a related list now also reaches its app-shell face. A recipient-picker column there still draws stored text, because the related list passes no dependentValues. This is in the PR's Acceptance notes.
  • Overlap: PR feat(fields): every record reference shows a hover card with the target's declared highlights #27912 edits fields/src/index.tsx and RelatedList.tsx in other hunks, with no textual overlap.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure. That includes Build & E2E UI and check:eager-closure, which were not measured locally. NOT governed, 517 changed lines.
  • Landing: non-governed, all green, mergeable_state clean, so the seat lands it with pr_ready and automerge_enable.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 06:01
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 06:01
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit e15a87c Oct 30, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-j9w213 branch October 30, 2026 06:35
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/l tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A user's Permission Sets tab shows API names: permission-ref / position-ref cells have no label read face (#27521 row 14)

1 participant