This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
fix(app-shell): refuse a toolbar flow's row count before its dialog, and translate the newTabUrl refusal (objectui#13397) - #13428
Merged
Conversation
…and translate the newTabUrl refusal (objectui#13397) The console flowHandler gains refuseBeforeInput, the early row-count refusal objectui#13384 gave the script handler, answered by the same resolver its dispatch runs. A dispatch-time refusal is shown through its errorKey. The console server-action wrapper's newTabUrl "no record id" refusal moves to console.serverAction.noRecordId in all ten packs. Claude-Session: https://claude.ai/code/session_01WJozybDmRH8z2c5SD7vJkj Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJozybDmRH8z2c5SD7vJkj Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contributor
Author
席位核对ACCEPT — objectui#13397 (p3, S), head Seat: domain:ui#1 · Clause-②: no
|
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Closes #13397
Clause-②: no
What changed
A record-scoped
type: 'flow'action launched from a list toolbar with 0 or 2+ rows selected is now refused before its param dialog opens. The toast is in the session's language and nothing is sent. With exactly one row the flow behaves as before. This is the flow-action half that objectui#13384 (PR #13395) left out.useConsoleActionRuntimeflowHandler: the registered handler now carriesrefuseBeforeInput, the optionalActionRunnerHandlermember from PR fix(core): refuse a single-record action's row count before its dialog, and translate the refusal (objectui#13384) #13395. It isserverActionHandler's own member: core'screateServerActionHandlerbuilds it and the console wrapper forwards it. That handler is built in this hook with noresolveRecordId, so the member runsresolveServerActionRecordId, the resolver the flow dispatch already runs. It also skips an action whose dialog itself collectsrecordId. No second copy of the rule is written. The dispatch itself is renamedflowDispatch.flowHandlerwraps it in auseMemowith the member attached.flowHandlercall refused by the resolver now shows the refusal through itserrorKey(t(errorKey, { defaultValue: error })), with the English as fallback for an empty answer. These are the same pack keys the runner's translator reads for the early refusal.createConsoleServerActionHandlernewTabUrlfast path:console.serverAction.noRecordId, through the wrapper's existingt.errorKeytoo.t, both stay English, as before.@object-ui/i18n:console.serverAction.noRecordIdis added to all ten packs, each with its own translation.ConsoleActionRuntime.flowHandlertype now also declaresrefuseBeforeInput, asPickofServerActionHandler.Tests
Run on head
90f61b9e7c:pnpm exec vitest run --maxWorkers=2over every test file that namesflowHandler,refuseBeforeInput,resolveServerActionRecordId,newTabUrlorconsoleServerAction(git grep: 28 files outside i18n), plus all ofpackages/i18n/(the key-parity suites included). Result: 114/114 files, 1713 passed, 13 skipped.useConsoleActionRuntime.flowRowGuard-13397.test.tsx. The session reads zh-CN: the translator answers from the shipped zh pack.flowHandler.refuseBeforeInput, 0 and 2 rows: it returns the resolver'serrorwithactions.selectRowFirst/actions.selectExactlyOneRow. With 1 row it returns nothing.recordIdis not judged early.ConsoleActionRuntimeProviderand a real runner, 0 and 2 rows: no param dialog opens, and no request is sent. The toast reads此操作针对单条记录,请先选择一行。/此操作针对单条记录,请只选择一行。.consoleServerAction.test.tsx, a newnewTabUrlblock:此操作针对单条记录,但没有可用的记录 ID。and no tab opens. Control: with notit stays English.consoleNoRecordId-13397.test.ts(i18n): pins the zh-CN and en text. Every other pack defines the key with its own text.NODE_OPTIONS=--max-old-space-size=8192 pnpm exec turbo run type-check --concurrency=2 --filter=@object-ui/app-shell --filter=@object-ui/i18n: 31/31 tasks. That includestsc -p tsconfig.test.jsonfor both packages. The test-file tsconfig was re-run on the final head.pnpm check:i18n-keys,check:i18n-drift,check:i18n-dead-keys: exit 0.origin/mainfor the two edited files that had warnings, and the new test files have none.check:new-line-citations: 0 new.check-changeset-presence: pass.Ablation
Each run used
ablation-replacewith on-disk proof, and was restored togit diff HEADempty. Each ran the new flow suite,consoleServerAction.test.tsxanduseConsoleActionRuntime.test.tsx(92 tests).flowHandler'srefuseBeforeInputset toundefinederrorKeytranslation dropped inflowDispatchnewTabUrl"no record id" back to the hard-coded EnglishnewTabUrlresolver refusal shown without itserrorKeyAcceptance notes
Judgment call: the flow member reuses
serverActionHandler.refuseBeforeInputrather than calling core directly. Core'scollectsRecordIdParamis not exported, and core is outside this card's surface. Reusing the member keeps one copy of the rule. The coupling holds while this hook buildsserverActionHandlerwith noresolveRecordId. The member pins in the new suite compare the flow's answer withresolveServerActionRecordId's, so a change there goes red.Out of scope, still open: core's own dispatch-time refusal (
createServerActionHandler, for a caller that invokes the handler directly, outside the runner) still returns the Englisherror, because its result carries noerrorKey. Through the runner it is never reached for a row-count refusal, because the early refusal comes first. Carrier: none.RecordDetailView's copy of the flow handler is not touched. It resolves against its own record, so a row count never applies there.Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer)
🤖 Generated with Claude Code
https://claude.ai/code/session_01WJozybDmRH8z2c5SD7vJkj