Repository navigation
fix(plugin-grid): "Match on" offers only fields the server takes as a match key (#27567) - #27645
Conversation
… match key (#27567) The import wizard's options step listed every mapped field under "Match on". The server refuses a list or structured field as a match key, so the list now filters on the same spec definitions (isMultiValueField, STRUCTURED_JSON_TYPES), and the console's field-shape builders carry the schema's `multiple` flag. Claude-Session: https://claude.ai/code/session_01Utp6CXKADE9Bt6J32Lacv5 Co-authored-by: Claude <noreply@anthropic.com>
…w optional `multiple` prop key Claude-Session: https://claude.ai/code/session_01Utp6CXKADE9Bt6J32Lacv5 Co-authored-by: Claude <noreply@anthropic.com>
…, as the console list does (#27567) Claude-Session: https://claude.ai/code/session_01Utp6CXKADE9Bt6J32Lacv5 Co-authored-by: Claude <noreply@anthropic.com>
…hout `as any` Claude-Session: https://claude.ai/code/session_01Utp6CXKADE9Bt6J32Lacv5 Co-authored-by: Claude <noreply@anthropic.com>
|
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC Contract reviewServed-tier: Face: the ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC 席位核对ACCEPT · head
Generated by Claude Code |
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Requested by Bill · project thread
Fixes #27567
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
multiple,由控制台的两处字段构建(列表导入、AI Excel 导入)从对象定义带过来。multiple: truelookup ticked as a match field fails every row withOperator "=" … received an array#27465 / PR fix(rest, core)!: refuse a multi-value or structured field as an import match key (#27465) #27562,400 INVALID_REQUEST),但向导照样让用户勾选,要到「Validate」才被整单拒绝。ui/packages/plugin-grid/src/ImportWizard.tsx(isMatchKeyField与matchable过滤)→ui/packages/app-shell/src/views/importTargetFields.ts(带multiple)→ 新测试ImportWizard.matchKeyFields-27567.test.tsx。pnpm --dir ui exec vitest run packages/plugin-grid/src/ImportWizard.matchKeyFields-27567.test.tsx,预期 1/1 通过(只剩 code、email、owner、stage 四个可选)。What changes
In "Update existing" and "Update if matched, else create", the import wizard's "Match on" listed every mapped field. Since #27465 the server refuses a match key whose value is a list or a structured payload, so ticking such a field got the whole import refused at Validate. "Match on" now offers only the mapped fields the server takes as a key.
isMatchKeyFieldinImportWizard.tsxis!STRUCTURED_JSON_TYPES.has(type) && !isMultiValueField({ type, multiple }), the same two@objectstack/spec/datadefinitions the server'smultiValueMatchKeyRefusal(@objectstack/core) composes.plugin-gridalready imported from@objectstack/spec/data, so no dependency edge and nopackage.jsonchange.matchableis the existing list with that filter added: no new widget, dialog or hook.multipleon the field shape.ImportWizardProps['fields'][number]takes an optionalmultiple?: boolean(the declared widening:ImportWizardPropsis re-exported by name from the package entry). The wizard does not build its field shape; its hosts do, so the flag is carried at both:importTargetFields(app-shell/src/views/importTargetFields.ts, the console list's Import), only when the schema saysmultiple: true;normalizeFieldsinExcelImportBar.tsx(the AI build panel's spreadsheet import, which offers all three write modes), the same way. Cleared for this PR by the seat that holds that path.identityImportFields(text/email only) is unchanged.multiple: truelookup,user,select,radio,fileorimage; anymultiselect,checkboxesortags; anyjson,composite,repeater,record,location,addressorvector. A single-value lookup or select and every scalar field stay offered. A host that leavesmultipleout still has the inherently multi and structured types filtered by type alone.refusedOptionValue's note said the field shape does not carrymultiple; it now says the cell check does not read it (a host may leave it out), so its behaviour is unchanged.Tests
ui/packages/plugin-grid/src/ImportWizard.matchKeyFields-27567.test.tsx: on an upsert import with ten mapped fields, "Match on" lists exactlycode(text),email,owner(single lookup),stage(single select);owners(lookup,multiple: true),stages(select,multiple: true),labels(tags),regions(multiselect),meta(json),site(address) are absent.importTargetFields.test.ts: a new case pins thatmultiple: trueis carried andmultiple: false/ absent is not.Acceptance notes
multiplefrom the object schema (both hosts that build it); "Match on" lists only mapped fields the rule admits; the change is a filter onmatchable.ExcelImportBar's one carried line has no pin of its own: its existing tests (ExcelImportBar.sharedSelect-11865) compare the wizard's fields as JSON text, and they stay byte-identical because the key is written only when true.upsertKeythat names such a field is applied as the mapping says (setMatchFields(m.upsertKey…)), and the server's refusal names the mapping; the wizard does not edit an authored mapping. Not changed here.importTargetFields.test.tsis outside both ofapp-shell's tsc programs (tsc --noEmitandtsconfig.test.jsonlist neither it nor the otherviews/*.test.tsbeside it, measured with--listFiles); vitest runs it. Pre-existing, not widened by this PR.Verification
Ablation (filter removed, then restored)
node scripts/ablation-replace.mjs --file ui/packages/plugin-grid/src/ImportWizard.tsx --anchor 'mappedFieldNames.has(f.name) && isMatchKeyField(f)' --replacement 'mappedFieldNames.has(f.name) /* ABLATED_27567 */' -- pnpm --dir ui exec vitest run packages/plugin-grid/src/ImportWizard.matchKeyFields-27567.test.tsxbff5282cf050→cd3b19e941f3Tests 1 failed (1), received the six refused fields in addition (owners,stages,labels,regions,meta,site)bff5282cf050),git diff HEADempty; the pin passes again (Tests 1 passed (1))@object-ui/*resolves to source in ui vitest, so no rebuild between legs.Tests and type-check
06d76839:pnpm --dir ui exec vitest run --maxWorkers=2 packages/plugin-grid/ packages/app-shell/src/views/importTargetFields.test.ts packages/app-shell/src/console/ai/__tests__/→Test Files 305 passed (305),Tests 2530 passed (2530)(lock VERDICT command-exit 0).0c73a9da: the new pin,importWriteModes-12697,importTargetFields.test.ts, bothExcelImportBartest files →Test Files 5 passed (5),Tests 31 passed (31). Theorigin/mainmerge moved noplugin-gridfile.pnpm --filter @object-ui/app-shell --filter @object-ui/plugin-grid run type-checkon the merged head → VERDICT command-exit 0.Derived gates (dispatch-gates --commands, merged head)
Head
0c73a9da,node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE→34 derived famil(ies) accounted for — 34 run, 0 NOT-MEASURED.Generated by Claude Code