Repository navigation
fix(console): a record save whose answer carries warnings shows one toast, the record-named save message carrying the warning lines - #28114
Merged
Conversation
…ecord-named toast Claude-Session: https://claude.ai/code/session_01Utp6CbDAucNyQ4UtzCJKyh Co-authored-by: Claude <noreply@anthropic.com>
…on both save surfaces Claude-Session: https://claude.ai/code/session_01Utp6CbDAucNyQ4UtzCJKyh Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CbDAucNyQ4UtzCJKyh Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CbDAucNyQ4UtzCJKyh Co-authored-by: Claude <noreply@anthropic.com>
…-j9w213 # Conflicts: # ui/packages/app-shell/src/views/RecordFormPage.tsx
Contributor
Author
|
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh 席位核对ACCEPT · head
Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
Requested by Bill · project thread
Fixes #27999
Clause-②: no
Metadata-protocol: none
维护者速读
severity: 'warning'校验规则的提示,现在只弹一条提示:带记录名的保存提示(如Task "Quarterly review" updated),警告级样式,每条规则提示单独一行。@object-ui/app-shell三个文件。表单打开期间,写入警告通道把「这张表单的那次写入」的答复警告交给表单,不再自己弹;字段被剥离的提示照旧单独弹;其它写入照旧弹「Saved — with warnings」;表单关闭时把没认领的警告全部照常弹出,不丢。回滚 = revert 本 PR。ui/packages/app-shell/src/providers/writeWarningToast.ts的emitWriteWarning与claimAnswerWarnings(风险点:认领判定必须在第一个await之前同步完成);console/AppContent.tsx的answerWarningClaimeffect 与handleRecordFormSuccess;views/RecordFormPage.tsx的handleSuccess。ui/下跑pnpm exec vitest run packages/app-shell/src/views/RecordFormPage.saveToastCarriesWarnings-27999.test.tsx packages/app-shell/src/console/__tests__/AppContent.recordSaveOneToast-27999.test.tsx,预期 2 个文件、10 个用例全部通过。What changes
providers/writeWarningToast.ts). NewclaimAnswerWarnings(adapter, scope): a record save surface claims the answer warnings of the writes it makes, for as long as it is open. The scope is the record's update (object + id), or a create of the object.emitWriteWarningnow decides, before its firstawait, whether an open claim on the adapter it is handed matches the event; if so the event'swarningsare parked on that claim instead of toasted. The stripped-fields toast is never claimed and is unchanged.take(saved)returns the distinct messages of the write that answeredsaved(an update's parked events already name its record; a create's are its own when the answer's record id is the saved record's id) and shows every other parked event on the channel's own toast at once.release()shows whatever is still parked. No warning is dropped on either path.toastRecordSave(sink, message, warnings)is the one save toast: the warning variant with the lines as its description when there are warnings, the success toast otherwise.console/AppContent.tsx). While?form=is open, an effect holds a claim keyed on the URL primitives (recordFormParam, the form object's name), not on the memoisededitingRecord/formObjectDef(ui/AGENTS.md chore: version packages #10).handleRecordFormSuccesstakes its write's warnings first; the child-form task passes them totoastRecordSave, the main path hands them tocrud_successasparams.warnings, and thecrud_successhandler toasts throughtoastRecordSave. With nowarningsparam it is the success toast it was.views/RecordFormPage.tsx). Same claim for the page's mode, object and record id;handleSuccesstakes the warnings and toasts throughtoastRecordSave. The record naming of Record create/update success toasts name the record by its title, not only the object (ruling C on #25849) #26172 / app-shell: the full-page record form (/new, /edit route) still toasts "Task updated successfully" — #26172's fix covered AppContent's dialog paths only; RecordFormPage passes the object label alone #26461 is unchanged.create/update, before the write's promise settles, and the form callsonSuccessonly after that promise settles. So a claim opened while the form is open is already holding the warnings when the surface's success handler runs. That order is fixed by the code, not by timing, and it does not depend on how long the stripped-fields label lookup takes. The other routes were weaker. Deferring the channel's toast and letting the surface cancel it is a race against the form's own awaits. A per-write flag on the request, or returning the answer'swarningstoonSuccess, would change@object-ui/data-objectstack's published write API and everyplugin-formvariant: a wider surface and a Clause-② change. The claim stays inside the private@object-ui/app-shelland moves no published export or i18n key..changeset/27999-save-with-warnings-one-toast.md,@object-ui/app-shell+@object-ui/consolepatch.Tests
providers/writeWarningToast.test.ts: 5 new cells through the real adapter chain (the stubbed transport answers,onWriteWarninghands the event on): a claimed update leaves the channel silent andtakereturns the message; a claimed create takes only its own record id's warnings and shows another create's on the channel toast; the stripped-fields toast keeps firing while the warnings are claimed; CONTROL: writes the claim does not name keep the channel toast; a claim closed without a take shows what it parked and stops claiming.views/RecordFormPage.saveToastCarriesWarnings-27999.test.tsx(new, 5 cells) andconsole/__tests__/AppContent.recordSaveOneToast-27999.test.tsx(new, 5 cells, from the Record create/update success toasts name the record by its title, not only the object (ruling C on #25849) #26172 harness, with the runner running the realcrud_successhandler). Each replays the real order: the channel'semitWriteWarningis called with the adapter, NOT awaited, and thenonSuccess(saved)runs. The channel's sink and the surface's toast are the same sonnertoast, so every toast the user would see is counted: one toast, the record-named message carrying the warning lines (update, create, child-form task); the stripped-fields notice still toasts beside it; CONTROL: a write the surface did not make keeps "Saved — with warnings" and the save toast stays a success; a save without warnings is the success toast.AppContent.recordSaveToastNamesRecord-26172,RecordFormPage.saveToastNamesRecord-26461, theConsoleToaster.*files (including thecrud_successauto-dismiss pin),AdapterProvider.*, and theresolveCheckToFilesmatches only.mjs|.cjs|.js|.sh, so all 23 TypeScript-authored gates resolve to ZERO gate files and contribute ZERO watch hints #12107 cells inwriteWarningToast.test.ts.Test runs (head 2fcbdbc)
RecordFormPage*andAppContent*test underpackages/app-shellandapps/console,AdapterProvider*,ConsoleToaster*,writeWarningToast.test.ts.pnpm --dir ui exec vitest run --maxWorkers=2 FILESunderscripts/pm/os-verify-lock.sh:VERDICT command-exit 0, Test Files 61 passed (61), Tests 433 passed (433).pnpm --filter @object-ui/app-shell run type-check:VERDICT command-exit 0. It covers the new tests: on an earlier head,tsc -p tsconfig.test.jsonwent red with TS7031 on two callbacks in the new overlay test, which were then typed.packages/app-shellsuite (1963 files) was not run locally. At two workers it would have held the shared verification lock for over an hour, so the run was stopped and narrowed to the set above.Test UIin CI runs the full sharded set.Ablation (head 2fcbdbc)
node scripts/ablation-replace.mjsonproviders/writeWarningToast.ts: the anchorconst claim = messages.length > 0 && adapter ? matchingClaim(adapter, ev) : undefined;was replaced so that the claim lookup never runs (the channel ignores every claim). The anchor went x1 to x0, the replacement x0 to x1, and the blob wentaf23c268to95733a37.Direction, written before the run: 11 RED (4 channel cells, 3 page-mode cells, 4 overlay cells); every CONTROL cell and the earlier #12107 cells GREEN.
Observed: Tests 11 failed, 24 passed (35), exactly those 11. Restored blob
af23c268= HEAD blob,git diff HEADempty.Acceptance notes
batchTransaction, used by master-detail record forms) carries no answerwarningsinto the write-warning event today. A master-detail save therefore has no warnings for either toast to show. This PR neither widens nor narrows that.Verification
Gates (head 2fcbdbc)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 34 commands; each is recorded as command :: exit code, captured before any pipe:dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.node scripts/check-sdui-manifest.mjsexit 0. The CI-owned families (the lint farm, Test UI, Type Check UI) are read from this PR's check runs, not re-run here.Generated by Claude Code