Skip to content

fix(ui): record delete says it cannot be undone and the toast names the record - #27850

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

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-ttt0dx

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

维护者速读

  • 改了什么:删除单条记录时,确认框现在写明「此操作无法撤销」;删除成功的提示写出记录名,例如 Task "Website Relaunch" deleted,批量删除仍报条数。十个语言包都有。
  • 为什么改:平台没有回收站,删除不可恢复,但原确认框只问「确定要删除吗」,提示只说「Record deleted」,删错了事前没有警告、事后也看不出删了哪条。
  • 风险与回滚:只改文案和 toast 取名,不改删除行为;新增一个语言键 objectActions.deletedNamed。回滚就是 revert 本 PR。
  • 先看:ui/packages/core/src/actions/recordDelete.ts(successText 与 run 的单条分支)、ui/packages/app-shell/src/views/RecordDetailView.tsx(记录页删除段)、ui/packages/i18n/src/locales/zh.ts。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/core/src/actions/__tests__/recordDelete.test.ts packages/i18n/src/__tests__/record-delete-permanent-27823.test.ts,预期全绿。
  • 需要你做的:无,席位落地。

Fixes #27823

Clause-②: yes (widening)
Metadata-protocol: none

What changes

Measured on origin/main at 359e935d before the edit. Every one-record delete entry point asks through the shared recordDelete.confirmCopy in @object-ui/core, and the copy question is objectActions.deleteConfirm:

