Skip to content

Commit 5866877

Browse files
fix(plugin-list): show list view sharing type and lock owner as read-only text, drop the dead Share button (#27013)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8G41SwYqhjjNvKBvSwT3KBm)_ Fixes #26844 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:列表视图工具栏上那个点了没反应的「Share」按钮,换成只读的共享状态文字(个人视图 / 共享视图),并在设置了 `sharing.lockedBy` 时显示锁图标和「Locked by 某人」。 - 为什么改:原按钮没有任何点击处理,`lockedBy` 也从未显示;仓内不存在可以打开的视图共享控件或接口,按分诊裁决「不接就不渲染按钮」。 - 风险与回滚:只动 plugin-list 工具栏这一处渲染和 10 个语言包各 3 个新键;不改 spec、不改接口;回滚即 revert 本 PR。 - 先看:`ui/packages/plugin-list/src/ListView.tsx` 的 Sharing 指示块;`ListView.test.tsx` 的 `sharing spec format — additional`;`ui/packages/i18n/src/locales/en.ts` 的 `sharingLockedBy`。 - 两分钟验证:`pnpm --dir ui exec vitest run packages/plugin-list/src/__tests__/ListView.test.tsx -t sharing`,预期 7 条全绿。 - 需要你做的:无,席位落地。 ## What changes - `ListView` no longer renders a ghost `Button` for `sharing`. It renders a non-interactive `span` (no role, no tabindex, not inside a button) keeping the `share-button` test id, showing the localized sharing type (`list.sharingPersonal` "Personal view" / `list.sharingCollaborative` "Shared view") and, when `sharing.lockedBy` is set, a lock icon plus `list.sharingLockedBy` "Locked by USER". The tooltip carries both, so the narrow toolbar that hides the text still says them. - `lockedBy`: `ViewSharingSchema` declares it as a free `z.string()` described "User who locked the view configuration"; spec fixtures use ids (`user_123`, `admin`) and the plugin-list test an email. No user-lookup seam exists on this path, so it is rendered as written. - Three new `list.*` keys in all ten `@object-ui/i18n` locale packs and in `LIST_DEFAULT_TRANSLATIONS` (byte-identical to `en`). - Tests: the misnamed "should display lockedBy in sharing tooltip when set" (which asserted only `Sharing: collaborative`) is replaced by real coverage: collaborative + `lockedBy` shows the owner; personal shows no owner; collaborative without `lockedBy` shows no owner; the indicator is never a button. Two existing title assertions move to the new label. - Changeset: `@object-ui/plugin-list` patch, `@object-ui/i18n` patch. ## Why Triage ruling on the card: "Show the lock owner, and either wire Share to the sharing control or do not render it." / "⛔ No dead button." No view-sharing control or endpoint was found on `main` (`ShareDialog` in components is the record share-link dialog, a different feature; the list-view registration publishes no `sharing` input), so the second branch applies. ## Acceptance notes - `ListViewBlock.inertKeys-13074.test.tsx` CONTROL "the Share button still carries no click handler" stays green unchanged (a click on the span changes nothing); its name now says "button" for a non-button. Outside the claimed file surface, so left untouched. - `packages/spec/liveness/view.json` row `sharing` cites "ListView.test.tsx:2572 pins the lockedBy tooltip" and the test name "should display lockedBy in sharing tooltip when set". That test is renamed here, and the old one never pinned `lockedBy`. Not edited (`packages/spec/**` out of scope); reported to the seat for routing. - The `list.share` default key is no longer read by `ListView`; left in place (still in every locale pack). ## Verification <details><summary>Tests and ablations</summary> - Closure: `pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-list^...' build` under the lock, VERDICT command-exit 0 (5m44s). - `vitest run packages/plugin-list/src/__tests__/ListView.test.tsx packages/plugin-list/src/__tests__/ListViewBlock.inertKeys-13074.test.tsx`: Test Files 2 passed, Tests 167 passed. - After merging `origin/main`: `vitest run packages/i18n/ packages/plugin-list/ packages/app-shell/src/__tests__/defaults-maps-mirror-en-pack.test.tsx`: Test Files 255 passed, Tests 3045 passed, 13 skipped. - `pnpm --filter @object-ui/plugin-list --filter @object-ui/i18n run type-check`: exit 0. - Ablation 1 (`ablation-replace.mjs`, anchor `const lockedBy = schema.sharing.lockedBy;` replaced by an `undefined`): "shows the lock owner from `sharing.lockedBy` beside a collaborative type" red, 1 failed / 6 passed; restored, blob == HEAD. - Ablation 2 (the indicator's opening and closing `span` replaced by the old ghost `Button`): "renders the sharing indicator as read-only text, never a button" red, 1 failed / 6 passed; restored, blob == HEAD and `git diff HEAD` empty. - Tests import `ListView` by relative path, so no dist leg. </details> <details><summary>Gates</summary> - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at 2ccb965 (after merging `origin/main`): 34 families, each run, all exit 0, including `node scripts/check-sdui-manifest.mjs` and `pnpm check:nul-bytes`. `--ran` reconciliation: 34 derived, 34 run, 0 NOT-MEASURED. - `pnpm check:new-line-citations` (ui): 0 new citations, exit 0. - CI families: see this PR's check-runs. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_01JQwxbWRtAdijdY6zPkJ9Pq)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1900c02 commit 5866877

13 files changed

Lines changed: 122 additions & 23 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
'@object-ui/plugin-list': patch
3+
'@object-ui/i18n': patch
4+
---
5+
6+
fix(plugin-list): the list toolbar shows a view's sharing type and lock owner as read-only text instead of a Share button that did nothing
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
A list view declaring `sharing` drew a ghost "Share" button with no click handler: clicking it opened nothing and sent nothing, and `sharing.lockedBy` was never shown anywhere. No view-sharing control or endpoint exists for the button to open, so it is now a non-interactive indicator:
12+
13+
- **The sharing type**, localized: "Personal view" for `type: 'personal'`, "Shared view" for `type: 'collaborative'`.
14+
- **The lock owner**, when `sharing.lockedBy` is set: a lock icon and "Locked by USER", with `lockedBy` rendered as written (the spec declares it a free string naming the user who locked the view configuration).
15+
- The tooltip carries both, so the narrow toolbar, which hides the text, still says them.
16+
17+
New `list.*` keys `sharingPersonal`, `sharingCollaborative` and `sharingLockedBy` ship in all ten `@object-ui/i18n` locale packs and in the plugin's English defaults. The element keeps its `share-button` test id.

‎ui/packages/i18n/src/locales/ar.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,9 @@ const ar = {
928928
pullToRefresh: "اسحب للتحديث",
929929
refreshing: "جارٍ التحديث…",
930930
share: "مشاركة",
931+
sharingPersonal: "عرض شخصي",
932+
sharingCollaborative: "عرض مشترك",
933+
sharingLockedBy: "مقفل بواسطة {{user}}",
931934
print: "طباعة",
932935
hideFieldsTitle: "إخفاء الحقول",
933936
dataLimitReached: "يتم عرض أول {{limit}} سجل. قد تتوفر بيانات إضافية.",

‎ui/packages/i18n/src/locales/de.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,9 @@ const de = {
823823
pullToRefresh: "Zum Aktualisieren ziehen",
824824
refreshing: "Aktualisiere…",
825825
share: "Teilen",
826+
sharingPersonal: "Persönliche Ansicht",
827+
sharingCollaborative: "Geteilte Ansicht",
828+
sharingLockedBy: "Gesperrt von {{user}}",
826829
print: "Drucken",
827830
hideFieldsTitle: "Felder ausblenden",
828831
dataLimitReached: "Die ersten {{limit}} Datensätze werden angezeigt. Möglicherweise sind weitere Daten verfügbar.",

‎ui/packages/i18n/src/locales/en.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,9 @@ const en = {
10821082
pullToRefresh: 'Pull to refresh',
10831083
refreshing: 'Refreshing…',
10841084
share: 'Share',
1085+
sharingPersonal: 'Personal view',
1086+
sharingCollaborative: 'Shared view',
1087+
sharingLockedBy: 'Locked by {{user}}',
10851088
print: 'Print',
10861089
hideFieldsTitle: 'Hide Fields',
10871090
dataLimitReached: 'Showing first {{limit}} records. More data may be available.',

‎ui/packages/i18n/src/locales/es.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,9 @@ const es = {
852852
pullToRefresh: "Tirar para actualizar",
853853
refreshing: "Actualizando…",
854854
share: "Compartir",
855+
sharingPersonal: "Vista personal",
856+
sharingCollaborative: "Vista compartida",
857+
sharingLockedBy: "Bloqueada por {{user}}",
855858
print: "Imprimir",
856859
hideFieldsTitle: "Ocultar campos",
857860
dataLimitReached: "Se muestran los primeros {{limit}} registros. Puede haber más datos disponibles.",

‎ui/packages/i18n/src/locales/fr.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,9 @@ const fr = {
847847
pullToRefresh: "Tirer pour actualiser",
848848
refreshing: "Actualisation…",
849849
share: "Partager",
850+
sharingPersonal: "Vue personnelle",
851+
sharingCollaborative: "Vue partagée",
852+
sharingLockedBy: "Verrouillée par {{user}}",
850853
print: "Imprimer",
851854
hideFieldsTitle: "Masquer les champs",
852855
dataLimitReached: "Les {{limit}} premiers enregistrements sont affichés. Il peut y avoir plus de données disponibles.",

‎ui/packages/i18n/src/locales/ja.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,9 @@ const ja = {
823823
pullToRefresh: "引っ張って更新",
824824
refreshing: "更新中…",
825825
share: "共有",
826+
sharingPersonal: "個人ビュー",
827+
sharingCollaborative: "共有ビュー",
828+
sharingLockedBy: "{{user}} がロック中",
826829
print: "印刷",
827830
hideFieldsTitle: "フィールドを非表示",
828831
dataLimitReached: "最初の {{limit}} 件のレコードを表示しています。さらにデータがある場合があります。",

‎ui/packages/i18n/src/locales/ko.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,9 @@ const ko = {
823823
pullToRefresh: "당겨서 새로고침",
824824
refreshing: "새로고침 중…",
825825
share: "공유",
826+
sharingPersonal: "개인 보기",
827+
sharingCollaborative: "공유 보기",
828+
sharingLockedBy: "{{user}} 님이 잠금",
826829
print: "인쇄",
827830
hideFieldsTitle: "필드 숨기기",
828831
dataLimitReached: "처음 {{limit}}개 레코드를 표시합니다. 더 많은 데이터가 있을 수 있습니다.",

‎ui/packages/i18n/src/locales/pt.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,9 @@ const pt = {
847847
pullToRefresh: "Puxar para atualizar",
848848
refreshing: "Atualizando…",
849849
share: "Compartilhar",
850+
sharingPersonal: "Visualização pessoal",
851+
sharingCollaborative: "Visualização compartilhada",
852+
sharingLockedBy: "Bloqueada por {{user}}",
850853
print: "Imprimir",
851854
hideFieldsTitle: "Ocultar campos",
852855
dataLimitReached: "Os primeiros {{limit}} registros estão sendo exibidos. Pode haver mais dados disponíveis.",

‎ui/packages/i18n/src/locales/ru.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,9 @@ const ru = {
877877
pullToRefresh: "Потяните для обновления",
878878
refreshing: "Обновление…",
879879
share: "Поделиться",
880+
sharingPersonal: "Личное представление",
881+
sharingCollaborative: "Общее представление",
882+
sharingLockedBy: "Заблокировано: {{user}}",
880883
print: "Печать",
881884
hideFieldsTitle: "Скрыть поля",
882885
dataLimitReached: "Отображаются первые {{limit}} записей. Возможно, есть ещё данные.",

0 commit comments

Comments
 (0)