@dataverse-kit/export-engine 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +78 -19
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +78 -19
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -14359,7 +14359,8 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14359
14359
|
itemsExpr,
|
|
14360
14360
|
selectionExpr,
|
|
14361
14361
|
exportColumnsLiteral,
|
|
14362
|
-
createColumnsLiteral
|
|
14362
|
+
createColumnsLiteral,
|
|
14363
|
+
addExisting
|
|
14363
14364
|
} = args;
|
|
14364
14365
|
const exportCase = exportColumnsLiteral ? `{
|
|
14365
14366
|
const exportColumns = [${exportColumnsLiteral}];
|
|
@@ -14431,6 +14432,36 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14431
14432
|
}
|
|
14432
14433
|
return;
|
|
14433
14434
|
}`;
|
|
14435
|
+
const addExistingStateBlock = addExisting ? `
|
|
14436
|
+
const gridAddExistingMutation = useUpdateRecord<Record<string, unknown>>('${addExisting.childEntitySet}');` : "";
|
|
14437
|
+
const addExistingCase = addExisting ? `{
|
|
14438
|
+
const parentId = selectedIds[0];
|
|
14439
|
+
if (!parentId) {
|
|
14440
|
+
console.warn('[grid] Select or open a parent record before adding an existing ${addExisting.childEntityLogical}.');
|
|
14441
|
+
return;
|
|
14442
|
+
}
|
|
14443
|
+
const lookup = (xrm as { Utility?: { lookupObjects?: (opts: unknown) => Promise<Array<{ id: string }>> } } | undefined)?.Utility;
|
|
14444
|
+
if (lookup?.lookupObjects) {
|
|
14445
|
+
const picked = await lookup.lookupObjects({ entityTypes: ['${addExisting.childEntityLogical}'], allowMultiSelect: true });
|
|
14446
|
+
if (!picked || picked.length === 0) return;
|
|
14447
|
+
for (const rec of picked) {
|
|
14448
|
+
const childId = String(rec.id).replace(/[{}]/g, '');
|
|
14449
|
+
await gridAddExistingMutation.mutateAsync({ id: childId, data: { '${addExisting.childField}@odata.bind': '/${addExisting.parentEntitySet}(' + parentId + ')' } as Record<string, unknown> });
|
|
14450
|
+
}
|
|
14451
|
+
await refreshGrid();
|
|
14452
|
+
} else {
|
|
14453
|
+
console.warn('[grid] Add Existing requires Xrm.Utility.lookupObjects; not available in this host.');
|
|
14454
|
+
}
|
|
14455
|
+
return;
|
|
14456
|
+
}` : `{
|
|
14457
|
+
if (xrm?.Navigation?.openForm) {
|
|
14458
|
+
await xrm.Navigation.openForm({ entityName: '${entityName}' });
|
|
14459
|
+
await refreshGrid();
|
|
14460
|
+
} else {
|
|
14461
|
+
console.warn('[grid] Add Existing requires Xrm.Navigation; not available in this host.');
|
|
14462
|
+
}
|
|
14463
|
+
return;
|
|
14464
|
+
}`;
|
|
14434
14465
|
return `
|
|
14435
14466
|
const queryClient = useQueryClient();
|
|
14436
14467
|
const gridUpdateMutation = useUpdateRecord<Record<string, unknown>>('${entitySetName}');
|
|
@@ -14454,7 +14485,7 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14454
14485
|
} catch (err) {
|
|
14455
14486
|
setDeleteError((err as Error)?.message ?? 'Delete failed.');
|
|
14456
14487
|
}
|
|
14457
|
-
}, [pendingDelete, gridDeleteMutation]);${createStateBlock}
|
|
14488
|
+
}, [pendingDelete, gridDeleteMutation]);${createStateBlock}${addExistingStateBlock}
|
|
14458
14489
|
const handleGridCommand = React.useCallback(async (actionType: string, overrideRowIndex?: number) => {
|
|
14459
14490
|
const xrm = (typeof window !== 'undefined' ? (window as unknown as { Xrm?: any }).Xrm : undefined);
|
|
14460
14491
|
const items = ${itemsExpr} as ReadonlyArray<Record<string, unknown>>;
|
|
@@ -14480,15 +14511,7 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14480
14511
|
};
|
|
14481
14512
|
switch (actionType) {
|
|
14482
14513
|
case 'new': ${newCase}
|
|
14483
|
-
case 'addExisting': {
|
|
14484
|
-
if (xrm?.Navigation?.openForm) {
|
|
14485
|
-
await xrm.Navigation.openForm({ entityName: '${entityName}' });
|
|
14486
|
-
await refreshGrid();
|
|
14487
|
-
} else {
|
|
14488
|
-
console.warn('[grid] Add Existing requires Xrm.Navigation; not available in this host.');
|
|
14489
|
-
}
|
|
14490
|
-
return;
|
|
14491
|
-
}
|
|
14514
|
+
case 'addExisting': ${addExistingCase}
|
|
14492
14515
|
case 'edit': {
|
|
14493
14516
|
if (!requireSel('edit')) return;
|
|
14494
14517
|
if (selectedIds.length > 1 && xrm?.Navigation?.openBulkEditForm) {
|
|
@@ -14538,7 +14561,7 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14538
14561
|
default:
|
|
14539
14562
|
return;
|
|
14540
14563
|
}
|
|
14541
|
-
}, [${itemsExpr}, ${selectionExpr}, gridUpdateMutation, refreshGrid]);`;
|
|
14564
|
+
}, [${itemsExpr}, ${selectionExpr}, gridUpdateMutation, refreshGrid${addExisting ? ", gridAddExistingMutation" : ""}]);`;
|
|
14542
14565
|
}
|
|
14543
14566
|
function buildRowCommandsLiteral(contextMenuItems) {
|
|
14544
14567
|
return contextMenuItems.filter((ci) => (ci.actionType ?? "custom") !== "custom").filter((ci) => ci.actionType !== "new").map(
|
|
@@ -15001,12 +15024,18 @@ function generateLinkedSubgrid(gridDef, entityName, imports, library = "fluent-v
|
|
|
15001
15024
|
const showRefresh = gridDef.toolbar?.showRefresh ?? false;
|
|
15002
15025
|
const showColumnChooser = gridDef.toolbar?.showColumnChooser ?? false;
|
|
15003
15026
|
const hasToolbarIcons = showFilters || showViewToggle || showExport || showRefresh || showColumnChooser;
|
|
15027
|
+
const childGridDef = gridDef.nestedGridId ? _currentGridCustomizers.find((g) => g.id === gridDef.nestedGridId) : void 0;
|
|
15028
|
+
const _aeRel = gridDef.nestedRelationship;
|
|
15029
|
+
const addExistingFeasible = Boolean(
|
|
15030
|
+
childGridDef && _includeDataAccessLayer && _aeRel?.relationshipType === "OneToMany" && _aeRel?.parentField && _aeRel?.childField && gridDef.dataSource?.entitySetName && gridDef.dataSource?.fetchXml && childGridDef.dataSource?.entitySetName && childGridDef.dataSource?.entityName && childGridDef.dataSource?.fetchXml
|
|
15031
|
+
);
|
|
15004
15032
|
const barItems = (gridDef.commandBarItems ?? []).filter(
|
|
15005
15033
|
(ci) => ci.visibility === "commandBar" || ci.visibility === "both" || !ci.visibility
|
|
15006
|
-
);
|
|
15034
|
+
).filter((ci) => ci.actionType !== "addExisting" || addExistingFeasible);
|
|
15007
15035
|
const contextMenuItems = (gridDef.commandBarItems ?? []).filter(
|
|
15008
15036
|
(ci) => ci.visibility === "contextMenu" || ci.visibility === "both" || !ci.visibility
|
|
15009
|
-
);
|
|
15037
|
+
).filter((ci) => ci.actionType !== "addExisting" || addExistingFeasible);
|
|
15038
|
+
const enableAddExisting = addExistingFeasible && (barItems.some((ci) => ci.actionType === "addExisting") || contextMenuItems.some((ci) => ci.actionType === "addExisting"));
|
|
15010
15039
|
const _handlerAvailable = (
|
|
15011
15040
|
// The dispatcher calls useUpdateRecord/useDeleteRecord/useQueryClient — which only
|
|
15012
15041
|
// exist (module + provider + dep) when the data-access layer is included. Without it,
|
|
@@ -15095,7 +15124,6 @@ function generateLinkedSubgrid(gridDef, entityName, imports, library = "fluent-v
|
|
|
15095
15124
|
</div>
|
|
15096
15125
|
</div>`;
|
|
15097
15126
|
}
|
|
15098
|
-
const childGridDef = gridDef.nestedGridId ? _currentGridCustomizers.find((g) => g.id === gridDef.nestedGridId) : void 0;
|
|
15099
15127
|
const isGridKitNested = !!childGridDef;
|
|
15100
15128
|
const visibleCols = [...gridDef.columns].filter((c) => c.isVisible).sort((a, b) => a.order - b.order);
|
|
15101
15129
|
const exportColumnsLiteral = enableExport ? buildExportColumnsLiteral(visibleCols) : "";
|
|
@@ -15168,7 +15196,18 @@ ${childEntries.join(",\n")},
|
|
|
15168
15196
|
itemsExpr: "keyedItems",
|
|
15169
15197
|
selectionExpr: "selectedIndices",
|
|
15170
15198
|
exportColumnsLiteral,
|
|
15171
|
-
createColumnsLiteral
|
|
15199
|
+
createColumnsLiteral,
|
|
15200
|
+
// Associate an existing child to the clicked/active parent (the ONLY call site
|
|
15201
|
+
// that wires it). Shared by the nested AND focused-view emitters below — both
|
|
15202
|
+
// reuse this ngHandlerBlock. Gated on enableAddExisting (feasible AND an
|
|
15203
|
+
// addExisting item present); the && chain narrows the optional entity-set strings
|
|
15204
|
+
// to `string` (enableAddExisting ⟹ addExistingFeasible guarantees they're present).
|
|
15205
|
+
addExisting: enableAddExisting && childEntitySet && childEntityLogical && parentEntitySet && nestedRel?.childField ? {
|
|
15206
|
+
childEntitySet,
|
|
15207
|
+
childEntityLogical,
|
|
15208
|
+
childField: nestedRel.childField,
|
|
15209
|
+
parentEntitySet
|
|
15210
|
+
} : null
|
|
15172
15211
|
}) : "";
|
|
15173
15212
|
const ngHasDelete = (gridDef.commandBarItems ?? []).some(
|
|
15174
15213
|
(ci) => ci.actionType === "delete"
|
|
@@ -15399,7 +15438,9 @@ ${childEntries.join(",\n")},
|
|
|
15399
15438
|
itemsExpr: "rows",
|
|
15400
15439
|
selectionExpr: "selectedIndices",
|
|
15401
15440
|
exportColumnsLiteral,
|
|
15402
|
-
createColumnsLiteral
|
|
15441
|
+
createColumnsLiteral,
|
|
15442
|
+
addExisting: null
|
|
15443
|
+
// flat (no parent relationship) → addExisting filtered out above
|
|
15403
15444
|
}) : "";
|
|
15404
15445
|
const cardSelectedIndicesState = cardEmitHandler ? "\n const [selectedIndices, setSelectedIndices] = React.useState<Set<number>>(new Set());" : "";
|
|
15405
15446
|
const cardRowCommandsLiteral = cardEmitRowCommands ? buildRowCommandsLiteral(contextMenuItems) : "";
|
|
@@ -15493,7 +15534,9 @@ ${childEntries.join(",\n")},
|
|
|
15493
15534
|
itemsExpr: "rows",
|
|
15494
15535
|
selectionExpr: "selectedIndices",
|
|
15495
15536
|
exportColumnsLiteral,
|
|
15496
|
-
createColumnsLiteral
|
|
15537
|
+
createColumnsLiteral,
|
|
15538
|
+
addExisting: null
|
|
15539
|
+
// flat (no parent relationship) → addExisting filtered out above
|
|
15497
15540
|
}) : "";
|
|
15498
15541
|
const roSelectedIndicesState = roEmitHandler ? "\n const [selectedIndices, setSelectedIndices] = React.useState<Set<number>>(new Set());" : "";
|
|
15499
15542
|
const roRowCommandsLiteral = roEmitRowCommands ? buildRowCommandsLiteral(contextMenuItems) : "";
|
|
@@ -15605,7 +15648,9 @@ const ${liveWrapperName}: React.FC = () => {
|
|
|
15605
15648
|
itemsExpr: "keyedItems",
|
|
15606
15649
|
selectionExpr: "selectedIndices",
|
|
15607
15650
|
exportColumnsLiteral,
|
|
15608
|
-
createColumnsLiteral
|
|
15651
|
+
createColumnsLiteral,
|
|
15652
|
+
addExisting: null
|
|
15653
|
+
// flat (no parent relationship) → addExisting filtered out above
|
|
15609
15654
|
}) : "";
|
|
15610
15655
|
const edSelectedIndicesState = edEmitHandler ? "\n const [selectedIndices, setSelectedIndices] = React.useState<Set<number>>(new Set());" : "";
|
|
15611
15656
|
const edRowCommandsLiteral = edEmitRowCommands ? buildRowCommandsLiteral(contextMenuItems) : "";
|
|
@@ -18465,6 +18510,19 @@ ${code}
|
|
|
18465
18510
|
};
|
|
18466
18511
|
`;
|
|
18467
18512
|
}
|
|
18513
|
+
function dedupeImportStatements(content) {
|
|
18514
|
+
const isImportLine = (l) => /^import\b[^\n]*\bfrom\b[^\n]*;[ \t]*$/.test(l) || /^import\s+['"][^'"]+['"];[ \t]*$/.test(l);
|
|
18515
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18516
|
+
const out = [];
|
|
18517
|
+
for (const line of content.split("\n")) {
|
|
18518
|
+
if (isImportLine(line)) {
|
|
18519
|
+
if (seen.has(line)) continue;
|
|
18520
|
+
seen.add(line);
|
|
18521
|
+
}
|
|
18522
|
+
out.push(line);
|
|
18523
|
+
}
|
|
18524
|
+
return out.join("\n");
|
|
18525
|
+
}
|
|
18468
18526
|
function generateFormCode(form, options) {
|
|
18469
18527
|
_currentGridCustomizers = options?.gridCustomizers ?? [];
|
|
18470
18528
|
_includeSampleData = options?.includeSampleData ?? false;
|
|
@@ -18495,6 +18553,7 @@ function generateFormCode(form, options) {
|
|
|
18495
18553
|
default:
|
|
18496
18554
|
content = generateMainForm(form, hasRules, library);
|
|
18497
18555
|
}
|
|
18556
|
+
content = dedupeImportStatements(content);
|
|
18498
18557
|
const files = [
|
|
18499
18558
|
{ path: `src/components/${fileName}`, content }
|
|
18500
18559
|
];
|
package/dist/index.d.cts
CHANGED
|
@@ -148,7 +148,6 @@ interface GenerateFormCodeOptions {
|
|
|
148
148
|
*/
|
|
149
149
|
componentLibrary?: 'fluent-v8' | 'fluent-v9';
|
|
150
150
|
}
|
|
151
|
-
/** Generate React component source files from a FormDefinition. */
|
|
152
151
|
declare function generateFormCode(form: FormDefinition, options?: GenerateFormCodeOptions): GeneratedFile[];
|
|
153
152
|
/** Options for `generateAllFormCode`. */
|
|
154
153
|
interface GenerateAllFormCodeOptions {
|
package/dist/index.d.ts
CHANGED
|
@@ -148,7 +148,6 @@ interface GenerateFormCodeOptions {
|
|
|
148
148
|
*/
|
|
149
149
|
componentLibrary?: 'fluent-v8' | 'fluent-v9';
|
|
150
150
|
}
|
|
151
|
-
/** Generate React component source files from a FormDefinition. */
|
|
152
151
|
declare function generateFormCode(form: FormDefinition, options?: GenerateFormCodeOptions): GeneratedFile[];
|
|
153
152
|
/** Options for `generateAllFormCode`. */
|
|
154
153
|
interface GenerateAllFormCodeOptions {
|
package/dist/index.mjs
CHANGED
|
@@ -14339,7 +14339,8 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14339
14339
|
itemsExpr,
|
|
14340
14340
|
selectionExpr,
|
|
14341
14341
|
exportColumnsLiteral,
|
|
14342
|
-
createColumnsLiteral
|
|
14342
|
+
createColumnsLiteral,
|
|
14343
|
+
addExisting
|
|
14343
14344
|
} = args;
|
|
14344
14345
|
const exportCase = exportColumnsLiteral ? `{
|
|
14345
14346
|
const exportColumns = [${exportColumnsLiteral}];
|
|
@@ -14411,6 +14412,36 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14411
14412
|
}
|
|
14412
14413
|
return;
|
|
14413
14414
|
}`;
|
|
14415
|
+
const addExistingStateBlock = addExisting ? `
|
|
14416
|
+
const gridAddExistingMutation = useUpdateRecord<Record<string, unknown>>('${addExisting.childEntitySet}');` : "";
|
|
14417
|
+
const addExistingCase = addExisting ? `{
|
|
14418
|
+
const parentId = selectedIds[0];
|
|
14419
|
+
if (!parentId) {
|
|
14420
|
+
console.warn('[grid] Select or open a parent record before adding an existing ${addExisting.childEntityLogical}.');
|
|
14421
|
+
return;
|
|
14422
|
+
}
|
|
14423
|
+
const lookup = (xrm as { Utility?: { lookupObjects?: (opts: unknown) => Promise<Array<{ id: string }>> } } | undefined)?.Utility;
|
|
14424
|
+
if (lookup?.lookupObjects) {
|
|
14425
|
+
const picked = await lookup.lookupObjects({ entityTypes: ['${addExisting.childEntityLogical}'], allowMultiSelect: true });
|
|
14426
|
+
if (!picked || picked.length === 0) return;
|
|
14427
|
+
for (const rec of picked) {
|
|
14428
|
+
const childId = String(rec.id).replace(/[{}]/g, '');
|
|
14429
|
+
await gridAddExistingMutation.mutateAsync({ id: childId, data: { '${addExisting.childField}@odata.bind': '/${addExisting.parentEntitySet}(' + parentId + ')' } as Record<string, unknown> });
|
|
14430
|
+
}
|
|
14431
|
+
await refreshGrid();
|
|
14432
|
+
} else {
|
|
14433
|
+
console.warn('[grid] Add Existing requires Xrm.Utility.lookupObjects; not available in this host.');
|
|
14434
|
+
}
|
|
14435
|
+
return;
|
|
14436
|
+
}` : `{
|
|
14437
|
+
if (xrm?.Navigation?.openForm) {
|
|
14438
|
+
await xrm.Navigation.openForm({ entityName: '${entityName}' });
|
|
14439
|
+
await refreshGrid();
|
|
14440
|
+
} else {
|
|
14441
|
+
console.warn('[grid] Add Existing requires Xrm.Navigation; not available in this host.');
|
|
14442
|
+
}
|
|
14443
|
+
return;
|
|
14444
|
+
}`;
|
|
14414
14445
|
return `
|
|
14415
14446
|
const queryClient = useQueryClient();
|
|
14416
14447
|
const gridUpdateMutation = useUpdateRecord<Record<string, unknown>>('${entitySetName}');
|
|
@@ -14434,7 +14465,7 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14434
14465
|
} catch (err) {
|
|
14435
14466
|
setDeleteError((err as Error)?.message ?? 'Delete failed.');
|
|
14436
14467
|
}
|
|
14437
|
-
}, [pendingDelete, gridDeleteMutation]);${createStateBlock}
|
|
14468
|
+
}, [pendingDelete, gridDeleteMutation]);${createStateBlock}${addExistingStateBlock}
|
|
14438
14469
|
const handleGridCommand = React.useCallback(async (actionType: string, overrideRowIndex?: number) => {
|
|
14439
14470
|
const xrm = (typeof window !== 'undefined' ? (window as unknown as { Xrm?: any }).Xrm : undefined);
|
|
14440
14471
|
const items = ${itemsExpr} as ReadonlyArray<Record<string, unknown>>;
|
|
@@ -14460,15 +14491,7 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14460
14491
|
};
|
|
14461
14492
|
switch (actionType) {
|
|
14462
14493
|
case 'new': ${newCase}
|
|
14463
|
-
case 'addExisting': {
|
|
14464
|
-
if (xrm?.Navigation?.openForm) {
|
|
14465
|
-
await xrm.Navigation.openForm({ entityName: '${entityName}' });
|
|
14466
|
-
await refreshGrid();
|
|
14467
|
-
} else {
|
|
14468
|
-
console.warn('[grid] Add Existing requires Xrm.Navigation; not available in this host.');
|
|
14469
|
-
}
|
|
14470
|
-
return;
|
|
14471
|
-
}
|
|
14494
|
+
case 'addExisting': ${addExistingCase}
|
|
14472
14495
|
case 'edit': {
|
|
14473
14496
|
if (!requireSel('edit')) return;
|
|
14474
14497
|
if (selectedIds.length > 1 && xrm?.Navigation?.openBulkEditForm) {
|
|
@@ -14518,7 +14541,7 @@ function buildGridCommandHandlerBlock(args) {
|
|
|
14518
14541
|
default:
|
|
14519
14542
|
return;
|
|
14520
14543
|
}
|
|
14521
|
-
}, [${itemsExpr}, ${selectionExpr}, gridUpdateMutation, refreshGrid]);`;
|
|
14544
|
+
}, [${itemsExpr}, ${selectionExpr}, gridUpdateMutation, refreshGrid${addExisting ? ", gridAddExistingMutation" : ""}]);`;
|
|
14522
14545
|
}
|
|
14523
14546
|
function buildRowCommandsLiteral(contextMenuItems) {
|
|
14524
14547
|
return contextMenuItems.filter((ci) => (ci.actionType ?? "custom") !== "custom").filter((ci) => ci.actionType !== "new").map(
|
|
@@ -14981,12 +15004,18 @@ function generateLinkedSubgrid(gridDef, entityName, imports, library = "fluent-v
|
|
|
14981
15004
|
const showRefresh = gridDef.toolbar?.showRefresh ?? false;
|
|
14982
15005
|
const showColumnChooser = gridDef.toolbar?.showColumnChooser ?? false;
|
|
14983
15006
|
const hasToolbarIcons = showFilters || showViewToggle || showExport || showRefresh || showColumnChooser;
|
|
15007
|
+
const childGridDef = gridDef.nestedGridId ? _currentGridCustomizers.find((g) => g.id === gridDef.nestedGridId) : void 0;
|
|
15008
|
+
const _aeRel = gridDef.nestedRelationship;
|
|
15009
|
+
const addExistingFeasible = Boolean(
|
|
15010
|
+
childGridDef && _includeDataAccessLayer && _aeRel?.relationshipType === "OneToMany" && _aeRel?.parentField && _aeRel?.childField && gridDef.dataSource?.entitySetName && gridDef.dataSource?.fetchXml && childGridDef.dataSource?.entitySetName && childGridDef.dataSource?.entityName && childGridDef.dataSource?.fetchXml
|
|
15011
|
+
);
|
|
14984
15012
|
const barItems = (gridDef.commandBarItems ?? []).filter(
|
|
14985
15013
|
(ci) => ci.visibility === "commandBar" || ci.visibility === "both" || !ci.visibility
|
|
14986
|
-
);
|
|
15014
|
+
).filter((ci) => ci.actionType !== "addExisting" || addExistingFeasible);
|
|
14987
15015
|
const contextMenuItems = (gridDef.commandBarItems ?? []).filter(
|
|
14988
15016
|
(ci) => ci.visibility === "contextMenu" || ci.visibility === "both" || !ci.visibility
|
|
14989
|
-
);
|
|
15017
|
+
).filter((ci) => ci.actionType !== "addExisting" || addExistingFeasible);
|
|
15018
|
+
const enableAddExisting = addExistingFeasible && (barItems.some((ci) => ci.actionType === "addExisting") || contextMenuItems.some((ci) => ci.actionType === "addExisting"));
|
|
14990
15019
|
const _handlerAvailable = (
|
|
14991
15020
|
// The dispatcher calls useUpdateRecord/useDeleteRecord/useQueryClient — which only
|
|
14992
15021
|
// exist (module + provider + dep) when the data-access layer is included. Without it,
|
|
@@ -15075,7 +15104,6 @@ function generateLinkedSubgrid(gridDef, entityName, imports, library = "fluent-v
|
|
|
15075
15104
|
</div>
|
|
15076
15105
|
</div>`;
|
|
15077
15106
|
}
|
|
15078
|
-
const childGridDef = gridDef.nestedGridId ? _currentGridCustomizers.find((g) => g.id === gridDef.nestedGridId) : void 0;
|
|
15079
15107
|
const isGridKitNested = !!childGridDef;
|
|
15080
15108
|
const visibleCols = [...gridDef.columns].filter((c) => c.isVisible).sort((a, b) => a.order - b.order);
|
|
15081
15109
|
const exportColumnsLiteral = enableExport ? buildExportColumnsLiteral(visibleCols) : "";
|
|
@@ -15148,7 +15176,18 @@ ${childEntries.join(",\n")},
|
|
|
15148
15176
|
itemsExpr: "keyedItems",
|
|
15149
15177
|
selectionExpr: "selectedIndices",
|
|
15150
15178
|
exportColumnsLiteral,
|
|
15151
|
-
createColumnsLiteral
|
|
15179
|
+
createColumnsLiteral,
|
|
15180
|
+
// Associate an existing child to the clicked/active parent (the ONLY call site
|
|
15181
|
+
// that wires it). Shared by the nested AND focused-view emitters below — both
|
|
15182
|
+
// reuse this ngHandlerBlock. Gated on enableAddExisting (feasible AND an
|
|
15183
|
+
// addExisting item present); the && chain narrows the optional entity-set strings
|
|
15184
|
+
// to `string` (enableAddExisting ⟹ addExistingFeasible guarantees they're present).
|
|
15185
|
+
addExisting: enableAddExisting && childEntitySet && childEntityLogical && parentEntitySet && nestedRel?.childField ? {
|
|
15186
|
+
childEntitySet,
|
|
15187
|
+
childEntityLogical,
|
|
15188
|
+
childField: nestedRel.childField,
|
|
15189
|
+
parentEntitySet
|
|
15190
|
+
} : null
|
|
15152
15191
|
}) : "";
|
|
15153
15192
|
const ngHasDelete = (gridDef.commandBarItems ?? []).some(
|
|
15154
15193
|
(ci) => ci.actionType === "delete"
|
|
@@ -15379,7 +15418,9 @@ ${childEntries.join(",\n")},
|
|
|
15379
15418
|
itemsExpr: "rows",
|
|
15380
15419
|
selectionExpr: "selectedIndices",
|
|
15381
15420
|
exportColumnsLiteral,
|
|
15382
|
-
createColumnsLiteral
|
|
15421
|
+
createColumnsLiteral,
|
|
15422
|
+
addExisting: null
|
|
15423
|
+
// flat (no parent relationship) → addExisting filtered out above
|
|
15383
15424
|
}) : "";
|
|
15384
15425
|
const cardSelectedIndicesState = cardEmitHandler ? "\n const [selectedIndices, setSelectedIndices] = React.useState<Set<number>>(new Set());" : "";
|
|
15385
15426
|
const cardRowCommandsLiteral = cardEmitRowCommands ? buildRowCommandsLiteral(contextMenuItems) : "";
|
|
@@ -15473,7 +15514,9 @@ ${childEntries.join(",\n")},
|
|
|
15473
15514
|
itemsExpr: "rows",
|
|
15474
15515
|
selectionExpr: "selectedIndices",
|
|
15475
15516
|
exportColumnsLiteral,
|
|
15476
|
-
createColumnsLiteral
|
|
15517
|
+
createColumnsLiteral,
|
|
15518
|
+
addExisting: null
|
|
15519
|
+
// flat (no parent relationship) → addExisting filtered out above
|
|
15477
15520
|
}) : "";
|
|
15478
15521
|
const roSelectedIndicesState = roEmitHandler ? "\n const [selectedIndices, setSelectedIndices] = React.useState<Set<number>>(new Set());" : "";
|
|
15479
15522
|
const roRowCommandsLiteral = roEmitRowCommands ? buildRowCommandsLiteral(contextMenuItems) : "";
|
|
@@ -15585,7 +15628,9 @@ const ${liveWrapperName}: React.FC = () => {
|
|
|
15585
15628
|
itemsExpr: "keyedItems",
|
|
15586
15629
|
selectionExpr: "selectedIndices",
|
|
15587
15630
|
exportColumnsLiteral,
|
|
15588
|
-
createColumnsLiteral
|
|
15631
|
+
createColumnsLiteral,
|
|
15632
|
+
addExisting: null
|
|
15633
|
+
// flat (no parent relationship) → addExisting filtered out above
|
|
15589
15634
|
}) : "";
|
|
15590
15635
|
const edSelectedIndicesState = edEmitHandler ? "\n const [selectedIndices, setSelectedIndices] = React.useState<Set<number>>(new Set());" : "";
|
|
15591
15636
|
const edRowCommandsLiteral = edEmitRowCommands ? buildRowCommandsLiteral(contextMenuItems) : "";
|
|
@@ -18445,6 +18490,19 @@ ${code}
|
|
|
18445
18490
|
};
|
|
18446
18491
|
`;
|
|
18447
18492
|
}
|
|
18493
|
+
function dedupeImportStatements(content) {
|
|
18494
|
+
const isImportLine = (l) => /^import\b[^\n]*\bfrom\b[^\n]*;[ \t]*$/.test(l) || /^import\s+['"][^'"]+['"];[ \t]*$/.test(l);
|
|
18495
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18496
|
+
const out = [];
|
|
18497
|
+
for (const line of content.split("\n")) {
|
|
18498
|
+
if (isImportLine(line)) {
|
|
18499
|
+
if (seen.has(line)) continue;
|
|
18500
|
+
seen.add(line);
|
|
18501
|
+
}
|
|
18502
|
+
out.push(line);
|
|
18503
|
+
}
|
|
18504
|
+
return out.join("\n");
|
|
18505
|
+
}
|
|
18448
18506
|
function generateFormCode(form, options) {
|
|
18449
18507
|
_currentGridCustomizers = options?.gridCustomizers ?? [];
|
|
18450
18508
|
_includeSampleData = options?.includeSampleData ?? false;
|
|
@@ -18475,6 +18533,7 @@ function generateFormCode(form, options) {
|
|
|
18475
18533
|
default:
|
|
18476
18534
|
content = generateMainForm(form, hasRules, library);
|
|
18477
18535
|
}
|
|
18536
|
+
content = dedupeImportStatements(content);
|
|
18478
18537
|
const files = [
|
|
18479
18538
|
{ path: `src/components/${fileName}`, content }
|
|
18480
18539
|
];
|