@nocobase/client-v2 2.1.0-beta.42 → 2.1.0-beta.43
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/TypedVariableInput.d.ts +75 -0
- package/es/components/form/index.d.ts +1 -0
- package/es/flow/models/blocks/assign-form/assignFieldValuesFlow.d.ts +8 -0
- package/es/index.mjs +70 -70
- package/lib/index.js +91 -91
- package/package.json +7 -7
- package/src/components/README.md +48 -0
- package/src/components/README.zh-CN.md +48 -0
- package/src/components/form/TypedVariableInput.tsx +441 -0
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +152 -0
- package/src/components/form/index.tsx +1 -0
- package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +100 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +23 -1
- package/src/flow/actions/linkageRules.tsx +5 -4
- package/src/flow/actions/linkageRulesRefresh.tsx +2 -3
- package/src/flow/components/code-editor/__tests__/runjsCompletions.test.ts +272 -27
- package/src/flow/components/code-editor/runjsCompletions.ts +490 -9
- package/src/flow/models/actions/__tests__/AssignFormRefill.test.ts +90 -0
- package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +14 -3
- package/src/flow/models/blocks/assign-form/__tests__/assignFieldValuesFlow.editor.test.tsx +94 -2
- package/src/flow/models/blocks/assign-form/assignFieldValuesFlow.tsx +67 -13
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import React from 'react';
|
|
11
11
|
import { App, ConfigProvider } from 'antd';
|
|
12
12
|
import { describe, expect, it } from 'vitest';
|
|
13
|
-
import { render, screen, waitFor } from '@nocobase/test/client';
|
|
13
|
+
import { render, screen, userEvent, waitFor } from '@nocobase/test/client';
|
|
14
14
|
import {
|
|
15
15
|
FlowEngine,
|
|
16
16
|
FlowEngineProvider,
|
|
@@ -24,6 +24,7 @@ import { AssignFormItemModel } from '../AssignFormItemModel';
|
|
|
24
24
|
import { AssignFormModel } from '../AssignFormModel';
|
|
25
25
|
import { createAssignFieldValuesStep } from '../assignFieldValuesFlow';
|
|
26
26
|
import { InputFieldModel } from '../../../fields/InputFieldModel';
|
|
27
|
+
import { VariableFieldFormModel } from '../../../fields/VariableFieldFormModel';
|
|
27
28
|
|
|
28
29
|
class MockFlowModelRepository implements IFlowModelRepository {
|
|
29
30
|
async findOne(): Promise<Record<string, any> | null> {
|
|
@@ -49,7 +50,13 @@ describe('assignFieldValuesFlow (editor)', () => {
|
|
|
49
50
|
it('repairs AssignFormModel resource init and clears cached collection', async () => {
|
|
50
51
|
const engine = new FlowEngine();
|
|
51
52
|
engine.setModelRepository(new MockFlowModelRepository());
|
|
52
|
-
engine.registerModels({
|
|
53
|
+
engine.registerModels({
|
|
54
|
+
AssignFormModel,
|
|
55
|
+
AssignFormGridModel,
|
|
56
|
+
AssignFormItemModel,
|
|
57
|
+
InputFieldModel,
|
|
58
|
+
VariableFieldFormModel,
|
|
59
|
+
});
|
|
53
60
|
engine.context.defineProperty('location', { value: { search: '' } });
|
|
54
61
|
engine.context.defineProperty('themeToken', { value: { marginLG: 24 } });
|
|
55
62
|
|
|
@@ -120,5 +127,90 @@ describe('assignFieldValuesFlow (editor)', () => {
|
|
|
120
127
|
const form = engine.findModelByParentId<AssignFormModel>(action.uid, 'assignForm');
|
|
121
128
|
expect(form?.subModels.grid.subModels.items.length).toBe(1);
|
|
122
129
|
});
|
|
130
|
+
|
|
131
|
+
await waitFor(() => {
|
|
132
|
+
expect(screen.getByDisplayValue('1111')).toBeInTheDocument();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const input = screen.getByDisplayValue('1111') as HTMLInputElement;
|
|
136
|
+
await userEvent.clear(input);
|
|
137
|
+
await userEvent.type(input, '2222');
|
|
138
|
+
|
|
139
|
+
await waitFor(() => {
|
|
140
|
+
const form = engine.findModelByParentId<AssignFormModel>(action.uid, 'assignForm');
|
|
141
|
+
expect(form?.getAssignedValues()).toEqual({ nickname: '2222' });
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('does not clear delegated parent resource cache when repairing AssignFormModel init', async () => {
|
|
146
|
+
const engine = new FlowEngine();
|
|
147
|
+
engine.setModelRepository(new MockFlowModelRepository());
|
|
148
|
+
engine.registerModels({ AssignFormModel, AssignFormGridModel, AssignFormItemModel, InputFieldModel });
|
|
149
|
+
engine.context.defineProperty('location', { value: { search: '' } });
|
|
150
|
+
engine.context.defineProperty('themeToken', { value: { marginLG: 24 } });
|
|
151
|
+
|
|
152
|
+
const dsm = engine.context.dataSourceManager;
|
|
153
|
+
const main = dsm.getDataSource('main');
|
|
154
|
+
main.addCollection({
|
|
155
|
+
name: 'users',
|
|
156
|
+
fields: [{ name: 'nickname', type: 'string', interface: 'input' }],
|
|
157
|
+
});
|
|
158
|
+
const users = dsm.getCollection('main', 'users');
|
|
159
|
+
|
|
160
|
+
const action = engine.createModel({
|
|
161
|
+
use: 'FlowModel',
|
|
162
|
+
uid: 'act-assign-parent-resource',
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
let resourceCreateCount = 0;
|
|
166
|
+
action.context.defineProperty('resource', {
|
|
167
|
+
get: () => ({ id: ++resourceCreateCount }),
|
|
168
|
+
});
|
|
169
|
+
const cachedResource = action.context.resource;
|
|
170
|
+
|
|
171
|
+
engine.createModel<AssignFormModel>({
|
|
172
|
+
use: 'AssignFormModel',
|
|
173
|
+
uid: 'form-assign-parent-resource',
|
|
174
|
+
parentId: action.uid,
|
|
175
|
+
subKey: 'assignForm',
|
|
176
|
+
stepParams: {
|
|
177
|
+
resourceSettings: {
|
|
178
|
+
init: {
|
|
179
|
+
dataSourceKey: 'main',
|
|
180
|
+
collectionName: 'missing',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
action.context.defineProperty('blockModel', { value: { collection: users } });
|
|
187
|
+
|
|
188
|
+
const step = createAssignFieldValuesStep({ settingsFlowKey: 'assignSettings' });
|
|
189
|
+
const schema = step.uiSchema();
|
|
190
|
+
const Editor = schema.editor?.['x-component'] as React.ComponentType;
|
|
191
|
+
const flowSettingsCtx = new FlowRuntimeContext(action as any, 'assignSettings', 'settings');
|
|
192
|
+
|
|
193
|
+
render(
|
|
194
|
+
<FlowEngineProvider engine={engine}>
|
|
195
|
+
<ConfigProvider>
|
|
196
|
+
<App>
|
|
197
|
+
<FlowSettingsContextProvider value={flowSettingsCtx}>
|
|
198
|
+
<Editor />
|
|
199
|
+
</FlowSettingsContextProvider>
|
|
200
|
+
</App>
|
|
201
|
+
</ConfigProvider>
|
|
202
|
+
</FlowEngineProvider>,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
await waitFor(() => {
|
|
206
|
+
const form = engine.findModelByParentId<AssignFormModel>(action.uid, 'assignForm');
|
|
207
|
+
expect(form?.getStepParams('resourceSettings', 'init')).toEqual({
|
|
208
|
+
dataSourceKey: 'main',
|
|
209
|
+
collectionName: 'users',
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
expect(action.context.resource).toBe(cachedResource);
|
|
214
|
+
expect(resourceCreateCount).toBe(1);
|
|
123
215
|
});
|
|
124
216
|
});
|
|
@@ -38,6 +38,9 @@ type AssignFieldValuesModel = {
|
|
|
38
38
|
uid: string;
|
|
39
39
|
assignFormUid?: string;
|
|
40
40
|
context?: AssignFieldValuesContext;
|
|
41
|
+
subModels?: {
|
|
42
|
+
assignForm?: AssignFormModel;
|
|
43
|
+
};
|
|
41
44
|
getStepParams?: (flowKey: string, stepKey: string) => { assignedValues?: AssignedValues } | undefined;
|
|
42
45
|
setStepParams?: (flowKey: string, stepKey: string, params: { assignedValues: AssignedValues }) => void;
|
|
43
46
|
};
|
|
@@ -88,11 +91,53 @@ function isValidResourceInit(init: unknown): init is {
|
|
|
88
91
|
);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
type LocalCacheContext = {
|
|
95
|
+
_observableCache?: Record<string, unknown>;
|
|
96
|
+
_cache?: Record<string, unknown>;
|
|
97
|
+
_pending?: Record<string, unknown>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
function toLocalCacheContext(context: unknown): LocalCacheContext | undefined {
|
|
101
|
+
return context && typeof context === 'object' ? (context as LocalCacheContext) : undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function clearOwnContextCache(context: unknown, key: string) {
|
|
105
|
+
const localContext = toLocalCacheContext(context);
|
|
106
|
+
if (!localContext) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
delete localContext._observableCache?.[key];
|
|
110
|
+
delete localContext._cache?.[key];
|
|
111
|
+
delete localContext._pending?.[key];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function clearResourceContextCache(model: { context?: unknown } | undefined) {
|
|
115
|
+
clearOwnContextCache(model?.context, 'dataSource');
|
|
116
|
+
clearOwnContextCache(model?.context, 'collection');
|
|
117
|
+
clearOwnContextCache(model?.context, 'resource');
|
|
118
|
+
clearOwnContextCache(model?.context, 'association');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function resolveAssignFormModel(ctx: {
|
|
122
|
+
model: AssignFieldValuesModel;
|
|
123
|
+
engine: {
|
|
124
|
+
getModel?: (uid: string, fromRoot?: boolean) => AssignFormModel | undefined;
|
|
125
|
+
findModelByParentId?: (parentId: string, subKey: string) => AssignFormModel | undefined | null;
|
|
126
|
+
};
|
|
127
|
+
}) {
|
|
128
|
+
if (ctx.model.assignFormUid) {
|
|
129
|
+
const form = ctx.engine.getModel?.(ctx.model.assignFormUid, true);
|
|
130
|
+
if (form) {
|
|
131
|
+
return form;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const localForm = ctx.model.subModels?.assignForm;
|
|
136
|
+
if (localForm) {
|
|
137
|
+
return localForm;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return ctx.engine.findModelByParentId?.(ctx.model.uid, 'assignForm') || undefined;
|
|
96
141
|
}
|
|
97
142
|
|
|
98
143
|
export function createAssignFormSubModelOptions(ctx: AssignFieldValuesContext) {
|
|
@@ -235,14 +280,23 @@ export function createAssignFieldValuesStep(options: AssignFieldValuesStepOption
|
|
|
235
280
|
},
|
|
236
281
|
};
|
|
237
282
|
},
|
|
238
|
-
async beforeParamsSave(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
283
|
+
async beforeParamsSave(
|
|
284
|
+
ctx: {
|
|
285
|
+
model: AssignFieldValuesModel;
|
|
286
|
+
engine: {
|
|
287
|
+
getModel?: (uid: string, fromRoot?: boolean) => AssignFormModel | undefined;
|
|
288
|
+
findModelByParentId?: (parentId: string, subKey: string) => AssignFormModel | undefined | null;
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
params?: { assignedValues?: AssignedValues },
|
|
292
|
+
previousParams?: { assignedValues?: AssignedValues },
|
|
293
|
+
) {
|
|
294
|
+
const form = resolveAssignFormModel(ctx);
|
|
295
|
+
if (!form) {
|
|
296
|
+
const assignedValues = params?.assignedValues || previousParams?.assignedValues || {};
|
|
297
|
+
ctx.model.setStepParams?.(options.settingsFlowKey, ASSIGN_FIELD_VALUES_STEP_KEY, { assignedValues });
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
246
300
|
if (options.validateBeforeSave) {
|
|
247
301
|
await form.form?.validateFields?.();
|
|
248
302
|
}
|