Repository navigation
fix(ui): judge requiredWhen as a transition gate on the console form page and the kanban drop prompt - #30301
Draft
objectstack-fleet[bot] wants to merge 3 commits into
Draft
fix(ui): judge requiredWhen as a transition gate on the console form page and the kanban drop prompt#30301objectstack-fleet[bot] wants to merge 3 commits into
objectstack-fleet[bot] wants to merge 3 commits into
Conversation
…age and the kanban drop prompt An Edit through /forms/:name?recordId= and a kanban drop now read the stored-row verdict resolveFieldRuleState already carries (requiredWhenAtRest): a record already inside the gate without the value saves an unrelated edit, as the engine allows. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziwFKBXQchtNMQYZSX
…ge and the kanban drop prompt Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziwFKBXQchtNMQYZSX
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziwFKBXQchtNMQYZSX
Contributor
Author
|
domain:ui#4 · os-support-ai · session_01WGufzinedUGSXteN45poyo 维护者速读
席位意见:ACCEPT(本 PR 覆盖的两处)。向导一处未动,卡片 #30220 在合并后仍保持打开。 席位核对ACCEPT → PR #30301 @
|
This branch has not been deployed
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.
Requested by Yibo Wang · project thread
Refs #30220
Clause-②: no
Metadata-protocol: none
维护者速读
/forms/:name?recordId=编辑)和看板拖放提示,改为按引擎的方式判requiredWhen(转移闸门):记录本来就处在闸门内且缺值时,不再拦住无关编辑、也不再弹窗索要该字段;把记录移入闸门、清空已有值的编辑照旧拦截。编辑向导(WizardForm)未改,需要你裁决(见下方 Open question)。PATCH本身返回 200。name参数,读的是 fix(ui): judge requiredWhen as the engine's transition gate on the record Edit form #30216 已有的requiredWhenAtRest,没有第二套规则;最坏情况是客户端放行、服务端拒绝,拒绝信息照常显示。回滚即还原本 PR。ui/apps/console/src/components/FormPage.tsx(resolveRowState的 statics 多了name: field.name)、ui/packages/plugin-kanban/src/requiredWhenPrompt.ts(statics 多了name)、FormPage.conditionalRules.test.tsx新增的 describe。pnpm --dir ui exec vitest run apps/console/src/components/FormPage.conditionalRules.test.tsx packages/plugin-kanban/src/requiredWhenPrompt.test.ts,预期 39 个用例全绿,其中「saves an unrelated edit to a record already inside the gate without the value」与「asks for nothing when the stored record already rests inside the gate」通过。requiredWhenRestsOnStoredRecord),其余两处席位落地。What changes
The engine's rule (
packages/objectql/src/validation/rule-validator.ts, the "ADR-0113 non-regression: reject iff the MERGED state violates AND the PRE state complied" block,preViolated) refuses an update only when the merged record violatesrequiredWhenand the stored row complied. #30216 mirrored that in@object-ui/coreresolveFieldRuleState: givenprevious(the stored row) andstatics.name, a stored row already inside the gate without the value resolvesrequired: false/requiredWhenAtRest: true. A caller that passes nonamekeeps the plain verdict. This PR makes two more callers pass it:ui/apps/console/src/components/FormPage.tsx,resolveRowState): it already passed the stored record (loaded.record, theGET /data/:object/:idrow) asprevious; it now passesname: field.name. The asterisk,aria-requiredand the page's own submit check (findSubmitRefusals) all read this one verdict, so all three follow. A create form passes nopreviousand is unchanged.ui/packages/plugin-kanban/src/requiredWhenPrompt.ts,collectRequiredWhenPromptFields): it already passed the pre-drop record asprevious; it now passesname. A drop of a record already inside the gate without the value issues the plain single-keyPATCHwith no dialog; a drop that moves a compliant record into the gate still opens the "Complete required fields" dialog.No new rule and no change in
@object-ui/core. No engine-side door: the engine already implements the gate (thepreViolatedcheck), so there is nodomain:serverhalf.Not changed: the edit wizard (open question)
ui/packages/plugin-form/src/WizardForm.tsxgateFinalSubmitpassesundefinedaspreviousin both modes, sorequiredWhenAtRestis alwaysfalsethere and an Edit wizard on a record already inside the gate is refused at the final submit (each step's own form renders withpreviousValuesand already lets it through since #30216). Its note fences this:The order asked to read the ruling text first; objectstack-ai/objectui is outside this session's GitHub access, and the repository holds only the paraphrase above (and the ADR-0137 header naming the ruling). So the wizard site is left untouched and reported on the card as
needs_decision, with these options:gateFinalSubmit, on an Edit wizard only, after the live verdict, callrequiredWhenRestsOnStoredRecord(field.requiredWhen, name, persistedRecord, predicateScope)and skip the field when it answers true and the field is not statically required. The liveresolveFieldRuleStatecall still binds noprevious, so thevisibleWhenfault residual the ruling accepted is unchanged; the stored row reaches only the stored-row check, which can only relax arequiredWhen, never reports a fault, and counts an unevaluable predicate as compliant.persistedRecordalready feeds this component (gateFormFieldspreviousValues, and the step renderer'spreviousValues). About 10 lines plus one pin and one control.persistedRecordas the gate's livepreviouson an Edit wizard. This is the binding the ruling refused (it would also change thevisibleWhenfault answer), so not recommended.requiredWhengate, while the record Edit form, the form page and the board can.Why
#30216 fixed the record Edit form only. The same record (a contract activated before its signed-copy rule existed) was still refused by the console form page ("Required: Signed Copy") and prompted for the signed copy by a kanban drop into another priority column, while REST
PATCHanswers 200 for both writes.Tests
FormPage.conditionalRules.test.tsx(the file's existing harness, new top-level describe, realFormPageon/forms/:name?recordId=): a record already activated with no signed copy shows no required marker and saves an unrelated edit (onePATCH, body carries the edit). CONTROL: clearing the value of an activated record that held it is refused (marker shown,toast.error, no write).requiredWhenPrompt.test.ts(new top-level describe): a record already inside the gate dropped into another column of an unrelated grouping collects nothing. CONTROL: a draft dropped intoactivatedstill collectssigned_copy.Acceptance notes
Clause-②: no:resolveRowStateandcollectRequiredWhenPromptFieldskeep their signatures; only the verdict for a stored row already inside the gate changes.PATCH ... -> 200reading are the evidence.Verification
Head:
4febaa77(baseorigin/mainmerged at959c26be).Browser check on a dev boot (showcase, fresh, built from this branch at origin/main 31260ca + this diff; Vite console serving src)
Seeded by API as admin: writable package
com.qa.rwgate, objectrwgate_contract(status draft/activated, priority low/high,signed_copytext) with three rows inserted BEFORE the rule existed, then the object re-saved withsigned_copy.requiredWhen: record.status == 'activated'; a kanban grouped by priority (default list), a kanban grouped by status (by_status), a simple form view, an app.Engine control on the same boot (REST):
PATCHthe activated row with no signed copy{priority: high}answered 200;PATCHthe draft row{status: activated}answered 400VALIDATION_FAILED("Signed Copy is required").--force, served code checked)Signed Copy*, refused "Required: Signed Copy", no writeSigned Copy,PATCH /data/rwgate_contract/0zgY… -> 200, "Submitted"Signed Copy*)PATCH ... -> 200, card in HighShots:
/mnt/project-files/ui-orders/30220-shots/(before-1..4,after-1..4, one per leg). The boot and the Vite server were stopped after the run (health 000).Targeted tests, type-check, lint
Re-run on the merged head 4febaa7:
FormPage.conditionalRules.test.tsx,requiredWhenPrompt.test.ts,ObjectKanban.requiredWhenPrompt.test.tsx: Test Files 3 passed (3), Tests 47 passed (47).npx eslinton the four touched files from their package dirs: 0 errors (26 pre-existing warnings in FormPage.tsx, none on touched lines).Ablation per site (fix removed, pin goes red, restored to HEAD)
Both CONTROL cases stayed green under the ablation, as predicted: they pin the gate holding, which the plain verdict also gives. Both subjects are imported by relative path from their tests, so no
dist/is involved.Derived gates (dispatch-gates --commands on 4febaa7, 35 families, all run)
dispatch-gates --ran: "35 derived famil(ies) accounted for — 35 run, 0 NOT-MEASURED (a DERIVED zero — all 35 recorded an exit code and none of them is 3)".Human Minimum
packages/specholds no runtime logic. (not touched)main, one pull request.packages/spectouched: not touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufziwFKBXQchtNMQYZSX