@nocobase/plugin-workflow 0.11.0-alpha.1 → 0.11.1-alpha.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/lib/client/AddButton.js +13 -4
- package/lib/client/Branch.js +4 -2
- package/lib/client/CanvasContent.js +6 -4
- package/lib/client/ExecutionCanvas.js +18 -7
- package/lib/client/ExecutionPage.js +4 -2
- package/lib/client/WorkflowCanvas.js +16 -6
- package/lib/client/WorkflowPage.js +4 -2
- package/lib/client/WorkflowProvider.js +2 -2
- package/lib/client/components/CollectionBlockInitializer.js +3 -3
- package/lib/client/components/CollectionFieldset.js +7 -1
- package/lib/client/components/FieldsSelect.js +4 -1
- package/lib/client/components/NodeDescription.js +36 -22
- package/lib/client/index.js +3 -3
- package/lib/client/locale/zh-CN.d.ts +5 -1
- package/lib/client/locale/zh-CN.js +6 -2
- package/lib/client/nodes/aggregate.d.ts +6 -1
- package/lib/client/nodes/aggregate.js +4 -3
- package/lib/client/nodes/calculation.d.ts +5 -3
- package/lib/client/nodes/calculation.js +6 -5
- package/lib/client/nodes/condition.d.ts +1 -7
- package/lib/client/nodes/condition.js +12 -23
- package/lib/client/nodes/create.d.ts +2 -4
- package/lib/client/nodes/create.js +1 -3
- package/lib/client/nodes/index.d.ts +1 -2
- package/lib/client/nodes/index.js +24 -24
- package/lib/client/nodes/loop.js +19 -28
- package/lib/client/nodes/manual/FormBlockInitializer.js +6 -5
- package/lib/client/nodes/manual/SchemaConfig.d.ts +1 -2
- package/lib/client/nodes/manual/SchemaConfig.js +175 -21
- package/lib/client/nodes/manual/WorkflowTodo.js +39 -46
- package/lib/client/nodes/manual/forms/create.js +8 -1
- package/lib/client/nodes/manual/forms/custom.js +11 -4
- package/lib/client/nodes/manual/forms/update.js +8 -1
- package/lib/client/nodes/manual/index.d.ts +6 -1
- package/lib/client/nodes/manual/index.js +5 -4
- package/lib/client/nodes/parallel.js +7 -4
- package/lib/client/nodes/query.d.ts +2 -5
- package/lib/client/nodes/query.js +1 -3
- package/lib/client/nodes/sql.d.ts +26 -0
- package/lib/client/{triggers/schedule/DateFieldsSelect.js → nodes/sql.js} +37 -46
- package/lib/client/schemas/collection.d.ts +2 -3
- package/lib/client/schemas/collection.js +8 -7
- package/lib/client/style.d.ts +18 -13
- package/lib/client/style.js +312 -289
- package/lib/client/triggers/collection.d.ts +9 -10
- package/lib/client/triggers/collection.js +4 -0
- package/lib/client/triggers/index.d.ts +2 -3
- package/lib/client/triggers/index.js +10 -5
- package/lib/client/triggers/schedule/OnField.js +35 -23
- package/lib/client/triggers/schedule/ScheduleConfig.js +7 -7
- package/lib/client/triggers/schedule/index.d.ts +0 -1
- package/lib/client/triggers/schedule/index.js +31 -19
- package/lib/client/variable.d.ts +29 -11
- package/lib/client/variable.js +39 -24
- package/lib/server/Plugin.d.ts +1 -3
- package/lib/server/Plugin.js +10 -6
- package/lib/server/Processor.d.ts +1 -1
- package/lib/server/Processor.js +2 -2
- package/lib/server/instructions/create.d.ts +1 -1
- package/lib/server/instructions/create.js +13 -13
- package/lib/server/instructions/index.js +1 -1
- package/lib/server/instructions/manual/actions.js +19 -7
- package/lib/server/instructions/manual/forms/create.js +7 -1
- package/lib/server/instructions/manual/forms/update.js +7 -1
- package/lib/server/instructions/query.js +8 -1
- package/lib/server/instructions/request.d.ts +1 -1
- package/lib/server/instructions/request.js +4 -2
- package/lib/server/instructions/sql.d.ts +12 -0
- package/lib/server/instructions/sql.js +34 -0
- package/lib/server/migrations/20230710115902-manual-action-values.d.ts +4 -0
- package/lib/server/migrations/20230710115902-manual-action-values.js +97 -0
- package/lib/server/triggers/collection.js +13 -11
- package/lib/server/utils.d.ts +2 -0
- package/lib/server/utils.js +21 -0
- package/package.json +12 -11
- package/src/client/AddButton.tsx +17 -5
- package/src/client/Branch.tsx +4 -2
- package/src/client/CanvasContent.tsx +6 -4
- package/src/client/ExecutionCanvas.tsx +11 -13
- package/src/client/ExecutionPage.tsx +3 -2
- package/src/client/WorkflowCanvas.tsx +14 -13
- package/src/client/WorkflowPage.tsx +3 -2
- package/src/client/WorkflowProvider.tsx +2 -2
- package/src/client/components/CollectionBlockInitializer.tsx +3 -3
- package/src/client/components/CollectionFieldset.tsx +5 -3
- package/src/client/components/FieldsSelect.tsx +5 -1
- package/src/client/components/NodeDescription.tsx +30 -23
- package/src/client/index.tsx +3 -3
- package/src/client/locale/zh-CN.ts +8 -2
- package/src/client/nodes/aggregate.tsx +4 -4
- package/src/client/nodes/calculation.tsx +4 -5
- package/src/client/nodes/condition.tsx +7 -34
- package/src/client/nodes/create.tsx +0 -1
- package/src/client/nodes/index.tsx +21 -25
- package/src/client/nodes/loop.tsx +16 -31
- package/src/client/nodes/manual/FormBlockInitializer.tsx +6 -5
- package/src/client/nodes/manual/SchemaConfig.tsx +162 -18
- package/src/client/nodes/manual/WorkflowTodo.tsx +43 -47
- package/src/client/nodes/manual/forms/create.tsx +5 -1
- package/src/client/nodes/manual/forms/custom.tsx +7 -3
- package/src/client/nodes/manual/forms/update.tsx +5 -1
- package/src/client/nodes/manual/index.tsx +5 -5
- package/src/client/nodes/parallel.tsx +6 -5
- package/src/client/nodes/query.tsx +0 -1
- package/src/client/nodes/sql.tsx +37 -0
- package/src/client/schemas/collection.ts +6 -6
- package/src/client/style.tsx +324 -289
- package/src/client/triggers/collection.tsx +4 -0
- package/src/client/triggers/index.tsx +14 -10
- package/src/client/triggers/schedule/OnField.tsx +29 -15
- package/src/client/triggers/schedule/ScheduleConfig.tsx +21 -19
- package/src/client/triggers/schedule/index.tsx +25 -19
- package/src/client/variable.tsx +48 -26
- package/src/server/Plugin.ts +13 -9
- package/src/server/Processor.ts +2 -2
- package/src/server/__tests__/collections/categories.ts +4 -0
- package/src/server/__tests__/instructions/manual.test.ts +391 -72
- package/src/server/__tests__/instructions/request.test.ts +30 -0
- package/src/server/__tests__/instructions/sql.test.ts +162 -0
- package/src/server/__tests__/triggers/collection.test.ts +35 -0
- package/src/server/instructions/create.ts +13 -11
- package/src/server/instructions/index.ts +1 -0
- package/src/server/instructions/manual/actions.ts +16 -4
- package/src/server/instructions/manual/forms/create.ts +2 -1
- package/src/server/instructions/manual/forms/update.ts +3 -2
- package/src/server/instructions/query.ts +12 -1
- package/src/server/instructions/request.ts +2 -1
- package/src/server/instructions/sql.ts +25 -0
- package/src/server/migrations/20230710115902-manual-action-values.ts +78 -0
- package/src/server/triggers/collection.ts +15 -11
- package/src/server/utils.ts +17 -0
- package/lib/client/triggers/schedule/DateFieldsSelect.d.ts +0 -2
- package/src/client/triggers/schedule/DateFieldsSelect.tsx +0 -28
|
@@ -5,8 +5,8 @@ import { NodeDefaultView } from '.';
|
|
|
5
5
|
import { Branch } from '../Branch';
|
|
6
6
|
import { useFlowContext } from '../FlowContext';
|
|
7
7
|
import { NAMESPACE, lang } from '../locale';
|
|
8
|
-
import
|
|
9
|
-
import { VariableOption, nodesOptions, triggerOptions, useWorkflowVariableOptions } from '../variable';
|
|
8
|
+
import useStyles from '../style';
|
|
9
|
+
import { VariableOption, defaultFieldNames, nodesOptions, triggerOptions, useWorkflowVariableOptions } from '../variable';
|
|
10
10
|
|
|
11
11
|
function findOption(options: VariableOption[], paths: string[]) {
|
|
12
12
|
let opts = options;
|
|
@@ -59,14 +59,15 @@ export default {
|
|
|
59
59
|
view: {},
|
|
60
60
|
component: function Component({ data }) {
|
|
61
61
|
const { nodes } = useFlowContext();
|
|
62
|
+
const { styles } = useStyles();
|
|
62
63
|
const entry = nodes.find((node) => node.upstreamId === data.id && node.branchIndex != null);
|
|
63
64
|
|
|
64
65
|
return (
|
|
65
66
|
<NodeDefaultView data={data}>
|
|
66
|
-
<div className={
|
|
67
|
+
<div className={styles.nodeSubtreeClass}>
|
|
67
68
|
<div
|
|
68
69
|
className={cx(
|
|
69
|
-
branchBlockClass,
|
|
70
|
+
styles.branchBlockClass,
|
|
70
71
|
css`
|
|
71
72
|
padding-left: 20em;
|
|
72
73
|
`,
|
|
@@ -74,28 +75,10 @@ export default {
|
|
|
74
75
|
>
|
|
75
76
|
<Branch from={data} entry={entry} branchIndex={entry?.branchIndex ?? 0} />
|
|
76
77
|
|
|
77
|
-
<div className={
|
|
78
|
+
<div className={styles.branchClass}>
|
|
78
79
|
<div className="workflow-branch-lines" />
|
|
79
|
-
<div
|
|
80
|
-
|
|
81
|
-
addButtonClass,
|
|
82
|
-
css`
|
|
83
|
-
display: flex;
|
|
84
|
-
justify-content: center;
|
|
85
|
-
align-items: center;
|
|
86
|
-
position: absolute;
|
|
87
|
-
top: 50%;
|
|
88
|
-
transform: translateY(-50%);
|
|
89
|
-
width: 2em;
|
|
90
|
-
height: 6em;
|
|
91
|
-
`,
|
|
92
|
-
)}
|
|
93
|
-
>
|
|
94
|
-
<ArrowUpOutlined
|
|
95
|
-
className={css`
|
|
96
|
-
background-color: var(--nb-box-bg);
|
|
97
|
-
`}
|
|
98
|
-
/>
|
|
80
|
+
<div className={cx(styles.addButtonClass, styles.loopLineClass)}>
|
|
81
|
+
<ArrowUpOutlined />
|
|
99
82
|
</div>
|
|
100
83
|
</div>
|
|
101
84
|
</div>
|
|
@@ -120,13 +103,15 @@ export default {
|
|
|
120
103
|
return null;
|
|
121
104
|
}
|
|
122
105
|
|
|
106
|
+
const { fieldNames = defaultFieldNames } = options;
|
|
107
|
+
|
|
123
108
|
// const { workflow } = useFlowContext();
|
|
124
109
|
// const current = useNodeContext();
|
|
125
110
|
// const upstreams = useAvailableUpstreams(current);
|
|
126
111
|
// find target data model by path described in `config.target`
|
|
127
112
|
// 1. get options from $context/$jobsMapByNodeId
|
|
128
113
|
// 2. route to sub-options and use as loop target options
|
|
129
|
-
let targetOption: VariableOption = { key: 'item', value: 'item', label: lang('Loop target') };
|
|
114
|
+
let targetOption: VariableOption = { key: 'item', [fieldNames.value]: 'item', [fieldNames.label]: lang('Loop target') };
|
|
130
115
|
|
|
131
116
|
if (typeof target === 'string' && target.startsWith('{{') && target.endsWith('}}')) {
|
|
132
117
|
const paths = target
|
|
@@ -137,10 +122,10 @@ export default {
|
|
|
137
122
|
const targetOptions = [nodesOptions, triggerOptions].map((item: any) => {
|
|
138
123
|
const opts = item.useOptions(options).filter(Boolean);
|
|
139
124
|
return {
|
|
140
|
-
label: compile(item.title),
|
|
141
|
-
value: item.value,
|
|
125
|
+
[fieldNames.label]: compile(item.title),
|
|
126
|
+
[fieldNames.value]: item.value,
|
|
142
127
|
key: item.value,
|
|
143
|
-
children: opts,
|
|
128
|
+
[fieldNames.children]: opts,
|
|
144
129
|
disabled: opts && !opts.length,
|
|
145
130
|
};
|
|
146
131
|
});
|
|
@@ -152,8 +137,8 @@ export default {
|
|
|
152
137
|
|
|
153
138
|
return [
|
|
154
139
|
targetOption,
|
|
155
|
-
{ key: 'index', value: 'index', label: lang('Loop index') },
|
|
156
|
-
{ key: 'length', value: 'length', label: lang('Loop length') },
|
|
140
|
+
{ key: 'index', [fieldNames.value]: 'index', [fieldNames.label]: lang('Loop index') },
|
|
141
|
+
{ key: 'length', [fieldNames.value]: 'length', [fieldNames.label]: lang('Loop length') },
|
|
157
142
|
];
|
|
158
143
|
},
|
|
159
144
|
};
|
|
@@ -34,11 +34,8 @@ function InternalFormBlockInitializer({ insert, schema, ...others }) {
|
|
|
34
34
|
type: 'primary',
|
|
35
35
|
useAction: '{{ useSubmit }}',
|
|
36
36
|
},
|
|
37
|
-
'x-designer': '
|
|
38
|
-
'x-designer-props': {
|
|
39
|
-
type: 'record',
|
|
40
|
-
},
|
|
41
|
-
'x-action': `${JOB_STATUS.RESOLVED}`,
|
|
37
|
+
'x-designer': 'ManualActionDesigner',
|
|
38
|
+
'x-designer-props': {},
|
|
42
39
|
},
|
|
43
40
|
},
|
|
44
41
|
...schema,
|
|
@@ -48,6 +45,10 @@ function InternalFormBlockInitializer({ insert, schema, ...others }) {
|
|
|
48
45
|
delete result['x-acl-action'];
|
|
49
46
|
const [formKey] = Object.keys(result.properties);
|
|
50
47
|
result.properties[formKey].properties.actions['x-decorator'] = 'ActionBarProvider';
|
|
48
|
+
result.properties[formKey].properties.actions['x-component-props'].style = {
|
|
49
|
+
marginTop: '1.5em',
|
|
50
|
+
flexWrap: 'wrap',
|
|
51
|
+
};
|
|
51
52
|
traverseSchema(result, (node) => {
|
|
52
53
|
if (node['x-uid']) {
|
|
53
54
|
delete node['x-uid'];
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import React, { useContext, useMemo, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import { ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
|
|
1
|
+
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { createForm } from '@formily/core';
|
|
3
|
+
import { FormProvider, ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
|
|
4
|
+
import { FormLayout } from '@formily/antd-v5';
|
|
5
|
+
import { Alert, Button, Modal, Space } from 'antd';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
4
7
|
|
|
5
8
|
import {
|
|
9
|
+
Action,
|
|
6
10
|
ActionContextProvider,
|
|
7
11
|
GeneralSchemaDesigner,
|
|
8
12
|
InitializerWithSwitch,
|
|
@@ -12,22 +16,24 @@ import {
|
|
|
12
16
|
SchemaInitializerItemOptions,
|
|
13
17
|
SchemaInitializerProvider,
|
|
14
18
|
SchemaSettings,
|
|
19
|
+
VariableScopeProvider,
|
|
15
20
|
gridRowColWrap,
|
|
16
21
|
useCompile,
|
|
17
22
|
useFormBlockContext,
|
|
23
|
+
useSchemaOptionsContext,
|
|
18
24
|
} from '@nocobase/client';
|
|
19
25
|
import { Registry, lodash } from '@nocobase/utils/client';
|
|
20
|
-
import { Button } from 'antd';
|
|
21
26
|
import { instructions, useAvailableUpstreams, useNodeContext } from '..';
|
|
22
|
-
import { useFlowContext } from '../../FlowContext';
|
|
23
27
|
import { JOB_STATUS } from '../../constants';
|
|
28
|
+
import { useFlowContext } from '../../FlowContext';
|
|
24
29
|
import { NAMESPACE, lang } from '../../locale';
|
|
25
30
|
import { useTrigger } from '../../triggers';
|
|
26
31
|
import { DetailsBlockProvider } from './DetailsBlockProvider';
|
|
27
32
|
import { FormBlockProvider } from './FormBlockProvider';
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import
|
|
33
|
+
import createRecordForm from './forms/create';
|
|
34
|
+
import customRecordForm from './forms/custom';
|
|
35
|
+
import updateRecordForm from './forms/update';
|
|
36
|
+
import { useWorkflowVariableOptions } from '../../variable';
|
|
31
37
|
|
|
32
38
|
type ValueOf<T> = T[keyof T];
|
|
33
39
|
|
|
@@ -68,9 +74,9 @@ export type ManualFormType = {
|
|
|
68
74
|
|
|
69
75
|
export const manualFormTypes = new Registry<ManualFormType>();
|
|
70
76
|
|
|
71
|
-
manualFormTypes.register('customForm',
|
|
72
|
-
manualFormTypes.register('createForm',
|
|
73
|
-
manualFormTypes.register('updateForm',
|
|
77
|
+
manualFormTypes.register('customForm', customRecordForm);
|
|
78
|
+
manualFormTypes.register('createForm', createRecordForm);
|
|
79
|
+
manualFormTypes.register('updateForm', updateRecordForm);
|
|
74
80
|
|
|
75
81
|
function useTriggerInitializers(): SchemaInitializerItemOptions | null {
|
|
76
82
|
const { workflow } = useFlowContext();
|
|
@@ -79,7 +85,7 @@ function useTriggerInitializers(): SchemaInitializerItemOptions | null {
|
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
const blockTypeNames = {
|
|
82
|
-
customForm:
|
|
88
|
+
customForm: customRecordForm.title,
|
|
83
89
|
record: `{{t("Data record", { ns: "${NAMESPACE}" })}}`,
|
|
84
90
|
};
|
|
85
91
|
|
|
@@ -138,7 +144,7 @@ function AddBlockButton(props: any) {
|
|
|
138
144
|
{
|
|
139
145
|
type: 'itemGroup',
|
|
140
146
|
title: '{{t("Form")}}',
|
|
141
|
-
children: Array.from(manualFormTypes.getValues()).map((item) => {
|
|
147
|
+
children: Array.from(manualFormTypes.getValues()).map((item: ManualFormType) => {
|
|
142
148
|
const { useInitializer: getInitializer } = item.config;
|
|
143
149
|
return getInitializer();
|
|
144
150
|
}),
|
|
@@ -159,6 +165,142 @@ function AddBlockButton(props: any) {
|
|
|
159
165
|
return <SchemaInitializer.Button {...props} wrap={gridRowColWrap} items={items} title="{{t('Add block')}}" />;
|
|
160
166
|
}
|
|
161
167
|
|
|
168
|
+
function AssignedFieldValues() {
|
|
169
|
+
const ctx = useContext(SchemaComponentContext);
|
|
170
|
+
const { t } = useTranslation();
|
|
171
|
+
const fieldSchema = useFieldSchema();
|
|
172
|
+
const scope = useWorkflowVariableOptions({ fieldNames: { label: 'title', value: 'name' } });
|
|
173
|
+
const [open, setOpen] = useState(false);
|
|
174
|
+
const [initialSchema, setInitialSchema] = useState(fieldSchema?.['x-action-settings']?.assignedValues?.schema ?? {
|
|
175
|
+
type: 'void',
|
|
176
|
+
'x-component': 'Grid',
|
|
177
|
+
'x-initializer': 'CustomFormItemInitializers',
|
|
178
|
+
properties: {},
|
|
179
|
+
});
|
|
180
|
+
const [schema, setSchema] = useState<Schema>(null);
|
|
181
|
+
const { components } = useSchemaOptionsContext();
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
setSchema(new Schema({
|
|
184
|
+
properties: {
|
|
185
|
+
grid: initialSchema
|
|
186
|
+
},
|
|
187
|
+
}));
|
|
188
|
+
}, [initialSchema]);
|
|
189
|
+
const form = useMemo(
|
|
190
|
+
() => {
|
|
191
|
+
const initialValues = fieldSchema?.['x-action-settings']?.assignedValues?.values;
|
|
192
|
+
return createForm({
|
|
193
|
+
initialValues: lodash.cloneDeep(initialValues),
|
|
194
|
+
values: lodash.cloneDeep(initialValues),
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
[],
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const title = t('Assign field values');
|
|
201
|
+
|
|
202
|
+
function onCancel() {
|
|
203
|
+
setOpen(false);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function onSubmit() {
|
|
207
|
+
if (!fieldSchema['x-action-settings']) {
|
|
208
|
+
fieldSchema['x-action-settings'] = {};
|
|
209
|
+
}
|
|
210
|
+
if (!fieldSchema['x-action-settings'].assignedValues) {
|
|
211
|
+
fieldSchema['x-action-settings'].assignedValues = {};
|
|
212
|
+
}
|
|
213
|
+
fieldSchema['x-action-settings'].assignedValues.schema = initialSchema;
|
|
214
|
+
fieldSchema['x-action-settings'].assignedValues.values = form.values;
|
|
215
|
+
setOpen(false);
|
|
216
|
+
setTimeout(() => {
|
|
217
|
+
ctx.refresh?.();
|
|
218
|
+
}, 300);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<>
|
|
223
|
+
<SchemaSettings.Item onClick={() => setOpen(true)}>
|
|
224
|
+
{title}
|
|
225
|
+
</SchemaSettings.Item>
|
|
226
|
+
<Modal
|
|
227
|
+
width={'50%'}
|
|
228
|
+
title={title}
|
|
229
|
+
open={open}
|
|
230
|
+
onCancel={onCancel}
|
|
231
|
+
footer={
|
|
232
|
+
<Space>
|
|
233
|
+
<Button onClick={onCancel}>{t('Cancel')}</Button>
|
|
234
|
+
<Button type="primary" onClick={onSubmit}>{t('Submit')}</Button>
|
|
235
|
+
</Space>
|
|
236
|
+
}
|
|
237
|
+
>
|
|
238
|
+
<VariableScopeProvider scope={scope}>
|
|
239
|
+
<FormProvider form={form}>
|
|
240
|
+
<FormLayout layout={'vertical'}>
|
|
241
|
+
<Alert message={lang('Values preset in this form will override user submitted ones when continue or reject.')} />
|
|
242
|
+
<br />
|
|
243
|
+
{open && schema && (
|
|
244
|
+
<SchemaComponentContext.Provider
|
|
245
|
+
value={{
|
|
246
|
+
...ctx,
|
|
247
|
+
refresh() {
|
|
248
|
+
setInitialSchema(lodash.get(schema.toJSON(), 'properties.grid'));
|
|
249
|
+
}
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
<SchemaComponent schema={schema} components={components} />
|
|
253
|
+
</SchemaComponentContext.Provider>
|
|
254
|
+
)}
|
|
255
|
+
</FormLayout>
|
|
256
|
+
</FormProvider>
|
|
257
|
+
</VariableScopeProvider>
|
|
258
|
+
</Modal>
|
|
259
|
+
</>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function ManualActionDesigner(props) {
|
|
264
|
+
return (
|
|
265
|
+
<GeneralSchemaDesigner {...props} disableInitializer>
|
|
266
|
+
<Action.Designer.ButtonEditor />
|
|
267
|
+
<AssignedFieldValues />
|
|
268
|
+
<SchemaSettings.Divider />
|
|
269
|
+
<SchemaSettings.Remove
|
|
270
|
+
removeParentsIfNoChildren
|
|
271
|
+
breakRemoveOn={{
|
|
272
|
+
'x-component': 'ActionBar',
|
|
273
|
+
}}
|
|
274
|
+
/>
|
|
275
|
+
</GeneralSchemaDesigner>
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function ContinueInitializer({ action, actionProps, insert, ...props }) {
|
|
280
|
+
return (
|
|
281
|
+
<SchemaInitializer.Item
|
|
282
|
+
{...props}
|
|
283
|
+
onClick={() => {
|
|
284
|
+
insert({
|
|
285
|
+
type: 'void',
|
|
286
|
+
title: props.title,
|
|
287
|
+
'x-decorator': 'ManualActionStatusProvider',
|
|
288
|
+
'x-decorator-props': {
|
|
289
|
+
value: action,
|
|
290
|
+
},
|
|
291
|
+
'x-component': 'Action',
|
|
292
|
+
'x-component-props': {
|
|
293
|
+
...actionProps,
|
|
294
|
+
useAction: '{{ useSubmit }}',
|
|
295
|
+
},
|
|
296
|
+
'x-designer': 'ManualActionDesigner',
|
|
297
|
+
'x-action-settings': {},
|
|
298
|
+
});
|
|
299
|
+
}}
|
|
300
|
+
/>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
162
304
|
function ActionInitializer({ action, actionProps, ...props }) {
|
|
163
305
|
return (
|
|
164
306
|
<InitializerWithSwitch
|
|
@@ -192,7 +334,7 @@ function AddActionButton(props) {
|
|
|
192
334
|
key: JOB_STATUS.RESOLVED,
|
|
193
335
|
type: 'item',
|
|
194
336
|
title: `{{t("Continue the process", { ns: "${NAMESPACE}" })}}`,
|
|
195
|
-
component:
|
|
337
|
+
component: ContinueInitializer,
|
|
196
338
|
action: JOB_STATUS.RESOLVED,
|
|
197
339
|
actionProps: {
|
|
198
340
|
type: 'primary',
|
|
@@ -205,7 +347,6 @@ function AddActionButton(props) {
|
|
|
205
347
|
component: ActionInitializer,
|
|
206
348
|
action: JOB_STATUS.REJECTED,
|
|
207
349
|
actionProps: {
|
|
208
|
-
type: 'primary',
|
|
209
350
|
danger: true,
|
|
210
351
|
},
|
|
211
352
|
},
|
|
@@ -301,7 +442,7 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
301
442
|
ctx.refresh?.();
|
|
302
443
|
const { tabs } = lodash.get(schema.toJSON(), 'properties.drawer.properties') as { tabs: ISchema };
|
|
303
444
|
const forms = Array.from(manualFormTypes.getValues()).reduce(
|
|
304
|
-
(result, item) => Object.assign(result, item.config.parseFormOptions(tabs)),
|
|
445
|
+
(result, item: ManualFormType) => Object.assign(result, item.config.parseFormOptions(tabs)),
|
|
305
446
|
{},
|
|
306
447
|
);
|
|
307
448
|
form.setValuesIn('forms', forms);
|
|
@@ -316,8 +457,9 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
316
457
|
AddActionButton,
|
|
317
458
|
...trigger.initializers,
|
|
318
459
|
...nodeInitializers,
|
|
460
|
+
// @ts-ignore
|
|
319
461
|
...Array.from(manualFormTypes.getValues()).reduce(
|
|
320
|
-
(result, item) => Object.assign(result, item.config.initializers),
|
|
462
|
+
(result, item: ManualFormType) => Object.assign(result, item.config.initializers),
|
|
321
463
|
{},
|
|
322
464
|
),
|
|
323
465
|
}}
|
|
@@ -326,8 +468,9 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
326
468
|
schema={schema}
|
|
327
469
|
components={{
|
|
328
470
|
...nodeComponents,
|
|
471
|
+
// @ts-ignore
|
|
329
472
|
...Array.from(manualFormTypes.getValues()).reduce(
|
|
330
|
-
(result, item) => Object.assign(result, item.config.components),
|
|
473
|
+
(result, item: ManualFormType) => Object.assign(result, item.config.components),
|
|
331
474
|
{},
|
|
332
475
|
),
|
|
333
476
|
FormBlockProvider,
|
|
@@ -340,6 +483,7 @@ export function SchemaConfig({ value, onChange }) {
|
|
|
340
483
|
return props.children;
|
|
341
484
|
},
|
|
342
485
|
SimpleDesigner,
|
|
486
|
+
ManualActionDesigner,
|
|
343
487
|
}}
|
|
344
488
|
scope={{
|
|
345
489
|
useSubmit,
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import { css } from '@emotion/css';
|
|
2
2
|
import { observer, useField, useFieldSchema, useForm } from '@formily/react';
|
|
3
3
|
import { dayjs } from '@nocobase/utils/client';
|
|
4
|
-
import { Spin, Tag } from 'antd';
|
|
4
|
+
import { Space, Spin, Tag } from 'antd';
|
|
5
5
|
import React, { createContext, useContext, useEffect, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
CollectionManagerProvider,
|
|
9
|
-
FormBlockContext,
|
|
10
9
|
SchemaComponent,
|
|
11
10
|
SchemaComponentContext,
|
|
12
11
|
TableBlockProvider,
|
|
13
12
|
useAPIClient,
|
|
14
13
|
useActionContext,
|
|
15
14
|
useCollectionManager,
|
|
15
|
+
useCompile,
|
|
16
16
|
useCurrentUserContext,
|
|
17
17
|
useFormBlockContext,
|
|
18
18
|
useRecord,
|
|
19
19
|
useTableBlockContext,
|
|
20
20
|
} from '@nocobase/client';
|
|
21
|
-
import { uid } from '@nocobase/utils/client';
|
|
22
21
|
import { instructions, useAvailableUpstreams } from '..';
|
|
23
22
|
import { FlowContext, useFlowContext } from '../../FlowContext';
|
|
24
23
|
import { JobStatusOptions, JobStatusOptionsMap } from '../../constants';
|
|
@@ -26,7 +25,7 @@ import { NAMESPACE } from '../../locale';
|
|
|
26
25
|
import { linkNodes } from '../../utils';
|
|
27
26
|
import { DetailsBlockProvider } from './DetailsBlockProvider';
|
|
28
27
|
import { FormBlockProvider } from './FormBlockProvider';
|
|
29
|
-
import { manualFormTypes } from './SchemaConfig';
|
|
28
|
+
import { ManualFormType, manualFormTypes } from './SchemaConfig';
|
|
30
29
|
|
|
31
30
|
const nodeCollection = {
|
|
32
31
|
title: `{{t("Task", { ns: "${NAMESPACE}" })}}`,
|
|
@@ -177,7 +176,6 @@ const todoCollection = {
|
|
|
177
176
|
'x-component-props': {
|
|
178
177
|
showTime: true,
|
|
179
178
|
},
|
|
180
|
-
'x-read-pretty': true,
|
|
181
179
|
},
|
|
182
180
|
},
|
|
183
181
|
],
|
|
@@ -217,8 +215,6 @@ export const WorkflowTodo: React.FC & { Drawer: React.FC; Decorator: React.FC }
|
|
|
217
215
|
}}
|
|
218
216
|
schema={{
|
|
219
217
|
type: 'void',
|
|
220
|
-
name: uid(),
|
|
221
|
-
'x-component': 'div',
|
|
222
218
|
properties: {
|
|
223
219
|
actions: {
|
|
224
220
|
type: 'void',
|
|
@@ -293,7 +289,7 @@ export const WorkflowTodo: React.FC & { Drawer: React.FC; Decorator: React.FC }
|
|
|
293
289
|
'x-component': 'TableV2.Column',
|
|
294
290
|
properties: {
|
|
295
291
|
createdAt: {
|
|
296
|
-
type: '
|
|
292
|
+
type: 'string',
|
|
297
293
|
'x-component': 'CollectionField',
|
|
298
294
|
'x-read-pretty': true,
|
|
299
295
|
},
|
|
@@ -317,7 +313,6 @@ export const WorkflowTodo: React.FC & { Drawer: React.FC; Decorator: React.FC }
|
|
|
317
313
|
'x-component': 'TableV2.Column',
|
|
318
314
|
properties: {
|
|
319
315
|
status: {
|
|
320
|
-
type: 'number',
|
|
321
316
|
'x-component': 'CollectionField',
|
|
322
317
|
'x-read-pretty': true,
|
|
323
318
|
},
|
|
@@ -382,13 +377,14 @@ const ManualActionStatusContext = createContext<number | null>(null);
|
|
|
382
377
|
function ManualActionStatusProvider({ value, children }) {
|
|
383
378
|
const { userJob } = useFlowContext();
|
|
384
379
|
const button = useField();
|
|
380
|
+
const buttonSchema = useFieldSchema();
|
|
385
381
|
|
|
386
382
|
useEffect(() => {
|
|
387
383
|
if (userJob.status) {
|
|
388
384
|
button.disabled = true;
|
|
389
|
-
button.visible = userJob.status === value;
|
|
385
|
+
button.visible = userJob.status === value && userJob.result._ === buttonSchema.name;
|
|
390
386
|
}
|
|
391
|
-
}, [userJob
|
|
387
|
+
}, [userJob, value, button]);
|
|
392
388
|
|
|
393
389
|
return <ManualActionStatusContext.Provider value={value}>{children}</ManualActionStatusContext.Provider>;
|
|
394
390
|
}
|
|
@@ -398,21 +394,21 @@ function useSubmit() {
|
|
|
398
394
|
const { setVisible } = useActionContext();
|
|
399
395
|
const { values, submit } = useForm();
|
|
400
396
|
const buttonSchema = useFieldSchema();
|
|
401
|
-
const nextStatus = useContext(ManualActionStatusContext);
|
|
402
397
|
const { service } = useTableBlockContext();
|
|
403
398
|
const { userJob } = useFlowContext();
|
|
404
|
-
const {
|
|
399
|
+
const { name: actionKey } = buttonSchema;
|
|
400
|
+
const { name: formKey } = buttonSchema.parent.parent;
|
|
405
401
|
return {
|
|
406
402
|
async run() {
|
|
403
|
+
if (userJob.status) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
407
406
|
await submit();
|
|
408
|
-
const { name } = buttonSchema.parent.parent.toJSON();
|
|
409
407
|
await api.resource('users_jobs').submit({
|
|
410
408
|
filterByTk: userJob.id,
|
|
411
409
|
values: {
|
|
412
|
-
|
|
413
|
-
result: { [name]: values },
|
|
410
|
+
result: { [formKey]: values, _: actionKey },
|
|
414
411
|
},
|
|
415
|
-
updateAssociationValues,
|
|
416
412
|
});
|
|
417
413
|
setVisible(false);
|
|
418
414
|
service.refresh();
|
|
@@ -464,8 +460,9 @@ function FlowContextProvider(props) {
|
|
|
464
460
|
DetailsBlockProvider,
|
|
465
461
|
ActionBarProvider,
|
|
466
462
|
ManualActionStatusProvider,
|
|
463
|
+
// @ts-ignore
|
|
467
464
|
...Array.from(manualFormTypes.getValues()).reduce(
|
|
468
|
-
(result, item) => Object.assign(result, item.block.components),
|
|
465
|
+
(result, item: ManualFormType) => Object.assign(result, item.block.components),
|
|
469
466
|
{},
|
|
470
467
|
),
|
|
471
468
|
...nodeComponents,
|
|
@@ -474,8 +471,9 @@ function FlowContextProvider(props) {
|
|
|
474
471
|
useSubmit,
|
|
475
472
|
useFormBlockProps,
|
|
476
473
|
useDetailsBlockProps,
|
|
474
|
+
// @ts-ignore
|
|
477
475
|
...Array.from(manualFormTypes.getValues()).reduce(
|
|
478
|
-
(result, item) => Object.assign(result, item.block.scope),
|
|
476
|
+
(result, item: ManualFormType) => Object.assign(result, item.block.scope),
|
|
479
477
|
{},
|
|
480
478
|
),
|
|
481
479
|
}}
|
|
@@ -518,40 +516,33 @@ function useDetailsBlockProps() {
|
|
|
518
516
|
return { form };
|
|
519
517
|
}
|
|
520
518
|
|
|
519
|
+
function FooterStatus() {
|
|
520
|
+
const compile = useCompile();
|
|
521
|
+
const { status, updatedAt } = useRecord();
|
|
522
|
+
const statusOption = JobStatusOptionsMap[status];
|
|
523
|
+
return status ? (
|
|
524
|
+
<Space>
|
|
525
|
+
<time
|
|
526
|
+
className={css`
|
|
527
|
+
margin-right: 0.5em;
|
|
528
|
+
`}
|
|
529
|
+
>
|
|
530
|
+
{dayjs(updatedAt).format('YYYY-MM-DD HH:mm:ss')}
|
|
531
|
+
</time>
|
|
532
|
+
<Tag icon={statusOption.icon} color={statusOption.color}>{compile(statusOption.label)}</Tag>
|
|
533
|
+
</Space>
|
|
534
|
+
) : null;
|
|
535
|
+
}
|
|
536
|
+
|
|
521
537
|
function Drawer() {
|
|
522
538
|
const ctx = useContext(SchemaComponentContext);
|
|
523
|
-
const { id, node, workflow, status
|
|
524
|
-
|
|
525
|
-
const statusOption = JobStatusOptionsMap[status];
|
|
526
|
-
const footerSchema = status
|
|
527
|
-
? {
|
|
528
|
-
date: {
|
|
529
|
-
type: 'void',
|
|
530
|
-
'x-component': 'time',
|
|
531
|
-
'x-component-props': {
|
|
532
|
-
className: css`
|
|
533
|
-
margin-right: 0.5em;
|
|
534
|
-
`,
|
|
535
|
-
},
|
|
536
|
-
'x-content': dayjs(updatedAt).format('YYYY-MM-DD HH:mm:ss'),
|
|
537
|
-
},
|
|
538
|
-
status: {
|
|
539
|
-
type: 'void',
|
|
540
|
-
'x-component': 'Tag',
|
|
541
|
-
'x-component-props': {
|
|
542
|
-
icon: statusOption.icon,
|
|
543
|
-
color: statusOption.color,
|
|
544
|
-
},
|
|
545
|
-
'x-content': statusOption.label,
|
|
546
|
-
},
|
|
547
|
-
}
|
|
548
|
-
: null;
|
|
539
|
+
const { id, node, workflow, status } = useRecord();
|
|
549
540
|
|
|
550
541
|
return (
|
|
551
542
|
<SchemaComponentContext.Provider value={{ ...ctx, reset() {}, designable: false }}>
|
|
552
543
|
<SchemaComponent
|
|
553
544
|
components={{
|
|
554
|
-
|
|
545
|
+
FooterStatus,
|
|
555
546
|
FlowContextProvider,
|
|
556
547
|
}}
|
|
557
548
|
schema={{
|
|
@@ -570,7 +561,12 @@ function Drawer() {
|
|
|
570
561
|
footer: {
|
|
571
562
|
type: 'void',
|
|
572
563
|
'x-component': 'Action.Drawer.Footer',
|
|
573
|
-
properties:
|
|
564
|
+
properties: {
|
|
565
|
+
content: {
|
|
566
|
+
type: 'void',
|
|
567
|
+
'x-component': 'FooterStatus',
|
|
568
|
+
}
|
|
569
|
+
},
|
|
574
570
|
},
|
|
575
571
|
},
|
|
576
572
|
}}
|
|
@@ -71,7 +71,11 @@ export default {
|
|
|
71
71
|
type: 'create',
|
|
72
72
|
title: formBlock['x-component-props']?.title || formKey,
|
|
73
73
|
actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
|
|
74
|
-
(item) =>
|
|
74
|
+
(item) => ({
|
|
75
|
+
status: item['x-decorator-props'].value,
|
|
76
|
+
values: item['x-action-settings']?.assignedValues?.values,
|
|
77
|
+
key: item.name,
|
|
78
|
+
}),
|
|
75
79
|
),
|
|
76
80
|
collection: formBlock['x-decorator-props'].collection,
|
|
77
81
|
};
|
|
@@ -105,6 +105,7 @@ function CustomFormBlockInitializer({ insert, ...props }) {
|
|
|
105
105
|
layout: 'one-column',
|
|
106
106
|
style: {
|
|
107
107
|
marginTop: '1.5em',
|
|
108
|
+
flexWrap: 'wrap',
|
|
108
109
|
},
|
|
109
110
|
},
|
|
110
111
|
'x-initializer': 'AddActionButton',
|
|
@@ -121,8 +122,7 @@ function CustomFormBlockInitializer({ insert, ...props }) {
|
|
|
121
122
|
type: 'primary',
|
|
122
123
|
useAction: '{{ useSubmit }}',
|
|
123
124
|
},
|
|
124
|
-
'x-designer': '
|
|
125
|
-
'x-action': `${JOB_STATUS.RESOLVED}`,
|
|
125
|
+
'x-designer': 'ManualActionDesigner',
|
|
126
126
|
},
|
|
127
127
|
},
|
|
128
128
|
},
|
|
@@ -371,7 +371,11 @@ export default {
|
|
|
371
371
|
type: 'custom',
|
|
372
372
|
title: formBlock['x-component-props']?.title || formKey,
|
|
373
373
|
actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
|
|
374
|
-
(item) =>
|
|
374
|
+
(item) => ({
|
|
375
|
+
status: item['x-decorator-props'].value,
|
|
376
|
+
values: item['x-action-settings']?.assignedValues?.values,
|
|
377
|
+
key: item.name,
|
|
378
|
+
}),
|
|
375
379
|
),
|
|
376
380
|
collection: formBlock['x-decorator-props'].collection,
|
|
377
381
|
};
|
|
@@ -114,7 +114,11 @@ export default {
|
|
|
114
114
|
type: 'update',
|
|
115
115
|
title: formBlock['x-component-props']?.title || formKey,
|
|
116
116
|
actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
|
|
117
|
-
(item) =>
|
|
117
|
+
(item) => ({
|
|
118
|
+
status: item['x-decorator-props'].value,
|
|
119
|
+
values: item['x-action-settings']?.assignedValues?.values,
|
|
120
|
+
key: item.name,
|
|
121
|
+
}),
|
|
118
122
|
),
|
|
119
123
|
};
|
|
120
124
|
});
|