Entry point Confirm body (before) Success toast (before)
Record page header Delete (RecordDetailView) objectActions.deleteConfirm detail.deleted "Record deleted"
Console list row Delete (useObjectActions.deleteRecord) objectActions.deleteConfirm objectActions.deleteSuccess "{{label}} deleted successfully"
Console bulk Delete (useObjectActions.deleteRecords) console.objectView.bulkDeleteConfirm (already "This cannot be undone.") objectActions.bulkDeleteSuccess (count)
Object-view grid row / bulk Delete (plugin-view ObjectView) same keys as the console list same keys as the console list
plugin-detail DetailView handleDelete detail.deleteConfirmation (native confirm) none (host's onDelete)

After:

  • Permanence. objectActions.deleteConfirm and detail.deleteConfirmation end with the pack's own permanence sentence, the exact sentence console.objectView.bulkDeleteConfirm already ends with, in all ten packs (en "This cannot be undone.", zh "此操作无法撤销。"). The inline fallback maps in plugin-view and plugin-detail match en.
  • Named toast. New recordDelete.successText(deps, record): the object label plus the record's display name from getRecordDisplayName (the resolver the confirm title already uses). The resolver's Record #id floor is not a name, so a nameless record keeps objectActions.deleteSuccess, the same rule the record-save toasts (form.createdNamed) follow. recordDelete.run uses it for one record (the row from params.record, or the single params.records entry) and takes an optional objectDef so the name follows the declared nameField; the console list and the object-view grid now pass it. The record page uses the same helper over the same readable row its confirm title reads.
  • Batch unchanged. A bulk delete keeps its count toast.
  • No Undo, per the ruling: there is nothing to restore from.
  • @object-ui/i18n gains objectActions.deletedNamed ({{label}} "{{name}}" deleted, each pack in its form.createdNamed style, so de uses „…“).

Overlap: none. Seat 4's PR #27793 edits RecordDetailView.tsx apiHandler only; this PR edits only the header Delete onClick there. origin/main was merged before the PR (14 commits, no file in common).

Tests

  • core/src/actions/__tests__/recordDelete.test.ts: successText names the record by its declared name field; a nameless record (Record #id floor) and a missing row keep the object-label toast; run names the params.record row; control: the batch toast keeps its count.
  • i18n/src/__tests__/record-delete-permanent-27823.test.ts: in each of the ten packs both one-record questions end with that pack's batch permanence sentence (read from the pack, not written out), and deletedNamed interpolates exactly {{label}} and {{name}}.
  • RecordDetailView.deleteConfirmDialog-11001.test.tsx: the record page's dialog body carries the permanence sentence and the success toast is the named one.
  • ObjectView.gridDelete-10383.test.tsx: the grid row Delete's question and named toast.
  • Updated pins: residue-namespaces-3546 (detail.deleted left the inline-default table because its call site is gone, accounted for like kanban.columns), de-quote-pairing-3876 (one more „…“ pair: 100 → 101).
Ablations (two legs, through scripts/ablation-replace.mjs, restored to HEAD blob)
  1. recordDelete.successText returns objectActions.deleteSuccess unconditionally (anchor 1 → 0, blob 5dc54382 → c23705e9): 4 failed / 23 passed across recordDelete.test.ts, ObjectView.gridDelete-10383, RecordDetailView.deleteConfirmDialog-11001. The nameless-record case and the batch control stayed green, as they should. Restored: blob == HEAD, git diff HEAD empty.
  2. en objectActions.deleteConfirm without the sentence (blob bec64d03 → ffdb6618): 2 failed / 23 passed (record-delete-permanent-27823 en case, RecordDetailView.deleteConfirmDialog-11001 dialog case). Restored: blob == HEAD.
Local runs

Final head 6ff4636e (branch tip c92450e9 + a merge of origin/main, 14 commits, no file in common).

  • Targeted, pre-merge: 97 files, 1448 passed / 13 skipped (core recordDelete, all of i18n/src/__tests__/, the object-view grid delete, the record page delete dialog and confirm parity, both useObjectActions suites).

  • Neighbours, pre-merge: core/src/actions/, plugin-view/, plugin-detail/ and the other files that pin these keys: 468 files, 4579 passed / 18 skipped.

  • Derived gates (dispatch-gates --commands): 33 of 34 run, every one exit 0; the 34th, pnpm --dir ui exec vitest run scripts/, ran alone after the merge (below).

  • After the merge, on 6ff4636e: pnpm install --frozen-lockfile, rebuilt the @object-ui/app-shell closure (lock VERDICT exit 0), then type-check exit 0 for @object-ui/core, @object-ui/i18n, @object-ui/plugin-view, @object-ui/plugin-detail and @object-ui/app-shell; pnpm --dir ui exec vitest run scripts/ 171 files, 4902 passed / 2 skipped; the targeted set again 97 files, 1448 passed / 13 skipped.

  • dispatch-gates --ran: 34 derived families accounted for, 0 NOT-MEASURED. The 33 check:* / node gates ran on c92450e9 (pre-merge; the merge touched none of this diff's files).

  • pnpm check:new-line-citations: 0 new citations.

Acceptance notes

  • detail.deleted ("Record deleted") has no call site after this PR. The key is left in the packs: retiring it is the dead-key sweep's call (check-i18n-dead-keys.mjs, report-only), the same disposition kanban.columns got.
  • Out of scope, not changed: an author-declared bulk action with operation: 'delete' in ObjectGrid's BulkActionDialog shows its own declared copy; the built-in Delete paths above are the ones the card names.
  • plugin-detail's DetailView delete still asks through window.confirm; only its copy changed here.

Verification

CI runs the full ui battery (Type Check UI, Test UI, Build & E2E UI, Live E2E UI).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Utp6CYTT4mayn9WzbCF7tz


Generated by Claude Code

…he record

Fixes the one-record delete question on the list, the record page and the
object-view grid, and plugin-detail's own confirm, in all ten packs; the
success toast names the record through recordDelete.successText.

Claude-Session: https://claude.ai/code/session_01Utp6CbDAucNyQ4UtzCJKyh
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
Contract-review-claim: session_01Utp6CbDAucNyQ4UtzCJKyh · head 6ff4636 · 2026-10-30T02:23Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 6ff4636e5919035babaf4a3c5af15b3d8fcae891
Local-runs: none

Face: declaration only. The PR body, the changeset and claim 6512214417 each say Clause-②: yes (widening). The tree touches no packages/spec/src/**, no governed path and no narrowing line. Read against origin/main: 22 files, +258/−51. Inputs: the card, dev report 6513185864.

① Derived judgments

  • @object-ui/i18n (published). It gains one key, objectActions.deletedNamed ({{label}} "{{name}}" deleted, zh {{label}}“{{name}}”已删除), in all ten packs. Two existing values are edited in place, objectActions.deleteConfirm and detail.deleteConfirmation: each gains the pack's own "This cannot be undone." sentence, the one console.objectView.bulkDeleteConfirm already carries. No key is renamed or removed, and the interpolation tokens of the edited values are unchanged. Additive.
  • @object-ui/core (published, reached through actions/index.ts's export *).
    • recordDelete gains a method, successText(deps, record).
    • RecordDeleteDeps gains an optional objectDef?: unknown, so run accepts it.
    • No existing signature changes, and a caller that passes no objectDef gets the same toast copy as before, the object-label deleteSuccess, whenever the record has no resolvable name. Additive.
    • The name comes from getRecordDisplayName, the resolver confirmCopy already uses, and its Record #<id> floor is treated as no name. So the toast never invents one.
  • @object-ui/plugin-view and @object-ui/plugin-detail (published). Only their in-package default translation tables move, mirroring the pack values, and ObjectView passes objectDef. No export changes.
  • @object-ui/app-shell (private). The record page's Delete uses recordDelete.successText on the same readable row its confirm title reads, and useObjectActions passes objectDef. RecordDetailView's apiHandler is untouched (in-flight PR fix(console): a declared same-origin type: 'api' click goes through the action door #27793).
  • The batch path keeps its count toast, and there is no Undo: there is no recycle bin (enable.trash retired) to restore from.

② Semver level

patch on all four published packages. That matches Metadata-protocol: none: AGENTS.md step 3 ships a non-protocol widening as patch.

③ Boundary flags

  • open_questions is empty.
  • The first commit's Claude-Session trailer names the seat's session instead of the thread's. This is declared in the report and not rewritten. It is provenance only, not a contract matter.
  • The PR author is objectstack-fleet[bot] (a relay write).

Implemented-by: claude/project-thread-ttt0dx
Reviewed-by: session_01Utp6CbDAucNyQ4UtzCJKyh

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

席位核对

ACCEPT · head 6ff4636e5919035babaf4a3c5af15b3d8fcae891 · 2026-10-30T02:24Z

  • Shape: draft → main, Fixes #27823. Clause-②: yes (widening) and Metadata-protocol: none. The seat's TIER_DEFAULT contract review is 6513414448 (claim 6513406829), VERDICT PASS on this head. The widening is one new key, objectActions.deletedNamed, in ten packs, plus recordDelete.successText and an optional RecordDeleteDeps.objectDef in @object-ui/core. The changeset is patch on four published packages.
  • Change, read (22 files, +258/−51 against origin/main):
    • objectActions.deleteConfirm and detail.deleteConfirmation end with each pack's own batch permanence sentence.
    • A one-record delete toast names the record through getRecordDisplayName. The Record #id floor is not treated as a name, so a nameless record keeps the object-label toast. The batch keeps its count toast.
    • There is no Undo: there is no recycle bin to restore from.
    • RecordDetailView.tsx is edited only at the header Delete; apiHandler (in-flight PR fix(console): a declared same-origin type: 'api' click goes through the action door #27793) is untouched.
  • Evidence (report 6513185864): new and updated tests in recordDelete.test.ts, record-delete-permanent-27823, RecordDetailView.deleteConfirmDialog-11001 and ObjectView.gridDelete-10383. Two ablation legs turn red as expected (4 and 2 failures) and their controls stay green. Neighbours: 4579 passed.
  • Deviation: the first commit's Claude-Session trailer names the seat's session instead of the thread's. It is declared, and history is not rewritten.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure. check-governed-merges --pr 27850: NOT governed, 22 files, 309 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 02:26
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 02:26
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit c0f9fdb Oct 30, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-ttt0dx branch October 30, 2026 02:42
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 tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Record delete: the confirm dialog never says the delete is permanent, and the toast says "Record deleted" without naming the record

1 participant