@nocobase/plugin-workflow 0.10.1-alpha.1 → 0.11.1-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 (289) hide show
  1. package/client.d.ts +2 -3
  2. package/client.js +1 -30
  3. package/lib/client/AddButton.js +13 -11
  4. package/lib/client/Branch.js +10 -8
  5. package/lib/client/CanvasContent.js +12 -10
  6. package/lib/client/ExecutionCanvas.js +37 -33
  7. package/lib/client/ExecutionPage.js +4 -9
  8. package/lib/client/WorkflowCanvas.js +18 -15
  9. package/lib/client/WorkflowPage.js +4 -9
  10. package/lib/client/WorkflowProvider.js +1 -40
  11. package/lib/client/components/CollectionBlockInitializer.js +3 -3
  12. package/lib/client/components/CollectionFieldset.d.ts +1 -1
  13. package/lib/client/components/CollectionFieldset.js +15 -16
  14. package/lib/client/components/Duration.js +5 -5
  15. package/lib/client/components/DynamicExpression.d.ts +3 -3
  16. package/lib/client/components/FieldsSelect.d.ts +1 -1
  17. package/lib/client/components/FieldsSelect.js +10 -7
  18. package/lib/client/components/NodeDescription.js +45 -31
  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/locale/zh-CN.d.ts +5 -1
  25. package/lib/client/locale/zh-CN.js +6 -2
  26. package/lib/client/nodes/aggregate.d.ts +8 -3
  27. package/lib/client/nodes/aggregate.js +5 -4
  28. package/lib/client/nodes/calculation.d.ts +6 -4
  29. package/lib/client/nodes/calculation.js +22 -28
  30. package/lib/client/nodes/condition.d.ts +2 -10
  31. package/lib/client/nodes/condition.js +19 -37
  32. package/lib/client/nodes/create.d.ts +5 -6
  33. package/lib/client/nodes/create.js +1 -3
  34. package/lib/client/nodes/destroy.d.ts +1 -1
  35. package/lib/client/nodes/index.d.ts +2 -3
  36. package/lib/client/nodes/index.js +95 -102
  37. package/lib/client/nodes/loop.d.ts +1 -1
  38. package/lib/client/nodes/loop.js +46 -54
  39. package/lib/client/nodes/manual/FormBlockInitializer.js +6 -5
  40. package/lib/client/nodes/manual/ModeConfig.js +23 -30
  41. package/lib/client/nodes/manual/SchemaConfig.d.ts +4 -5
  42. package/lib/client/nodes/manual/SchemaConfig.js +180 -25
  43. package/lib/client/nodes/manual/WorkflowTodo.js +95 -110
  44. package/lib/client/nodes/manual/WorkflowTodoBlockInitializer.d.ts +2 -5
  45. package/lib/client/nodes/manual/WorkflowTodoBlockInitializer.js +6 -5
  46. package/lib/client/nodes/manual/forms/create.js +8 -1
  47. package/lib/client/nodes/manual/forms/custom.js +22 -22
  48. package/lib/client/nodes/manual/forms/update.js +8 -1
  49. package/lib/client/nodes/manual/index.d.ts +6 -1
  50. package/lib/client/nodes/manual/index.js +5 -4
  51. package/lib/client/nodes/parallel.js +23 -20
  52. package/lib/client/nodes/query.d.ts +3 -5
  53. package/lib/client/nodes/query.js +1 -3
  54. package/lib/client/nodes/request.d.ts +2 -2
  55. package/lib/client/nodes/request.js +7 -7
  56. package/lib/client/nodes/sql.d.ts +26 -0
  57. package/lib/client/{triggers/schedule/DateFieldsSelect.js → nodes/sql.js} +37 -46
  58. package/lib/client/nodes/update.d.ts +2 -2
  59. package/lib/client/nodes/update.js +1 -1
  60. package/lib/client/schemas/collection.d.ts +3 -4
  61. package/lib/client/schemas/collection.js +11 -17
  62. package/lib/client/style.d.ts +18 -13
  63. package/lib/client/style.js +315 -292
  64. package/lib/client/triggers/collection.d.ts +13 -13
  65. package/lib/client/triggers/collection.js +5 -1
  66. package/lib/client/triggers/index.d.ts +3 -4
  67. package/lib/client/triggers/index.js +51 -53
  68. package/lib/client/triggers/schedule/EndsByField.js +11 -11
  69. package/lib/client/triggers/schedule/OnField.js +45 -33
  70. package/lib/client/triggers/schedule/RepeatField.js +4 -4
  71. package/lib/client/triggers/schedule/ScheduleConfig.js +24 -31
  72. package/lib/client/triggers/schedule/index.d.ts +1 -1
  73. package/lib/client/triggers/schedule/index.js +32 -20
  74. package/lib/client/variable.d.ts +31 -13
  75. package/lib/client/variable.js +44 -29
  76. package/lib/server/Plugin.d.ts +3 -6
  77. package/lib/server/Plugin.js +15 -12
  78. package/lib/server/Processor.d.ts +3 -5
  79. package/lib/server/Processor.js +2 -2
  80. package/lib/server/actions/nodes.js +7 -7
  81. package/lib/server/fields/expression-field.d.ts +1 -2
  82. package/lib/server/fields/expression-field.js +1 -8
  83. package/lib/server/functions/index.d.ts +2 -3
  84. package/lib/server/index.d.ts +1 -0
  85. package/lib/server/index.js +12 -0
  86. package/lib/server/instructions/aggregate.d.ts +1 -1
  87. package/lib/server/instructions/aggregate.js +5 -5
  88. package/lib/server/instructions/condition.d.ts +2 -1
  89. package/lib/server/instructions/create.d.ts +2 -2
  90. package/lib/server/instructions/create.js +13 -13
  91. package/lib/server/instructions/delay.d.ts +3 -3
  92. package/lib/server/instructions/delay.js +66 -64
  93. package/lib/server/instructions/destroy.d.ts +1 -1
  94. package/lib/server/instructions/index.d.ts +5 -5
  95. package/lib/server/instructions/index.js +1 -1
  96. package/lib/server/instructions/loop.d.ts +1 -2
  97. package/lib/server/instructions/manual/actions.js +19 -7
  98. package/lib/server/instructions/manual/forms/create.js +7 -1
  99. package/lib/server/instructions/manual/forms/index.d.ts +1 -1
  100. package/lib/server/instructions/manual/forms/update.js +7 -1
  101. package/lib/server/instructions/manual/index.d.ts +1 -1
  102. package/lib/server/instructions/parallel.d.ts +1 -2
  103. package/lib/server/instructions/query.d.ts +1 -1
  104. package/lib/server/instructions/query.js +8 -1
  105. package/lib/server/instructions/request.d.ts +3 -3
  106. package/lib/server/instructions/request.js +5 -2
  107. package/lib/server/instructions/sql.d.ts +12 -0
  108. package/lib/server/instructions/sql.js +34 -0
  109. package/lib/server/instructions/update.d.ts +1 -1
  110. package/lib/server/migrations/20230221071831-calculation-expression.js +1 -1
  111. package/lib/server/migrations/20230221121203-condition-calculation.js +1 -1
  112. package/lib/server/migrations/20230221162902-jsonb-to-json.js +7 -7
  113. package/lib/server/migrations/20230411034722-manual-multi-form.js +1 -8
  114. package/lib/server/migrations/20230710115902-manual-action-values.d.ts +4 -0
  115. package/lib/server/migrations/20230710115902-manual-action-values.js +97 -0
  116. package/lib/server/triggers/collection.d.ts +1 -1
  117. package/lib/server/triggers/collection.js +15 -13
  118. package/lib/server/triggers/index.d.ts +1 -1
  119. package/lib/server/triggers/schedule.d.ts +1 -1
  120. package/lib/server/triggers/schedule.js +18 -18
  121. package/lib/server/{models → types}/Execution.d.ts +2 -3
  122. package/lib/server/{models → types}/FlowNode.d.ts +1 -2
  123. package/lib/server/{models → types}/Job.d.ts +1 -2
  124. package/lib/server/{models → types}/Workflow.d.ts +1 -2
  125. package/lib/server/types/index.d.ts +4 -0
  126. package/lib/server/types/index.js +5 -0
  127. package/lib/server/utils.d.ts +2 -0
  128. package/lib/server/utils.js +21 -0
  129. package/package.json +39 -18
  130. package/server.d.ts +2 -3
  131. package/server.js +1 -30
  132. package/src/client/AddButton.tsx +111 -0
  133. package/src/client/Branch.tsx +37 -0
  134. package/src/client/CanvasContent.tsx +25 -0
  135. package/src/client/ExecutionCanvas.tsx +166 -0
  136. package/src/client/ExecutionLink.tsx +16 -0
  137. package/src/client/ExecutionPage.tsx +45 -0
  138. package/src/client/ExecutionResourceProvider.tsx +21 -0
  139. package/src/client/FlowContext.ts +7 -0
  140. package/src/client/WorkflowCanvas.tsx +221 -0
  141. package/src/client/WorkflowLink.tsx +16 -0
  142. package/src/client/WorkflowPage.tsx +52 -0
  143. package/src/client/WorkflowProvider.tsx +84 -0
  144. package/src/client/components/CollectionBlockInitializer.tsx +71 -0
  145. package/src/client/components/CollectionFieldset.tsx +160 -0
  146. package/src/client/components/Duration.tsx +45 -0
  147. package/src/client/components/DynamicExpression.tsx +53 -0
  148. package/src/client/components/FieldsSelect.tsx +32 -0
  149. package/src/client/components/FilterDynamicComponent.tsx +15 -0
  150. package/src/client/components/NodeDescription.tsx +51 -0
  151. package/src/client/components/NullRender.tsx +3 -0
  152. package/src/client/components/OpenDrawer.tsx +24 -0
  153. package/src/client/components/RadioWithTooltip.tsx +38 -0
  154. package/src/client/components/ValueBlock.tsx +67 -0
  155. package/src/client/components/renderEngineReference.tsx +30 -0
  156. package/src/client/constants.tsx +91 -0
  157. package/src/client/index.tsx +51 -0
  158. package/src/client/interfaces/expression.tsx +25 -0
  159. package/src/client/locale/en-US.ts +136 -0
  160. package/src/client/locale/es-ES.ts +129 -0
  161. package/src/client/locale/index.ts +18 -0
  162. package/src/client/locale/ja-JP.ts +90 -0
  163. package/src/client/locale/pt-BR.ts +136 -0
  164. package/src/client/locale/ru-RU.ts +90 -0
  165. package/src/client/locale/tr-TR.ts +90 -0
  166. package/src/client/locale/zh-CN.ts +248 -0
  167. package/src/client/nodes/aggregate.tsx +327 -0
  168. package/src/client/nodes/calculation.tsx +216 -0
  169. package/src/client/nodes/condition.tsx +463 -0
  170. package/src/client/nodes/create.tsx +85 -0
  171. package/src/client/nodes/delay.tsx +37 -0
  172. package/src/client/nodes/destroy.tsx +34 -0
  173. package/src/client/nodes/index.tsx +485 -0
  174. package/src/client/nodes/loop.tsx +144 -0
  175. package/src/client/nodes/manual/AssigneesSelect.tsx +33 -0
  176. package/src/client/nodes/manual/DetailsBlockProvider.tsx +80 -0
  177. package/src/client/nodes/manual/FormBlockInitializer.tsx +69 -0
  178. package/src/client/nodes/manual/FormBlockProvider.tsx +75 -0
  179. package/src/client/nodes/manual/ModeConfig.tsx +84 -0
  180. package/src/client/nodes/manual/SchemaConfig.tsx +509 -0
  181. package/src/client/nodes/manual/WorkflowTodo.tsx +607 -0
  182. package/src/client/nodes/manual/WorkflowTodoBlockInitializer.tsx +28 -0
  183. package/src/client/nodes/manual/forms/create.tsx +92 -0
  184. package/src/client/nodes/manual/forms/custom.tsx +392 -0
  185. package/src/client/nodes/manual/forms/update.tsx +134 -0
  186. package/src/client/nodes/manual/index.tsx +162 -0
  187. package/src/client/nodes/manual/utils.ts +28 -0
  188. package/src/client/nodes/parallel.tsx +138 -0
  189. package/src/client/nodes/query.tsx +88 -0
  190. package/src/client/nodes/request.tsx +185 -0
  191. package/src/client/nodes/sql.tsx +37 -0
  192. package/src/client/nodes/update.tsx +99 -0
  193. package/src/client/schemas/collection.ts +75 -0
  194. package/src/client/schemas/executions.tsx +169 -0
  195. package/src/client/schemas/workflows.ts +364 -0
  196. package/src/client/style.tsx +347 -0
  197. package/src/client/triggers/collection.tsx +190 -0
  198. package/src/client/triggers/index.tsx +311 -0
  199. package/src/client/triggers/schedule/EndsByField.tsx +40 -0
  200. package/src/client/triggers/schedule/OnField.tsx +64 -0
  201. package/src/client/triggers/schedule/RepeatField.tsx +116 -0
  202. package/src/client/triggers/schedule/ScheduleConfig.tsx +227 -0
  203. package/src/client/triggers/schedule/constants.ts +4 -0
  204. package/src/client/triggers/schedule/index.tsx +78 -0
  205. package/src/client/triggers/schedule/locale/Cron.zh-CN.ts +79 -0
  206. package/src/client/utils.ts +36 -0
  207. package/src/client/variable.tsx +318 -0
  208. package/src/index.ts +1 -0
  209. package/src/server/Plugin.ts +355 -0
  210. package/src/server/Processor.ts +354 -0
  211. package/src/server/__tests__/Plugin.test.ts +398 -0
  212. package/src/server/__tests__/Processor.test.ts +474 -0
  213. package/src/server/__tests__/actions/workflows.test.ts +419 -0
  214. package/src/server/__tests__/collections/categories.ts +27 -0
  215. package/src/server/__tests__/collections/comments.ts +24 -0
  216. package/src/server/__tests__/collections/posts.ts +42 -0
  217. package/src/server/__tests__/collections/replies.ts +9 -0
  218. package/src/server/__tests__/collections/tags.ts +15 -0
  219. package/src/server/__tests__/index.ts +89 -0
  220. package/src/server/__tests__/instructions/aggregate.test.ts +294 -0
  221. package/src/server/__tests__/instructions/calculation.test.ts +265 -0
  222. package/src/server/__tests__/instructions/condition.test.ts +335 -0
  223. package/src/server/__tests__/instructions/create.test.ts +129 -0
  224. package/src/server/__tests__/instructions/delay.test.ts +182 -0
  225. package/src/server/__tests__/instructions/destroy.test.ts +58 -0
  226. package/src/server/__tests__/instructions/loop.test.ts +331 -0
  227. package/src/server/__tests__/instructions/manual.test.ts +1173 -0
  228. package/src/server/__tests__/instructions/parallel.test.ts +445 -0
  229. package/src/server/__tests__/instructions/query.test.ts +359 -0
  230. package/src/server/__tests__/instructions/request.test.ts +247 -0
  231. package/src/server/__tests__/instructions/sql.test.ts +162 -0
  232. package/src/server/__tests__/instructions/update.test.ts +189 -0
  233. package/src/server/__tests__/triggers/collection.test.ts +333 -0
  234. package/src/server/__tests__/triggers/schedule.test.ts +369 -0
  235. package/src/server/actions/index.ts +25 -0
  236. package/src/server/actions/nodes.ts +214 -0
  237. package/src/server/actions/workflows.ts +178 -0
  238. package/src/server/collections/executions.ts +35 -0
  239. package/src/server/collections/flow_nodes.ts +54 -0
  240. package/src/server/collections/jobs.ts +31 -0
  241. package/src/server/collections/workflows.ts +88 -0
  242. package/src/server/constants.ts +26 -0
  243. package/src/server/fields/expression-field.ts +11 -0
  244. package/src/server/fields/index.ts +7 -0
  245. package/src/server/functions/index.ts +16 -0
  246. package/src/server/index.ts +6 -0
  247. package/src/server/instructions/aggregate.ts +42 -0
  248. package/src/server/instructions/calculation.ts +41 -0
  249. package/src/server/instructions/condition.ts +172 -0
  250. package/src/server/instructions/create.ts +39 -0
  251. package/src/server/instructions/delay.ts +105 -0
  252. package/src/server/instructions/destroy.ts +23 -0
  253. package/src/server/instructions/index.ts +64 -0
  254. package/src/server/instructions/loop.ts +99 -0
  255. package/src/server/instructions/manual/actions.ts +91 -0
  256. package/src/server/instructions/manual/collecions/jobs.ts +17 -0
  257. package/src/server/instructions/manual/collecions/users.ts +15 -0
  258. package/src/server/instructions/manual/collecions/users_jobs.ts +50 -0
  259. package/src/server/instructions/manual/forms/create.ts +23 -0
  260. package/src/server/instructions/manual/forms/index.ts +12 -0
  261. package/src/server/instructions/manual/forms/update.ts +23 -0
  262. package/src/server/instructions/manual/index.ts +184 -0
  263. package/src/server/instructions/parallel.ts +121 -0
  264. package/src/server/instructions/query.ts +42 -0
  265. package/src/server/instructions/request.ts +88 -0
  266. package/src/server/instructions/sql.ts +25 -0
  267. package/src/server/instructions/update.ts +24 -0
  268. package/src/server/migrations/20221129153547-calculation-variables.ts +64 -0
  269. package/src/server/migrations/20230221032941-change-request-body-type.ts +76 -0
  270. package/src/server/migrations/20230221071831-calculation-expression.ts +102 -0
  271. package/src/server/migrations/20230221121203-condition-calculation.ts +82 -0
  272. package/src/server/migrations/20230221162902-jsonb-to-json.ts +51 -0
  273. package/src/server/migrations/20230411034722-manual-multi-form.ts +282 -0
  274. package/src/server/migrations/20230612021134-manual-collection-block.ts +138 -0
  275. package/src/server/migrations/20230710115902-manual-action-values.ts +78 -0
  276. package/src/server/triggers/collection.ts +146 -0
  277. package/src/server/triggers/index.ts +22 -0
  278. package/src/server/triggers/schedule.ts +567 -0
  279. package/src/server/types/Execution.ts +26 -0
  280. package/src/server/types/FlowNode.ts +21 -0
  281. package/src/server/types/Job.ts +18 -0
  282. package/src/server/types/Workflow.ts +36 -0
  283. package/src/server/types/index.ts +4 -0
  284. package/src/server/utils.ts +17 -0
  285. package/lib/client/triggers/schedule/DateFieldsSelect.d.ts +0 -2
  286. /package/lib/server/{models → types}/Execution.js +0 -0
  287. /package/lib/server/{models → types}/FlowNode.js +0 -0
  288. /package/lib/server/{models → types}/Job.js +0 -0
  289. /package/lib/server/{models → types}/Workflow.js +0 -0
