You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 5174603
Browse filesBrowse the repository at this point in the historyBrowse files
fix(ui): Setup record pages show names, not ids, for sharing-rule recipients, conditions and sign-in audit rows (#30496)
<!-- claude-projects-attribution: {"github_login":"os-sales"} -->
_Requested by **Sales** · [project
thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuT8Khw8CoWCTDdkBhufE8uP)_
domain:ui#6 · os-sales · session_01L6bhgWs5eCv64CbCPwjWhV
Refs #30209 (rows 2 and the record-label half of row 3; rows 1, 3-rest,
4, 5 and 6 are not in this PR, see Acceptance notes)
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:Setup 的共享规则记录页,「接收方」显示用户/团队/岗位名称而不是 id,「条件」显示成「优先级 等于 紧急」这样的文字而不是
JSON;审计日志列表里登录行的「记录」列显示会话所属用户名,不再是用户 id。
- 为什么改:管理员排查权限问题时读不懂这些页面(#30209
实测)。列表页早已显示名称,记录页没把同行数据交给显示组件,条件字段也没有阅读态。
- 风险与回滚:只动 ui 显示层,三处改动各自独立,不改任何存储或接口;回滚即还原本 PR。条件无法用可视化表达时仍显示原始 JSON。
-
先看:`ui/packages/plugin-grid/src/RecordPointerCell.tsx`(读取等定义返回后再查记录,名称字段是引用时才
`$expand`)、`ui/packages/fields/src/widgets/FilterConditionField.tsx`(只读态的文字化)、`ui/packages/plugin-detail/src/DetailSection.tsx`。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/fields/src/widgets/__tests__/FilterConditionField.readWords-30209.test.tsx
packages/plugin-detail/src/__tests__/recordFace.siblingValues-30209.test.tsx
packages/plugin-grid/src/__tests__/ObjectGrid.recordPointerCell-12608.test.tsx`,预期全部通过;或在控制台打开一条共享规则记录,看「接收方」是人名、「条件」是一句话。
- 需要你做的:无,席位落地。
## What changes
- **Record page faces get the record** (`@object-ui/plugin-detail`).
`HeaderHighlight` and `DetailSection` hand each read cell
`dependentValues` (the staged record / the record), as the list grid
hands its row. The `recipient-picker` face reads `recipient_type` from
it, so a sharing rule's 接收方 reads the recipient's name instead of the
stored id.
- **`filter-condition` has a read face** (`@object-ui/fields`). The key
joins `WIDGET_CELL_RENDERER_TYPES` and its cell (`FilterConditionCell`,
lazy, stored text until the widget module lands) draws the widget's
read-only display. That display now says a representable criteria in
words, in the object's field and option labels, joined by the AND / OR
word, with booleans as words and both bounds of a range; the words are
the filter builder's own `filterBuilder.*` rows, so no language-pack key
is added. A criteria the builder cannot represent still reads as the
stored JSON; a non-string value reads as the text cell reads it; a
read-only widget no longer refuses to speak without `object_name`
(fields keep their api names).
- **Pointer cells name a lookup-named record**
(`@object-ui/plugin-grid`). `RecordPointerCell`'s batched read now waits
for the target definition (already in flight) and adds `$expand:
[nameField]` when the object's name field is a reference type the viewer
may read (`buildExpandFields` over that one field, gated by `checkField`
once the policy has answered). `sys_session` is named by `user_id`, so
the audit list's sign-in rows read "Dev Admin" instead of the user id.
Any other name field is read exactly as before, with no `$expand`.
## Tests
- New
`ui/packages/fields/src/widgets/__tests__/FilterConditionField.readWords-30209.test.tsx`
(zh provider): one condition reads `优先级 等于 紧急`; an OR group with a
boolean reads `优先级 等于 低 或 已完成 等于 是`; a nested criteria stays the stored
JSON (control).
- New
`ui/packages/plugin-detail/src/__tests__/recordFace.siblingValues-30209.test.tsx`:
a probe face registered under `recipient-picker` receives the record
from the highlights strip and from the details body.
-
`ui/packages/plugin-grid/src/__tests__/ObjectGrid.recordPointerCell-12608.test.tsx`
gains a top-level `describe`: a session row names its user and the read
expands only `user_id`; a text-named record is read with no `$expand`
(control).
- Two registry censuses gain the new key's row:
`cellRenderers.objectLiteral-8596` and `summaryChip.badgeFitCensus-8464`
(fit side 40 → 41).
## Readings (head `f122316d`, base `c5800818`)
- Positive control: with the three source files restored to the base, 5
of the new assertions are red and both controls stay green.
- Ablations (each restored, `git diff HEAD` empty): `DetailSection`
`dependentValues={data}` removed → the details case red (1 failed / 1
passed); the words branch disabled (`if (false)`) → 2 failed / 1 passed;
the `$expand` spread deleted → 1 failed / 4 passed.
- Suites: `fields`, `plugin-detail`, `plugin-grid` and the app-shell
widget-ref-cells / record-preview directories: the only reds were the
four registry censuses, now carrying the new key (rerun 36 files / 453
tests green).
- Type-check: `turbo run type-check --filter=@object-ui/fields
--filter=@object-ui/plugin-detail --filter=@object-ui/plugin-grid`,
55/55.
- Gates: the 35 derived dispatch gates exit 0 (`vitest run scripts/`
rerun alone: 171 files passed); ui `check:spec-symbols`,
`check:i18n-keys`, `check:unreferenced-sources`,
`check:side-effects-array`, `check:phantom-deps`,
`check:esm-specifiers`, `check:i18n-drift`, `check:new-line-citations`
and root `check:doc-authoring` exit 0. eslint on the changed files: 0
errors.
## Acceptance notes
Re-measured on `origin/main` `c5800818` with app-showcase (`objectstack
dev --seed-admin`) and the console on vite, zh-CN, before any edit:
| Row | Reading on main | This PR | Not shipped: reason · owning lane |
| --- | --- | --- | --- |
| 1 | 林伟's 权限集 tab: `0`, 暂无相关记录 | — | The tab is page metadata
(`packages/platform-objects/src/pages/sys-user.page.ts`, a
`record:related_list` over `sys_user_permission_set`). Showing effective
access needs a page node that calls the explain door, i.e. a
page-component vocabulary entry in `packages/spec` plus the page edit in
`packages/platform-objects`, then the ui block. ⛔ `packages/**` in this
claim · spec + platform-objects (server) lanes, then ui |
| 2 | 接收方 `zlom5o5m8OyCwF3aBgywwFWOHKJ03mou`; 条件 `{"priority":"urgent"}`
| 接收方 林伟; 条件 优先级 等于 紧急 | — |
| 3 | 记录 column: sign-in rows `05bdsJ9C…` (a `sys_session`, named by its
`user_id` lookup); other rows already named | sign-in rows name the user
| Object labels: `sys_platform_setting_audit` (and others) have no zh-CN
row in `packages/platform-objects` translations, so the label is the
English source · i18n source, server/platform lane. "One sign-in writes
several rows" and a default view that hides them are the audit writer
and the object's list views in `packages/**` · server lane |
| 4 | not measured (claim ⛔) | — | What is secret is a server decision ·
server lane |
| 5 | not measured (claim ⛔, reading only) | — | security-sensitive
picker filtering · security lane |
| 6 | queue record shows only its label; members only under Queue
Members | — | `sys_queue_member.queue` is a text field holding the queue
name, not a lookup, so no related list is synthesized and none can be
authored without metadata: a lookup, or a `sys_queue` page with a
members list, both in `packages/plugins/plugin-sharing` · server lane |
- Noted, not filed: on the same pages the Setup navigation and the
`sys_queue` labels ("Queues", "Queue", "Display Label") read English
under zh-CN; that is translation coverage in `packages/**`.
- Trade-off: a filter-condition cell in a grid column now loads the
widget chunk once per page that shows one (stored text until it lands).
## Verification
Screenshots (zh-CN console, 1440×900 @2x) on the never-merged evidence
branch:
| | Before (main) | After (this PR) |
| --- | --- | --- |
| Sharing rule record (row 2) |

|

|
| Audit list 记录 column (row 3) |

|

|
Evidence commit `994f8a84` (removed again in `165c14ce`, so the PR diff
carries no images).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01L6bhgWs5eCv64CbCPwjWhV
---------
Co-authored-by: Claude <noreply@anthropic.com>
fix(ui): Setup record pages name a sharing rule's recipient and read its condition in words, and the audit list names a sign-in row's session by its user
8
+
9
+
Clause-②: no
10
+
Metadata-protocol: none
11
+
12
+
-**`@object-ui/plugin-detail`.** The record page's highlights strip and details body hand each read face the record as `dependentValues`, as a list grid hands its row. A `recipient-picker` value is an id that means something only beside its `recipient_type`, so a sharing rule's page read the stored user id under 接收方 where its list read the user's name; it now reads the name.
13
+
-**`@object-ui/fields`.**`widget: 'filter-condition'` has a read face of its own: a list or detail cell draws the criteria through the widget's read-only display, which says it in the object's field and option labels ("Priority equals Urgent"; an OR group joined by its word, a boolean as a word). A criteria the builder cannot represent still reads as the stored JSON, and an empty one is the empty cell. A read-only widget no longer waits for its `object_name` to say anything: without it, the fields keep their api names.
14
+
-**`@object-ui/plugin-grid`.** A pointer cell (`referenceVia`) reads the target record with its name field expanded when that field is a reference the viewer may read, so a record named by a lookup reads as the referenced record's name: the audit list's sign-in rows name the session by its user instead of printing the user id. Any other name field is read as before, with no `$expand`.
0 commit comments