@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,162 @@
1
+ import { BlockInitializers, SchemaInitializerItemOptions, useCollectionManager, useCompile } from '@nocobase/client';
2
+
3
+ import { CollectionBlockInitializer } from '../../components/CollectionBlockInitializer';
4
+ import { defaultFieldNames, getCollectionFieldOptions } from '../../variable';
5
+ import { NAMESPACE } from '../../locale';
6
+ import { SchemaConfig, SchemaConfigButton } from './SchemaConfig';
7
+ import { ModeConfig } from './ModeConfig';
8
+ import { AssigneesSelect } from './AssigneesSelect';
9
+
10
+ const MULTIPLE_ASSIGNED_MODE = {
11
+ SINGLE: Symbol('single'),
12
+ ALL: Symbol('all'),
13
+ ANY: Symbol('any'),
14
+ ALL_PERCENTAGE: Symbol('all percentage'),
15
+ ANY_PERCENTAGE: Symbol('any percentage'),
16
+ };
17
+
18
+ // TODO(optimize): change to register way
19
+ const initializerGroup = BlockInitializers.items.find((group) => group.key === 'media');
20
+ if (!initializerGroup.children.find((item) => item.key === 'workflowTodos')) {
21
+ initializerGroup.children.push({
22
+ key: 'workflowTodos',
23
+ type: 'item',
24
+ title: `{{t("Workflow todos", { ns: "${NAMESPACE}" })}}`,
25
+ component: 'WorkflowTodoBlockInitializer',
26
+ icon: 'CheckSquareOutlined',
27
+ } as any);
28
+ }
29
+
30
+ export default {
31
+ title: `{{t("Manual", { ns: "${NAMESPACE}" })}}`,
32
+ type: 'manual',
33
+ group: 'manual',
34
+ description: `{{t("Could be used for manually submitting data, and determine whether to continue or exit. Workflow will generate a todo item for assigned user when it reaches a manual node, and continue processing after user submits the form.", { ns: "${NAMESPACE}" })}}`,
35
+ fieldset: {
36
+ assignees: {
37
+ type: 'array',
38
+ title: `{{t("Assignees", { ns: "${NAMESPACE}" })}}`,
39
+ 'x-decorator': 'FormItem',
40
+ 'x-component': 'AssigneesSelect',
41
+ 'x-component-props': {
42
+ // multiple: true,
43
+ },
44
+ required: true,
45
+ default: [],
46
+ },
47
+ mode: {
48
+ type: 'number',
49
+ title: `{{t("Mode", { ns: "${NAMESPACE}" })}}`,
50
+ 'x-decorator': 'FormItem',
51
+ 'x-component': 'ModeConfig',
52
+ default: 1,
53
+ 'x-reactions': {
54
+ dependencies: ['assignees'],
55
+ fulfill: {
56
+ state: {
57
+ visible: '{{$deps[0].length > 1}}',
58
+ },
59
+ },
60
+ },
61
+ },
62
+ schema: {
63
+ type: 'void',
64
+ title: `{{t("User interface", { ns: "${NAMESPACE}" })}}`,
65
+ 'x-decorator': 'FormItem',
66
+ 'x-component': 'SchemaConfigButton',
67
+ properties: {
68
+ schema: {
69
+ type: 'object',
70
+ 'x-component': 'SchemaConfig',
71
+ default: null,
72
+ },
73
+ },
74
+ },
75
+ forms: {
76
+ type: 'object',
77
+ default: {},
78
+ },
79
+ },
80
+ view: {},
81
+ scope: {},
82
+ components: {
83
+ SchemaConfigButton,
84
+ SchemaConfig,
85
+ ModeConfig,
86
+ AssigneesSelect,
87
+ },
88
+ useVariables({ id, title, config }, { types, fieldNames = defaultFieldNames }) {
89
+ const compile = useCompile();
90
+ const { getCollectionFields } = useCollectionManager();
91
+ const formKeys = Object.keys(config.forms ?? {});
92
+ if (!formKeys.length) {
93
+ return null;
94
+ }
95
+
96
+ const options = formKeys
97
+ .map((formKey) => {
98
+ const form = config.forms[formKey];
99
+
100
+ const fieldsOptions = getCollectionFieldOptions({
101
+ fields: form.collection?.fields,
102
+ collection: form.collection,
103
+ types,
104
+ compile,
105
+ getCollectionFields,
106
+ });
107
+ const label = compile(form.title) || formKey;
108
+ return fieldsOptions.length
109
+ ? {
110
+ key: formKey,
111
+ value: formKey,
112
+ label,
113
+ title: label,
114
+ children: fieldsOptions,
115
+ }
116
+ : null;
117
+ })
118
+ .filter(Boolean);
119
+
120
+ return options.length
121
+ ? {
122
+ [fieldNames.value]: `${id}`,
123
+ [fieldNames.label]: title,
124
+ [fieldNames.children]: options,
125
+ }
126
+ : null;
127
+ },
128
+ useInitializers(node): SchemaInitializerItemOptions | null {
129
+ const { getCollection } = useCollectionManager();
130
+ const formKeys = Object.keys(node.config.forms ?? {});
131
+ if (!formKeys.length || node.config.mode) {
132
+ return null;
133
+ }
134
+
135
+ const forms = formKeys
136
+ .map((formKey) => {
137
+ const form = node.config.forms[formKey];
138
+ const { fields = [] } = getCollection(form.collection);
139
+
140
+ return fields.length
141
+ ? ({
142
+ type: 'item',
143
+ title: form.title ?? formKey,
144
+ component: CollectionBlockInitializer,
145
+ collection: form.collection,
146
+ dataSource: `{{$jobsMapByNodeId.${node.id}.${formKey}}}`,
147
+ } as SchemaInitializerItemOptions)
148
+ : null;
149
+ })
150
+ .filter(Boolean);
151
+
152
+ return forms.length
153
+ ? {
154
+ key: 'forms',
155
+ type: 'subMenu',
156
+ title: node.title,
157
+ children: forms,
158
+ }
159
+ : null;
160
+ },
161
+ initializers: {},
162
+ };
@@ -0,0 +1,28 @@
1
+ export function traverseSchema(schema, fn) {
2
+ fn(schema);
3
+ if (schema.properties) {
4
+ Object.keys(schema.properties).forEach((key) => {
5
+ traverseSchema(schema.properties[key], fn);
6
+ });
7
+ }
8
+ }
9
+
10
+ export function findSchema(schema, filter, onlyLeaf = false) {
11
+ const result = [];
12
+
13
+ if (!schema) {
14
+ return result;
15
+ }
16
+
17
+ if (filter(schema) && (!onlyLeaf || !schema.properties)) {
18
+ result.push(schema);
19
+ return result;
20
+ }
21
+
22
+ if (schema.properties) {
23
+ Object.keys(schema.properties).forEach((key) => {
24
+ result.push(...findSchema(schema.properties[key], filter));
25
+ });
26
+ }
27
+ return result;
28
+ }
@@ -0,0 +1,138 @@
1
+ import { PlusOutlined } from '@ant-design/icons';
2
+ import { css, cx } from '@nocobase/client';
3
+ import { Button, Tooltip } from 'antd';
4
+ import React, { useState } from 'react';
5
+ import { NodeDefaultView } from '.';
6
+ import { Branch } from '../Branch';
7
+ import { useFlowContext } from '../FlowContext';
8
+ import { RadioWithTooltip } from '../components/RadioWithTooltip';
9
+ import { NAMESPACE, lang } from '../locale';
10
+ import useStyles from '../style';
11
+
12
+ export default {
13
+ title: `{{t("Parallel branch", { ns: "${NAMESPACE}" })}}`,
14
+ type: 'parallel',
15
+ group: 'control',
16
+ description: `{{t("Run multiple branch processes in parallel.", { ns: "${NAMESPACE}" })}}`,
17
+ fieldset: {
18
+ mode: {
19
+ type: 'string',
20
+ title: `{{t("Mode", { ns: "${NAMESPACE}" })}}`,
21
+ 'x-decorator': 'FormItem',
22
+ 'x-component': 'RadioWithTooltip',
23
+ 'x-component-props': {
24
+ options: [
25
+ {
26
+ value: 'all',
27
+ label: `{{t('All succeeded', { ns: "${NAMESPACE}" })}}`,
28
+ tooltip: `{{t('Continue after all branches succeeded', { ns: "${NAMESPACE}" })}}`,
29
+ },
30
+ {
31
+ value: 'any',
32
+ label: `{{t('Any succeeded', { ns: "${NAMESPACE}" })}}`,
33
+ tooltip: `{{t('Continue after any branch succeeded', { ns: "${NAMESPACE}" })}}`,
34
+ },
35
+ {
36
+ value: 'race',
37
+ label: `{{t('Any succeeded or failed', { ns: "${NAMESPACE}" })}}`,
38
+ tooltip: `{{t('Continue after any branch succeeded, or exit after any branch failed.', { ns: "${NAMESPACE}" })}}`,
39
+ },
40
+ ],
41
+ },
42
+ default: 'all',
43
+ },
44
+ },
45
+ view: {},
46
+ component: function Component({ data }) {
47
+ const { styles } = useStyles();
48
+ const {
49
+ id,
50
+ config: { mode },
51
+ } = data;
52
+ const { workflow, nodes } = useFlowContext();
53
+ const branches = nodes
54
+ .reduce((result, node) => {
55
+ if (node.upstreamId === id && node.branchIndex != null) {
56
+ return result.concat(node);
57
+ }
58
+ return result;
59
+ }, [])
60
+ .sort((a, b) => a.branchIndex - b.branchIndex);
61
+ const [branchCount, setBranchCount] = useState(Math.max(2, branches.length));
62
+
63
+ const tempBranches = Array(Math.max(0, branchCount - branches.length)).fill(null);
64
+ const lastBranchHead = branches[branches.length - 1];
65
+
66
+ return (
67
+ <NodeDefaultView data={data}>
68
+ <div className={cx(styles.nodeSubtreeClass)}>
69
+ <div className={cx(styles.branchBlockClass)}>
70
+ {branches.map((branch) => (
71
+ <Branch key={branch.id} from={data} entry={branch} branchIndex={branch.branchIndex} />
72
+ ))}
73
+ {tempBranches.map((_, i) => (
74
+ <Branch
75
+ key={`temp_${branches.length + i}`}
76
+ from={data}
77
+ branchIndex={(lastBranchHead ? lastBranchHead.branchIndex : 0) + i + 1}
78
+ controller={
79
+ branches.length + i > 1 ? (
80
+ <div
81
+ className={css`
82
+ padding-top: 2em;
83
+
84
+ > button {
85
+ .anticon {
86
+ transform: rotate(45deg);
87
+ }
88
+ }
89
+ `}
90
+ >
91
+ <Button
92
+ shape="circle"
93
+ icon={<PlusOutlined />}
94
+ onClick={() => setBranchCount(branchCount - 1)}
95
+ disabled={workflow.executed}
96
+ />
97
+ </div>
98
+ ) : null
99
+ }
100
+ />
101
+ ))}
102
+ </div>
103
+ <div
104
+ className={css`
105
+ position: relative;
106
+ height: 2em;
107
+ `}
108
+ >
109
+ <Tooltip
110
+ title={lang('Add branch')}
111
+ className={css`
112
+ visibility: ${workflow.executed ? 'hidden' : 'visible'};
113
+ `}
114
+ >
115
+ <Button
116
+ icon={<PlusOutlined />}
117
+ className={css`
118
+ position: absolute;
119
+ top: calc(50% - 1px);
120
+ transform: translateX(-50%) rotate(45deg);
121
+
122
+ .anticon {
123
+ transform: rotate(-45deg);
124
+ }
125
+ `}
126
+ onClick={() => setBranchCount(branchCount + 1)}
127
+ disabled={workflow.executed}
128
+ />
129
+ </Tooltip>
130
+ </div>
131
+ </div>
132
+ </NodeDefaultView>
133
+ );
134
+ },
135
+ components: {
136
+ RadioWithTooltip,
137
+ },
138
+ };
@@ -0,0 +1,88 @@
1
+ import { SchemaInitializerItemOptions, useCollectionDataSource, useCollectionManager, useCompile } from '@nocobase/client';
2
+
3
+ import { appends, collection, filter } from '../schemas/collection';
4
+ import { NAMESPACE } from '../locale';
5
+ import { CollectionBlockInitializer } from '../components/CollectionBlockInitializer';
6
+ import { FilterDynamicComponent } from '../components/FilterDynamicComponent';
7
+ import { getCollectionFieldOptions } from '../variable';
8
+ import { FieldsSelect } from '../components/FieldsSelect';
9
+
10
+ export default {
11
+ title: `{{t("Query record", { ns: "${NAMESPACE}" })}}`,
12
+ type: 'query',
13
+ group: 'collection',
14
+ description: `{{t("Query records from a collection. You can use variables from upstream nodes as query conditions.", { ns: "${NAMESPACE}" })}}`,
15
+ fieldset: {
16
+ collection,
17
+ multiple: {
18
+ type: 'boolean',
19
+ title: `{{t("Allow multiple records as result", { ns: "${NAMESPACE}" })}}`,
20
+ 'x-decorator': 'FormItem',
21
+ 'x-component': 'Checkbox',
22
+ description: `{{t("If checked, when there are multiple records in the query result, an array will be returned as the result, which can be operated on one by one using a loop node. Otherwise, only one record will be returned.", { ns: "${NAMESPACE}" })}}`,
23
+ },
24
+ params: {
25
+ type: 'object',
26
+ properties: {
27
+ filter,
28
+ appends,
29
+ },
30
+ },
31
+ failOnEmpty: {
32
+ type: 'boolean',
33
+ title: `{{t("Exit when query result is null", { ns: "${NAMESPACE}" })}}`,
34
+ 'x-decorator': 'FormItem',
35
+ 'x-component': 'Checkbox',
36
+ },
37
+ },
38
+ view: {},
39
+ scope: {
40
+ useCollectionDataSource,
41
+ },
42
+ components: {
43
+ FilterDynamicComponent,
44
+ },
45
+ useVariables({ id, title, config }, options) {
46
+ const compile = useCompile();
47
+ const { getCollectionFields } = useCollectionManager();
48
+ // const depth = config?.params?.appends?.length
49
+ // ? config?.params?.appends.reduce((max, item) => Math.max(max, item.split('.').length), 1)
50
+ // : 0;
51
+ const name = `${id}`;
52
+ const [result] = getCollectionFieldOptions({
53
+ // collection: config.collection,
54
+ ...options,
55
+ fields: [
56
+ {
57
+ collectionName: config.collection,
58
+ name,
59
+ type: 'hasOne',
60
+ target: config.collection,
61
+ uiSchema: {
62
+ title,
63
+ },
64
+ },
65
+ ],
66
+ // depth: options?.depth ?? depth,
67
+ appends: [name, ...(config.params?.appends?.map((item) => `${name}.${item}`) || [])],
68
+ compile,
69
+ getCollectionFields,
70
+ });
71
+
72
+ return result;
73
+ },
74
+ useInitializers(node): SchemaInitializerItemOptions | null {
75
+ if (!node.config.collection || node.config.multiple) {
76
+ return null;
77
+ }
78
+
79
+ return {
80
+ type: 'item',
81
+ title: node.title ?? `#${node.id}`,
82
+ component: CollectionBlockInitializer,
83
+ collection: node.config.collection,
84
+ dataSource: `{{$jobsMapByNodeId.${node.id}}}`,
85
+ };
86
+ },
87
+ initializers: {},
88
+ };
@@ -0,0 +1,185 @@
1
+ import { ArrayItems } from '@formily/antd-v5';
2
+ import React from 'react';
3
+
4
+ import { Variable } from '@nocobase/client';
5
+ import { NAMESPACE } from '../locale';
6
+ import { useWorkflowVariableOptions } from '../variable';
7
+
8
+ export default {
9
+ title: `{{t("HTTP request", { ns: "${NAMESPACE}" })}}`,
10
+ type: 'request',
11
+ group: 'extended',
12
+ description: `{{t("Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.", { ns: "${NAMESPACE}" })}}`,
13
+ fieldset: {
14
+ method: {
15
+ type: 'string',
16
+ required: true,
17
+ title: `{{t("HTTP method", { ns: "${NAMESPACE}" })}}`,
18
+ 'x-decorator': 'FormItem',
19
+ 'x-component': 'Select',
20
+ 'x-component-props': {
21
+ showSearch: false,
22
+ allowClear: false,
23
+ },
24
+ enum: [
25
+ { label: 'GET', value: 'GET' },
26
+ { label: 'POST', value: 'POST' },
27
+ { label: 'PUT', value: 'PUT' },
28
+ { label: 'PATCH', value: 'PATCH' },
29
+ { label: 'DELETE', value: 'DELETE' },
30
+ ],
31
+ default: 'POST',
32
+ },
33
+ url: {
34
+ type: 'string',
35
+ required: true,
36
+ title: `{{t("URL", { ns: "${NAMESPACE}" })}}`,
37
+ 'x-decorator': 'FormItem',
38
+ 'x-decorator-props': {},
39
+ 'x-component': 'Input',
40
+ 'x-component-props': {
41
+ placeholder: 'https://www.nocobase.com',
42
+ className: 'full-width',
43
+ },
44
+ },
45
+ headers: {
46
+ type: 'array',
47
+ 'x-component': 'ArrayItems',
48
+ 'x-decorator': 'FormItem',
49
+ title: `{{t("Headers", { ns: "${NAMESPACE}" })}}`,
50
+ description: `{{t('"Content-Type" only support "application/json", and no need to specify', { ns: "${NAMESPACE}" })}}`,
51
+ items: {
52
+ type: 'object',
53
+ properties: {
54
+ space: {
55
+ type: 'void',
56
+ 'x-component': 'Space',
57
+ properties: {
58
+ name: {
59
+ type: 'string',
60
+ 'x-decorator': 'FormItem',
61
+ 'x-component': 'Input',
62
+ 'x-component-props': {
63
+ placeholder: `{{t("Name")}}`,
64
+ },
65
+ },
66
+ value: {
67
+ type: 'string',
68
+ 'x-decorator': 'FormItem',
69
+ 'x-component': 'Variable.Input',
70
+ 'x-component-props': {
71
+ scope: '{{useWorkflowVariableOptions()}}',
72
+ useTypedConstant: true,
73
+ },
74
+ },
75
+ remove: {
76
+ type: 'void',
77
+ 'x-decorator': 'FormItem',
78
+ 'x-component': 'ArrayItems.Remove',
79
+ },
80
+ },
81
+ },
82
+ },
83
+ },
84
+ properties: {
85
+ add: {
86
+ type: 'void',
87
+ title: `{{t("Add request header", { ns: "${NAMESPACE}" })}}`,
88
+ 'x-component': 'ArrayItems.Addition',
89
+ },
90
+ },
91
+ },
92
+ params: {
93
+ type: 'array',
94
+ 'x-component': 'ArrayItems',
95
+ 'x-decorator': 'FormItem',
96
+ title: `{{t("Parameters", { ns: "${NAMESPACE}" })}}`,
97
+ items: {
98
+ type: 'object',
99
+ properties: {
100
+ space: {
101
+ type: 'void',
102
+ 'x-component': 'Space',
103
+ properties: {
104
+ name: {
105
+ type: 'string',
106
+ 'x-decorator': 'FormItem',
107
+ 'x-component': 'Input',
108
+ 'x-component-props': {
109
+ placeholder: `{{t("Name")}}`,
110
+ },
111
+ },
112
+ value: {
113
+ type: 'string',
114
+ 'x-decorator': 'FormItem',
115
+ 'x-component': 'Variable.Input',
116
+ 'x-component-props': {
117
+ scope: '{{useWorkflowVariableOptions()}}',
118
+ useTypedConstant: true,
119
+ },
120
+ },
121
+ remove: {
122
+ type: 'void',
123
+ 'x-decorator': 'FormItem',
124
+ 'x-component': 'ArrayItems.Remove',
125
+ },
126
+ },
127
+ },
128
+ },
129
+ },
130
+ properties: {
131
+ add: {
132
+ type: 'void',
133
+ title: `{{t("Add parameter", { ns: "${NAMESPACE}" })}}`,
134
+ 'x-component': 'ArrayItems.Addition',
135
+ },
136
+ },
137
+ },
138
+ data: {
139
+ type: 'string',
140
+ title: `{{t("Body", { ns: "${NAMESPACE}" })}}`,
141
+ 'x-decorator': 'FormItem',
142
+ 'x-decorator-props': {},
143
+ 'x-component': 'RequestBody',
144
+ 'x-component-props': {
145
+ changeOnSelect: true,
146
+ autoSize: {
147
+ minRows: 10,
148
+ },
149
+ placeholder: `{{t("Input request data", { ns: "${NAMESPACE}" })}}`,
150
+ className: 'full-width',
151
+ },
152
+ description: `{{t("Only support standard JSON data", { ns: "${NAMESPACE}" })}}`,
153
+ },
154
+ timeout: {
155
+ type: 'number',
156
+ title: `{{t("Timeout config", { ns: "${NAMESPACE}" })}}`,
157
+ 'x-decorator': 'FormItem',
158
+ 'x-decorator-props': {},
159
+ 'x-component': 'InputNumber',
160
+ 'x-component-props': {
161
+ addonAfter: `{{t("ms", { ns: "${NAMESPACE}" })}}`,
162
+ min: 1,
163
+ step: 1000,
164
+ defaultValue: 5000,
165
+ },
166
+ },
167
+ ignoreFail: {
168
+ type: 'boolean',
169
+ title: `{{t("Ignore fail request and continue workflow", { ns: "${NAMESPACE}" })}}`,
170
+ 'x-decorator': 'FormItem',
171
+ 'x-component': 'Checkbox',
172
+ },
173
+ },
174
+ view: {},
175
+ scope: {
176
+ useWorkflowVariableOptions,
177
+ },
178
+ components: {
179
+ ArrayItems,
180
+ RequestBody(props) {
181
+ const scope = useWorkflowVariableOptions();
182
+ return <Variable.JSON scope={scope} {...props} />;
183
+ },
184
+ },
185
+ };
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+
3
+ import { Variable, css } from '@nocobase/client';
4
+
5
+ import { NAMESPACE } from '../locale';
6
+ import { useWorkflowVariableOptions } from '../variable';
7
+
8
+ export default {
9
+ title: `{{t("SQL action", { ns: "${NAMESPACE}" })}}`,
10
+ type: 'sql',
11
+ group: 'extended',
12
+ description: `{{t("Execute a SQL statement in database.", { ns: "${NAMESPACE}" })}}`,
13
+ fieldset: {
14
+ sql: {
15
+ type: 'string',
16
+ required: true,
17
+ title: 'SQL',
18
+ description: `{{t("Usage of SQL query result is not supported yet.", { ns: "${NAMESPACE}" })}}`,
19
+ 'x-decorator': 'FormItem',
20
+ 'x-component': 'SQLInput',
21
+ 'x-component-props': {
22
+ rows: 20,
23
+ className: css`
24
+ font-size: 80%;
25
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
26
+ `,
27
+ },
28
+ },
29
+ },
30
+ scope: {},
31
+ components: {
32
+ SQLInput(props) {
33
+ const scope = useWorkflowVariableOptions();
34
+ return <Variable.RawTextArea scope={scope} {...props} />;
35
+ },
36
+ },
37
+ };