@nocobase/client-v2 2.3.0-alpha.1 → 2.3.0-beta.2
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/APIClient.d.ts +12 -0
- package/es/components/form/ScanInput/useCodeScanner.d.ts +2 -2
- package/es/flow/actions/linkageRules.d.ts +25 -0
- package/es/flow/components/FieldAssignValueInput.d.ts +4 -30
- package/es/flow/components/FlowRoute.d.ts +2 -2
- package/es/flow/components/field-value-variable/DateVariableEditor.d.ts +24 -0
- package/es/flow/components/field-value-variable/FieldValueVariableInput.d.ts +31 -0
- package/es/flow/components/field-value-variable/dateValue.d.ts +36 -0
- package/es/flow/components/field-value-variable/index.d.ts +11 -0
- package/es/flow/components/placeholders/BlockPlaceholder.d.ts +1 -0
- package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
- package/es/flow/internal/utils/operatorSchemaHelper.d.ts +2 -2
- package/es/flow/models/actions/UpdateRecordActionUtils.d.ts +8 -2
- package/es/flow/models/base/ActionModelCore.d.ts +4 -2
- package/es/flow/models/base/BlockGridModel.d.ts +3 -0
- package/es/flow/models/base/CollectionBlockModel.d.ts +3 -0
- package/es/flow/models/blocks/details/DetailsBlockModel.d.ts +3 -0
- package/es/flow/models/blocks/filter-form/FilterFormGridModel.d.ts +1 -0
- package/es/flow/models/blocks/filter-form/FilterFormSubmitActionModel.d.ts +3 -1
- package/es/flow/models/blocks/form/FormBlockModel.d.ts +7 -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/flow/models/blocks/table/JSColumnModel.d.ts +2 -0
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableColumnModel.d.ts +12 -0
- package/es/flow/models/blocks/table/utils.d.ts +1 -0
- package/es/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.d.ts +2 -1
- package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +0 -17
- package/es/flow/models/fields/AssociationFieldModel/recordSelectShared.d.ts +41 -0
- package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
- package/es/flow-compat/passwordUtils.d.ts +1 -1
- package/es/index.d.ts +1 -0
- package/es/index.mjs +147 -144
- package/es/ui-operation/index.d.ts +15 -0
- package/es/ui-operation/ui-operation-codec.d.ts +10 -0
- package/lib/index.js +170 -167
- package/lib/locale/languageCodes.js +1 -0
- package/package.json +8 -7
- package/src/APIClient.ts +92 -0
- package/src/Application.tsx +3 -1
- package/src/__tests__/APIClient.test.tsx +58 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +7 -2
- package/src/__tests__/settings-center.test.tsx +270 -6
- package/src/acl/ACLProvider.tsx +2 -0
- package/src/acl/__tests__/ACLProvider.test.tsx +92 -0
- package/src/components/form/ScanInput/CodeScanner.tsx +61 -34
- package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
- package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +114 -18
- package/src/components/form/ScanInput/useCodeScanner.ts +166 -23
- package/src/components/form/filter/CollectionFilterItem.tsx +4 -2
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +17 -0
- package/src/components/form/table/Table.tsx +81 -6
- package/src/components/form/table/__tests__/Table.columnWidth.test.tsx +433 -0
- package/src/flow/__tests__/FlowRoute.test.tsx +126 -8
- package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
- package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +314 -0
- package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +102 -0
- package/src/flow/actions/__tests__/linkageRules.actionStates.test.ts +33 -0
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +72 -0
- package/src/flow/actions/linkageRules.tsx +59 -16
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +78 -59
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +228 -0
- package/src/flow/common/Markdown/style.ts +4 -0
- package/src/flow/components/BlockItemCard.tsx +2 -2
- package/src/flow/components/FieldAssignValueInput.tsx +38 -621
- package/src/flow/components/FlowRoute.tsx +71 -29
- package/src/flow/components/field-value-variable/DateVariableEditor.tsx +181 -0
- package/src/flow/components/field-value-variable/FieldValueVariableInput.tsx +326 -0
- package/src/flow/components/field-value-variable/__tests__/FieldValueVariableInput.test.tsx +380 -0
- package/src/flow/components/field-value-variable/dateValue.ts +223 -0
- package/src/flow/components/field-value-variable/index.ts +12 -0
- package/src/flow/components/filter/VariableFilterItem.tsx +12 -3
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +125 -0
- package/src/flow/components/placeholders/BlockPlaceholder.tsx +70 -23
- package/src/flow/components/placeholders/__tests__/BlockPlaceholder.test.tsx +57 -7
- package/src/flow/index.ts +2 -0
- package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
- package/src/flow/internal/utils/operatorSchemaHelper.ts +3 -2
- package/src/flow/models/actions/UpdateRecordActionModel.tsx +18 -1
- package/src/flow/models/actions/UpdateRecordActionUtils.ts +18 -6
- package/src/flow/models/actions/__tests__/UpdateRecordActionModel.test.ts +76 -4
- package/src/flow/models/base/ActionModelCore.tsx +11 -2
- package/src/flow/models/base/BlockGridModel.tsx +26 -0
- package/src/flow/models/base/CollectionBlockModel.tsx +38 -3
- package/src/flow/models/base/PageModel/PageTabModel.tsx +67 -17
- package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +509 -12
- package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +49 -0
- package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts +125 -9
- package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +28 -53
- package/src/flow/models/blocks/details/DetailsBlockModel.tsx +8 -3
- package/src/flow/models/blocks/details/__tests__/DetailsBlockModel.initialPaginationChangeRefresh.test.ts +32 -1
- package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +27 -3
- package/src/flow/models/blocks/filter-form/FilterFormGridModel.tsx +36 -5
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +129 -14
- package/src/flow/models/blocks/filter-form/FilterFormSubmitActionModel.tsx +57 -4
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormGridModel.onModelCreated.test.ts +174 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +359 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.getFilterValue.test.ts +72 -0
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormSubmitActionModel.lifecycle.test.ts +90 -0
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +32 -4
- package/src/flow/models/blocks/filter-manager/FilterManager.ts +5 -0
- package/src/flow/models/blocks/filter-manager/__tests__/FilterManager.test.ts +40 -0
- package/src/flow/models/blocks/form/FormBlockModel.tsx +47 -0
- package/src/flow/models/blocks/form/FormGridModel.tsx +4 -0
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +8 -2
- package/src/flow/models/blocks/form/__tests__/runJsFormSubmit.test.ts +131 -0
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +435 -0
- package/src/flow/models/blocks/form/value-runtime/rules.ts +67 -14
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +43 -19
- package/src/flow/models/blocks/js-block/JSBlock.tsx +1 -1
- package/src/flow/models/blocks/table/JSColumnModel.tsx +10 -1
- package/src/flow/models/blocks/table/TableBlockModel.tsx +28 -2
- package/src/flow/models/blocks/table/TableColumnModel.tsx +48 -9
- package/src/flow/models/blocks/table/__tests__/JSColumnModel.test.tsx +52 -5
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.filterReset.test.ts +78 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +33 -0
- package/src/flow/models/blocks/table/utils.ts +7 -0
- package/src/flow/models/fields/AssociationFieldModel/CascadeSelectFieldModel.tsx +33 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +8 -0
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/__tests__/popupContext.test.ts +120 -0
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/actions/PopupSubTableEditActionModel.tsx +10 -2
- package/src/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.tsx +24 -1
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +9 -136
- package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +167 -3
- package/src/flow/models/fields/AssociationFieldModel/recordSelectShared.tsx +156 -0
- package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
- package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
- package/src/flow/models/fields/DisplayNumberFieldModel.tsx +1 -1
- package/src/flow/models/fields/JsonFieldModel.tsx +31 -8
- package/src/flow/models/fields/NumberFieldModel.tsx +1 -1
- package/src/flow/models/fields/__tests__/DisplayNumberFieldModel.test.ts +33 -0
- package/src/flow/models/fields/__tests__/JsonFieldModel.test.ts +82 -0
- package/src/flow/models/fields/__tests__/NumberFieldModel.test.tsx +47 -0
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +6 -0
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +27 -2
- package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +139 -13
- package/src/flow/utils/dataScopeFormValueClear.ts +4 -3
- package/src/index.ts +1 -0
- package/src/layout-manager/LayoutContentRoute.tsx +2 -1
- package/src/layout-manager/LayoutRoute.tsx +2 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +87 -1
- package/src/locale/languageCodes.ts +1 -0
- package/src/settings-center/AdminSettingsLayout.tsx +23 -2
- package/src/ui-operation/index.ts +33 -0
- package/src/ui-operation/ui-operation-codec.ts +54 -0
|
@@ -0,0 +1,124 @@
|
|
|
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 { FlowEngine, type FlowModelContext, MultiRecordResource, VIEW_ACTIVATED_EVENT } from '@nocobase/flow-engine';
|
|
11
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
12
|
+
import { BlockGridModel } from '../BlockGridModel';
|
|
13
|
+
import { CollectionBlockModel } from '../CollectionBlockModel';
|
|
14
|
+
|
|
15
|
+
class TestBlockGridModel extends BlockGridModel {
|
|
16
|
+
mountForTest() {
|
|
17
|
+
super.onMount();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
unmountForTest() {
|
|
21
|
+
super.onUnmount();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class TestMultiRecordResource extends MultiRecordResource<Record<string, unknown>> {
|
|
26
|
+
refreshCalls = 0;
|
|
27
|
+
|
|
28
|
+
override async refresh(): Promise<void> {
|
|
29
|
+
this.refreshCalls += 1;
|
|
30
|
+
this.emit('refresh');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class TestCollectionBlockModel extends CollectionBlockModel {
|
|
35
|
+
createResource(ctx: FlowModelContext) {
|
|
36
|
+
return ctx.createResource(TestMultiRecordResource);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
mountForTest() {
|
|
40
|
+
super.onMount();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe('BlockGridModel - select scene activation', () => {
|
|
45
|
+
let engine: FlowEngine;
|
|
46
|
+
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
engine = new FlowEngine();
|
|
49
|
+
engine.context.defineProperty('location', { value: { search: '' } });
|
|
50
|
+
engine.registerModels({ TestBlockGridModel, TestCollectionBlockModel });
|
|
51
|
+
|
|
52
|
+
engine.dataSourceManager.getDataSource('main').addCollection({
|
|
53
|
+
name: 'roles',
|
|
54
|
+
filterTargetKey: 'id',
|
|
55
|
+
fields: [
|
|
56
|
+
{ name: 'id', type: 'integer', interface: 'number' },
|
|
57
|
+
{ name: 'name', type: 'string', interface: 'input' },
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function createModels(scene = 'select') {
|
|
63
|
+
engine.context.defineProperty('view', { value: { inputArgs: { scene } } });
|
|
64
|
+
const grid = engine.createModel<TestBlockGridModel>({ use: 'TestBlockGridModel' });
|
|
65
|
+
const block = grid.addSubModel<TestCollectionBlockModel>('items', {
|
|
66
|
+
use: 'TestCollectionBlockModel',
|
|
67
|
+
stepParams: {
|
|
68
|
+
resourceSettings: {
|
|
69
|
+
init: {
|
|
70
|
+
dataSourceKey: 'main',
|
|
71
|
+
collectionName: 'roles',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const resource = block.context.resource as TestMultiRecordResource;
|
|
77
|
+
|
|
78
|
+
block.mountForTest();
|
|
79
|
+
grid.mountForTest();
|
|
80
|
+
return { grid, resource };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
it('refreshes dirty collection blocks once when a nested view closes', async () => {
|
|
84
|
+
const { grid, resource } = createModels();
|
|
85
|
+
|
|
86
|
+
engine.markDataSourceDirty('main', 'roles');
|
|
87
|
+
engine.emitter.emit(VIEW_ACTIVATED_EVENT);
|
|
88
|
+
await Promise.resolve();
|
|
89
|
+
|
|
90
|
+
expect(resource.refreshCalls).toBe(1);
|
|
91
|
+
|
|
92
|
+
engine.emitter.emit(VIEW_ACTIVATED_EVENT);
|
|
93
|
+
await Promise.resolve();
|
|
94
|
+
|
|
95
|
+
expect(resource.refreshCalls).toBe(1);
|
|
96
|
+
grid.unmountForTest();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('does not refresh without dirty data or after the grid unmounts', async () => {
|
|
100
|
+
const { grid, resource } = createModels();
|
|
101
|
+
|
|
102
|
+
engine.emitter.emit(VIEW_ACTIVATED_EVENT);
|
|
103
|
+
await Promise.resolve();
|
|
104
|
+
expect(resource.refreshCalls).toBe(0);
|
|
105
|
+
|
|
106
|
+
grid.unmountForTest();
|
|
107
|
+
engine.markDataSourceDirty('main', 'roles');
|
|
108
|
+
engine.emitter.emit(VIEW_ACTIVATED_EVENT);
|
|
109
|
+
await Promise.resolve();
|
|
110
|
+
|
|
111
|
+
expect(resource.refreshCalls).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('does not handle activation outside the select scene', async () => {
|
|
115
|
+
const { grid, resource } = createModels('list');
|
|
116
|
+
|
|
117
|
+
engine.markDataSourceDirty('main', 'roles');
|
|
118
|
+
engine.emitter.emit(VIEW_ACTIVATED_EVENT);
|
|
119
|
+
await Promise.resolve();
|
|
120
|
+
|
|
121
|
+
expect(resource.refreshCalls).toBe(0);
|
|
122
|
+
grid.unmountForTest();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
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 { FlowEngine, FlowModelContext, MultiRecordResource } from '@nocobase/flow-engine';
|
|
11
|
+
import { describe, expect, it } from 'vitest';
|
|
12
|
+
import { CollectionBlockModel } from '../CollectionBlockModel';
|
|
13
|
+
|
|
14
|
+
class AddAppendsCollectionBlockModel extends CollectionBlockModel {
|
|
15
|
+
createResource(ctx: FlowModelContext) {
|
|
16
|
+
return ctx.createResource(MultiRecordResource);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('CollectionBlockModel addAppends', () => {
|
|
21
|
+
it('does not throw for a nested field path when the collection is unavailable', () => {
|
|
22
|
+
const engine = new FlowEngine();
|
|
23
|
+
engine.registerModels({ AddAppendsCollectionBlockModel });
|
|
24
|
+
|
|
25
|
+
const model = engine.createModel<AddAppendsCollectionBlockModel>({
|
|
26
|
+
uid: 'missing-collection-add-appends-block',
|
|
27
|
+
use: 'AddAppendsCollectionBlockModel',
|
|
28
|
+
stepParams: {
|
|
29
|
+
resourceSettings: {
|
|
30
|
+
init: {
|
|
31
|
+
dataSourceKey: 'main',
|
|
32
|
+
collectionName: 'missing_collection',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(model.collection).toBeUndefined();
|
|
39
|
+
expect(() => model.addAppends('createdBy.departments')).not.toThrow();
|
|
40
|
+
});
|
|
41
|
+
});
|
package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { afterEach,
|
|
11
|
-
import { FlowEngine, MultiRecordResource } from '@nocobase/flow-engine';
|
|
10
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
11
|
+
import { FlowEngine, FlowRuntimeContext, MultiRecordResource, ResourceError } from '@nocobase/flow-engine';
|
|
12
12
|
import '../../../index';
|
|
13
|
+
import { BlockResourceErrorPlaceholder } from '../../../components/placeholders/BlockPlaceholder';
|
|
13
14
|
import { CollectionBlockModel } from '../CollectionBlockModel';
|
|
14
15
|
import { dataLoadingMode } from '../../../actions/dataLoadingMode';
|
|
15
16
|
|
|
@@ -19,13 +20,16 @@ class InitialBeforeRenderTestBlockModel extends CollectionBlockModel {
|
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
function setupModel() {
|
|
23
|
+
function setupModel(dataSourceKey = 'main') {
|
|
23
24
|
const engine = new FlowEngine();
|
|
24
25
|
engine.context.defineProperty('location', { value: { search: '' } as any });
|
|
25
26
|
engine.registerActions({ dataLoadingMode });
|
|
26
27
|
engine.registerModels({ InitialBeforeRenderTestBlockModel });
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
if (!engine.dataSourceManager.getDataSource(dataSourceKey)) {
|
|
30
|
+
engine.dataSourceManager.addDataSource({ key: dataSourceKey });
|
|
31
|
+
}
|
|
32
|
+
const ds = engine.dataSourceManager.getDataSource(dataSourceKey);
|
|
29
33
|
ds.addCollection({
|
|
30
34
|
name: 'users',
|
|
31
35
|
filterTargetKey: 'id',
|
|
@@ -41,7 +45,7 @@ function setupModel() {
|
|
|
41
45
|
stepParams: {
|
|
42
46
|
resourceSettings: {
|
|
43
47
|
init: {
|
|
44
|
-
dataSourceKey
|
|
48
|
+
dataSourceKey,
|
|
45
49
|
collectionName: 'users',
|
|
46
50
|
},
|
|
47
51
|
},
|
|
@@ -88,16 +92,21 @@ function setupModelWithManualMode() {
|
|
|
88
92
|
return { model, resource: model.resource as MultiRecordResource };
|
|
89
93
|
}
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
async function runRefreshStep(model: InitialBeforeRenderTestBlockModel) {
|
|
96
|
+
const handler = model.getFlow('refreshSettings')?.getStep('refresh')?.serialize().handler;
|
|
97
|
+
if (!handler) {
|
|
98
|
+
throw new Error('refreshSettings.refresh handler is not registered');
|
|
99
|
+
}
|
|
100
|
+
await handler(new FlowRuntimeContext(model, 'refreshSettings'), {});
|
|
101
|
+
}
|
|
95
102
|
|
|
103
|
+
describe('CollectionBlockModel initial beforeRender refresh', () => {
|
|
96
104
|
afterEach(() => {
|
|
97
105
|
vi.useRealTimers();
|
|
98
106
|
});
|
|
99
107
|
|
|
100
108
|
it('only performs one actual data request on first beforeRender', async () => {
|
|
109
|
+
vi.useFakeTimers();
|
|
101
110
|
const { model, resource } = setupModel();
|
|
102
111
|
const runActionSpy = vi.spyOn(resource, 'runAction').mockResolvedValue({
|
|
103
112
|
data: [{ id: 1, name: 'Alice' }],
|
|
@@ -112,7 +121,54 @@ describe('CollectionBlockModel initial beforeRender refresh', () => {
|
|
|
112
121
|
expect(runActionSpy).toHaveBeenCalledTimes(1);
|
|
113
122
|
});
|
|
114
123
|
|
|
124
|
+
it('keeps resource request failures in the block error state', async () => {
|
|
125
|
+
const { model, resource } = setupModel('external');
|
|
126
|
+
const resourceError = new ResourceError({
|
|
127
|
+
response: {
|
|
128
|
+
data: {
|
|
129
|
+
errors: [{ code: 'DATA_SOURCE_UNAVAILABLE', message: 'Data source unavailable' }],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
vi.spyOn(resource, 'refresh').mockImplementation(async () => {
|
|
134
|
+
resource.setError(resourceError);
|
|
135
|
+
throw resourceError;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await runRefreshStep(model);
|
|
139
|
+
|
|
140
|
+
expect(resource.getError()).toBe(resourceError);
|
|
141
|
+
expect(CollectionBlockModel.prototype.render.call(model)).toMatchObject({
|
|
142
|
+
type: BlockResourceErrorPlaceholder,
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('continues to throw resource request failures from the main data source', async () => {
|
|
147
|
+
const { model, resource } = setupModel();
|
|
148
|
+
const resourceError = new ResourceError({
|
|
149
|
+
response: {
|
|
150
|
+
data: {
|
|
151
|
+
errors: [{ code: 'UNKNOWN_ERROR', message: 'Main data source failed' }],
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
vi.spyOn(resource, 'refresh').mockImplementation(async () => {
|
|
156
|
+
resource.setError(resourceError);
|
|
157
|
+
throw resourceError;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await expect(runRefreshStep(model)).rejects.toBe(resourceError);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('continues to throw non-resource errors from beforeRender', async () => {
|
|
164
|
+
const { model, resource } = setupModel('external');
|
|
165
|
+
vi.spyOn(resource, 'refresh').mockRejectedValue(new Error('beforeRender bug'));
|
|
166
|
+
|
|
167
|
+
await expect(runRefreshStep(model)).rejects.toThrow('beforeRender bug');
|
|
168
|
+
});
|
|
169
|
+
|
|
115
170
|
it('respects saved manual mode and skips initial request when filters are empty', async () => {
|
|
171
|
+
vi.useFakeTimers();
|
|
116
172
|
const { model, resource } = setupModelWithManualMode();
|
|
117
173
|
const runActionSpy = vi.spyOn(resource, 'runAction').mockResolvedValue({
|
|
118
174
|
data: [{ id: 1, name: 'Alice' }],
|
|
@@ -128,4 +184,64 @@ describe('CollectionBlockModel initial beforeRender refresh', () => {
|
|
|
128
184
|
expect(resource.getData()).toEqual([]);
|
|
129
185
|
expect(resource.getMeta('count')).toBe(0);
|
|
130
186
|
});
|
|
187
|
+
|
|
188
|
+
it('skips forced active refresh in manual mode when filters are empty', async () => {
|
|
189
|
+
const { model, resource } = setupModelWithManualMode();
|
|
190
|
+
const refreshSpy = vi.spyOn(resource, 'refresh');
|
|
191
|
+
|
|
192
|
+
resource.setData([{ id: 2, name: 'Stale' }]);
|
|
193
|
+
resource.setMeta({ count: 1, hasNext: true });
|
|
194
|
+
resource.setPage(2);
|
|
195
|
+
resource.loading = true;
|
|
196
|
+
|
|
197
|
+
model.onActive(true);
|
|
198
|
+
await Promise.resolve();
|
|
199
|
+
await Promise.resolve();
|
|
200
|
+
|
|
201
|
+
expect(refreshSpy).not.toHaveBeenCalled();
|
|
202
|
+
expect(resource.getData()).toEqual([]);
|
|
203
|
+
expect(resource.getMeta('count')).toBe(0);
|
|
204
|
+
expect(resource.getMeta('hasNext')).toBe(false);
|
|
205
|
+
expect(resource.getMeta('page')).toBe(1);
|
|
206
|
+
expect(resource.getRequestParameter('page')).toBe(1);
|
|
207
|
+
expect(resource.loading).toBe(false);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('keeps forced active refresh in manual mode when filters are active', async () => {
|
|
211
|
+
const { model, resource } = setupModelWithManualMode();
|
|
212
|
+
const refreshSpy = vi.spyOn(resource, 'refresh').mockResolvedValue();
|
|
213
|
+
|
|
214
|
+
resource.setData([{ id: 2, name: 'Stale' }]);
|
|
215
|
+
resource.setMeta({ count: 1, hasNext: true, page: 2 });
|
|
216
|
+
model.setFilterActive('filter-form-item', true);
|
|
217
|
+
|
|
218
|
+
model.onActive(true);
|
|
219
|
+
await Promise.resolve();
|
|
220
|
+
|
|
221
|
+
expect(refreshSpy).toHaveBeenCalledTimes(1);
|
|
222
|
+
expect(resource.getData()).toEqual([{ id: 2, name: 'Stale' }]);
|
|
223
|
+
expect(resource.getMeta('count')).toBe(1);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('skips forced active refresh in manual mode when only resource filters are active', async () => {
|
|
227
|
+
const { model, resource } = setupModelWithManualMode();
|
|
228
|
+
const refreshSpy = vi.spyOn(resource, 'refresh');
|
|
229
|
+
|
|
230
|
+
resource.setData([{ id: 2, name: 'Stale' }]);
|
|
231
|
+
resource.setMeta({ count: 1, hasNext: true });
|
|
232
|
+
resource.setPage(2);
|
|
233
|
+
resource.loading = true;
|
|
234
|
+
resource.addFilterGroup('data-scope', { status: { $eq: 'active' } });
|
|
235
|
+
|
|
236
|
+
model.onActive(true);
|
|
237
|
+
await Promise.resolve();
|
|
238
|
+
|
|
239
|
+
expect(refreshSpy).not.toHaveBeenCalled();
|
|
240
|
+
expect(resource.getData()).toEqual([]);
|
|
241
|
+
expect(resource.getMeta('count')).toBe(0);
|
|
242
|
+
expect(resource.getMeta('hasNext')).toBe(false);
|
|
243
|
+
expect(resource.getMeta('page')).toBe(1);
|
|
244
|
+
expect(resource.getRequestParameter('page')).toBe(1);
|
|
245
|
+
expect(resource.loading).toBe(false);
|
|
246
|
+
});
|
|
131
247
|
});
|
|
@@ -10,23 +10,20 @@
|
|
|
10
10
|
import React from 'react';
|
|
11
11
|
import { Input } from 'antd';
|
|
12
12
|
import { define, observable } from '@formily/reactive';
|
|
13
|
-
import {
|
|
14
|
-
FlowModelRenderer,
|
|
15
|
-
FormItem,
|
|
16
|
-
VariableInput,
|
|
17
|
-
tExpr,
|
|
18
|
-
isVariableExpression,
|
|
19
|
-
parseValueToPath,
|
|
20
|
-
isRunJSValue,
|
|
21
|
-
EditableItemModel,
|
|
22
|
-
jioToJoiSchema,
|
|
23
|
-
} from '@nocobase/flow-engine';
|
|
13
|
+
import { FlowModelRenderer, FormItem, tExpr, EditableItemModel, jioToJoiSchema } from '@nocobase/flow-engine';
|
|
24
14
|
// 无需类型导入(避免未使用的类型)
|
|
25
15
|
import { FormItemModel } from '../form/FormItemModel';
|
|
26
16
|
import { EditFormModel } from '../form/EditFormModel';
|
|
27
17
|
import { customAlphabet as Alphabet } from 'nanoid';
|
|
28
18
|
import { ensureOptionsFromUiSchemaEnumIfAbsent } from '../../../internal/utils/enumOptionsUtils';
|
|
29
19
|
import { RunJSValueEditor } from '../../../components/RunJSValueEditor';
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_DATE_VARIABLE_COMPONENT_PROPS,
|
|
22
|
+
FieldValueVariableInput,
|
|
23
|
+
getFieldInterface,
|
|
24
|
+
isDateLikeField,
|
|
25
|
+
resolveDateVariableComponentProps,
|
|
26
|
+
} from '../../../components/field-value-variable';
|
|
30
27
|
|
|
31
28
|
type AssignFormTempOriginField = {
|
|
32
29
|
uid?: string;
|
|
@@ -285,7 +282,9 @@ export class AssignFormItemModel extends FormItemModel {
|
|
|
285
282
|
) : null;
|
|
286
283
|
};
|
|
287
284
|
|
|
288
|
-
const NullComponent: React.FC = () =>
|
|
285
|
+
const NullComponent: React.FC = () => (
|
|
286
|
+
<Input placeholder={`<${this.context.t?.('Null') ?? 'Null'}>`} readOnly style={{ width: '100%' }} />
|
|
287
|
+
);
|
|
289
288
|
|
|
290
289
|
const RunJSComponent: React.FC<any> = (inputProps: any) => {
|
|
291
290
|
return (
|
|
@@ -298,46 +297,18 @@ export class AssignFormItemModel extends FormItemModel {
|
|
|
298
297
|
);
|
|
299
298
|
};
|
|
300
299
|
|
|
301
|
-
const
|
|
302
|
-
renderInputComponent: (meta: any) => {
|
|
303
|
-
const firstPath = meta?.paths?.[0];
|
|
304
|
-
if (firstPath === 'constant') return ConstantValueEditor as any;
|
|
305
|
-
if (firstPath === 'null') return NullComponent as any;
|
|
306
|
-
if (firstPath === 'runjs') return RunJSComponent as any;
|
|
307
|
-
return undefined;
|
|
308
|
-
},
|
|
309
|
-
resolveValueFromPath: (item: any) => {
|
|
310
|
-
const firstPath = item?.paths?.[0];
|
|
311
|
-
if (firstPath === 'constant') return '';
|
|
312
|
-
if (firstPath === 'null') return null;
|
|
313
|
-
if (firstPath === 'runjs') return { code: '', version: 'v2' };
|
|
314
|
-
return undefined;
|
|
315
|
-
},
|
|
316
|
-
resolvePathFromValue: (currentValue: any) => {
|
|
317
|
-
if (currentValue === null) return ['null'];
|
|
318
|
-
if (isRunJSValue(currentValue)) return ['runjs'];
|
|
319
|
-
return isVariableExpression(currentValue) ? parseValueToPath(currentValue) : ['constant'];
|
|
320
|
-
},
|
|
321
|
-
} as any;
|
|
322
|
-
|
|
323
|
-
// 合并变量树:在最前面追加“常量/空值”两个选项
|
|
324
|
-
const mergedMetaTree = async () => {
|
|
300
|
+
const baseMetaTree = async () => {
|
|
325
301
|
const getTree = (this.context as any)?.getPropertyMetaTree;
|
|
326
|
-
|
|
327
|
-
return [
|
|
328
|
-
{
|
|
329
|
-
title: tExpr('Constant'),
|
|
330
|
-
name: 'constant',
|
|
331
|
-
type: 'string',
|
|
332
|
-
paths: ['constant'],
|
|
333
|
-
render: ConstantValueEditor,
|
|
334
|
-
},
|
|
335
|
-
{ title: tExpr('Null'), name: 'null', type: 'object', paths: ['null'], render: NullComponent },
|
|
336
|
-
{ title: tExpr('RunJS'), name: 'runjs', type: 'object', paths: ['runjs'], render: RunJSComponent },
|
|
337
|
-
...base,
|
|
338
|
-
];
|
|
302
|
+
return typeof getTree === 'function' ? await getTree() : [];
|
|
339
303
|
};
|
|
340
304
|
|
|
305
|
+
const targetCollectionField = collection?.getField?.(this.fieldPath);
|
|
306
|
+
const targetFieldInterface = getFieldInterface(targetCollectionField);
|
|
307
|
+
const dateLike = isDateLikeField(targetCollectionField, this.fieldPath?.split('.').slice(-1)[0]);
|
|
308
|
+
const dateComponentProps = dateLike
|
|
309
|
+
? resolveDateVariableComponentProps(targetCollectionField, targetFieldInterface)
|
|
310
|
+
: DEFAULT_DATE_VARIABLE_COMPONENT_PROPS;
|
|
311
|
+
|
|
341
312
|
// 计算 label:优先使用配置中的 label,其次集合字段标题,最后回退字段路径
|
|
342
313
|
let labelText = this.props?.label ?? this.fieldPath ?? '';
|
|
343
314
|
const cf = collection?.getField?.(this.fieldPath);
|
|
@@ -357,14 +328,18 @@ export class AssignFormItemModel extends FormItemModel {
|
|
|
357
328
|
const formValue = formBindingProps?.__assign_value__;
|
|
358
329
|
const mergedValue = typeof formValue === 'undefined' ? this.assignValue : formValue;
|
|
359
330
|
return (
|
|
360
|
-
<
|
|
331
|
+
<FieldValueVariableInput
|
|
361
332
|
value={mergedValue}
|
|
362
|
-
onChange={(v
|
|
333
|
+
onChange={(v) => {
|
|
363
334
|
this.assignValue = v;
|
|
364
335
|
formBindingProps?.__assign_trigger__?.(v);
|
|
365
336
|
}}
|
|
366
|
-
|
|
367
|
-
|
|
337
|
+
baseMetaTree={baseMetaTree}
|
|
338
|
+
constantComponent={ConstantValueEditor}
|
|
339
|
+
nullComponent={NullComponent}
|
|
340
|
+
runJSComponent={RunJSComponent}
|
|
341
|
+
isDateLikeField={dateLike}
|
|
342
|
+
dateComponentProps={dateComponentProps}
|
|
368
343
|
clearValue={''}
|
|
369
344
|
/>
|
|
370
345
|
);
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
SingleRecordResource,
|
|
21
21
|
createCurrentRecordMetaFactory,
|
|
22
22
|
createRecordResolveOnServerWithLocal,
|
|
23
|
+
observer,
|
|
23
24
|
tExpr,
|
|
24
25
|
} from '@nocobase/flow-engine';
|
|
25
26
|
import { Pagination, Space } from 'antd';
|
|
@@ -154,8 +155,8 @@ export class DetailsBlockModel extends CollectionBlockModel<{
|
|
|
154
155
|
simple
|
|
155
156
|
pageSize={1}
|
|
156
157
|
showSizeChanger={false}
|
|
157
|
-
|
|
158
|
-
total={resource.
|
|
158
|
+
current={resource.getPage()}
|
|
159
|
+
total={resource.getCount()}
|
|
159
160
|
onChange={this.handlePageChange}
|
|
160
161
|
style={{ display: 'inline-block' }}
|
|
161
162
|
/>
|
|
@@ -226,6 +227,8 @@ export class DetailsBlockModel extends CollectionBlockModel<{
|
|
|
226
227
|
}
|
|
227
228
|
}
|
|
228
229
|
|
|
230
|
+
export const DetailsPagination = observer(({ model }: { model: DetailsBlockModel }) => model.renderPagination());
|
|
231
|
+
|
|
229
232
|
const DetailsBlockContent = ({
|
|
230
233
|
model,
|
|
231
234
|
gridModel,
|
|
@@ -297,7 +300,9 @@ const DetailsBlockContent = ({
|
|
|
297
300
|
model={gridModel}
|
|
298
301
|
showFlowSettings={false}
|
|
299
302
|
/>
|
|
300
|
-
<div ref={paginationRef}>
|
|
303
|
+
<div ref={paginationRef}>
|
|
304
|
+
<DetailsPagination model={model} />
|
|
305
|
+
</div>
|
|
301
306
|
</div>
|
|
302
307
|
</FormComponent>
|
|
303
308
|
);
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { act, render, screen } from '@testing-library/react';
|
|
10
11
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
11
12
|
import { FlowEngine, MultiRecordResource, SingleRecordResource } from '@nocobase/flow-engine';
|
|
13
|
+
import React from 'react';
|
|
12
14
|
import '../../../../index';
|
|
13
|
-
import { DetailsBlockModel } from '../DetailsBlockModel';
|
|
15
|
+
import { DetailsBlockModel, DetailsPagination } from '../DetailsBlockModel';
|
|
14
16
|
import { DetailsGridModel } from '../DetailsGridModel';
|
|
15
17
|
|
|
16
18
|
function setupDetailsBlockModel(options?: { filterByTk?: string | number }) {
|
|
@@ -93,6 +95,35 @@ describe('DetailsBlockModel initial pagination refresh', () => {
|
|
|
93
95
|
expect(dispatchSpy.mock.calls.filter(([eventName]) => eventName === 'paginationChange')).toHaveLength(1);
|
|
94
96
|
});
|
|
95
97
|
|
|
98
|
+
it('renders pagination from the current count and page after filtering', () => {
|
|
99
|
+
const { model, resource } = setupDetailsBlockModel();
|
|
100
|
+
resource.setData([{ id: 3, name: 'CC', title: 'filtered' }] as any);
|
|
101
|
+
resource.setMeta({ count: 7, page: 3, pageSize: 1, totalPage: 20 });
|
|
102
|
+
|
|
103
|
+
const paginationContainer = model.renderPagination() as any;
|
|
104
|
+
const pagination = paginationContainer.props.children;
|
|
105
|
+
|
|
106
|
+
expect(pagination.props.total).toBe(7);
|
|
107
|
+
expect(pagination.props.current).toBe(3);
|
|
108
|
+
expect(pagination.props.defaultCurrent).toBeUndefined();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('updates the rendered pagination when filtering changes only resource metadata', () => {
|
|
112
|
+
const { model, resource } = setupDetailsBlockModel();
|
|
113
|
+
resource.setData([{ id: 1, name: 'AA', title: 'foo' }] as any);
|
|
114
|
+
resource.setMeta({ count: 7, page: 1, pageSize: 1, totalPage: 7 });
|
|
115
|
+
|
|
116
|
+
render(React.createElement(DetailsPagination, { model }));
|
|
117
|
+
|
|
118
|
+
expect(screen.getByRole('list')).toBeInTheDocument();
|
|
119
|
+
|
|
120
|
+
act(() => {
|
|
121
|
+
resource.setMeta({ count: 1, page: 1, pageSize: 1, totalPage: 1 });
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(screen.queryByRole('list')).not.toBeInTheDocument();
|
|
125
|
+
});
|
|
126
|
+
|
|
96
127
|
it('uses a real single-record details model and does not emit root paginationChange on initial render', async () => {
|
|
97
128
|
const { model, resource } = setupDetailsBlockModel({ filterByTk: 1 });
|
|
98
129
|
expect(resource).toBeInstanceOf(SingleRecordResource);
|
|
@@ -15,8 +15,10 @@ import {
|
|
|
15
15
|
DndProvider,
|
|
16
16
|
DragHandler,
|
|
17
17
|
Droppable,
|
|
18
|
+
isCtxDateExpression,
|
|
18
19
|
isRunJSValue,
|
|
19
20
|
normalizeRunJSValue,
|
|
21
|
+
parseCtxDateExpression,
|
|
20
22
|
tExpr,
|
|
21
23
|
FlowModelRenderer,
|
|
22
24
|
FlowSettingsButton,
|
|
@@ -44,6 +46,15 @@ import { normalizeFilterValueByOperator } from './valueNormalization';
|
|
|
44
46
|
|
|
45
47
|
const RELATION_FIELD_TYPES = ['belongsTo', 'hasOne', 'hasMany', 'belongsToMany', 'belongsToArray'];
|
|
46
48
|
const NUMERIC_FIELD_TYPES = ['integer', 'float', 'double', 'decimal'];
|
|
49
|
+
const DATE_FILTER_OPERATORS = new Set([
|
|
50
|
+
'$dateOn',
|
|
51
|
+
'$dateNotOn',
|
|
52
|
+
'$dateBefore',
|
|
53
|
+
'$dateAfter',
|
|
54
|
+
'$dateNotBefore',
|
|
55
|
+
'$dateNotAfter',
|
|
56
|
+
'$dateBetween',
|
|
57
|
+
]);
|
|
47
58
|
|
|
48
59
|
function getFilterFormFieldMetaType(field: CollectionField) {
|
|
49
60
|
if (RELATION_FIELD_TYPES.includes(field.type)) {
|
|
@@ -66,6 +77,14 @@ function getFilterFormFieldMetaType(field: CollectionField) {
|
|
|
66
77
|
}
|
|
67
78
|
}
|
|
68
79
|
|
|
80
|
+
function parseDateFilterDefaultValue(operator: string | undefined, rawValue: unknown) {
|
|
81
|
+
if (!operator || !DATE_FILTER_OPERATORS.has(operator) || !isCtxDateExpression(rawValue)) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return parseCtxDateExpression(rawValue);
|
|
86
|
+
}
|
|
87
|
+
|
|
69
88
|
function shouldShowFilterFormFieldMeta(field: CollectionField) {
|
|
70
89
|
return Boolean(field?.interface);
|
|
71
90
|
}
|
|
@@ -489,7 +508,7 @@ export class FilterFormBlockModel extends FilterBlockModel<{
|
|
|
489
508
|
const rules = (params?.value || []) as any[];
|
|
490
509
|
if (!Array.isArray(rules) || rules.length === 0) return appliedValues;
|
|
491
510
|
|
|
492
|
-
const resolveValue = async (raw: any) => {
|
|
511
|
+
const resolveValue = async (raw: any, operator?: string) => {
|
|
493
512
|
// RunJS support
|
|
494
513
|
if (isRunJSValue(raw)) {
|
|
495
514
|
const { code, version } = normalizeRunJSValue(raw);
|
|
@@ -497,6 +516,11 @@ export class FilterFormBlockModel extends FilterBlockModel<{
|
|
|
497
516
|
return ret?.success ? ret.value : undefined;
|
|
498
517
|
}
|
|
499
518
|
|
|
519
|
+
const parsedDateFilterValue = parseDateFilterDefaultValue(operator, raw);
|
|
520
|
+
if (typeof parsedDateFilterValue !== 'undefined') {
|
|
521
|
+
return parsedDateFilterValue;
|
|
522
|
+
}
|
|
523
|
+
|
|
500
524
|
return await (this.context as any).resolveJsonTemplate?.(raw);
|
|
501
525
|
};
|
|
502
526
|
|
|
@@ -520,11 +544,11 @@ export class FilterFormBlockModel extends FilterBlockModel<{
|
|
|
520
544
|
|
|
521
545
|
const current = (form as any).getFieldValue?.(name);
|
|
522
546
|
|
|
523
|
-
const
|
|
547
|
+
const operator = getDefaultOperator(itemModel as any);
|
|
548
|
+
const resolved = await resolveValue(rule.value, operator);
|
|
524
549
|
if (options?.refreshSeq && options.refreshSeq !== this.defaultValuesRefreshSeq) return appliedValues;
|
|
525
550
|
if (typeof resolved === 'undefined') continue;
|
|
526
551
|
|
|
527
|
-
const operator = getDefaultOperator(itemModel as any);
|
|
528
552
|
const normalized = normalizeFilterValueByOperator(operator, resolved);
|
|
529
553
|
const mode = this.normalizeFieldValueMode(rule.mode);
|
|
530
554
|
if (mode === 'default' && !this.canApplyFormDefaultValue(String(name), current, force)) continue;
|