@nocobase/plugin-workflow-manual 0.20.0-alpha.9 → 0.21.0-alpha.10
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/client/index.js +4 -4
- package/dist/client/instruction/SchemaConfig.d.ts +14 -3
- package/dist/client/instruction/createManualFormBlockUISchema.d.ts +57 -0
- package/dist/client/instruction/forms/custom.d.ts +7 -2
- package/dist/externalVersion.js +9 -9
- package/dist/locale/index.d.ts +2 -1
- package/dist/locale/index.js +3 -0
- package/dist/locale/zh-CN.json +2 -1
- package/dist/server/forms/create.d.ts +2 -1
- package/dist/server/forms/create.js +4 -4
- package/dist/server/forms/update.d.ts +2 -1
- package/dist/server/forms/update.js +4 -4
- package/dist/server/migrations/20240325213145-fix-schema.d.ts +4 -0
- package/dist/server/migrations/20240325213145-fix-schema.js +88 -0
- package/package.json +2 -2
- package/src/client/WorkflowTodo.tsx +4 -4
- package/src/client/__e2e__/createRecordForm.test.ts +123 -67
- package/src/client/__e2e__/customFormBlocks.test.ts +135 -70
- package/src/client/__e2e__/datablocks.test.ts +43 -30
- package/src/client/__e2e__/updateRecordForm.test.ts +241 -57
- package/src/client/__e2e__/workflowTodo.test.ts +16 -7
- package/src/client/index.ts +12 -4
- package/src/client/instruction/FormBlockInitializer.tsx +3 -3
- package/src/client/instruction/SchemaConfig.tsx +163 -41
- package/src/client/instruction/createManualFormBlockUISchema.ts +5 -0
- package/src/client/instruction/forms/create.tsx +1 -1
- package/src/client/instruction/forms/custom.tsx +52 -21
- package/src/client/instruction/forms/update.tsx +16 -8
- package/src/client/instruction/index.tsx +1 -1
- package/src/locale/index.ts +3 -1
- package/src/locale/zh-CN.json +2 -1
- package/src/server/__tests__/data-source.test.ts +223 -0
- package/src/server/__tests__/{instruction.test.ts → form.test.ts} +1 -510
- package/src/server/__tests__/mode.test.ts +561 -0
- package/src/server/forms/create.ts +10 -3
- package/src/server/forms/update.ts +10 -3
- package/src/server/migrations/20240325213145-fix-schema.ts +81 -0
- package/dist/client/instruction/DetailsBlockProvider.d.ts +0 -2
- package/src/client/instruction/DetailsBlockProvider.tsx +0 -87
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { faker } from '@faker-js/faker';
|
|
2
2
|
import {
|
|
3
3
|
CollectionTriggerNode,
|
|
4
|
+
ManualNode,
|
|
4
5
|
apiCreateWorkflow,
|
|
5
6
|
apiDeleteWorkflow,
|
|
6
7
|
apiGetWorkflow,
|
|
7
8
|
apiUpdateWorkflowTrigger,
|
|
8
9
|
appendJsonCollectionName,
|
|
9
10
|
generalWithNoRelationalFields,
|
|
10
|
-
|
|
11
|
+
apiGetDataSourceCount,
|
|
11
12
|
} from '@nocobase/plugin-workflow-test/e2e';
|
|
12
13
|
import { expect, test } from '@nocobase/test/e2e';
|
|
13
14
|
import { dayjs } from '@nocobase/utils';
|
|
@@ -69,10 +70,14 @@ test('filter task node', async ({ page, mockPage, mockCollections, mockRecords }
|
|
|
69
70
|
await manualNode.configureUserInterfaceButton.click();
|
|
70
71
|
await manualNode.addBlockButton.hover();
|
|
71
72
|
await manualNode.createRecordFormMenu.hover();
|
|
73
|
+
const dataSourcesCount = await apiGetDataSourceCount();
|
|
74
|
+
if (dataSourcesCount > 1) {
|
|
75
|
+
await page.getByRole('menuitem', { name: 'Main right' }).hover();
|
|
76
|
+
}
|
|
72
77
|
await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click();
|
|
73
78
|
await page.mouse.move(300, 0, { steps: 100 });
|
|
74
79
|
await page
|
|
75
|
-
.locator(`button[aria-label^="schema-initializer-Grid-
|
|
80
|
+
.locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
|
|
76
81
|
.hover();
|
|
77
82
|
await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover();
|
|
78
83
|
await page.getByRole('menuitem', { name: 'Edit block title' }).click();
|
|
@@ -80,7 +85,7 @@ test('filter task node', async ({ page, mockPage, mockCollections, mockRecords }
|
|
|
80
85
|
await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle);
|
|
81
86
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
|
82
87
|
await page
|
|
83
|
-
.locator(`button[aria-label^="schema-initializer-Grid-
|
|
88
|
+
.locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
|
|
84
89
|
.hover();
|
|
85
90
|
await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click();
|
|
86
91
|
await page.mouse.move(300, 0, { steps: 100 });
|
|
@@ -103,7 +108,7 @@ test('filter task node', async ({ page, mockPage, mockCollections, mockRecords }
|
|
|
103
108
|
const newPage = mockPage();
|
|
104
109
|
await newPage.goto();
|
|
105
110
|
await page.waitForLoadState('networkidle');
|
|
106
|
-
await page.getByLabel('schema-initializer-Grid-
|
|
111
|
+
await page.getByLabel('schema-initializer-Grid-page:addBlock').hover();
|
|
107
112
|
await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click();
|
|
108
113
|
await page.mouse.move(300, 0, { steps: 100 });
|
|
109
114
|
await page.waitForTimeout(300);
|
|
@@ -179,10 +184,14 @@ test('filter workflow name', async ({ page, mockPage, mockCollections, mockRecor
|
|
|
179
184
|
await manualNode.configureUserInterfaceButton.click();
|
|
180
185
|
await manualNode.addBlockButton.hover();
|
|
181
186
|
await manualNode.createRecordFormMenu.hover();
|
|
187
|
+
const dataSourcesCount = await apiGetDataSourceCount();
|
|
188
|
+
if (dataSourcesCount > 1) {
|
|
189
|
+
await page.getByRole('menuitem', { name: 'Main right' }).hover();
|
|
190
|
+
}
|
|
182
191
|
await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click();
|
|
183
192
|
await page.mouse.move(300, 0, { steps: 100 });
|
|
184
193
|
await page
|
|
185
|
-
.locator(`button[aria-label^="schema-initializer-Grid-
|
|
194
|
+
.locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
|
|
186
195
|
.hover();
|
|
187
196
|
await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover();
|
|
188
197
|
await page.getByRole('menuitem', { name: 'Edit block title' }).click();
|
|
@@ -190,7 +199,7 @@ test('filter workflow name', async ({ page, mockPage, mockCollections, mockRecor
|
|
|
190
199
|
await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle);
|
|
191
200
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
|
192
201
|
await page
|
|
193
|
-
.locator(`button[aria-label^="schema-initializer-Grid-
|
|
202
|
+
.locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
|
|
194
203
|
.hover();
|
|
195
204
|
await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click();
|
|
196
205
|
await page.mouse.move(300, 0, { steps: 100 });
|
|
@@ -213,7 +222,7 @@ test('filter workflow name', async ({ page, mockPage, mockCollections, mockRecor
|
|
|
213
222
|
const newPage = mockPage();
|
|
214
223
|
await newPage.goto();
|
|
215
224
|
await page.waitForLoadState('networkidle');
|
|
216
|
-
await page.getByLabel('schema-initializer-Grid-
|
|
225
|
+
await page.getByLabel('schema-initializer-Grid-page:addBlock').hover();
|
|
217
226
|
await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click();
|
|
218
227
|
await page.mouse.move(300, 0, { steps: 100 });
|
|
219
228
|
await page.waitForTimeout(300);
|
package/src/client/index.ts
CHANGED
|
@@ -3,11 +3,16 @@ import WorkflowPlugin from '@nocobase/plugin-workflow/client';
|
|
|
3
3
|
|
|
4
4
|
import Manual from './instruction';
|
|
5
5
|
|
|
6
|
+
import { NAMESPACE } from '../locale';
|
|
6
7
|
import { WorkflowTodo } from './WorkflowTodo';
|
|
7
8
|
import { WorkflowTodoBlockInitializer } from './WorkflowTodoBlockInitializer';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
addActionButton,
|
|
11
|
+
addActionButton_deprecated,
|
|
12
|
+
addBlockButton,
|
|
13
|
+
addBlockButton_deprecated,
|
|
14
|
+
} from './instruction/SchemaConfig';
|
|
15
|
+
import { addCustomFormField, addCustomFormField_deprecated } from './instruction/forms/custom';
|
|
11
16
|
|
|
12
17
|
export default class extends Plugin {
|
|
13
18
|
async afterAdd() {
|
|
@@ -22,11 +27,14 @@ export default class extends Plugin {
|
|
|
22
27
|
const workflow = this.app.pm.get('workflow') as WorkflowPlugin;
|
|
23
28
|
workflow.registerInstruction('manual', Manual);
|
|
24
29
|
|
|
30
|
+
this.app.schemaInitializerManager.add(addBlockButton_deprecated);
|
|
25
31
|
this.app.schemaInitializerManager.add(addBlockButton);
|
|
32
|
+
this.app.schemaInitializerManager.add(addActionButton_deprecated);
|
|
26
33
|
this.app.schemaInitializerManager.add(addActionButton);
|
|
34
|
+
this.app.schemaInitializerManager.add(addCustomFormField_deprecated);
|
|
27
35
|
this.app.schemaInitializerManager.add(addCustomFormField);
|
|
28
36
|
|
|
29
|
-
const blockInitializers = this.app.schemaInitializerManager.get('
|
|
37
|
+
const blockInitializers = this.app.schemaInitializerManager.get('page:addBlock');
|
|
30
38
|
blockInitializers.add('otherBlocks.workflowTodos', {
|
|
31
39
|
title: `{{t("Workflow todos", { ns: "${NAMESPACE}" })}}`,
|
|
32
40
|
Component: 'WorkflowTodoBlockInitializer',
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
CollectionProvider_deprecated,
|
|
5
5
|
SchemaInitializerItem,
|
|
6
6
|
SchemaInitializerItemType,
|
|
7
|
-
createFormBlockSchema,
|
|
8
7
|
useRecordCollectionDataSourceItems,
|
|
9
8
|
useSchemaInitializer,
|
|
10
9
|
useSchemaInitializerItem,
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
import { JOB_STATUS, traverseSchema } from '@nocobase/plugin-workflow/client';
|
|
15
14
|
|
|
16
15
|
import { NAMESPACE } from '../../locale';
|
|
16
|
+
import { createManualFormBlockUISchema } from './createManualFormBlockUISchema';
|
|
17
17
|
|
|
18
18
|
function InternalFormBlockInitializer({ schema, ...others }) {
|
|
19
19
|
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
|
@@ -21,8 +21,8 @@ function InternalFormBlockInitializer({ schema, ...others }) {
|
|
|
21
21
|
const items = useRecordCollectionDataSourceItems('FormItem') as SchemaInitializerItemType[];
|
|
22
22
|
async function onConfirm({ item }) {
|
|
23
23
|
const template = item.template ? await getTemplateSchemaByMode(item) : null;
|
|
24
|
-
const result =
|
|
25
|
-
actionInitializers: '
|
|
24
|
+
const result = createManualFormBlockUISchema({
|
|
25
|
+
actionInitializers: 'workflowManual:form:configureActions',
|
|
26
26
|
actions: {
|
|
27
27
|
resolve: {
|
|
28
28
|
type: 'void',
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import { FormLayout } from '@formily/antd-v5';
|
|
2
2
|
import { createForm } from '@formily/core';
|
|
3
3
|
import { FormProvider, ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
|
|
4
|
-
import { Alert, Button, Modal, Space } from 'antd';
|
|
4
|
+
import { Alert, Button, Modal, Space, message } from 'antd';
|
|
5
5
|
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
Action,
|
|
10
10
|
ActionContextProvider,
|
|
11
|
+
CompatibleSchemaInitializer,
|
|
11
12
|
DefaultValueProvider,
|
|
12
13
|
FormActiveFieldsProvider,
|
|
13
14
|
GeneralSchemaDesigner,
|
|
14
15
|
InitializerWithSwitch,
|
|
15
16
|
SchemaComponent,
|
|
16
17
|
SchemaComponentContext,
|
|
17
|
-
SchemaInitializer,
|
|
18
18
|
SchemaInitializerItem,
|
|
19
19
|
SchemaInitializerItemType,
|
|
20
|
-
SchemaSettingsBlockTitleItem,
|
|
21
20
|
SchemaSettingsDivider,
|
|
22
21
|
SchemaSettingsItem,
|
|
23
22
|
SchemaSettingsRemove,
|
|
24
23
|
VariableScopeProvider,
|
|
25
24
|
css,
|
|
26
25
|
gridRowColWrap,
|
|
27
|
-
useCompile,
|
|
28
26
|
useDataSourceManager,
|
|
29
27
|
useFormActiveFields,
|
|
30
28
|
useFormBlockContext,
|
|
@@ -34,7 +32,9 @@ import {
|
|
|
34
32
|
useSchemaOptionsContext,
|
|
35
33
|
} from '@nocobase/client';
|
|
36
34
|
import WorkflowPlugin, {
|
|
35
|
+
DetailsBlockProvider,
|
|
37
36
|
JOB_STATUS,
|
|
37
|
+
SimpleDesigner,
|
|
38
38
|
useAvailableUpstreams,
|
|
39
39
|
useFlowContext,
|
|
40
40
|
useNodeContext,
|
|
@@ -43,8 +43,7 @@ import WorkflowPlugin, {
|
|
|
43
43
|
} from '@nocobase/plugin-workflow/client';
|
|
44
44
|
import { Registry, lodash } from '@nocobase/utils/client';
|
|
45
45
|
|
|
46
|
-
import { NAMESPACE,
|
|
47
|
-
import { DetailsBlockProvider } from './DetailsBlockProvider';
|
|
46
|
+
import { NAMESPACE, usePluginTranslation } from '../../locale';
|
|
48
47
|
import { FormBlockProvider } from './FormBlockProvider';
|
|
49
48
|
import createRecordForm from './forms/create';
|
|
50
49
|
import customRecordForm from './forms/custom';
|
|
@@ -85,13 +84,14 @@ export type ManualFormType = {
|
|
|
85
84
|
[key: string]: React.FC;
|
|
86
85
|
};
|
|
87
86
|
};
|
|
87
|
+
validate?: (config: any) => string | null;
|
|
88
88
|
};
|
|
89
89
|
|
|
90
90
|
export const manualFormTypes = new Registry<ManualFormType>();
|
|
91
91
|
|
|
92
|
-
manualFormTypes.register('
|
|
93
|
-
manualFormTypes.register('
|
|
94
|
-
manualFormTypes.register('
|
|
92
|
+
manualFormTypes.register('custom', customRecordForm);
|
|
93
|
+
manualFormTypes.register('create', createRecordForm);
|
|
94
|
+
manualFormTypes.register('update', updateRecordForm);
|
|
95
95
|
|
|
96
96
|
function useTriggerInitializers(): SchemaInitializerItemType | null {
|
|
97
97
|
const { workflow } = useFlowContext();
|
|
@@ -104,25 +104,11 @@ const blockTypeNames = {
|
|
|
104
104
|
record: `{{t("Data record", { ns: "${NAMESPACE}" })}}`,
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
<GeneralSchemaDesigner title={compile(title)}>
|
|
113
|
-
<SchemaSettingsBlockTitleItem />
|
|
114
|
-
<SchemaSettingsDivider />
|
|
115
|
-
<SchemaSettingsRemove
|
|
116
|
-
removeParentsIfNoChildren
|
|
117
|
-
breakRemoveOn={{
|
|
118
|
-
'x-component': 'Grid',
|
|
119
|
-
}}
|
|
120
|
-
/>
|
|
121
|
-
</GeneralSchemaDesigner>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export const addBlockButton: SchemaInitializer = new SchemaInitializer({
|
|
107
|
+
/**
|
|
108
|
+
* @deprecated
|
|
109
|
+
* use `addBlockButton` instead
|
|
110
|
+
*/
|
|
111
|
+
export const addBlockButton_deprecated = new CompatibleSchemaInitializer({
|
|
126
112
|
name: 'AddBlockButton',
|
|
127
113
|
wrap: gridRowColWrap,
|
|
128
114
|
title: '{{t("Add block")}}',
|
|
@@ -150,7 +136,7 @@ export const addBlockButton: SchemaInitializer = new SchemaInitializer({
|
|
|
150
136
|
{
|
|
151
137
|
name: 'nodes',
|
|
152
138
|
type: 'subMenu',
|
|
153
|
-
title: `{{t("Node result", { ns: "
|
|
139
|
+
title: `{{t("Node result", { ns: "workflow" })}}`,
|
|
154
140
|
children: nodeBlockInitializers,
|
|
155
141
|
},
|
|
156
142
|
]
|
|
@@ -187,9 +173,78 @@ export const addBlockButton: SchemaInitializer = new SchemaInitializer({
|
|
|
187
173
|
],
|
|
188
174
|
});
|
|
189
175
|
|
|
176
|
+
export const addBlockButton = new CompatibleSchemaInitializer(
|
|
177
|
+
{
|
|
178
|
+
name: 'workflowManual:popup:configureUserInterface:addBlock',
|
|
179
|
+
wrap: gridRowColWrap,
|
|
180
|
+
title: '{{t("Add block")}}',
|
|
181
|
+
items: [
|
|
182
|
+
{
|
|
183
|
+
type: 'itemGroup',
|
|
184
|
+
name: 'dataBlocks',
|
|
185
|
+
title: '{{t("Data blocks")}}',
|
|
186
|
+
hideIfNoChildren: true,
|
|
187
|
+
useChildren() {
|
|
188
|
+
const workflowPlugin = usePlugin(WorkflowPlugin);
|
|
189
|
+
const current = useNodeContext();
|
|
190
|
+
const nodes = useAvailableUpstreams(current);
|
|
191
|
+
const triggerInitializers = [useTriggerInitializers()].filter(Boolean);
|
|
192
|
+
const nodeBlockInitializers = nodes
|
|
193
|
+
.map((node) => {
|
|
194
|
+
const instruction = workflowPlugin.instructions.get(node.type);
|
|
195
|
+
return instruction?.useInitializers?.(node);
|
|
196
|
+
})
|
|
197
|
+
.filter(Boolean);
|
|
198
|
+
const dataBlockInitializers: any = [
|
|
199
|
+
...triggerInitializers,
|
|
200
|
+
...(nodeBlockInitializers.length
|
|
201
|
+
? [
|
|
202
|
+
{
|
|
203
|
+
name: 'nodes',
|
|
204
|
+
type: 'subMenu',
|
|
205
|
+
title: `{{t("Node result", { ns: "${NAMESPACE}" })}}`,
|
|
206
|
+
children: nodeBlockInitializers,
|
|
207
|
+
},
|
|
208
|
+
]
|
|
209
|
+
: []),
|
|
210
|
+
].filter(Boolean);
|
|
211
|
+
return dataBlockInitializers;
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
type: 'itemGroup',
|
|
216
|
+
name: 'form',
|
|
217
|
+
title: '{{t("Form")}}',
|
|
218
|
+
useChildren() {
|
|
219
|
+
const dm = useDataSourceManager();
|
|
220
|
+
const allCollections = dm.getAllCollections();
|
|
221
|
+
return Array.from(manualFormTypes.getValues()).map((item: ManualFormType) => {
|
|
222
|
+
const { useInitializer: getInitializer } = item.config;
|
|
223
|
+
return getInitializer({ allCollections });
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
type: 'itemGroup',
|
|
229
|
+
name: 'otherBlocks',
|
|
230
|
+
title: '{{t("Other blocks")}}',
|
|
231
|
+
children: [
|
|
232
|
+
{
|
|
233
|
+
name: 'markdown',
|
|
234
|
+
title: '{{t("Markdown")}}',
|
|
235
|
+
Component: 'MarkdownBlockInitializer',
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
},
|
|
241
|
+
addBlockButton_deprecated,
|
|
242
|
+
);
|
|
243
|
+
|
|
190
244
|
function AssignedFieldValues() {
|
|
191
245
|
const ctx = useContext(SchemaComponentContext);
|
|
192
|
-
const { t } = useTranslation();
|
|
246
|
+
const { t: coreT } = useTranslation();
|
|
247
|
+
const { t } = usePluginTranslation();
|
|
193
248
|
const fieldSchema = useFieldSchema();
|
|
194
249
|
const scope = useWorkflowVariableOptions();
|
|
195
250
|
const [open, setOpen] = useState(false);
|
|
@@ -197,7 +252,7 @@ function AssignedFieldValues() {
|
|
|
197
252
|
fieldSchema?.['x-action-settings']?.assignedValues?.schema ?? {
|
|
198
253
|
type: 'void',
|
|
199
254
|
'x-component': 'Grid',
|
|
200
|
-
'x-initializer': '
|
|
255
|
+
'x-initializer': 'assignFieldValuesForm:configureFields',
|
|
201
256
|
properties: {},
|
|
202
257
|
},
|
|
203
258
|
);
|
|
@@ -221,7 +276,7 @@ function AssignedFieldValues() {
|
|
|
221
276
|
}, [fieldSchema]);
|
|
222
277
|
const upLevelActiveFields = useFormActiveFields();
|
|
223
278
|
|
|
224
|
-
const title =
|
|
279
|
+
const title = coreT('Assign field values');
|
|
225
280
|
|
|
226
281
|
function onCancel() {
|
|
227
282
|
setOpen(false);
|
|
@@ -267,9 +322,7 @@ function AssignedFieldValues() {
|
|
|
267
322
|
<FormProvider form={form}>
|
|
268
323
|
<FormLayout layout={'vertical'}>
|
|
269
324
|
<Alert
|
|
270
|
-
message={
|
|
271
|
-
'Values preset in this form will override user submitted ones when continue or reject.',
|
|
272
|
-
)}
|
|
325
|
+
message={t('Values preset in this form will override user submitted ones when continue or reject.')}
|
|
273
326
|
/>
|
|
274
327
|
<br />
|
|
275
328
|
{open && schema && (
|
|
@@ -365,7 +418,11 @@ function ActionInitializer() {
|
|
|
365
418
|
);
|
|
366
419
|
}
|
|
367
420
|
|
|
368
|
-
|
|
421
|
+
/**
|
|
422
|
+
* @deprecated
|
|
423
|
+
* use `addActionButton` instead
|
|
424
|
+
*/
|
|
425
|
+
export const addActionButton_deprecated = new CompatibleSchemaInitializer({
|
|
369
426
|
name: 'AddActionButton',
|
|
370
427
|
title: '{{t("Configure actions")}}',
|
|
371
428
|
items: [
|
|
@@ -396,6 +453,40 @@ export const addActionButton: SchemaInitializer = new SchemaInitializer({
|
|
|
396
453
|
],
|
|
397
454
|
});
|
|
398
455
|
|
|
456
|
+
export const addActionButton = new CompatibleSchemaInitializer(
|
|
457
|
+
{
|
|
458
|
+
name: 'workflowManual:form:configureActions',
|
|
459
|
+
title: '{{t("Configure actions")}}',
|
|
460
|
+
items: [
|
|
461
|
+
{
|
|
462
|
+
name: 'jobStatusResolved',
|
|
463
|
+
title: `{{t("Continue the process", { ns: "${NAMESPACE}" })}}`,
|
|
464
|
+
Component: ContinueInitializer,
|
|
465
|
+
action: JOB_STATUS.RESOLVED,
|
|
466
|
+
actionProps: {
|
|
467
|
+
type: 'primary',
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
name: 'jobStatusRejected',
|
|
472
|
+
title: `{{t("Terminate the process", { ns: "${NAMESPACE}" })}}`,
|
|
473
|
+
Component: ActionInitializer,
|
|
474
|
+
action: JOB_STATUS.REJECTED,
|
|
475
|
+
actionProps: {
|
|
476
|
+
danger: true,
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
name: 'jobStatusPending',
|
|
481
|
+
title: `{{t("Save temporarily", { ns: "${NAMESPACE}" })}}`,
|
|
482
|
+
Component: ActionInitializer,
|
|
483
|
+
action: JOB_STATUS.PENDING,
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
},
|
|
487
|
+
addActionButton_deprecated,
|
|
488
|
+
);
|
|
489
|
+
|
|
399
490
|
// NOTE: fake useAction for ui configuration
|
|
400
491
|
function useSubmit() {
|
|
401
492
|
// const { values, submit, id: formId } = useForm();
|
|
@@ -440,9 +531,9 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
440
531
|
type: 'void',
|
|
441
532
|
'x-component': 'Tabs',
|
|
442
533
|
'x-component-props': {},
|
|
443
|
-
'x-initializer': '
|
|
534
|
+
'x-initializer': 'popup:addTab',
|
|
444
535
|
'x-initializer-props': {
|
|
445
|
-
gridInitializer: '
|
|
536
|
+
gridInitializer: 'workflowManual:popup:configureUserInterface:addBlock',
|
|
446
537
|
},
|
|
447
538
|
properties: value ?? {
|
|
448
539
|
tab1: {
|
|
@@ -454,7 +545,7 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
454
545
|
grid: {
|
|
455
546
|
type: 'void',
|
|
456
547
|
'x-component': 'Grid',
|
|
457
|
-
'x-initializer': '
|
|
548
|
+
'x-initializer': 'workflowManual:popup:configureUserInterface:addBlock',
|
|
458
549
|
properties: {},
|
|
459
550
|
},
|
|
460
551
|
},
|
|
@@ -521,15 +612,46 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
521
612
|
);
|
|
522
613
|
}
|
|
523
614
|
|
|
615
|
+
function validateForms(forms: Record<string, any> = {}) {
|
|
616
|
+
for (const form of Object.values(forms)) {
|
|
617
|
+
const formType = manualFormTypes.get(form.type);
|
|
618
|
+
if (typeof formType.validate === 'function') {
|
|
619
|
+
const msg = formType.validate(form);
|
|
620
|
+
if (msg) {
|
|
621
|
+
return msg;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
524
627
|
export function SchemaConfigButton(props) {
|
|
525
628
|
const { workflow } = useFlowContext();
|
|
526
629
|
const [visible, setVisible] = useState(false);
|
|
630
|
+
const { values } = useForm();
|
|
631
|
+
const { t } = usePluginTranslation();
|
|
632
|
+
const onSetVisible = useCallback(
|
|
633
|
+
(v) => {
|
|
634
|
+
if (!v) {
|
|
635
|
+
const msg = validateForms(values.forms);
|
|
636
|
+
if (msg) {
|
|
637
|
+
message.error({
|
|
638
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
639
|
+
title: t('Validation failed'),
|
|
640
|
+
content: t(msg),
|
|
641
|
+
});
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
setVisible(v);
|
|
646
|
+
},
|
|
647
|
+
[values.forms],
|
|
648
|
+
);
|
|
527
649
|
return (
|
|
528
650
|
<>
|
|
529
651
|
<Button type="primary" onClick={() => setVisible(true)} disabled={false}>
|
|
530
|
-
{
|
|
652
|
+
{t(workflow.executed ? 'View user interface' : 'Configure user interface')}
|
|
531
653
|
</Button>
|
|
532
|
-
<ActionContextProvider value={{ visible, setVisible, formValueChanged: false }}>
|
|
654
|
+
<ActionContextProvider value={{ visible, setVisible: onSetVisible, formValueChanged: false }}>
|
|
533
655
|
{props.children}
|
|
534
656
|
</ActionContextProvider>
|
|
535
657
|
</>
|
|
@@ -65,7 +65,7 @@ export default {
|
|
|
65
65
|
[allCollections],
|
|
66
66
|
);
|
|
67
67
|
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
|
68
|
-
const searchedChildren = useMenuSearch(childItems, openMenuKeys);
|
|
68
|
+
const searchedChildren = useMenuSearch({ data: childItems, openKeys: openMenuKeys });
|
|
69
69
|
|
|
70
70
|
return {
|
|
71
71
|
name: 'createRecordForm',
|
|
@@ -3,15 +3,15 @@ import React, { useContext, useMemo, useState } from 'react';
|
|
|
3
3
|
import { ArrayTable } from '@formily/antd-v5';
|
|
4
4
|
import { Field, createForm } from '@formily/core';
|
|
5
5
|
import { useField, useFieldSchema, useForm } from '@formily/react';
|
|
6
|
-
import
|
|
6
|
+
import { cloneDeep, pick, set } from 'lodash';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
ActionContextProvider,
|
|
10
10
|
CollectionProvider_deprecated,
|
|
11
|
+
CompatibleSchemaInitializer,
|
|
11
12
|
FormBlockContext,
|
|
12
13
|
RecordProvider,
|
|
13
14
|
SchemaComponent,
|
|
14
|
-
SchemaInitializer,
|
|
15
15
|
SchemaInitializerItem,
|
|
16
16
|
SchemaInitializerItemType,
|
|
17
17
|
SchemaInitializerItems,
|
|
@@ -95,15 +95,12 @@ function CustomFormBlockInitializer() {
|
|
|
95
95
|
[uid()]: {
|
|
96
96
|
type: 'void',
|
|
97
97
|
'x-component': 'FormV2',
|
|
98
|
-
'x-component-props':
|
|
99
|
-
// disabled / read-pretty / initialValues
|
|
100
|
-
useProps: '{{ useFormBlockProps }}',
|
|
101
|
-
},
|
|
98
|
+
'x-use-component-props': 'useFormBlockProps',
|
|
102
99
|
properties: {
|
|
103
100
|
grid: {
|
|
104
101
|
type: 'void',
|
|
105
102
|
'x-component': 'Grid',
|
|
106
|
-
'x-initializer': '
|
|
103
|
+
'x-initializer': 'workflowManual:customForm:configureFields',
|
|
107
104
|
},
|
|
108
105
|
actions: {
|
|
109
106
|
type: 'void',
|
|
@@ -116,7 +113,7 @@ function CustomFormBlockInitializer() {
|
|
|
116
113
|
flexWrap: 'wrap',
|
|
117
114
|
},
|
|
118
115
|
},
|
|
119
|
-
'x-initializer': '
|
|
116
|
+
'x-initializer': 'workflowManual:form:configureActions',
|
|
120
117
|
properties: {
|
|
121
118
|
resolve: {
|
|
122
119
|
type: 'void',
|
|
@@ -161,7 +158,7 @@ function getOptions(interfaces) {
|
|
|
161
158
|
const schema = interfaces[type];
|
|
162
159
|
const { group = 'others' } = schema;
|
|
163
160
|
fields[group] = fields[group] || {};
|
|
164
|
-
|
|
161
|
+
set(fields, [group, type], schema);
|
|
165
162
|
});
|
|
166
163
|
|
|
167
164
|
return Object.keys(GroupLabels)
|
|
@@ -208,33 +205,51 @@ const CustomItemsComponent = (props) => {
|
|
|
208
205
|
const items = useCommonInterfaceInitializers();
|
|
209
206
|
const collection = useCollection_deprecated();
|
|
210
207
|
const { setCollectionFields } = useContext(FormBlockContext);
|
|
208
|
+
const form = useMemo(() => createForm(), [interfaceOptions]);
|
|
211
209
|
|
|
212
210
|
return (
|
|
213
211
|
<AddCustomFormFieldButtonContext.Provider
|
|
214
212
|
value={{
|
|
215
213
|
onAddField(item) {
|
|
214
|
+
const fieldInterface: Record<string, any> = pick(item, [
|
|
215
|
+
'name',
|
|
216
|
+
'group',
|
|
217
|
+
'title',
|
|
218
|
+
'default',
|
|
219
|
+
'validateSchema',
|
|
220
|
+
]);
|
|
216
221
|
const {
|
|
217
|
-
properties: { unique, type, ...properties },
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
properties,
|
|
224
|
-
});
|
|
222
|
+
properties: { unique, type, layout, autoIncrement, ...properties },
|
|
223
|
+
} = item;
|
|
224
|
+
fieldInterface.properties = properties;
|
|
225
|
+
const result = cloneDeep(fieldInterface);
|
|
226
|
+
delete result.properties.name['x-disabled'];
|
|
227
|
+
setInterface(result);
|
|
225
228
|
},
|
|
226
229
|
setCallback,
|
|
227
230
|
}}
|
|
228
231
|
>
|
|
229
232
|
<SchemaInitializerItems {...props} items={items} />
|
|
230
|
-
<ActionContextProvider
|
|
233
|
+
<ActionContextProvider
|
|
234
|
+
value={{
|
|
235
|
+
visible: Boolean(interfaceOptions),
|
|
236
|
+
setVisible(v) {
|
|
237
|
+
if (!v) {
|
|
238
|
+
setInterface(null);
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
}}
|
|
242
|
+
>
|
|
231
243
|
{interfaceOptions ? (
|
|
232
244
|
<SchemaComponent
|
|
233
245
|
schema={{
|
|
234
246
|
type: 'void',
|
|
235
247
|
name: 'drawer',
|
|
236
248
|
title: '{{t("Configure field")}}',
|
|
237
|
-
'x-decorator': '
|
|
249
|
+
'x-decorator': 'FormV2',
|
|
250
|
+
'x-decorator-props': {
|
|
251
|
+
form,
|
|
252
|
+
},
|
|
238
253
|
'x-component': 'Action.Drawer',
|
|
239
254
|
properties: {
|
|
240
255
|
...interfaceOptions.properties,
|
|
@@ -266,7 +281,7 @@ const CustomItemsComponent = (props) => {
|
|
|
266
281
|
'x-component-props': {
|
|
267
282
|
type: 'primary',
|
|
268
283
|
useAction() {
|
|
269
|
-
const { values, query } = useForm();
|
|
284
|
+
const { values, query, reset } = useForm();
|
|
270
285
|
const messages = [useLang('Field name existed in form')];
|
|
271
286
|
return {
|
|
272
287
|
async run() {
|
|
@@ -301,6 +316,7 @@ const CustomItemsComponent = (props) => {
|
|
|
301
316
|
'x-toolbar': 'FormItemSchemaToolbar',
|
|
302
317
|
'x-settings': 'fieldSettings:FormItem',
|
|
303
318
|
});
|
|
319
|
+
reset();
|
|
304
320
|
setCallback(null);
|
|
305
321
|
setInterface(null);
|
|
306
322
|
},
|
|
@@ -322,7 +338,11 @@ const CustomItemsComponent = (props) => {
|
|
|
322
338
|
);
|
|
323
339
|
};
|
|
324
340
|
|
|
325
|
-
|
|
341
|
+
/**
|
|
342
|
+
* @deprecated
|
|
343
|
+
* use `addCustomFormField` instead
|
|
344
|
+
*/
|
|
345
|
+
export const addCustomFormField_deprecated = new CompatibleSchemaInitializer({
|
|
326
346
|
name: 'AddCustomFormField',
|
|
327
347
|
wrap: gridRowColWrap,
|
|
328
348
|
insertPosition: 'beforeEnd',
|
|
@@ -330,6 +350,17 @@ export const addCustomFormField: SchemaInitializer = new SchemaInitializer({
|
|
|
330
350
|
ItemsComponent: CustomItemsComponent,
|
|
331
351
|
});
|
|
332
352
|
|
|
353
|
+
export const addCustomFormField = new CompatibleSchemaInitializer(
|
|
354
|
+
{
|
|
355
|
+
name: 'workflowManual:customForm:configureFields',
|
|
356
|
+
wrap: gridRowColWrap,
|
|
357
|
+
insertPosition: 'beforeEnd',
|
|
358
|
+
title: "{{t('Configure fields')}}",
|
|
359
|
+
ItemsComponent: CustomItemsComponent,
|
|
360
|
+
},
|
|
361
|
+
addCustomFormField_deprecated,
|
|
362
|
+
);
|
|
363
|
+
|
|
333
364
|
function CustomFormFieldInitializer() {
|
|
334
365
|
const itemConfig = useSchemaInitializerItem();
|
|
335
366
|
const { insert, setVisible } = useSchemaInitializer();
|