@nocobase/client-v2 2.1.0-alpha.30 → 2.1.0-alpha.32
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/es/components/form/JsonTextArea.d.ts +18 -0
- package/es/components/index.d.ts +1 -0
- package/es/flow/actions/dateRangeLimit.d.ts +9 -0
- package/es/flow/actions/index.d.ts +1 -0
- package/es/flow/actions/linkageRulesFormValueRefresh.d.ts +10 -0
- package/es/flow/index.d.ts +1 -0
- package/es/flow/models/actions/AssociateActionModel.d.ts +19 -0
- package/es/flow/models/actions/AssociationActionUtils.d.ts +17 -0
- package/es/flow/models/actions/DisassociateActionModel.d.ts +16 -0
- package/es/flow/models/actions/index.d.ts +3 -0
- package/es/flow/models/base/GridModel.d.ts +3 -1
- package/es/flow/models/base/PageModel/PageModel.d.ts +4 -0
- package/es/flow/models/base/PageModel/RootPageModel.d.ts +9 -0
- package/es/flow/models/blocks/filter-form/FilterFormGridModel.d.ts +15 -6
- package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +7 -0
- package/es/flow/models/blocks/shared/filterOperators.d.ts +9 -0
- package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.d.ts +3 -0
- package/es/flow/models/fields/AssociationFieldModel/recordSelectSettingsUtils.d.ts +9 -0
- package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +20 -0
- package/es/flow/models/fields/JSEditableFieldModel.d.ts +4 -0
- package/es/flow-compat/data.d.ts +9 -2
- package/es/flow-compat/index.d.ts +1 -1
- package/es/index.d.ts +1 -0
- package/es/index.mjs +100 -93
- package/lib/index.js +101 -94
- package/package.json +6 -5
- package/src/BaseApplication.tsx +1 -1
- package/src/__tests__/app.test.tsx +23 -6
- package/src/__tests__/globalDeps.test.ts +5 -0
- package/src/components/form/JsonTextArea.tsx +129 -0
- package/src/components/index.ts +1 -0
- package/src/flow/actions/__tests__/fieldLinkageRules.scopeDepth.test.ts +478 -0
- package/src/flow/actions/__tests__/linkageRules.formValueDrivenRefresh.test.ts +438 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +42 -0
- package/src/flow/actions/__tests__/pattern.test.ts +190 -0
- package/src/flow/actions/dateRangeLimit.tsx +66 -0
- package/src/flow/actions/index.ts +1 -0
- package/src/flow/actions/linkageRules.tsx +119 -14
- package/src/flow/actions/linkageRulesFormValueRefresh.ts +492 -0
- package/src/flow/actions/linkageRulesRefresh.tsx +4 -2
- package/src/flow/actions/openView.tsx +2 -1
- package/src/flow/actions/pattern.tsx +25 -2
- package/src/flow/actions/titleField.tsx +8 -3
- package/src/flow/admin-shell/AdminLayoutRouteCoordinator.ts +7 -1
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +117 -0
- package/src/flow/components/FieldAssignValueInput.tsx +1 -0
- package/src/flow/components/filter/LinkageFilterItem.tsx +6 -5
- package/src/flow/components/filter/VariableFilterItem.tsx +14 -13
- package/src/flow/components/filter/__tests__/LinkageFilterItem.test.tsx +33 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +48 -5
- package/src/flow/index.ts +1 -0
- package/src/flow/internal/utils/__tests__/titleFieldQuickSync.test.ts +1 -0
- package/src/flow/internal/utils/titleFieldQuickSync.ts +2 -2
- package/src/flow/models/actions/AssociateActionModel.tsx +196 -0
- package/src/flow/models/actions/AssociationActionUtils.ts +90 -0
- package/src/flow/models/actions/DisassociateActionModel.tsx +57 -0
- package/src/flow/models/actions/FilterActionModel.tsx +17 -9
- package/src/flow/models/actions/__tests__/AssociationActionModel.test.ts +250 -0
- package/src/flow/models/actions/index.ts +3 -0
- package/src/flow/models/base/GridModel.tsx +21 -1
- package/src/flow/models/base/PageModel/PageModel.tsx +15 -3
- package/src/flow/models/base/PageModel/RootPageModel.tsx +37 -2
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +73 -0
- package/src/flow/models/base/PageModel/__tests__/RootPageModel.test.ts +116 -0
- package/src/flow/models/base/__tests__/GridModel.dragSnapshotContainer.test.ts +98 -0
- package/src/flow/models/blocks/details/DetailsItemModel.tsx +3 -0
- package/src/flow/models/blocks/filter-form/FilterFormGridModel.tsx +200 -36
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormGridModel.toggleFormFieldsCollapse.test.ts +270 -1
- package/src/flow/models/blocks/filter-form/__tests__/customFieldOperators.test.tsx +23 -0
- package/src/flow/models/blocks/filter-form/customFieldOperators.ts +12 -1
- package/src/flow/models/blocks/filter-form/fields/FieldComponentProps.tsx +22 -8
- package/src/flow/models/blocks/filter-form/fields/__tests__/FilterFormCustomFieldModel.recordSelect.test.tsx +18 -0
- package/src/flow/models/blocks/filter-manager/FilterManager.ts +51 -1
- package/src/flow/models/blocks/filter-manager/__tests__/FilterManager.test.ts +75 -0
- package/src/flow/models/blocks/form/FormItemModel.tsx +48 -28
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +167 -1
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +103 -11
- package/src/flow/models/blocks/shared/filterOperators.ts +14 -0
- package/src/flow/models/blocks/table/TableBlockModel.tsx +19 -3
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +5 -1
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +48 -8
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +47 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableColumnModel.rowRecord.test.ts +42 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableField.refresh.test.tsx +122 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +2 -0
- package/src/flow/models/fields/AssociationFieldModel/recordSelectSettingsUtils.ts +20 -0
- package/src/flow/models/fields/ClickableFieldModel.tsx +21 -9
- package/src/flow/models/fields/DateTimeFieldModel/DateOnlyFieldModel.tsx +9 -0
- package/src/flow/models/fields/DateTimeFieldModel/DateTimeFieldModel.tsx +4 -0
- package/src/flow/models/fields/DateTimeFieldModel/DateTimeNoTzFieldModel.tsx +9 -0
- package/src/flow/models/fields/DateTimeFieldModel/DateTimeTzFieldModel.tsx +9 -0
- package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +242 -0
- package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +152 -0
- package/src/flow/models/fields/DividerItemModel.tsx +30 -15
- package/src/flow/models/fields/JSEditableFieldModel.tsx +110 -14
- package/src/flow/models/fields/__tests__/ClickableFieldModel.test.ts +87 -0
- package/src/flow/models/fields/__tests__/JSEditableFieldModel.test.tsx +210 -0
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +11 -3
- package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +235 -0
- package/src/flow-compat/data.ts +25 -3
- package/src/flow-compat/index.ts +7 -1
- package/src/index.ts +1 -0
- package/src/utils/globalDeps.ts +6 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { defineAction, tExpr } from '@nocobase/flow-engine';
|
|
11
|
+
import { FieldAssignValueInput } from '../components/FieldAssignValueInput';
|
|
12
|
+
|
|
13
|
+
function normalizeDateRangeValue(value: any) {
|
|
14
|
+
if (value === '' || value === null || typeof value === 'undefined') {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const dateRangeLimit = defineAction({
|
|
21
|
+
name: 'dateRangeLimit',
|
|
22
|
+
title: tExpr('Date range limit'),
|
|
23
|
+
uiMode: {
|
|
24
|
+
type: 'dialog',
|
|
25
|
+
props: {
|
|
26
|
+
width: 720,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
uiSchema(ctx: any) {
|
|
30
|
+
const targetPath = ctx.model.context?.collectionField?.name || '';
|
|
31
|
+
const dateLimitInputProps = {
|
|
32
|
+
targetPath,
|
|
33
|
+
enableDateVariableAsConstant: true,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
_minDate: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
title: tExpr('MinDate'),
|
|
40
|
+
'x-decorator': 'FormItem',
|
|
41
|
+
'x-component': FieldAssignValueInput,
|
|
42
|
+
'x-component-props': dateLimitInputProps,
|
|
43
|
+
},
|
|
44
|
+
_maxDate: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
title: tExpr('MaxDate'),
|
|
47
|
+
'x-decorator': 'FormItem',
|
|
48
|
+
'x-component': FieldAssignValueInput,
|
|
49
|
+
'x-component-props': dateLimitInputProps,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
defaultParams(ctx: any) {
|
|
54
|
+
return {
|
|
55
|
+
_minDate: normalizeDateRangeValue(ctx.model.props?._minDate),
|
|
56
|
+
_maxDate: normalizeDateRangeValue(ctx.model.props?._maxDate),
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
useRawParams: true,
|
|
60
|
+
async handler(ctx: any, params) {
|
|
61
|
+
ctx.model.setProps({
|
|
62
|
+
_minDate: normalizeDateRangeValue(params?._minDate),
|
|
63
|
+
_maxDate: normalizeDateRangeValue(params?._maxDate),
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
});
|
|
@@ -20,6 +20,7 @@ export * from './refreshTargetBlocks';
|
|
|
20
20
|
export * from './setTargetDataScope';
|
|
21
21
|
export { titleField } from './titleField';
|
|
22
22
|
export * from './dateTimeFormat';
|
|
23
|
+
export * from './dateRangeLimit';
|
|
23
24
|
export * from './sortingRules';
|
|
24
25
|
export * from './dataLoadingMode';
|
|
25
26
|
export * from './renderMode';
|
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
isToManyAssociationField,
|
|
53
53
|
} from '../internal/utils/modelUtils';
|
|
54
54
|
import { namePathToPathKey, parsePathString, resolveDynamicNamePath } from '../models/blocks/form/value-runtime/path';
|
|
55
|
+
import { ensureFormValueDrivenLinkageRefresh } from './linkageRulesFormValueRefresh';
|
|
55
56
|
|
|
56
57
|
interface LinkageRule {
|
|
57
58
|
/** 随机生成的字符串 */
|
|
@@ -1754,7 +1755,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1754
1755
|
|
|
1755
1756
|
const linkageRules: LinkageRule[] = params.value as LinkageRule[];
|
|
1756
1757
|
const allModels: FlowModel[] = ctx.model.__allModels || (ctx.model.__allModels = []);
|
|
1757
|
-
const directValuePatches: Array<{ path:
|
|
1758
|
+
const directValuePatches: Array<{ path: Array<string | number>; value: any; whenEmpty?: boolean }> = [];
|
|
1758
1759
|
const rootCollection = getCollectionFromModel((ctx.model as any)?.context?.blockModel ?? ctx.model);
|
|
1759
1760
|
const isSafeToWriteAssociationSubpath = (namePath: any): boolean => {
|
|
1760
1761
|
if (!Array.isArray(namePath) || !namePath.length) return true;
|
|
@@ -1795,6 +1796,24 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1795
1796
|
const fieldIndex = (ctx.model as any)?.context?.fieldIndex;
|
|
1796
1797
|
return resolveDynamicNamePath(path, fieldIndex);
|
|
1797
1798
|
};
|
|
1799
|
+
const getDefaultPatchRuntime = () => {
|
|
1800
|
+
const blockModel = (ctx.model as any)?.context?.blockModel ?? ctx.model;
|
|
1801
|
+
return blockModel?.formValueRuntime ?? (ctx as any)?.formValueRuntime;
|
|
1802
|
+
};
|
|
1803
|
+
const rememberAppliedDefaultPatches = (patches: typeof directValuePatches) => {
|
|
1804
|
+
const runtime = getDefaultPatchRuntime();
|
|
1805
|
+
if (typeof runtime?.recordDefaultValuePatch !== 'function') return;
|
|
1806
|
+
|
|
1807
|
+
const lastPatchByPathKey = new Map<string, (typeof directValuePatches)[number]>();
|
|
1808
|
+
for (const patch of patches) {
|
|
1809
|
+
lastPatchByPathKey.set(namePathToPathKey(patch.path), patch);
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
for (const patch of lastPatchByPathKey.values()) {
|
|
1813
|
+
if (!patch.whenEmpty) continue;
|
|
1814
|
+
runtime.recordDefaultValuePatch(patch.path, patch.value);
|
|
1815
|
+
}
|
|
1816
|
+
};
|
|
1798
1817
|
const addFormValuePatch = (patch: { path: any; value: any; whenEmpty?: boolean }) => {
|
|
1799
1818
|
if (!patch) return;
|
|
1800
1819
|
const path = (patch as any)?.path;
|
|
@@ -1818,20 +1837,33 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1818
1837
|
return;
|
|
1819
1838
|
}
|
|
1820
1839
|
const whenEmpty = !!(patch as any)?.whenEmpty;
|
|
1840
|
+
const value = (patch as any)?.value;
|
|
1821
1841
|
try {
|
|
1822
1842
|
const form = ctx.model?.context?.form;
|
|
1823
1843
|
const current = form?.getFieldValue?.(resolvedPath);
|
|
1824
|
-
if (whenEmpty
|
|
1825
|
-
|
|
1844
|
+
if (whenEmpty) {
|
|
1845
|
+
const runtime = getDefaultPatchRuntime();
|
|
1846
|
+
if (typeof runtime?.canApplyDefaultValuePatch === 'function') {
|
|
1847
|
+
const canApply = runtime.canApplyDefaultValuePatch(resolvedPath, value);
|
|
1848
|
+
if (!canApply) {
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
} else if (typeof current !== 'undefined' && current !== null && current !== '') {
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1826
1854
|
}
|
|
1827
|
-
if (_.isEqual(current,
|
|
1855
|
+
if (_.isEqual(current, value)) {
|
|
1828
1856
|
return;
|
|
1829
1857
|
}
|
|
1830
1858
|
} catch {
|
|
1831
1859
|
// ignore
|
|
1832
1860
|
}
|
|
1833
1861
|
|
|
1834
|
-
directValuePatches.push({
|
|
1862
|
+
directValuePatches.push({
|
|
1863
|
+
path: resolvedPath,
|
|
1864
|
+
value,
|
|
1865
|
+
...(whenEmpty ? { whenEmpty: true } : {}),
|
|
1866
|
+
});
|
|
1835
1867
|
};
|
|
1836
1868
|
|
|
1837
1869
|
const getModelTargetPathForPatch = (model: any): string | null => {
|
|
@@ -2013,6 +2045,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2013
2045
|
if (typeof directSetter === 'function') {
|
|
2014
2046
|
try {
|
|
2015
2047
|
await trySetFormValues(directSetter, directCtx, 'linkage');
|
|
2048
|
+
rememberAppliedDefaultPatches(allPatches);
|
|
2016
2049
|
return;
|
|
2017
2050
|
} catch (error) {
|
|
2018
2051
|
console.warn('[linkageRules] Failed to set form values via setFormValues', {
|
|
@@ -2029,6 +2062,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2029
2062
|
if (typeof blockSetter === 'function') {
|
|
2030
2063
|
try {
|
|
2031
2064
|
await trySetFormValues(blockSetter, blockCtx, 'linkage');
|
|
2065
|
+
rememberAppliedDefaultPatches(allPatches);
|
|
2032
2066
|
return;
|
|
2033
2067
|
} catch (error) {
|
|
2034
2068
|
console.warn('[linkageRules] Failed to set form values via setFormValues', {
|
|
@@ -2058,6 +2092,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2058
2092
|
console.warn('[linkageRules] Failed to set form field value (fallback setFieldValue)', { path }, error);
|
|
2059
2093
|
}
|
|
2060
2094
|
});
|
|
2095
|
+
rememberAppliedDefaultPatches(allPatches);
|
|
2061
2096
|
};
|
|
2062
2097
|
|
|
2063
2098
|
export const blockLinkageRules = defineAction({
|
|
@@ -2081,6 +2116,7 @@ export const blockLinkageRules = defineAction({
|
|
|
2081
2116
|
},
|
|
2082
2117
|
useRawParams: true,
|
|
2083
2118
|
handler: async (ctx, params) => {
|
|
2119
|
+
ensureFormValueDrivenLinkageRefresh(ctx, params, 'blockLinkageRules');
|
|
2084
2120
|
const resolved = await resolveLinkageRulesParamsPreservingRunJsScripts(ctx, params);
|
|
2085
2121
|
return commonLinkageRulesHandler(ctx, resolved);
|
|
2086
2122
|
},
|
|
@@ -2107,6 +2143,7 @@ export const actionLinkageRules = defineAction({
|
|
|
2107
2143
|
},
|
|
2108
2144
|
useRawParams: true,
|
|
2109
2145
|
handler: async (ctx, params) => {
|
|
2146
|
+
ensureFormValueDrivenLinkageRefresh(ctx, params, 'actionLinkageRules');
|
|
2110
2147
|
const resolved = await resolveLinkageRulesParamsPreservingRunJsScripts(ctx, params);
|
|
2111
2148
|
return commonLinkageRulesHandler(ctx, resolved);
|
|
2112
2149
|
},
|
|
@@ -2341,33 +2378,95 @@ export const fieldLinkageRules = defineAction({
|
|
|
2341
2378
|
return;
|
|
2342
2379
|
}
|
|
2343
2380
|
|
|
2344
|
-
const
|
|
2381
|
+
const getRowFieldIndexInfoFromModel = (model: any) => {
|
|
2345
2382
|
const fieldIndex = model?.context?.fieldIndex;
|
|
2346
2383
|
const arr = Array.isArray(fieldIndex) ? fieldIndex : [];
|
|
2347
|
-
|
|
2384
|
+
const normalized = arr.filter((it): it is string => typeof it === 'string');
|
|
2348
2385
|
const entries: Array<{ name: string; index: number }> = [];
|
|
2349
|
-
|
|
2350
|
-
|
|
2386
|
+
const path: Array<string | number> = [];
|
|
2387
|
+
for (const it of normalized) {
|
|
2351
2388
|
const [name, indexStr] = it.split(':');
|
|
2352
2389
|
const index = Number(indexStr);
|
|
2353
2390
|
if (!name || Number.isNaN(index)) continue;
|
|
2354
2391
|
entries.push({ name, index });
|
|
2392
|
+
path.push(name, index);
|
|
2355
2393
|
}
|
|
2394
|
+
return { normalized, entries, path };
|
|
2395
|
+
};
|
|
2396
|
+
|
|
2397
|
+
const getRowScopeKeyFromModel = (model: any): string | null => {
|
|
2398
|
+
const { entries } = getRowFieldIndexInfoFromModel(model);
|
|
2356
2399
|
if (!entries.length) return null;
|
|
2357
2400
|
const deepest = entries[entries.length - 1].name;
|
|
2358
2401
|
const occurrence = entries.reduce((count, e) => (e.name === deepest ? count + 1 : count), 0);
|
|
2359
2402
|
return `${deepest}#${occurrence}`;
|
|
2360
2403
|
};
|
|
2361
2404
|
|
|
2405
|
+
const getRowFieldIndexKeyFromModel = (model: any): string | null => {
|
|
2406
|
+
const { normalized } = getRowFieldIndexInfoFromModel(model);
|
|
2407
|
+
if (!normalized.length) return null;
|
|
2408
|
+
return JSON.stringify(normalized);
|
|
2409
|
+
};
|
|
2410
|
+
|
|
2411
|
+
const getRowPathFromModel = (model: any): Array<string | number> | null => {
|
|
2412
|
+
const { path } = getRowFieldIndexInfoFromModel(model);
|
|
2413
|
+
return path.length ? path : null;
|
|
2414
|
+
};
|
|
2415
|
+
|
|
2416
|
+
const getFormForRowFork = (model: any) => {
|
|
2417
|
+
return (
|
|
2418
|
+
model?.context?.form ??
|
|
2419
|
+
model?.context?.blockModel?.context?.form ??
|
|
2420
|
+
ctx.model?.context?.form ??
|
|
2421
|
+
ctx.model?.context?.blockModel?.context?.form
|
|
2422
|
+
);
|
|
2423
|
+
};
|
|
2424
|
+
|
|
2425
|
+
const isRowForkMountedInCurrentValue = (model: any): boolean => {
|
|
2426
|
+
const rowPath = getRowPathFromModel(model);
|
|
2427
|
+
if (!rowPath) return true;
|
|
2428
|
+
const form = getFormForRowFork(model);
|
|
2429
|
+
if (!form || typeof form.getFieldValue !== 'function') return true;
|
|
2430
|
+
return typeof form.getFieldValue(rowPath as any) !== 'undefined';
|
|
2431
|
+
};
|
|
2432
|
+
|
|
2433
|
+
const hasRowItemContext = (model: any): boolean => {
|
|
2434
|
+
const itemOptions = model?.context?.getPropertyOptions?.('item');
|
|
2435
|
+
if (itemOptions) return true;
|
|
2436
|
+
return typeof model?.context?.item !== 'undefined';
|
|
2437
|
+
};
|
|
2438
|
+
|
|
2439
|
+
const hasSubTableRowMarker = (model: any): boolean => {
|
|
2440
|
+
const markerOptions = model?.context?.getPropertyOptions?.('subTableRowFork');
|
|
2441
|
+
if (markerOptions) return true;
|
|
2442
|
+
return (
|
|
2443
|
+
typeof model?.context?.subTableRowFork !== 'undefined' ||
|
|
2444
|
+
typeof model?.subTableRowFork !== 'undefined' ||
|
|
2445
|
+
model?.subTableRowFork === true
|
|
2446
|
+
);
|
|
2447
|
+
};
|
|
2448
|
+
|
|
2362
2449
|
const isRowGridForkModel = (model: any): boolean => {
|
|
2363
2450
|
if (!model || typeof model !== 'object') return false;
|
|
2364
2451
|
if ((model as any)?.subModels?.field) return false;
|
|
2365
2452
|
if (!(model as any)?.subModels?.items) return false;
|
|
2366
|
-
return !!getRowScopeKeyFromModel(model);
|
|
2453
|
+
return !!getRowScopeKeyFromModel(model) && !!getRowFieldIndexKeyFromModel(model);
|
|
2454
|
+
};
|
|
2455
|
+
|
|
2456
|
+
const isSubTableRowForkModel = (model: any): boolean => {
|
|
2457
|
+
if (!model || typeof model !== 'object') return false;
|
|
2458
|
+
if (!hasSubTableRowMarker(model)) return false;
|
|
2459
|
+
if (!getRowScopeKeyFromModel(model) || !getRowFieldIndexKeyFromModel(model)) return false;
|
|
2460
|
+
return hasRowItemContext(model);
|
|
2461
|
+
};
|
|
2462
|
+
|
|
2463
|
+
const isRowScopedForkModel = (model: any): boolean => {
|
|
2464
|
+
return isRowGridForkModel(model) || isSubTableRowForkModel(model);
|
|
2367
2465
|
};
|
|
2368
2466
|
|
|
2369
|
-
const
|
|
2467
|
+
const collectRowScopedForksByKey = (): Map<string, FlowModel[]> => {
|
|
2370
2468
|
const out = new Map<string, FlowModel[]>();
|
|
2469
|
+
const seenByKey = new Map<string, Set<string>>();
|
|
2371
2470
|
const engine = ctx.engine;
|
|
2372
2471
|
if (!engine?.forEachModel) return out;
|
|
2373
2472
|
|
|
@@ -2376,9 +2475,15 @@ export const fieldLinkageRules = defineAction({
|
|
|
2376
2475
|
if (!forks || typeof forks.forEach !== 'function') return;
|
|
2377
2476
|
forks.forEach((fork: any) => {
|
|
2378
2477
|
if (!fork || fork.disposed) return;
|
|
2379
|
-
if (!
|
|
2478
|
+
if (!isRowScopedForkModel(fork)) return;
|
|
2479
|
+
if (!isRowForkMountedInCurrentValue(fork)) return;
|
|
2380
2480
|
const rowScopeKey = getRowScopeKeyFromModel(fork);
|
|
2381
|
-
|
|
2481
|
+
const fieldIndexKey = getRowFieldIndexKeyFromModel(fork);
|
|
2482
|
+
if (!rowScopeKey || !fieldIndexKey) return;
|
|
2483
|
+
const seen = seenByKey.get(rowScopeKey) || new Set<string>();
|
|
2484
|
+
if (seen.has(fieldIndexKey)) return;
|
|
2485
|
+
seen.add(fieldIndexKey);
|
|
2486
|
+
seenByKey.set(rowScopeKey, seen);
|
|
2382
2487
|
const arr = out.get(rowScopeKey) || [];
|
|
2383
2488
|
arr.push(fork as FlowModel);
|
|
2384
2489
|
out.set(rowScopeKey, arr);
|
|
@@ -2389,7 +2494,7 @@ export const fieldLinkageRules = defineAction({
|
|
|
2389
2494
|
};
|
|
2390
2495
|
|
|
2391
2496
|
const runRowScoped = async (): Promise<boolean> => {
|
|
2392
|
-
const forksByKey =
|
|
2497
|
+
const forksByKey = collectRowScopedForksByKey();
|
|
2393
2498
|
let hasAnyRowFork = false;
|
|
2394
2499
|
for (const [rowScopeKey, rowParams] of rowParamsByKey.entries()) {
|
|
2395
2500
|
const forks = forksByKey.get(rowScopeKey) || [];
|