@nocobase/plugin-workflow 0.10.0-alpha.5 → 0.11.0-alpha.1

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.
Files changed (265) hide show
  1. package/client.d.ts +2 -3
  2. package/client.js +1 -30
  3. package/lib/client/AddButton.js +1 -8
  4. package/lib/client/Branch.js +8 -8
  5. package/lib/client/CanvasContent.js +8 -8
  6. package/lib/client/ExecutionCanvas.js +20 -27
  7. package/lib/client/ExecutionPage.js +1 -8
  8. package/lib/client/WorkflowCanvas.js +3 -10
  9. package/lib/client/WorkflowPage.js +1 -8
  10. package/lib/client/WorkflowProvider.js +3 -42
  11. package/lib/client/components/CollectionFieldset.d.ts +1 -1
  12. package/lib/client/components/CollectionFieldset.js +8 -15
  13. package/lib/client/components/Duration.js +5 -5
  14. package/lib/client/components/DynamicExpression.d.ts +3 -3
  15. package/lib/client/components/DynamicExpression.js +14 -4
  16. package/lib/client/components/FieldsSelect.d.ts +1 -1
  17. package/lib/client/components/FieldsSelect.js +6 -6
  18. package/lib/client/components/NodeDescription.js +11 -11
  19. package/lib/client/components/RadioWithTooltip.js +13 -20
  20. package/lib/client/components/ValueBlock.js +14 -21
  21. package/lib/client/components/renderEngineReference.js +1 -8
  22. package/lib/client/index.d.ts +12 -4
  23. package/lib/client/index.js +78 -15
  24. package/lib/client/nodes/aggregate.d.ts +10 -4
  25. package/lib/client/nodes/aggregate.js +12 -9
  26. package/lib/client/nodes/calculation.d.ts +11 -16
  27. package/lib/client/nodes/calculation.js +72 -52
  28. package/lib/client/nodes/condition.d.ts +2 -6
  29. package/lib/client/nodes/condition.js +20 -24
  30. package/lib/client/nodes/create.d.ts +8 -5
  31. package/lib/client/nodes/create.js +34 -7
  32. package/lib/client/nodes/destroy.d.ts +1 -1
  33. package/lib/client/nodes/index.d.ts +4 -4
  34. package/lib/client/nodes/index.js +79 -86
  35. package/lib/client/nodes/loop.d.ts +3 -1
  36. package/lib/client/nodes/loop.js +48 -35
  37. package/lib/client/nodes/manual/ModeConfig.js +23 -30
  38. package/lib/client/nodes/manual/SchemaConfig.d.ts +3 -3
  39. package/lib/client/nodes/manual/SchemaConfig.js +18 -17
  40. package/lib/client/nodes/manual/WorkflowTodo.js +66 -72
  41. package/lib/client/nodes/manual/WorkflowTodoBlockInitializer.d.ts +2 -5
  42. package/lib/client/nodes/manual/WorkflowTodoBlockInitializer.js +6 -5
  43. package/lib/client/nodes/manual/forms/custom.js +11 -18
  44. package/lib/client/nodes/manual/index.d.ts +11 -5
  45. package/lib/client/nodes/manual/index.js +21 -10
  46. package/lib/client/nodes/parallel.js +20 -20
  47. package/lib/client/nodes/query.d.ts +7 -4
  48. package/lib/client/nodes/query.js +34 -7
  49. package/lib/client/nodes/request.d.ts +10 -6
  50. package/lib/client/nodes/request.js +37 -9
  51. package/lib/client/nodes/update.d.ts +2 -2
  52. package/lib/client/nodes/update.js +1 -1
  53. package/lib/client/schemas/collection.d.ts +1 -1
  54. package/lib/client/schemas/collection.js +3 -10
  55. package/lib/client/style.js +18 -18
  56. package/lib/client/triggers/collection.d.ts +4 -3
  57. package/lib/client/triggers/collection.js +21 -7
  58. package/lib/client/triggers/index.d.ts +2 -2
  59. package/lib/client/triggers/index.js +46 -52
  60. package/lib/client/triggers/schedule/DateFieldsSelect.js +1 -1
  61. package/lib/client/triggers/schedule/EndsByField.js +11 -11
  62. package/lib/client/triggers/schedule/OnField.js +11 -11
  63. package/lib/client/triggers/schedule/RepeatField.js +4 -4
  64. package/lib/client/triggers/schedule/ScheduleConfig.js +17 -24
  65. package/lib/client/triggers/schedule/index.d.ts +3 -4
  66. package/lib/client/triggers/schedule/index.js +21 -11
  67. package/lib/client/variable.d.ts +3 -4
  68. package/lib/client/variable.js +110 -45
  69. package/lib/server/Plugin.d.ts +2 -3
  70. package/lib/server/Plugin.js +8 -9
  71. package/lib/server/Processor.d.ts +2 -4
  72. package/lib/server/actions/nodes.js +7 -7
  73. package/lib/server/fields/expression-field.d.ts +1 -2
  74. package/lib/server/fields/expression-field.js +1 -8
  75. package/lib/server/functions/index.d.ts +2 -3
  76. package/lib/server/index.d.ts +1 -0
  77. package/lib/server/index.js +12 -0
  78. package/lib/server/instructions/aggregate.d.ts +1 -1
  79. package/lib/server/instructions/aggregate.js +5 -5
  80. package/lib/server/instructions/condition.d.ts +2 -1
  81. package/lib/server/instructions/create.d.ts +1 -1
  82. package/lib/server/instructions/delay.d.ts +3 -3
  83. package/lib/server/instructions/delay.js +66 -64
  84. package/lib/server/instructions/destroy.d.ts +1 -1
  85. package/lib/server/instructions/index.d.ts +5 -5
  86. package/lib/server/instructions/loop.d.ts +1 -2
  87. package/lib/server/instructions/manual/actions.js +1 -1
  88. package/lib/server/instructions/manual/forms/index.d.ts +1 -1
  89. package/lib/server/instructions/manual/index.d.ts +1 -1
  90. package/lib/server/instructions/parallel.d.ts +1 -2
  91. package/lib/server/instructions/query.d.ts +1 -1
  92. package/lib/server/instructions/request.d.ts +2 -2
  93. package/lib/server/instructions/request.js +1 -0
  94. package/lib/server/instructions/update.d.ts +1 -1
  95. package/lib/server/migrations/20230221071831-calculation-expression.js +1 -1
  96. package/lib/server/migrations/20230221121203-condition-calculation.js +1 -1
  97. package/lib/server/migrations/20230221162902-jsonb-to-json.js +7 -7
  98. package/lib/server/migrations/20230411034722-manual-multi-form.js +1 -8
  99. package/lib/server/triggers/collection.d.ts +1 -1
  100. package/lib/server/triggers/collection.js +2 -2
  101. package/lib/server/triggers/index.d.ts +1 -1
  102. package/lib/server/triggers/schedule.d.ts +1 -1
  103. package/lib/server/triggers/schedule.js +18 -18
  104. package/lib/server/{models → types}/Execution.d.ts +2 -3
  105. package/lib/server/{models → types}/FlowNode.d.ts +1 -2
  106. package/lib/server/{models → types}/Job.d.ts +1 -2
  107. package/lib/server/{models → types}/Workflow.d.ts +1 -2
  108. package/lib/server/types/index.d.ts +4 -0
  109. package/lib/server/types/index.js +5 -0
  110. package/package.json +40 -20
  111. package/server.d.ts +2 -3
  112. package/server.js +1 -30
  113. package/src/client/AddButton.tsx +99 -0
  114. package/src/client/Branch.tsx +35 -0
  115. package/src/client/CanvasContent.tsx +23 -0
  116. package/src/client/ExecutionCanvas.tsx +168 -0
  117. package/src/client/ExecutionLink.tsx +16 -0
  118. package/src/client/ExecutionPage.tsx +44 -0
  119. package/src/client/ExecutionResourceProvider.tsx +21 -0
  120. package/src/client/FlowContext.ts +7 -0
  121. package/src/client/WorkflowCanvas.tsx +220 -0
  122. package/src/client/WorkflowLink.tsx +16 -0
  123. package/src/client/WorkflowPage.tsx +51 -0
  124. package/src/client/WorkflowProvider.tsx +84 -0
  125. package/src/client/components/CollectionBlockInitializer.tsx +71 -0
  126. package/src/client/components/CollectionFieldset.tsx +158 -0
  127. package/src/client/components/Duration.tsx +45 -0
  128. package/src/client/components/DynamicExpression.tsx +53 -0
  129. package/src/client/components/FieldsSelect.tsx +28 -0
  130. package/src/client/components/FilterDynamicComponent.tsx +15 -0
  131. package/src/client/components/NodeDescription.tsx +44 -0
  132. package/src/client/components/NullRender.tsx +3 -0
  133. package/src/client/components/OpenDrawer.tsx +24 -0
  134. package/src/client/components/RadioWithTooltip.tsx +38 -0
  135. package/src/client/components/ValueBlock.tsx +67 -0
  136. package/src/client/components/renderEngineReference.tsx +30 -0
  137. package/src/client/constants.tsx +91 -0
  138. package/src/client/index.tsx +51 -0
  139. package/src/client/interfaces/expression.tsx +25 -0
  140. package/src/client/locale/en-US.ts +136 -0
  141. package/src/client/locale/es-ES.ts +129 -0
  142. package/src/client/locale/index.ts +18 -0
  143. package/src/client/locale/ja-JP.ts +90 -0
  144. package/src/client/locale/pt-BR.ts +136 -0
  145. package/src/client/locale/ru-RU.ts +90 -0
  146. package/src/client/locale/tr-TR.ts +90 -0
  147. package/src/client/locale/zh-CN.ts +242 -0
  148. package/src/client/nodes/aggregate.tsx +327 -0
  149. package/src/client/nodes/calculation.tsx +217 -0
  150. package/src/client/nodes/condition.tsx +490 -0
  151. package/src/client/nodes/create.tsx +86 -0
  152. package/src/client/nodes/delay.tsx +37 -0
  153. package/src/client/nodes/destroy.tsx +34 -0
  154. package/src/client/nodes/index.tsx +489 -0
  155. package/src/client/nodes/loop.tsx +159 -0
  156. package/src/client/nodes/manual/AssigneesSelect.tsx +33 -0
  157. package/src/client/nodes/manual/DetailsBlockProvider.tsx +80 -0
  158. package/src/client/nodes/manual/FormBlockInitializer.tsx +68 -0
  159. package/src/client/nodes/manual/FormBlockProvider.tsx +75 -0
  160. package/src/client/nodes/manual/ModeConfig.tsx +84 -0
  161. package/src/client/nodes/manual/SchemaConfig.tsx +365 -0
  162. package/src/client/nodes/manual/WorkflowTodo.tsx +611 -0
  163. package/src/client/nodes/manual/WorkflowTodoBlockInitializer.tsx +28 -0
  164. package/src/client/nodes/manual/forms/create.tsx +88 -0
  165. package/src/client/nodes/manual/forms/custom.tsx +388 -0
  166. package/src/client/nodes/manual/forms/update.tsx +130 -0
  167. package/src/client/nodes/manual/index.tsx +162 -0
  168. package/src/client/nodes/manual/utils.ts +28 -0
  169. package/src/client/nodes/parallel.tsx +137 -0
  170. package/src/client/nodes/query.tsx +89 -0
  171. package/src/client/nodes/request.tsx +185 -0
  172. package/src/client/nodes/update.tsx +99 -0
  173. package/src/client/schemas/collection.ts +75 -0
  174. package/src/client/schemas/executions.tsx +169 -0
  175. package/src/client/schemas/workflows.ts +364 -0
  176. package/src/client/style.tsx +312 -0
  177. package/src/client/triggers/collection.tsx +186 -0
  178. package/src/client/triggers/index.tsx +307 -0
  179. package/src/client/triggers/schedule/DateFieldsSelect.tsx +28 -0
  180. package/src/client/triggers/schedule/EndsByField.tsx +40 -0
  181. package/src/client/triggers/schedule/OnField.tsx +50 -0
  182. package/src/client/triggers/schedule/RepeatField.tsx +116 -0
  183. package/src/client/triggers/schedule/ScheduleConfig.tsx +225 -0
  184. package/src/client/triggers/schedule/constants.ts +4 -0
  185. package/src/client/triggers/schedule/index.tsx +72 -0
  186. package/src/client/triggers/schedule/locale/Cron.zh-CN.ts +79 -0
  187. package/src/client/utils.ts +36 -0
  188. package/src/client/variable.tsx +296 -0
  189. package/src/index.ts +1 -0
  190. package/src/server/Plugin.ts +351 -0
  191. package/src/server/Processor.ts +354 -0
  192. package/src/server/__tests__/Plugin.test.ts +398 -0
  193. package/src/server/__tests__/Processor.test.ts +474 -0
  194. package/src/server/__tests__/actions/workflows.test.ts +419 -0
  195. package/src/server/__tests__/collections/categories.ts +23 -0
  196. package/src/server/__tests__/collections/comments.ts +24 -0
  197. package/src/server/__tests__/collections/posts.ts +42 -0
  198. package/src/server/__tests__/collections/replies.ts +9 -0
  199. package/src/server/__tests__/collections/tags.ts +15 -0
  200. package/src/server/__tests__/index.ts +89 -0
  201. package/src/server/__tests__/instructions/aggregate.test.ts +294 -0
  202. package/src/server/__tests__/instructions/calculation.test.ts +265 -0
  203. package/src/server/__tests__/instructions/condition.test.ts +335 -0
  204. package/src/server/__tests__/instructions/create.test.ts +129 -0
  205. package/src/server/__tests__/instructions/delay.test.ts +182 -0
  206. package/src/server/__tests__/instructions/destroy.test.ts +58 -0
  207. package/src/server/__tests__/instructions/loop.test.ts +331 -0
  208. package/src/server/__tests__/instructions/manual.test.ts +854 -0
  209. package/src/server/__tests__/instructions/parallel.test.ts +445 -0
  210. package/src/server/__tests__/instructions/query.test.ts +359 -0
  211. package/src/server/__tests__/instructions/request.test.ts +217 -0
  212. package/src/server/__tests__/instructions/update.test.ts +189 -0
  213. package/src/server/__tests__/triggers/collection.test.ts +298 -0
  214. package/src/server/__tests__/triggers/schedule.test.ts +369 -0
  215. package/src/server/actions/index.ts +25 -0
  216. package/src/server/actions/nodes.ts +214 -0
  217. package/src/server/actions/workflows.ts +178 -0
  218. package/src/server/collections/executions.ts +35 -0
  219. package/src/server/collections/flow_nodes.ts +54 -0
  220. package/src/server/collections/jobs.ts +31 -0
  221. package/src/server/collections/workflows.ts +88 -0
  222. package/src/server/constants.ts +26 -0
  223. package/src/server/fields/expression-field.ts +11 -0
  224. package/src/server/fields/index.ts +7 -0
  225. package/src/server/functions/index.ts +16 -0
  226. package/src/server/index.ts +6 -0
  227. package/src/server/instructions/aggregate.ts +42 -0
  228. package/src/server/instructions/calculation.ts +41 -0
  229. package/src/server/instructions/condition.ts +172 -0
  230. package/src/server/instructions/create.ts +37 -0
  231. package/src/server/instructions/delay.ts +105 -0
  232. package/src/server/instructions/destroy.ts +23 -0
  233. package/src/server/instructions/index.ts +63 -0
  234. package/src/server/instructions/loop.ts +99 -0
  235. package/src/server/instructions/manual/actions.ts +79 -0
  236. package/src/server/instructions/manual/collecions/jobs.ts +17 -0
  237. package/src/server/instructions/manual/collecions/users.ts +15 -0
  238. package/src/server/instructions/manual/collecions/users_jobs.ts +50 -0
  239. package/src/server/instructions/manual/forms/create.ts +22 -0
  240. package/src/server/instructions/manual/forms/index.ts +12 -0
  241. package/src/server/instructions/manual/forms/update.ts +22 -0
  242. package/src/server/instructions/manual/index.ts +184 -0
  243. package/src/server/instructions/parallel.ts +121 -0
  244. package/src/server/instructions/query.ts +31 -0
  245. package/src/server/instructions/request.ts +87 -0
  246. package/src/server/instructions/update.ts +24 -0
  247. package/src/server/migrations/20221129153547-calculation-variables.ts +64 -0
  248. package/src/server/migrations/20230221032941-change-request-body-type.ts +76 -0
  249. package/src/server/migrations/20230221071831-calculation-expression.ts +102 -0
  250. package/src/server/migrations/20230221121203-condition-calculation.ts +82 -0
  251. package/src/server/migrations/20230221162902-jsonb-to-json.ts +51 -0
  252. package/src/server/migrations/20230411034722-manual-multi-form.ts +282 -0
  253. package/src/server/migrations/20230612021134-manual-collection-block.ts +138 -0
  254. package/src/server/triggers/collection.ts +142 -0
  255. package/src/server/triggers/index.ts +22 -0
  256. package/src/server/triggers/schedule.ts +567 -0
  257. package/src/server/types/Execution.ts +26 -0
  258. package/src/server/types/FlowNode.ts +21 -0
  259. package/src/server/types/Job.ts +18 -0
  260. package/src/server/types/Workflow.ts +36 -0
  261. package/src/server/types/index.ts +4 -0
  262. /package/lib/server/{models → types}/Execution.js +0 -0
  263. /package/lib/server/{models → types}/FlowNode.js +0 -0
  264. /package/lib/server/{models → types}/Job.js +0 -0
  265. /package/lib/server/{models → types}/Workflow.js +0 -0