@@ -0,0 +1,463 @@
1
+ import { CloseCircleOutlined } from '@ant-design/icons';
2
+ import { css, cx, useCompile, Variable } from '@nocobase/client';
3
+ import { evaluators } from '@nocobase/evaluators/client';
4
+ import { Registry } from '@nocobase/utils/client';
5
+ import { Button, Select } from 'antd';
6
+ import React from 'react';
7
+ import { Trans, useTranslation } from 'react-i18next';
8
+ import { NodeDefaultView } from '.';
9
+ import { Branch } from '../Branch';
10
+ import { RadioWithTooltip, RadioWithTooltipOption } from '../components/RadioWithTooltip';
11
+ import { renderEngineReference } from '../components/renderEngineReference';
12
+ import { useFlowContext } from '../FlowContext';
13
+ import { lang, NAMESPACE } from '../locale';
14
+ import useStyles from '../style';
15
+ import { useWorkflowVariableOptions } from '../variable';
16
+
17
+ interface Calculator {
18
+ name: string;
19
+ type: 'boolean' | 'number' | 'string' | 'date' | 'unknown' | 'null' | 'array';
20
+ group: string;
21
+ }
22
+
23
+ export const calculators = new Registry<Calculator>();
24
+
25
+ calculators.register('equal', {
26
+ name: '=',
27
+ type: 'boolean',
28
+ group: 'boolean',
29
+ });
30
+ calculators.register('notEqual', {
31
+ name: '≠',
32
+ type: 'boolean',
33
+ group: 'boolean',
34
+ });
35
+ calculators.register('gt', {
36
+ name: '>',
37
+ type: 'boolean',
38
+ group: 'boolean',
39
+ });
40
+ calculators.register('gte', {
41
+ name: '≥',
42
+ type: 'boolean',
43
+ group: 'boolean',
44
+ });
45
+ calculators.register('lt', {
46
+ name: '<',
47
+ type: 'boolean',
48
+ group: 'boolean',
49
+ });
50
+ calculators.register('lte', {
51
+ name: '≤',
52
+ type: 'boolean',
53
+ group: 'boolean',
54
+ });
55
+
56
+ calculators.register('add', {
57
+ name: '+',
58
+ type: 'number',
59
+ group: 'number',
60
+ });
61
+ calculators.register('minus', {
62
+ name: '-',
63
+ type: 'number',
64
+ group: 'number',
65
+ });
66
+ calculators.register('multiple', {
67
+ name: '*',
68
+ type: 'number',
69
+ group: 'number',
70
+ });
71
+ calculators.register('divide', {
72
+ name: '/',
73
+ type: 'number',
74
+ group: 'number',
75
+ });
76
+ calculators.register('mod', {
77
+ name: '%',
78
+ type: 'number',
79
+ group: 'number',
80
+ });
81
+
82
+ calculators.register('includes', {
83
+ name: '{{t("contains")}}',
84
+ type: 'boolean',
85
+ group: 'string',
86
+ });
87
+ calculators.register('notIncludes', {
88
+ name: '{{t("does not contain")}}',
89
+ type: 'boolean',
90
+ group: 'string',
91
+ });
92
+ calculators.register('startsWith', {
93
+ name: '{{t("starts with")}}',
94
+ type: 'boolean',
95
+ group: 'string',
96
+ });
97
+ calculators.register('notStartsWith', {
98
+ name: '{{t("not starts with")}}',
99
+ type: 'boolean',
100
+ group: 'string',
101
+ });
102
+ calculators.register('endsWith', {
103
+ name: '{{t("ends with")}}',
104
+ type: 'boolean',
105
+ group: 'string',
106
+ });
107
+ calculators.register('notEndsWith', {
108
+ name: '{{t("not ends with")}}',
109
+ type: 'boolean',
110
+ group: 'string',
111
+ });
112
+ calculators.register('concat', {
113
+ name: `{{t("concat", { ns: "${NAMESPACE}" })}}`,
114
+ type: 'string',
115
+ group: 'string',
116
+ });
117
+
118
+ const calculatorGroups = [
119
+ {
120
+ value: 'boolean',
121
+ title: '{{t("Comparision")}}',
122
+ },
123
+ {
124
+ value: 'number',
125
+ title: `{{t("Arithmetic calculation", { ns: "${NAMESPACE}" })}}`,
126
+ },
127
+ {
128
+ value: 'string',
129
+ title: `{{t("String operation", { ns: "${NAMESPACE}" })}}`,
130
+ },
131
+ {
132
+ value: 'date',
133
+ title: `{{t("Date", { ns: "${NAMESPACE}" })}}`,
134
+ },
135
+ ];
136
+
137
+ function getGroupCalculators(group) {
138
+ return Array.from(calculators.getEntities()).filter(([key, value]) => value.group === group);
139
+ }
140
+
141
+ function Calculation({ calculator, operands = [], onChange }) {
142
+ const compile = useCompile();
143
+ const options = useWorkflowVariableOptions();
144
+ return (
145
+ <fieldset
146
+ className={css`
147
+ display: flex;
148
+ gap: 0.5em;
149
+ align-items: center;
150
+ flex-wrap: wrap;
151
+ `}
152
+ >
153
+ <Variable.Input
154
+ value={operands[0]}
155
+ onChange={(v) => onChange({ calculator, operands: [v, operands[1]] })}
156
+ scope={options}
157
+ useTypedConstant
158
+ />
159
+ <Select
160
+ value={calculator}
161
+ onChange={(v) => onChange({ operands, calculator: v })}
162
+ placeholder={lang('Calculator')}
163
+ popupMatchSelectWidth={false}
164
+ >
165
+ {calculatorGroups
166
+ .filter((group) => Boolean(getGroupCalculators(group.value).length))
167
+ .map((group) => (
168
+ <Select.OptGroup key={group.value} label={compile(group.title)}>
169
+ {getGroupCalculators(group.value).map(([value, { name }]) => (
170
+ <Select.Option key={value} value={value}>
171
+ {compile(name)}
172
+ </Select.Option>
173
+ ))}
174
+ </Select.OptGroup>
175
+ ))}
176
+ </Select>
177
+ <Variable.Input
178
+ value={operands[1]}
179
+ onChange={(v) => onChange({ calculator, operands: [operands[0], v] })}
180
+ scope={options}
181
+ useTypedConstant
182
+ />
183
+ </fieldset>
184
+ );
185
+ }
186
+
187
+ function CalculationItem({ value, onChange, onRemove }) {
188
+ if (!value) {
189
+ return null;
190
+ }
191
+
192
+ const { calculator, operands = [] } = value;
193
+
194
+ return (
195
+ <div
196
+ className={css`
197
+ display: flex;
198
+ position: relative;
199
+ margin: 0.5em 0;
200
+ `}
201
+ >
202
+ {value.group ? (
203
+ <CalculationGroup value={value.group} onChange={(group) => onChange({ ...value, group })} />
204
+ ) : (
205
+ <Calculation operands={operands} calculator={calculator} onChange={onChange} />
206
+ )}
207
+ <Button onClick={onRemove} type="link" icon={<CloseCircleOutlined />} />
208
+ </div>
209
+ );
210
+ }
211
+
212
+ function CalculationGroup({ value, onChange }) {
213
+ const { t } = useTranslation();
214
+ const { type = 'and', calculations = [] } = value;
215
+
216
+ function onAddSingle() {
217
+ onChange({
218
+ ...value,
219
+ calculations: [...calculations, { not: false, calculator: 'equal' }],
220
+ });
221
+ }
222
+
223
+ function onAddGroup() {
224
+ onChange({
225
+ ...value,
226
+ calculations: [...calculations, { not: false, group: { type: 'and', calculations: [] } }],
227
+ });
228
+ }
229
+
230
+ function onRemove(i: number) {
231
+ calculations.splice(i, 1);
232
+ onChange({ ...value, calculations: [...calculations] });
233
+ }
234
+
235
+ function onItemChange(i: number, v) {
236
+ calculations.splice(i, 1, v);
237
+
238
+ onChange({ ...value, calculations: [...calculations] });
239
+ }
240
+
241
+ return (
242
+ <div
243
+ className={cx(
244
+ 'node-type-condition-group',
245
+ css`
246
+ position: relative;
247
+ width: 100%;
248
+ .node-type-condition-group {
249
+ padding: 0.5em 1em;
250
+ border: 1px dashed #ddd;
251
+ }
252
+ + button {
253
+ position: absolute;
254
+ right: 0;
255
+ }
256
+ `,
257
+ )}
258
+ >
259
+ <div
260
+ className={css`
261
+ display: flex;
262
+ align-items: center;
263
+ gap: 0.5em;
264
+ .ant-select {
265
+ width: auto;
266
+ min-width: 6em;
267
+ }
268
+ `}
269
+ >
270
+ <Trans>
271
+ {'Meet '}
272
+ <Select value={type} onChange={(t) => onChange({ ...value, type: t })}>
273
+ <Select.Option value="and">All</Select.Option>
274
+ <Select.Option value="or">Any</Select.Option>
275
+ </Select>
276
+ {' conditions in the group'}
277
+ </Trans>
278
+ </div>
279
+ <div className="calculation-items">
280
+ {calculations.map((calculation, i) => (
281
+ <CalculationItem
282
+ key={`${calculation.calculator}_${i}`}
283
+ value={calculation}
284
+ onChange={onItemChange.bind(this, i)}
285
+ onRemove={() => onRemove(i)}
286
+ />
287
+ ))}
288
+ </div>
289
+ <div
290
+ className={css`
291
+ button {
292
+ padding: 0;
293
+ &:not(:last-child) {
294
+ margin-right: 1em;
295
+ }
296
+ }
297
+ `}
298
+ >
299
+ <Button type="link" onClick={onAddSingle}>
300
+ {t('Add condition')}
301
+ </Button>
302
+ <Button type="link" onClick={onAddGroup}>
303
+ {t('Add condition group')}
304
+ </Button>
305
+ </div>
306
+ </div>
307
+ );
308
+ }
309
+
310
+ function CalculationConfig({ value, onChange }) {
311
+ const rule = value && Object.keys(value).length ? value : { group: { type: 'and', calculations: [] } };
312
+ return <CalculationGroup value={rule.group} onChange={(group) => onChange({ ...rule, group })} />;
313
+ }
314
+
315
+ export default {
316
+ title: `{{t("Condition", { ns: "${NAMESPACE}" })}}`,
317
+ type: 'condition',
318
+ group: 'control',
319
+ description: `{{t('Based on boolean result of the calculation to determine whether to "continue" or "exit" the process, or continue on different branches of "yes" and "no".', { ns: "${NAMESPACE}" })}}`,
320
+ fieldset: {
321
+ rejectOnFalse: {
322
+ type: 'boolean',
323
+ title: `{{t("Mode", { ns: "${NAMESPACE}" })}}`,
324
+ 'x-decorator': 'FormItem',
325
+ 'x-component': 'Radio.Group',
326
+ 'x-component-props': {
327
+ disabled: true,
328
+ },
329
+ enum: [
330
+ {
331
+ value: true,
332
+ label: `{{t('Continue when "Yes"', { ns: "${NAMESPACE}" })}}`,
333
+ },
334
+ {
335
+ value: false,
336
+ label: `{{t('Branch into "Yes" and "No"', { ns: "${NAMESPACE}" })}}`,
337
+ },
338
+ ],
339
+ },
340
+ engine: {
341
+ type: 'string',
342
+ title: `{{t("Calculation engine", { ns: "${NAMESPACE}" })}}`,
343
+ 'x-decorator': 'FormItem',
344
+ 'x-component': 'RadioWithTooltip',
345
+ 'x-component-props': {
346
+ options: [
347
+ ['basic', { label: `{{t("Basic", { ns: "${NAMESPACE}" })}}` }],
348
+ ...Array.from(evaluators.getEntities()),
349
+ ].reduce((result: RadioWithTooltipOption[], [value, options]: any) => result.concat({ value, ...options }), []),
350
+ },
351
+ required: true,
352
+ default: 'basic',
353
+ },
354
+ calculation: {
355
+ type: 'string',
356
+ title: `{{t("Condition", { ns: "${NAMESPACE}" })}}`,
357
+ 'x-decorator': 'FormItem',
358
+ 'x-component': 'CalculationConfig',
359
+ 'x-reactions': {
360
+ dependencies: ['engine'],
361
+ fulfill: {
362
+ state: {
363
+ visible: '{{$deps[0] === "basic"}}',
364
+ },
365
+ },
366
+ },
367
+ required: true,
368
+ },
369
+ expression: {
370
+ type: 'string',
371
+ title: `{{t("Condition expression", { ns: "${NAMESPACE}" })}}`,
372
+ 'x-decorator': 'FormItem',
373
+ 'x-component': 'CalculationExpression',
374
+ ['x-validator'](value, rules, { form }) {
375
+ const { values } = form;
376
+ const { evaluate } = evaluators.get(values.engine);
377
+ const exp = value.trim().replace(/{{([^{}]+)}}/g, ' 1 ');
378
+ try {
379
+ evaluate(exp);
380
+ return '';
381
+ } catch (e) {
382
+ return lang('Expression syntax error');
383
+ }
384
+ },
385
+ 'x-reactions': {
386
+ dependencies: ['engine'],
387
+ fulfill: {
388
+ state: {
389
+ visible: '{{$deps[0] !== "basic"}}',
390
+ },
391
+ schema: {
392
+ description: '{{renderEngineReference($deps[0])}}',
393
+ },
394
+ },
395
+ },
396
+ required: true,
397
+ },
398
+ },
399
+ view: {},
400
+ options: [
401
+ {
402
+ label: `{{t('Continue when "Yes"', { ns: "${NAMESPACE}" })}}`,
403
+ key: 'rejectOnFalse',
404
+ value: { rejectOnFalse: true },
405
+ },
406
+ {
407
+ label: `{{t('Branch into "Yes" and "No"', { ns: "${NAMESPACE}" })}}`,
408
+ key: 'branch',
409
+ value: { rejectOnFalse: false },
410
+ },
411
+ ],
412
+ component: function Component({ data }) {
413
+ const { t } = useTranslation();
414
+ const { nodes } = useFlowContext();
415
+ const { styles } = useStyles();
416
+ const {
417
+ id,
418
+ config: { rejectOnFalse },
419
+ } = data;
420
+ const trueEntry = nodes.find((item) => item.upstreamId === id && item.branchIndex === 1);
421
+ const falseEntry = nodes.find((item) => item.upstreamId === id && item.branchIndex === 0);
422
+ return (
423
+ <NodeDefaultView data={data}>
424
+ {rejectOnFalse ? null : (
425
+ <div className={cx(styles.nodeSubtreeClass)}>
426
+ <div
427
+ className={cx(
428
+ styles.branchBlockClass,
429
+ css`
430
+ > * > .workflow-branch-lines {
431
+ > button {
432
+ display: none;
433
+ }
434
+ }
435
+ `,
436
+ )}
437
+ >
438
+ <Branch from={data} entry={falseEntry} branchIndex={0} />
439
+ <Branch from={data} entry={trueEntry} branchIndex={1} />
440
+ </div>
441
+ <div className={styles.conditionClass}>
442
+ <span style={{ right: '4em' }}>{t('No')}</span>
443
+ <span style={{ left: '4em' }}>{t('Yes')}</span>
444
+ </div>
445
+ </div>
446
+ )}
447
+ </NodeDefaultView>
448
+ );
449
+ },
450
+ scope: {
451
+ renderEngineReference,
452
+ useWorkflowVariableOptions,
453
+ },
454
+ components: {
455
+ CalculationConfig,
456
+ CalculationExpression(props) {
457
+ const scope = useWorkflowVariableOptions();
458
+
459
+ return <Variable.TextArea scope={scope} {...props} />;
460
+ },
461
+ RadioWithTooltip,
462
+ },
463
+ };
@@ -0,0 +1,85 @@
1
+ import { SchemaInitializerItemOptions, useCollectionDataSource, useCollectionManager, useCompile } from '@nocobase/client';
2
+
3
+ import { appends, collection, values } from '../schemas/collection';
4
+ import CollectionFieldset from '../components/CollectionFieldset';
5
+ import { NAMESPACE } from '../locale';
6
+ import { CollectionBlockInitializer } from '../components/CollectionBlockInitializer';
7
+ import { getCollectionFieldOptions } from '../variable';
8
+ import { FieldsSelect } from '../components/FieldsSelect';
9
+
10
+ export default {
11
+ title: `{{t("Create record", { ns: "${NAMESPACE}" })}}`,
12
+ type: 'create',
13
+ group: 'collection',
14
+ description: `{{t("Add new record to a collection. You can use variables from upstream nodes to assign values to fields.", { ns: "${NAMESPACE}" })}}`,
15
+ fieldset: {
16
+ collection,
17
+ // multiple: {
18
+ // type: 'boolean',
19
+ // title: '多条数据',
20
+ // name: 'multiple',
21
+ // 'x-decorator': 'FormItem',
22
+ // 'x-component': 'Checkbox',
23
+ // 'x-component-props': {
24
+ // disabled: true
25
+ // }
26
+ // },
27
+ params: {
28
+ type: 'object',
29
+ properties: {
30
+ values,
31
+ appends,
32
+ },
33
+ },
34
+ },
35
+ view: {},
36
+ scope: {
37
+ useCollectionDataSource,
38
+ },
39
+ components: {
40
+ CollectionFieldset,
41
+ },
42
+ useVariables({ id, title, config }, options) {
43
+ const compile = useCompile();
44
+ const { getCollectionFields } = useCollectionManager();
45
+ // const depth = config?.params?.appends?.length
46
+ // ? config?.params?.appends.reduce((max, item) => Math.max(max, item.split('.').length), 1)
47
+ // : 0;
48
+ const name = `${id}`;
49
+ const [result] = getCollectionFieldOptions({
50
+ // collection: config.collection,
51
+ ...options,
52
+ fields: [
53
+ {
54
+ collectionName: config.collection,
55
+ name,
56
+ type: 'hasOne',
57
+ target: config.collection,
58
+ uiSchema: {
59
+ title,
60
+ },
61
+ },
62
+ ],
63
+ // depth: options?.depth ?? depth,
64
+ appends: [name, ...(config.params?.appends?.map((item) => `${name}.${item}`) || [])],
65
+ compile,
66
+ getCollectionFields,
67
+ });
68
+
69
+ return result;
70
+ },
71
+ useInitializers(node): SchemaInitializerItemOptions | null {
72
+ if (!node.config.collection) {
73
+ return null;
74
+ }
75
+
76
+ return {
77
+ type: 'item',
78
+ title: node.title ?? `#${node.id}`,
79
+ component: CollectionBlockInitializer,
80
+ collection: node.config.collection,
81
+ dataSource: `{{$jobsMapByNodeId.${node.id}}}`,
82
+ };
83
+ },
84
+ initializers: {},
85
+ };
@@ -0,0 +1,37 @@
1
+ import Duration from '../components/Duration';
2
+ import { JOB_STATUS } from '../constants';
3
+ import { NAMESPACE } from '../locale';
4
+
5
+ export default {
6
+ title: `{{t("Delay", { ns: "${NAMESPACE}" })}}`,
7
+ type: 'delay',
8
+ group: 'control',
9
+ description: `{{t("Delay a period of time and then continue or exit the process. Can be used to set wait or timeout times in parallel branches.", { ns: "${NAMESPACE}" })}}`,
10
+ fieldset: {
11
+ duration: {
12
+ type: 'number',
13
+ title: `{{t("Duration", { ns: "${NAMESPACE}" })}}`,
14
+ 'x-decorator': 'FormItem',
15
+ 'x-component': 'Duration',
16
+ default: 60000,
17
+ required: true,
18
+ },
19
+ endStatus: {
20
+ type: 'number',
21
+ title: `{{t("End Status", { ns: "${NAMESPACE}" })}}`,
22
+ 'x-decorator': 'FormItem',
23
+ 'x-component': 'Radio.Group',
24
+ enum: [
25
+ { label: `{{t("Succeed and continue", { ns: "${NAMESPACE}" })}}`, value: JOB_STATUS.RESOLVED },
26
+ { label: `{{t("Fail and exit", { ns: "${NAMESPACE}" })}}`, value: JOB_STATUS.FAILED },
27
+ ],
28
+ required: true,
29
+ default: JOB_STATUS.RESOLVED,
30
+ },
31
+ },
32
+ view: {},
33
+ scope: {},
34
+ components: {
35
+ Duration,
36
+ },
37
+ };
@@ -0,0 +1,34 @@
1
+ import { useCollectionDataSource } from '@nocobase/client';
2
+
3
+ import { FilterDynamicComponent } from '../components/FilterDynamicComponent';
4
+ import { collection, filter } from '../schemas/collection';
5
+ import { isValidFilter } from '../utils';
6
+ import { NAMESPACE } from '../locale';
7
+
8
+ export default {
9
+ title: '{{t("Delete record")}}',
10
+ type: 'destroy',
11
+ group: 'collection',
12
+ description: `{{t("Delete records of a collection. Could use variables in workflow context as filter. All records match the filter will be deleted.", { ns: "${NAMESPACE}" })}}`,
13
+ fieldset: {
14
+ collection,
15
+ params: {
16
+ type: 'object',
17
+ properties: {
18
+ filter: {
19
+ ...filter,
20
+ ['x-validator'](value) {
21
+ return isValidFilter(value) ? '' : `{{t("Please add at least one condition", { ns: "${NAMESPACE}" })}}`;
22
+ },
23
+ },
24
+ },
25
+ },
26
+ },
27
+ view: {},
28
+ scope: {
29
+ useCollectionDataSource,
30
+ },
31
+ components: {
32
+ FilterDynamicComponent,
33
+ },
34
+ };