diff --git a/.changeset/import-historical-checkbox.md b/.changeset/import-historical-checkbox.md new file mode 100644 index 000000000..a46cb82c9 --- /dev/null +++ b/.changeset/import-historical-checkbox.md @@ -0,0 +1,16 @@ +--- +"@object-ui/plugin-grid": patch +"@object-ui/types": patch +--- + +feat(plugin-grid): "Import as historical data" option in the Import Wizard (framework #3479) + +Adds a checkbox to the Import Wizard's options panel that sends `treatAsHistorical` +on the import request. When on, the server skips the object's `state_machine` rule so +mid-lifecycle rows — a batch of already-`closed` tickets, `closed_won` deals — aren't +rejected by `initialStates`. Off by default: a normal import still walks the FSM, so +the exemption is always an explicit opt-in. + +Pairs with the framework side (objectstack #3483). `ImportRequestOptions.treatAsHistorical` +is added to `@object-ui/types`, and `assembleImportRequest` threads it through both the +inline and named-mapping request shapes (sent only when on). diff --git a/packages/plugin-grid/src/ImportWizard.tsx b/packages/plugin-grid/src/ImportWizard.tsx index 767b4ac55..523b7b8e0 100644 --- a/packages/plugin-grid/src/ImportWizard.tsx +++ b/packages/plugin-grid/src/ImportWizard.tsx @@ -120,6 +120,8 @@ const IMPORT_DEFAULT_TRANSLATIONS: Record = { 'grid.import.needMatchFields': 'Select at least one field to match on.', 'grid.import.optCreateOptions': 'Keep unknown option values', 'grid.import.optRunAutomations': 'Run automations & triggers', + 'grid.import.optTreatHistorical': 'Import as historical data', + 'grid.import.optTreatHistoricalHint': '(skip state-machine checks so already-completed records import as-is)', 'grid.import.optSkipBlankKey': 'Skip rows with a blank match value', 'grid.import.optBackground': 'Import in the background', 'grid.import.optBackgroundHint': '(runs as an undoable job)', @@ -516,6 +518,7 @@ function assembleImportRequest( matchFields: string[]; createMissingOptions: boolean; runAutomations: boolean; + treatAsHistorical?: boolean; skipBlankMatchKey: boolean; dryRun?: boolean; /** When set, the server resolves this registered mapping and owns the @@ -532,6 +535,7 @@ function assembleImportRequest( rows, mappingName: opts.mappingName, runAutomations: opts.runAutomations, + ...(opts.treatAsHistorical ? { treatAsHistorical: true } : {}), ...(opts.dryRun ? { dryRun: true } : {}), }; } @@ -542,6 +546,7 @@ function assembleImportRequest( ...(opts.writeMode !== 'insert' ? { matchFields: opts.matchFields } : {}), createMissingOptions: opts.createMissingOptions, runAutomations: opts.runAutomations, + ...(opts.treatAsHistorical ? { treatAsHistorical: true } : {}), skipBlankMatchKey: opts.skipBlankMatchKey, ...(opts.dryRun ? { dryRun: true } : {}), }; @@ -1228,6 +1233,8 @@ const ImportOptions: React.FC<{ onCreateMissingOptions: (v: boolean) => void; runAutomations: boolean; onRunAutomations: (v: boolean) => void; + treatAsHistorical: boolean; + onTreatAsHistorical: (v: boolean) => void; skipBlankMatchKey: boolean; onSkipBlankMatchKey: (v: boolean) => void; showBackground: boolean; @@ -1236,6 +1243,7 @@ const ImportOptions: React.FC<{ }> = ({ fields, mapping, writeMode, onWriteMode, matchFields, onToggleMatchField, createMissingOptions, onCreateMissingOptions, runAutomations, onRunAutomations, + treatAsHistorical, onTreatAsHistorical, skipBlankMatchKey, onSkipBlankMatchKey, showBackground, backgroundImport, onBackgroundImport, }) => { @@ -1301,6 +1309,13 @@ const ImportOptions: React.FC<{ onRunAutomations(v === true)} /> {t('grid.import.optRunAutomations')} + {showBackground && (