@@ -0,0 +1,307 @@
1
+ import { InfoOutlined } from '@ant-design/icons';
2
+ import { createForm } from '@formily/core';
3
+ import { ISchema, useForm } from '@formily/react';
4
+ import {
5
+ ActionContextProvider,
6
+ css,
7
+ cx,
8
+ SchemaComponent,
9
+ SchemaInitializerItemOptions,
10
+ useActionContext,
11
+ useAPIClient,
12
+ useCompile,
13
+ useResourceActionContext,
14
+ } from '@nocobase/client';
15
+ import { Registry } from '@nocobase/utils/client';
16
+ import { Alert, Button, Input, message, Tag } from 'antd';
17
+ import React, { useEffect, useMemo, useState } from 'react';
18
+ import { useFlowContext } from '../FlowContext';
19
+ import { lang, NAMESPACE } from '../locale';
20
+ import { nodeCardClass, nodeJobButtonClass, nodeMetaClass, nodeTitleClass } from '../style';
21
+ import { VariableOptions } from '../variable';
22
+ import collection from './collection';
23
+ import schedule from './schedule/';
24
+
25
+ function useUpdateConfigAction() {
26
+ const form = useForm();
27
+ const api = useAPIClient();
28
+ const { workflow } = useFlowContext() ?? {};
29
+ const ctx = useActionContext();
30
+ const { refresh } = useResourceActionContext();
31
+ return {
32
+ async run() {
33
+ if (workflow.executed) {
34
+ message.error(lang('Trigger in executed workflow cannot be modified'));
35
+ return;
36
+ }
37
+ await form.submit();
38
+ await api.resource('workflows').update?.({
39
+ filterByTk: workflow.id,
40
+ values: {
41
+ config: form.values,
42
+ },
43
+ });
44
+ ctx.setVisible(false);
45
+ refresh();
46
+ },
47
+ };
48
+ }
49
+
50
+ export interface Trigger {
51
+ title: string;
52
+ type: string;
53
+ // group: string;
54
+ useVariables?(config: any, options?): VariableOptions;
55
+ fieldset: { [key: string]: ISchema };
56
+ view?: ISchema;
57
+ scope?: { [key: string]: any };
58
+ components?: { [key: string]: any };
59
+ useInitializers?(config): SchemaInitializerItemOptions | null;
60
+ initializers?: any;
61
+ }
62
+
63
+ export const triggers = new Registry<Trigger>();
64
+
65
+ triggers.register(collection.type, collection);
66
+ triggers.register(schedule.type, schedule);
67
+
68
+ function TriggerExecution() {
69
+ const compile = useCompile();
70
+ const { workflow, execution } = useFlowContext();
71
+ if (!execution) {
72
+ return null;
73
+ }
74
+
75
+ const trigger = triggers.get(workflow.type);
76
+
77
+ return (
78
+ <SchemaComponent
79
+ schema={{
80
+ type: 'void',
81
+ name: 'execution',
82
+ 'x-component': 'Action',
83
+ 'x-component-props': {
84
+ title: <InfoOutlined />,
85
+ shape: 'circle',
86
+ className: nodeJobButtonClass,
87
+ type: 'primary',
88
+ },
89
+ properties: {
90
+ [execution.id]: {
91
+ type: 'void',
92
+ 'x-decorator': 'Form',
93
+ 'x-decorator-props': {
94
+ initialValue: execution,
95
+ },
96
+ 'x-component': 'Action.Modal',
97
+ title: (
98
+ <div className={cx(nodeTitleClass)}>
99
+ <Tag>{compile(trigger.title)}</Tag>
100
+ <strong>{workflow.title}</strong>
101
+ <span className="workflow-node-id">#{execution.id}</span>
102
+ </div>
103
+ ),
104
+ properties: {
105
+ createdAt: {
106
+ type: 'string',
107
+ title: `{{t("Triggered at", { ns: "${NAMESPACE}" })}}`,
108
+ 'x-decorator': 'FormItem',
109
+ 'x-component': 'DatePicker',
110
+ 'x-component-props': {
111
+ showTime: true,
112
+ },
113
+ 'x-read-pretty': true,
114
+ },
115
+ context: {
116
+ type: 'object',
117
+ title: `{{t("Trigger variables", { ns: "${NAMESPACE}" })}}`,
118
+ 'x-decorator': 'FormItem',
119
+ 'x-component': 'Input.JSON',
120
+ 'x-component-props': {
121
+ className: css`
122
+ padding: 1em;
123
+ background-color: #eee;
124
+ `,
125
+ },
126
+ 'x-read-pretty': true,
127
+ },
128
+ },
129
+ },
130
+ },
131
+ }}
132
+ />
133
+ );
134
+ }
135
+
136
+ export const TriggerConfig = () => {
137
+ const api = useAPIClient();
138
+ const compile = useCompile();
139
+ const { workflow, refresh } = useFlowContext();
140
+ const [editingTitle, setEditingTitle] = useState<string>('');
141
+ const [editingConfig, setEditingConfig] = useState(false);
142
+ let typeTitle = '';
143
+ useEffect(() => {
144
+ if (workflow) {
145
+ setEditingTitle(workflow.title ?? typeTitle);
146
+ }
147
+ }, [workflow]);
148
+
149
+ const form = useMemo(
150
+ () =>
151
+ createForm({
152
+ initialValues: workflow?.config,
153
+ values: workflow?.config,
154
+ disabled: workflow?.executed,
155
+ }),
156
+ [workflow],
157
+ );
158
+
159
+ if (!workflow || !workflow.type) {
160
+ return null;
161
+ }
162
+ const { title, type, executed } = workflow;
163
+ const trigger = triggers.get(type);
164
+ const { fieldset, scope, components } = trigger;
165
+ typeTitle = trigger.title;
166
+ const detailText = executed ? '{{t("View")}}' : '{{t("Configure")}}';
167
+ const titleText = `${lang('Trigger')}: ${compile(typeTitle)}`;
168
+
169
+ async function onChangeTitle(next) {
170
+ const t = next || typeTitle;
171
+ setEditingTitle(t);
172
+ if (t === title) {
173
+ return;
174
+ }
175
+ await api.resource('workflows').update?.({
176
+ filterByTk: workflow.id,
177
+ values: {
178
+ title: t,
179
+ },
180
+ });
181
+ refresh();
182
+ }
183
+
184
+ function onOpenDrawer(ev) {
185
+ if (ev.target === ev.currentTarget) {
186
+ setEditingConfig(true);
187
+ return;
188
+ }
189
+ const whiteSet = new Set(['workflow-node-meta', 'workflow-node-config-button', 'ant-input-disabled']);
190
+ for (let el = ev.target; el && el !== ev.currentTarget; el = el.parentNode) {
191
+ if ((Array.from(el.classList ?? []) as string[]).some((name: string) => whiteSet.has(name))) {
192
+ setEditingConfig(true);
193
+ ev.stopPropagation();
194
+ return;
195
+ }
196
+ }
197
+ }
198
+
199
+ return (
200
+ <div className={cx(nodeCardClass)} onClick={onOpenDrawer}>
201
+ <div className={cx(nodeMetaClass, 'workflow-node-meta')}>
202
+ <Tag color="gold">{titleText}</Tag>
203
+ </div>
204
+ <div>
205
+ <Input.TextArea
206
+ value={editingTitle}
207
+ onChange={(ev) => setEditingTitle(ev.target.value)}
208
+ onBlur={(ev) => onChangeTitle(ev.target.value)}
209
+ autoSize
210
+ />
211
+ </div>
212
+ <TriggerExecution />
213
+ <ActionContextProvider value={{ visible: editingConfig, setVisible: setEditingConfig }}>
214
+ <SchemaComponent
215
+ schema={{
216
+ name: `workflow-trigger-${workflow.id}`,
217
+ type: 'void',
218
+ properties: {
219
+ config: {
220
+ type: 'void',
221
+ 'x-content': detailText,
222
+ 'x-component': Button,
223
+ 'x-component-props': {
224
+ type: 'link',
225
+ className: 'workflow-node-config-button',
226
+ },
227
+ },
228
+ drawer: {
229
+ type: 'void',
230
+ title: titleText,
231
+ 'x-component': 'Action.Drawer',
232
+ 'x-decorator': 'FormV2',
233
+ 'x-decorator-props': {
234
+ form,
235
+ },
236
+ properties: {
237
+ ...(executed
238
+ ? {
239
+ alert: {
240
+ 'x-component': Alert,
241
+ 'x-component-props': {
242
+ type: 'warning',
243
+ showIcon: true,
244
+ message: `{{t("Trigger in executed workflow cannot be modified", { ns: "${NAMESPACE}" })}}`,
245
+ className: css`
246
+ width: 100%;
247
+ font-size: 85%;
248
+ margin-bottom: 2em;
249
+ `,
250
+ },
251
+ },
252
+ }
253
+ : {}),
254
+ fieldset: {
255
+ type: 'void',
256
+ 'x-component': 'fieldset',
257
+ 'x-component-props': {
258
+ className: css`
259
+ .ant-select:not(.full-width) {
260
+ width: auto;
261
+ min-width: 6em;
262
+ }
263
+ `,
264
+ },
265
+ properties: fieldset,
266
+ },
267
+ actions: {
268
+ ...(executed
269
+ ? {}
270
+ : {
271
+ type: 'void',
272
+ 'x-component': 'Action.Drawer.Footer',
273
+ properties: {
274
+ cancel: {
275
+ title: '{{t("Cancel")}}',
276
+ 'x-component': 'Action',
277
+ 'x-component-props': {
278
+ useAction: '{{ cm.useCancelAction }}',
279
+ },
280
+ },
281
+ submit: {
282
+ title: '{{t("Submit")}}',
283
+ 'x-component': 'Action',
284
+ 'x-component-props': {
285
+ type: 'primary',
286
+ useAction: useUpdateConfigAction,
287
+ },
288
+ },
289
+ },
290
+ }),
291
+ },
292
+ },
293
+ },
294
+ },
295
+ }}
296
+ scope={scope}
297
+ components={components}
298
+ />
299
+ </ActionContextProvider>
300
+ </div>
301
+ );
302
+ };
303
+
304
+ export function useTrigger() {
305
+ const { workflow } = useFlowContext();
306
+ return triggers.get(workflow.type);
307
+ }
@@ -0,0 +1,28 @@
1
+ import { observer, useForm } from '@formily/react';
2
+ import { useCollectionManager, useCompile } from '@nocobase/client';
3
+ import { Select } from 'antd';
4
+ import React from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ export const DateFieldsSelect: React.FC<any> = observer(
8
+ (props) => {
9
+ const { t } = useTranslation();
10
+ const compile = useCompile();
11
+ const { getCollectionFields } = useCollectionManager();
12
+ const { values } = useForm();
13
+ const fields = getCollectionFields(values?.collection);
14
+
15
+ return (
16
+ <Select popupMatchSelectWidth={false} placeholder={t('Select field')} {...props}>
17
+ {fields
18
+ .filter((field) => !field.hidden && (field.uiSchema ? field.type === 'date' : false))
19
+ .map((field) => (
20
+ <Select.Option key={field.name} value={field.name}>
21
+ {compile(field.uiSchema?.title)}
22
+ </Select.Option>
23
+ ))}
24
+ </Select>
25
+ );
26
+ },
27
+ { displayName: 'DateFieldsSelect' },
28
+ );
@@ -0,0 +1,40 @@
1
+ import { css } from '@nocobase/client';
2
+ import { dayjs } from '@nocobase/utils/client';
3
+ import { DatePicker, Select } from 'antd';
4
+ import React from 'react';
5
+ import { useWorkflowTranslation } from '../../locale';
6
+ import { OnField } from './OnField';
7
+
8
+ export function EndsByField({ value, onChange }) {
9
+ const { t } = useWorkflowTranslation();
10
+ const type = value != null ? (typeof value === 'object' && !(value instanceof Date) ? 'field' : 'date') : null;
11
+ return (
12
+ <fieldset
13
+ className={css`
14
+ display: flex;
15
+ gap: 0.5em;
16
+ `}
17
+ >
18
+ <Select
19
+ value={type}
20
+ onChange={(t) => {
21
+ onChange(t ? (t === 'field' ? {} : new Date()) : null);
22
+ }}
23
+ >
24
+ <Select.Option value={null}>{t('No end')}</Select.Option>
25
+ <Select.Option value={'field'}>{t('By field')}</Select.Option>
26
+ <Select.Option value={'date'}>{t('By custom date')}</Select.Option>
27
+ </Select>
28
+ {type === 'field' ? <OnField value={value} onChange={onChange} /> : null}
29
+ {type === 'date' ? (
30
+ <DatePicker
31
+ showTime
32
+ value={dayjs(value)}
33
+ onChange={(v) => {
34
+ onChange(v ? v.toDate() : null);
35
+ }}
36
+ />
37
+ ) : null}
38
+ </fieldset>
39
+ );
40
+ }
@@ -0,0 +1,50 @@
1
+ import { css } from '@nocobase/client';
2
+ import { InputNumber, Select } from 'antd';
3
+ import React, { useState } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { useWorkflowTranslation } from '../../locale';
6
+ import { DateFieldsSelect } from './DateFieldsSelect';
7
+
8
+ export function OnField({ value, onChange }) {
9
+ const { t } = useTranslation();
10
+ const { t: localT } = useWorkflowTranslation();
11
+ const [dir, setDir] = useState(value.offset ? value.offset / Math.abs(value.offset) : 0);
12
+
13
+ return (
14
+ <fieldset
15
+ className={css`
16
+ display: flex;
17
+ gap: 0.5em;
18
+ `}
19
+ >
20
+ <DateFieldsSelect value={value.field} onChange={(field) => onChange({ ...value, field })} />
21
+ {value.field ? (
22
+ <Select
23
+ value={dir}
24
+ onChange={(v) => {
25
+ setDir(v);
26
+ onChange({ ...value, offset: Math.abs(value.offset) * v });
27
+ }}
28
+ >
29
+ <Select.Option value={0}>{localT('Exactly at')}</Select.Option>
30
+ <Select.Option value={-1}>{t('Before')}</Select.Option>
31
+ <Select.Option value={1}>{t('After')}</Select.Option>
32
+ </Select>
33
+ ) : null}
34
+ {dir ? (
35
+ <>
36
+ <InputNumber
37
+ value={Math.abs(value.offset)}
38
+ onChange={(v) => onChange({ ...value, offset: (v ?? 0) * dir })}
39
+ />
40
+ <Select value={value.unit || 86400000} onChange={(unit) => onChange({ ...value, unit })}>
41
+ <Select.Option value={86400000}>{localT('Days')}</Select.Option>
42
+ <Select.Option value={3600000}>{localT('Hours')}</Select.Option>
43
+ <Select.Option value={60000}>{localT('Minutes')}</Select.Option>
44
+ <Select.Option value={1000}>{localT('Seconds')}</Select.Option>
45
+ </Select>
46
+ </>
47
+ ) : null}
48
+ </fieldset>
49
+ );
50
+ }
@@ -0,0 +1,116 @@
1
+ import { css } from '@nocobase/client';
2
+ import { InputNumber, Select } from 'antd';
3
+ import React from 'react';
4
+ import { Cron } from 'react-js-cron';
5
+ import { useWorkflowTranslation } from '../../locale';
6
+ import CronZhCN from './locale/Cron.zh-CN';
7
+
8
+ const languages = {
9
+ 'zh-CN': CronZhCN,
10
+ };
11
+
12
+ const RepeatOptions = [
13
+ { value: 'none', text: 'No repeat' },
14
+ { value: 60_000, text: 'By minute', unitText: 'Minutes' },
15
+ { value: 3600_000, text: 'By hour', unitText: 'Hours' },
16
+ { value: 86400_000, text: 'By day', unitText: 'Days' },
17
+ { value: 604800_000, text: 'By week', unitText: 'Weeks' },
18
+ // { value: 18144_000_000, text: 'By 30 days' },
19
+ { value: 'cron', text: 'Advanced' },
20
+ ];
21
+
22
+ function getNumberOption(v) {
23
+ const opts = RepeatOptions.filter((option) => typeof option.value === 'number').reverse() as any[];
24
+ return opts.find((item) => !(v % item.value));
25
+ }
26
+
27
+ function getRepeatTypeValue(v) {
28
+ switch (typeof v) {
29
+ case 'number':
30
+ const option = getNumberOption(v);
31
+ return option ? option.value : 'none';
32
+ case 'string':
33
+ return 'cron';
34
+ default:
35
+ break;
36
+ }
37
+ return 'none';
38
+ }
39
+
40
+ function CommonRepeatField({ value, onChange }) {
41
+ const { t } = useWorkflowTranslation();
42
+ const option = getNumberOption(value);
43
+
44
+ return (
45
+ <InputNumber
46
+ value={value / option.value}
47
+ onChange={(v) => onChange(v * option.value)}
48
+ min={1}
49
+ addonBefore={t('Every')}
50
+ addonAfter={t(option.unitText)}
51
+ />
52
+ );
53
+ }
54
+
55
+ export function RepeatField({ value = null, onChange }) {
56
+ const { t } = useWorkflowTranslation();
57
+ const typeValue = getRepeatTypeValue(value);
58
+ function onTypeChange(v) {
59
+ if (v === 'none') {
60
+ onChange(null);
61
+ return;
62
+ }
63
+ if (v === 'cron') {
64
+ onChange('0 * * * * *');
65
+ return;
66
+ }
67
+ onChange(v);
68
+ }
69
+
70
+ const locale = languages[localStorage.getItem('NOCOBASE_LOCALE') || 'en-US'];
71
+
72
+ return (
73
+ <fieldset
74
+ className={css`
75
+ display: flex;
76
+ flex-direction: ${typeValue === 'cron' ? 'column' : 'row'};
77
+ align-items: flex-start;
78
+ gap: 0.5em;
79
+
80
+ .react-js-cron {
81
+ padding: 0.5em 0.5em 0 0.5em;
82
+ border: 1px dashed #ccc;
83
+
84
+ .react-js-cron-field {
85
+ margin-bottom: 0.5em;
86
+
87
+ > span {
88
+ margin: 0 0.5em 0 0;
89
+ }
90
+
91
+ > .react-js-cron-select {
92
+ margin: 0 0.5em 0 0;
93
+ }
94
+ }
95
+ }
96
+ `}
97
+ >
98
+ <Select value={typeValue} onChange={onTypeChange}>
99
+ {RepeatOptions.map((item) => (
100
+ <Select.Option key={item.value} value={item.value}>
101
+ {t(item.text)}
102
+ </Select.Option>
103
+ ))}
104
+ </Select>
105
+ {typeof typeValue === 'number' ? <CommonRepeatField value={value} onChange={onChange} /> : null}
106
+ {typeValue === 'cron' ? (
107
+ <Cron
108
+ value={value.trim().split(/\s+/).slice(1).join(' ')}
109
+ setValue={(v) => onChange(`0 ${v}`)}
110
+ clearButton={false}
111
+ locale={locale}
112
+ />
113
+ ) : null}
114
+ </fieldset>
115
+ );
116
+ }