Skip to content

Commit d3d70d3

Browse files
fix(example-showcase): label the project and invoice owner text field "Owner Email" (#28008)
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh <!-- claude-projects-attribution: {"github_login":"os-bill"} --> _Requested by **Bill** · [project thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgDFH4S5pR1C8YvYCWWsZfXx)_ Fixes #27916 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:showcase 的项目(`showcase_project`)和发票(`showcase_invoice`)上自带的文本字段 `owner` 改名显示为 "Owner Email"(中文 负责人邮箱),API 名仍是 `owner`。 - 为什么改:平台给这两个对象注入的 `owner_id`(用户查找字段)也叫 "Owner",管理员在字段列表、选择器、筛选里看到两个 "Owner",只能靠 API 名分辨;该字段在种子数据里存的就是负责人的邮箱。 - 风险与回滚:只改示例应用的两个显示标签和中英文翻译,不改字段名、数据、流程或权限规则;回滚即 revert 本 PR。 - 先看:`examples/app-showcase/src/data/objects/project.object.ts`、`examples/app-showcase/src/data/objects/invoice.object.ts`、`examples/app-showcase/src/system/translations/index.ts`。 - 两分钟验证:`pnpm dev` 打开 showcase 的项目或发票列表,点列设置或筛选,预期只看到一个 "Owner"(用户)和一个 "Owner Email"(文本)。 - 需要你做的:无,席位落地。 ## What changes `showcase_project` and `showcase_invoice` each declare a text field `owner` labelled "Owner". The registry also injects `owner_id`, a `sys_user` lookup labelled "Owner", so each object listed two "Owner" fields in the field grid, pickers and filters. The authored field is now labelled **"Owner Email"** on both objects, with the zh-CN translation **负责人邮箱**. The label comes from what the field holds in the seed rows: - `showcase_project.owner` holds the provisioned persona emails (`ADMIN_EMAIL`, `PHONE_DEMO_USER.email`, `AUDITOR_DEMO_USER.email`). The notify flows read it as an email-shaped recipient, as the seed's header comment explains. - `showcase_invoice.owner` holds `ada@example.com`-style addresses. The `showcase_contributor` row-level-security rule compares it to `current_user.email`, and the source comment above the field already called it "Owner email". The API name stays `owner`, so seeded rows, flows (`record.owner`), the RLS rule and every test that names the field are unchanged. The translation bundle follows in both locales it carries (`en` and `zh-CN`). The platform's zh-CN label for `owner_id` is 所有者 (`i18n-resolver` in `@objectstack/spec`), so the zh-CN labels stay distinct too. Files: the two object files, `src/system/translations/index.ts` (four `owner` entries) and a patch changeset for `@objectstack/example-showcase`. The root `.changeset/config.json` ignores only `@object-ui/example-*`, not this package, and an earlier showcase changeset set the precedent. ## Tests <details><summary>Registry reading, fix and control (in-process ObjectQL registry, the two objects registered as the app registers them)</summary> A throwaway vitest file, deleted after the run (`git status` clean), registered `Project` and `Invoice` in a real `ObjectQLPlugin` registry and printed the stored field labels. On this branch (head 832181e): ``` READING showcase_project: owner.label="Owner Email" owner_id.label="Owner" owner_id.reference=sys_user fields-labelled-Owner=["owner_id"] READING showcase_invoice: owner.label="Owner Email" owner_id.label="Owner" owner_id.reference=sys_user fields-labelled-Owner=["owner_id"] ``` Control: the two object files restored to the base commit 5e1342a (tree only), with the same run: ``` READING showcase_project: owner.label="Owner" owner_id.label="Owner" owner_id.reference=sys_user fields-labelled-Owner=["owner_id","owner"] READING showcase_invoice: owner.label="Owner" owner_id.label="Owner" owner_id.reference=sys_user fields-labelled-Owner=["owner_id","owner"] ``` The files were restored from `HEAD` afterwards. `git diff HEAD` on them was 0 bytes and the blob hash matched `HEAD`. </details> <details><summary>Showcase package, on the merged head 63aaa12</summary> - `pnpm --filter @objectstack/example-showcase run typecheck`: exit 0 - `pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2`: Test Files 41 passed (41), Tests 505 passed (505) - Run under `os-verify-lock.sh`, joined with `&&` after rebuilding the three dependencies the merge from `main` touched: VERDICT command-exit 0 </details> ## Acceptance notes - No test pinned the label "Owner" on either object's `owner` field. I searched `examples/app-showcase/**`, `ui/**` (fixtures, e2e specs), `packages/qa/dogfood`, `packages/lint` and the root folders for "Owner" next to `showcase_project` or `showcase_invoice`. The `ui/e2e/live/record-history-display.spec.ts` "Owner" assertions read `showcase_account.owner_id`, not these fields. So no test reads the new label, and no ablation applies. - `ui/apps/console/src/services/approvalRequestsDataSource.servedPageSummaryAmount-12534.test.tsx` keeps an inline copy of `showcase_invoice` (its header dates the copy to objectstack `9e0945cf4`) with `owner` labelled "Owner". It asserts nothing about that label, and it describes a dated snapshot, so I left it alone. - No new test pins the label. A label is display copy, and the card's ruling puts a platform-side guard against an authored label that matches an injected one out of scope, as a separate triage question. - The live `GET /api/v1/meta/object` reading was not taken. `pnpm dev -- --fresh` stopped at its prereq check because the Console's `ui/` packages had no build output in this worktree. The in-process registry reading above stands in for it. ## Verification <details><summary>Derived gates, on the merged head 63aaa12</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 45 commands. Each was run with its exit code captured before any pipe, then reconciled with `--ran`: ``` Run reconciliation — 45 derived, 45 run, 0 NOT-MEASURED, 0 UNRUN. ✓ dispatch-gates --ran: 45 derived famil(ies) accounted for — 45 run, 0 NOT-MEASURED (a DERIVED zero — all 45 recorded an exit code and none of them is 3). ``` All 45 exited 0. `pnpm check:changeset-fixed` was also run (its roster lives under `.changeset/`): exit 0. `check:dual-build-cjs-loads` first stopped at PREREQUISITE NOT MET because seven packages outside the showcase closure had no build output. I built those seven, and it then passed. CI owns the type-check lanes, the path-scheduled jobs and the repo-wide scans. </details> --- _Generated by [Claude Code](https://claude.ai/code/session_01Utp6CbDAucNyQ4UtzCJKyh)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent e199adf commit d3d70d3

4 files changed

Lines changed: 22 additions & 7 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@objectstack/example-showcase': patch
3+
---
4+
5+
Clause-②: no
6+
Metadata-protocol: none
7+
8+
The showcase's project and invoice objects no longer show two fields called "Owner". Their own `owner`
9+
text field, which holds the owner's email address, is now labelled "Owner Email" (负责人邮箱 in zh-CN),
10+
so the platform's `owner_id` user lookup is the one field labelled "Owner" in the field grid, pickers and
11+
filters. The API name stays `owner`, so seeded rows, flows, permission rules and anything else that
12+
reads `record.owner` are unchanged.

‎examples/app-showcase/src/data/objects/invoice.object.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ export const Invoice = ObjectSchema.create({
103103
// permission set scopes invoice SELECT to `owner = current_user.email` (email
104104
// is the unique, seedable identifier), so a contributor sees only their own
105105
// invoices; because `showcase_invoice_line` is `controlled_by_parent`, the
106-
// lines follow automatically (ADR-0055). Mirror of `project.owner`.
107-
owner: Field.text({ label: 'Owner', maxLength: 200 }),
106+
// lines follow automatically (ADR-0055). Mirror of `project.owner`, and
107+
// labelled apart from the platform-injected `owner_id` lookup ("Owner").
108+
owner: Field.text({ label: 'Owner Email', maxLength: 200 }),
108109
// Region the sale was booked in — the invoice-side target of the Revenue
109110
// Pulse dashboard's shared "region" filter (framework#2501): accounts map
110111
// the same filter to their own `sales_region` via `filterBindings`.

‎examples/app-showcase/src/data/objects/project.object.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ export const Project = ObjectSchema.create({
9090
}),
9191
start_date: Field.date({ label: 'Start Date' }),
9292
end_date: Field.date({ label: 'Target End Date' }),
93-
owner: Field.text({ label: 'Owner', maxLength: 200 }),
93+
// The owner's email, as text. Labelled apart from the platform-injected
94+
// `owner_id` lookup, which is the one field here labelled "Owner".
95+
owner: Field.text({ label: 'Owner Email', maxLength: 200 }),
9496
// Multi-value fields — the payload for the grid's *bulk-edit* showcase. A
9597
// multiselect (fixed options) and a multi-user field are exactly the two
9698
// shapes that, before #2185, the bulk dialog could not set: its people /

‎examples/app-showcase/src/system/translations/index.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const ShowcaseTranslationBundle = {
2626
fields: {
2727
name: { label: 'Project Name' },
2828
account: { label: 'Account' },
29-
owner: { label: 'Owner' },
29+
owner: { label: 'Owner Email' },
3030
status: { label: 'Status' },
3131
health: { label: 'Health' },
3232
budget: { label: 'Budget' },
@@ -226,7 +226,7 @@ export const ShowcaseTranslationBundle = {
226226
name: { label: 'Invoice Number' },
227227
account: { label: 'Account' },
228228
contact: { label: 'Contact' },
229-
owner: { label: 'Owner' },
229+
owner: { label: 'Owner Email' },
230230
status: { label: 'Status' },
231231
issued_on: { label: 'Issued On' },
232232
tax_rate: { label: 'Tax Rate (%)' },
@@ -383,7 +383,7 @@ export const ShowcaseTranslationBundle = {
383383
fields: {
384384
name: { label: '项目名称' },
385385
account: { label: '客户' },
386-
owner: { label: '负责人' },
386+
owner: { label: '负责人邮箱' },
387387
status: {
388388
label: '状态',
389389
options: { planned: '计划中', active: '进行中', on_hold: '已暂停', completed: '已完成', cancelled: '已取消' },
@@ -723,7 +723,7 @@ export const ShowcaseTranslationBundle = {
723723
name: { label: '发票号' },
724724
account: { label: '客户' },
725725
contact: { label: '联系人' },
726-
owner: { label: '负责人' },
726+
owner: { label: '负责人邮箱' },
727727
status: { label: '状态' },
728728
issued_on: { label: '开具日期' },
729729
tax_rate: { label: '税率 (%)' },

0 commit comments

Comments
 (0)