@nocobase/client-v2 2.1.37 → 2.1.38
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/flow/models/blocks/form/FormBlockModel.d.ts +6 -0
- package/es/flow/models/blocks/form/FormGridModel.d.ts +6 -0
- package/es/flow/models/blocks/form/value-runtime/rules.d.ts +1 -0
- package/es/index.mjs +3 -3
- package/lib/index.js +24 -24
- package/package.json +7 -7
- package/src/flow/models/blocks/form/FormBlockModel.tsx +4 -0
- package/src/flow/models/blocks/form/FormGridModel.tsx +4 -0
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +37 -0
- package/src/flow/models/blocks/form/value-runtime/rules.ts +29 -5
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/client-v2",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.38",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.mjs",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"@formily/antd-v5": "1.2.3",
|
|
28
28
|
"@formily/react": "^2.2.27",
|
|
29
29
|
"@formily/shared": "^2.2.27",
|
|
30
|
-
"@nocobase/evaluators": "2.1.
|
|
31
|
-
"@nocobase/flow-engine": "2.1.
|
|
32
|
-
"@nocobase/sdk": "2.1.
|
|
33
|
-
"@nocobase/shared": "2.1.
|
|
34
|
-
"@nocobase/utils": "2.1.
|
|
30
|
+
"@nocobase/evaluators": "2.1.38",
|
|
31
|
+
"@nocobase/flow-engine": "2.1.38",
|
|
32
|
+
"@nocobase/sdk": "2.1.38",
|
|
33
|
+
"@nocobase/shared": "2.1.38",
|
|
34
|
+
"@nocobase/utils": "2.1.38",
|
|
35
35
|
"ahooks": "^3.7.2",
|
|
36
36
|
"antd": "5.24.2",
|
|
37
37
|
"antd-style": "3.7.1",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"react-i18next": "^11.15.1",
|
|
49
49
|
"react-router-dom": "^6.30.1"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "cf73a1ede7f46029428d3ed143af2e5dc4f035e6"
|
|
52
52
|
}
|
|
@@ -77,6 +77,10 @@ export class FormBlockModel<
|
|
|
77
77
|
> extends CollectionBlockModel<T> {
|
|
78
78
|
formValueRuntime?: FormValueRuntime;
|
|
79
79
|
|
|
80
|
+
serialize() {
|
|
81
|
+
return { ...super.serialize(), variableContractType: { type: 'form', use: this.use } };
|
|
82
|
+
}
|
|
83
|
+
|
|
80
84
|
private userModifiedTopLevelFields = new Set<string>();
|
|
81
85
|
|
|
82
86
|
get form() {
|
|
@@ -21,6 +21,10 @@ export type DefaultFormGridStructure = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export class FormGridModel<T extends DefaultFormGridStructure = DefaultFormGridStructure> extends GridModel<T> {
|
|
24
|
+
serialize() {
|
|
25
|
+
return { ...super.serialize(), variableContractType: { type: 'formGrid', use: this.use } };
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
itemFallback = (<Skeleton.Input block size="small" style={{ marginBottom: '0.5rem' }} />);
|
|
25
29
|
itemSettingsMenuLevel = 2;
|
|
26
30
|
itemFlowSettings = {
|
|
@@ -445,6 +445,43 @@ describe('FormValueRuntime (default rules)', () => {
|
|
|
445
445
|
});
|
|
446
446
|
|
|
447
447
|
describe('FormValueRuntime (form assign rules)', () => {
|
|
448
|
+
it('uses the form grid as the variable contract owner', async () => {
|
|
449
|
+
const engineEmitter = new EventEmitter();
|
|
450
|
+
const formStub = createFormStub({ b: 'licensed' });
|
|
451
|
+
const onResolveJsonTemplate = vi.fn();
|
|
452
|
+
const blockModel: any = {
|
|
453
|
+
uid: 'form-contract-owner',
|
|
454
|
+
subModels: { grid: { uid: 'form-contract-owner-grid' } },
|
|
455
|
+
flowEngine: { emitter: engineEmitter },
|
|
456
|
+
emitter: new EventEmitter(),
|
|
457
|
+
dispatchEvent: vi.fn(),
|
|
458
|
+
getAclActionName: () => 'create',
|
|
459
|
+
};
|
|
460
|
+
const runtime = new FormValueRuntime({ model: blockModel, getForm: () => formStub as any });
|
|
461
|
+
const blockCtx = createFieldContext(runtime);
|
|
462
|
+
const resolveJsonTemplate = blockCtx.resolveJsonTemplate.bind(blockCtx);
|
|
463
|
+
blockCtx.defineMethod('resolveJsonTemplate', async (template: unknown, options?: unknown) => {
|
|
464
|
+
onResolveJsonTemplate(options);
|
|
465
|
+
return resolveJsonTemplate(template, options);
|
|
466
|
+
});
|
|
467
|
+
blockModel.context = blockCtx;
|
|
468
|
+
runtime.mount({ sync: true });
|
|
469
|
+
|
|
470
|
+
runtime.syncAssignRules([
|
|
471
|
+
{
|
|
472
|
+
key: 'license-version',
|
|
473
|
+
enable: true,
|
|
474
|
+
targetPath: 'a',
|
|
475
|
+
mode: 'assign',
|
|
476
|
+
condition: { logic: '$and', items: [] },
|
|
477
|
+
value: '__B__',
|
|
478
|
+
},
|
|
479
|
+
]);
|
|
480
|
+
|
|
481
|
+
await waitFor(() => expect(formStub.getFieldValue(['a'])).toBe('licensed'));
|
|
482
|
+
expect(onResolveJsonTemplate).toHaveBeenCalledWith({ contractModelUid: 'form-contract-owner-grid' });
|
|
483
|
+
});
|
|
484
|
+
|
|
448
485
|
it('migrates block-level rule to field instance on mount and restores on unmount', async () => {
|
|
449
486
|
const engineEmitter = new EventEmitter();
|
|
450
487
|
const blockEmitter = new EventEmitter();
|
|
@@ -8,7 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { isObservable, reaction, toJS } from '@formily/reactive';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
FlowContext,
|
|
13
|
+
FlowModel,
|
|
14
|
+
isRunJSValue,
|
|
15
|
+
normalizeRunJSValue,
|
|
16
|
+
runjsWithSafeGlobals,
|
|
17
|
+
type ResolveJsonTemplateOptions,
|
|
18
|
+
} from '@nocobase/flow-engine';
|
|
12
19
|
import { getValuesByPath } from '@nocobase/shared';
|
|
13
20
|
import _ from 'lodash';
|
|
14
21
|
import { dayjs } from '@nocobase/utils/client';
|
|
@@ -49,6 +56,7 @@ type RuntimeRule = {
|
|
|
49
56
|
getValue: () => any;
|
|
50
57
|
getCondition?: () => any;
|
|
51
58
|
getContext: () => any;
|
|
59
|
+
getContractModelUid?: () => string | undefined;
|
|
52
60
|
};
|
|
53
61
|
|
|
54
62
|
type ObservableBinding = {
|
|
@@ -94,6 +102,7 @@ type RuntimeItemChain = {
|
|
|
94
102
|
|
|
95
103
|
export type RuleEngineOptions = {
|
|
96
104
|
getBlockModelUid: () => string;
|
|
105
|
+
getAssignRulesModelUid: () => string | undefined;
|
|
97
106
|
getActionName: () => string | undefined;
|
|
98
107
|
getBlockContext: () => any;
|
|
99
108
|
getEngine: () => any;
|
|
@@ -217,6 +226,7 @@ export class RuleEngine {
|
|
|
217
226
|
getValue: () => template?.value,
|
|
218
227
|
getCondition: () => template?.condition,
|
|
219
228
|
getContext: () => this.options.getBlockContext(),
|
|
229
|
+
getContractModelUid: this.options.getAssignRulesModelUid,
|
|
220
230
|
};
|
|
221
231
|
|
|
222
232
|
this.rules.set(id, { rule, state: { deps: new Set(), depDisposers: [], runSeq: 0, scheduledAtWriteSeq: 0 } });
|
|
@@ -554,6 +564,7 @@ export class RuleEngine {
|
|
|
554
564
|
getValue: () => template?.value,
|
|
555
565
|
getCondition: () => template?.condition,
|
|
556
566
|
getContext: () => this.options.getBlockContext(),
|
|
567
|
+
getContractModelUid: this.options.getAssignRulesModelUid,
|
|
557
568
|
};
|
|
558
569
|
|
|
559
570
|
this.rules.set(id, { rule, state: { deps: new Set(), depDisposers: [], runSeq: 0, scheduledAtWriteSeq: 0 } });
|
|
@@ -922,6 +933,7 @@ export class RuleEngine {
|
|
|
922
933
|
getValue: () => template?.value,
|
|
923
934
|
getCondition: () => template?.condition,
|
|
924
935
|
getContext: () => model?.context,
|
|
936
|
+
getContractModelUid: this.options.getAssignRulesModelUid,
|
|
925
937
|
};
|
|
926
938
|
|
|
927
939
|
this.rules.set(id, { rule, state: { deps: new Set(), depDisposers: [], runSeq: 0, scheduledAtWriteSeq: 0 } });
|
|
@@ -1671,7 +1683,7 @@ export class RuleEngine {
|
|
|
1671
1683
|
}
|
|
1672
1684
|
}
|
|
1673
1685
|
|
|
1674
|
-
const evalCtx = this.createRuleEvaluationContext(baseCtx, collector, targetNamePath);
|
|
1686
|
+
const evalCtx = this.createRuleEvaluationContext(baseCtx, collector, targetNamePath, rule.getContractModelUid?.());
|
|
1675
1687
|
return { collector, evalCtx, rawValue, isRunJS };
|
|
1676
1688
|
}
|
|
1677
1689
|
|
|
@@ -2010,7 +2022,12 @@ export class RuleEngine {
|
|
|
2010
2022
|
return canOverwrite;
|
|
2011
2023
|
}
|
|
2012
2024
|
|
|
2013
|
-
private createRuleEvaluationContext(
|
|
2025
|
+
private createRuleEvaluationContext(
|
|
2026
|
+
baseCtx: any,
|
|
2027
|
+
collector: DepCollector,
|
|
2028
|
+
targetNamePath: NamePath | null,
|
|
2029
|
+
contractModelUid?: string,
|
|
2030
|
+
) {
|
|
2014
2031
|
const trackingFormValues = this.options.createTrackingFormValues(collector);
|
|
2015
2032
|
const ctx: any = new FlowContext();
|
|
2016
2033
|
try {
|
|
@@ -2030,12 +2047,19 @@ export class RuleEngine {
|
|
|
2030
2047
|
}
|
|
2031
2048
|
|
|
2032
2049
|
const delegatedResolveJsonTemplate =
|
|
2033
|
-
typeof ctx.resolveJsonTemplate === 'function'
|
|
2050
|
+
typeof ctx.resolveJsonTemplate === 'function'
|
|
2051
|
+
? (ctx.resolveJsonTemplate.bind(ctx) as (
|
|
2052
|
+
template: unknown,
|
|
2053
|
+
options?: ResolveJsonTemplateOptions,
|
|
2054
|
+
) => Promise<unknown>)
|
|
2055
|
+
: undefined;
|
|
2034
2056
|
ctx.defineMethod('resolveJsonTemplate', async (template: unknown) => {
|
|
2035
2057
|
const tokenStore = this.createLocalTemplateTokenStore();
|
|
2036
2058
|
const localResolved = this.resolveLocalFormValuesTemplates(baseCtx, template, collector, tokenStore);
|
|
2037
2059
|
const nextTemplate = localResolved.matched ? localResolved.value : template;
|
|
2038
|
-
const resolved = delegatedResolveJsonTemplate
|
|
2060
|
+
const resolved = delegatedResolveJsonTemplate
|
|
2061
|
+
? await delegatedResolveJsonTemplate(nextTemplate, contractModelUid ? { contractModelUid } : undefined)
|
|
2062
|
+
: nextTemplate;
|
|
2039
2063
|
return this.restoreLocalTemplateTokens(resolved, tokenStore);
|
|
2040
2064
|
});
|
|
2041
2065
|
|
|
@@ -81,6 +81,10 @@ export class FormValueRuntime {
|
|
|
81
81
|
|
|
82
82
|
this.ruleEngine = new RuleEngine({
|
|
83
83
|
getBlockModelUid: () => String(this.model?.uid),
|
|
84
|
+
getAssignRulesModelUid: () => {
|
|
85
|
+
const grid = this.model?.subModels?.grid;
|
|
86
|
+
return !Array.isArray(grid) && grid?.uid ? String(grid.uid) : undefined;
|
|
87
|
+
},
|
|
84
88
|
getActionName: () => this.model?.getAclActionName?.() ?? this.model?.context?.actionName,
|
|
85
89
|
getBlockContext: () => this.model?.context,
|
|
86
90
|
getEngine: () => this.model?.context?.engine,
|