Repository navigation
fix(console): Create User marks a missing email on its input, in the user's language - #28649
Merged
Merged
Conversation
Claude-Session: https://claude.ai/code/session_01FEkQ5mifB6V9sjWvKcperj Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5mifB6V9sjWvKcperj Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5mifB6V9sjWvKcperj Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH 席位核对 · ACCEPT · PR #28649 · 2026-11-01T12:05ZHead-sha: 维护者速读(席位终稿)
核对六项
|
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:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Requested by Leehom · project thread
Fixes #28289
Clause-②: yes (widening) —
@object-ui/corenewly exportsrefusalFieldErrors(reached through the package entry'sexport * from './actionResponse.js'); no server answer, accept set or spec key changes.Metadata-protocol: none
维护者速读
required字段错误现在直接标在「邮箱」输入框下(手机号登录开启时也标「手机号」),用用户当前语言的「X 为必填项」,不再只在按钮上方显示一句英文。error.fields,但 Console 读字段错误的那个函数只认error.details.fields,没读到error.fields,对话框也从不根据服务端结果标字段,所以非英文用户看到的还是英文。契约评审6539927716定了 A:由 Console 用自己的翻译措辞。required字段条目、且该字段正是对话框里画出的参数时才标字段;其它拒绝照旧显示服务端原文。回滚即 revert 本 PR。ui/packages/app-shell/src/views/ActionParamDialog.tsx(refusalParamMarks与handleSubmit里的失败分支);ui/packages/core/src/actions/actionResponse.ts(refusalFieldErrors多读一处error.fields);ui/packages/app-shell/src/utils/flowResponse.ts(apiActionRefusalResult)。pnpm --dir ui exec vitest run packages/app-shell/src/hooks/__tests__/useConsoleActionRuntime.createUserRequiredField-28289.test.tsx,预期 6/6 通过(main 上 4 个失败)。What changes
@object-ui/core,actions/actionResponse.ts:refusalFieldErrors, the reader behindActionResult.fieldErrors, now reads a refusal'serror.fieldsas well aserror.details.fieldsand the legacy innerfields. Both envelope members are on the spec'sEnhancedApiErrorSchema(fields, anddetailswhose documented example carriesdetails.fields). The data and action doors put a thrown validation failure underdetails.fields; plugin-auth's Create User builds its own refusal and names the listfields, and the action door relays it whole. The function is now exported, so the api handlers use the same reader the/actionsrefusals go through (no second spelling).@object-ui/app-shell,utils/flowResponse.ts: newapiActionRefusalResult(res, json, fallback, locale): the failedActionResultfor a non-2xxtype: 'api'answer, witherrorfromapiActionFailureMessage(unchanged) andfieldErrorsfromrefusalFieldErrorswhen the refusal named any. Both api hosts use it:useConsoleActionRuntime(list and page actions, both the action door and the direct fetch) andRecordDetailView(its door branch and its direct fetch).@object-ui/app-shell,views/ActionParamDialog.tsx: on a refused run,refusalParamMarksturns eachrequiredentry whosefieldnames a collected param into the dialog's own mark,actionDialog.requiredErrorwith the param's localized label (the same key and rendering the dialog's client-side required check uses, so it reads "邮箱 为必填项" in Chinese). When every entry is marked, the refusal box is not drawn, because it would only repeat the marks in English. An entry the dialog cannot mark (another code, a param it does not draw, an unresolved or carry-over param) keeps the box with the server's text. A refusal with no entries keeps today's display. Typing in a marked input clears its mark, as before. The header's objectui#13161 paragraph no longer says the dialog marks no field..changeset/28289-create-user-required-field-mark.md:@object-ui/corepatch,@object-ui/app-shellpatch. Core'sfiles[]shipsdist; app-shell is private, and its code ships in the Console bundle, as the other app-shell changesets record.Not touched, as ruled: the server answer, any error code,
packages/spec.Tests
The wire the dialog reads, measured at the action door
sys_user.create_useris a declared same-origintype: 'api'action, so the Console click goes throughPOST /api/v1/actions/sys_user/create_user. A throwaway probe onapi-action-forward.test.ts's own harness (boot({ answer }), not committed) had the target answer plugin-auth's body for an empty email. The door answered:That is the body the new Console test feeds through its mocked door. Producer check: the server's field names are
emailandphoneNumber, andsys_user.create_userdeclares the paramsemail(field-backed, sonameis the field name) andphoneNumber: they match.Red on base a798ae8, green at head
useConsoleActionRuntime.createUserRequiredField-28289.test.tsx: a realActionRunner, the console runtime's api and param handlers, the realActionParamDialog, a realI18nProviderinzh, and the mocked door answering the measured body.Base source (the five changed source files restored from
a798ae8f, the new test kept):Test Files 1 failed (1) · Tests 4 failed | 2 passed (6) · VERDICT command-exit 1. Each red case readsUnable to find an element with the text: 邮箱 为必填项. The two controls (a refusal naming no field keeps its box; a created user closes the dialog) pass on base. Restored withgit checkout HEAD,git diff HEADempty.Head:
Test Files 1 passed (1) · Tests 6 passed (6) · VERDICT command-exit 0.Cases: an empty email marks Email with the Chinese sentence,
aria-invalid="true", no refusal box and no English sentence, dialog still open; phone sign-in on marks Email and Phone Number; typing clears the mark; control, a refusal naming no field keeps the server's sentence in the box and marks nothing; control, an entry the dialog cannot mark keeps the box beside the mark it can make; control, success closes the dialog.actionRefusalFields-28289.test.ts(core):error.fieldsis read, an/actionsrefusal carrying it answersfieldErrors,error.details.fieldsis still read, a refusal naming no field answers none.Ablations, both through scripts/ablation-replace.mjs
The subjects are
src(@object-ui/coreis aliased topackages/core/srcinui/vitest.config.mts; the app-shell files are imported by relative path), so nodistis in the path and no rebuild is needed.?? b?.error?.fieldsdeleted fromactionResponse.ts(anchor 1 → 0, blob00c84412e26a→197eaad93a94):Tests 4 failed | 2 passed (6), VERDICT command-exit 1. Restored: blob00c84412e26aequal to HEAD,git diff HEADempty.setErrors(marks);deleted fromActionParamDialog.tsx(anchor 1 → 0, blob29087c772629→79e9f69aba8a):Tests 4 failed | 2 passed (6), VERDICT command-exit 1. Restored: blob equal to HEAD,git diff HEADempty.Package suites, typecheck, lint
pnpm --dir ui exec vitest run packages/core/:Test Files 228 passed (228) · Tests 4226 passed | 27 skipped (4253), VERDICT command-exit 0.packages/app-shell/srcandapps/console/srcthat namesActionParamDialog,useConsoleActionRuntime,flowResponse,RecordDetailView,apiActionDoor,refusalFieldErrorsorinterpretActionResponse:Test Files 284 passed (284) · Tests 2391 passed (2391), VERDICT command-exit 0. The full 2,029-file app-shell run on two workers was stopped after 34 minutes; CI's Test UI runs the full set.pnpm --filter @object-ui/core run type-check(src andtsconfig.test.json): exit 0.pnpm --filter @object-ui/app-shell run type-check(src andtsconfig.test.json): exit 0.--no-inline-configand theui/config: 0 errors under each. Package-wide, the root config reports 22 errors inui/packages/app-shellfiles this diff does not touch.Acceptance notes
error(the server's English sentence) as it did before; the dialog no longer repeats it when every entry is marked. Whether the toast should step aside for a fully marked refusal is the runner's call, not changed here.requiredentry for each of Email and Phone Number, so both inputs read "required" although either one satisfies the server. That is the marking the order asked for; a wording of "one of these" would need a second key.error.details.fieldsfrom the data and action doors,error.fieldsfrom plugin-auth's own refusals). This PR reads both; it does not choose one.Verification
cd271105.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this diff gave 34 commands. Each ran with its exit code captured before any pipe: all 34 exit 0.--ranreconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.check:type-check-debtfirst answered exit 3 (PREREQUISITE NOT MET: its closure build queued behind this branch's own test run on the shared lock); re-run under the lock it answered OK, 0 raw tsc errors, exit 0.pnpm check:new-line-citations(fromui/): 0 new citations.origin/mainmoved 13 commits past the basea798ae8f; none touches a file this diff changes, so the branch was not merged with it.Generated by Claude Code