@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,611 @@
1
+ import { css } from '@emotion/css';
2
+ import { observer, useField, useFieldSchema, useForm } from '@formily/react';
3
+ import { dayjs } from '@nocobase/utils/client';
4
+ import { Spin, Tag } from 'antd';
5
+ import React, { createContext, useContext, useEffect, useState } from 'react';
6
+
7
+ import {
8
+ CollectionManagerProvider,
9
+ FormBlockContext,
10
+ SchemaComponent,
11
+ SchemaComponentContext,
12
+ TableBlockProvider,
13
+ useAPIClient,
14
+ useActionContext,
15
+ useCollectionManager,
16
+ useCurrentUserContext,
17
+ useFormBlockContext,
18
+ useRecord,
19
+ useTableBlockContext,
20
+ } from '@nocobase/client';
21
+ import { uid } from '@nocobase/utils/client';
22
+ import { instructions, useAvailableUpstreams } from '..';
23
+ import { FlowContext, useFlowContext } from '../../FlowContext';
24
+ import { JobStatusOptions, JobStatusOptionsMap } from '../../constants';
25
+ import { NAMESPACE } from '../../locale';
26
+ import { linkNodes } from '../../utils';
27
+ import { DetailsBlockProvider } from './DetailsBlockProvider';
28
+ import { FormBlockProvider } from './FormBlockProvider';
29
+ import { manualFormTypes } from './SchemaConfig';
30
+
31
+ const nodeCollection = {
32
+ title: `{{t("Task", { ns: "${NAMESPACE}" })}}`,
33
+ name: 'flow_nodes',
34
+ fields: [
35
+ {
36
+ type: 'bigInt',
37
+ name: 'id',
38
+ interface: 'm2o',
39
+ uiSchema: {
40
+ type: 'number',
41
+ title: 'ID',
42
+ 'x-component': 'RemoteSelect',
43
+ 'x-component-props': {
44
+ fieldNames: {
45
+ label: 'title',
46
+ value: 'id',
47
+ },
48
+ service: {
49
+ resource: 'flow_nodes',
50
+ params: {
51
+ filter: {
52
+ type: 'manual',
53
+ },
54
+ },
55
+ },
56
+ },
57
+ },
58
+ },
59
+ {
60
+ type: 'string',
61
+ name: 'title',
62
+ interface: 'input',
63
+ uiSchema: {
64
+ type: 'string',
65
+ title: '{{t("Title")}}',
66
+ 'x-component': 'Input',
67
+ },
68
+ },
69
+ ],
70
+ };
71
+
72
+ const workflowCollection = {
73
+ title: `{{t("Workflow", { ns: "${NAMESPACE}" })}}`,
74
+ name: 'workflows',
75
+ fields: [
76
+ {
77
+ type: 'string',
78
+ name: 'title',
79
+ interface: 'input',
80
+ uiSchema: {
81
+ title: '{{t("Name")}}',
82
+ type: 'string',
83
+ 'x-component': 'Input',
84
+ required: true,
85
+ },
86
+ },
87
+ ],
88
+ };
89
+
90
+ const todoCollection = {
91
+ title: `{{t("Workflow todos", { ns: "${NAMESPACE}" })}}`,
92
+ name: 'users_jobs',
93
+ fields: [
94
+ {
95
+ type: 'belongsTo',
96
+ name: 'user',
97
+ target: 'users',
98
+ foreignKey: 'userId',
99
+ interface: 'm2o',
100
+ uiSchema: {
101
+ type: 'number',
102
+ title: '{{t("User")}}',
103
+ 'x-component': 'RemoteSelect',
104
+ 'x-component-props': {
105
+ fieldNames: {
106
+ label: 'nickname',
107
+ value: 'id',
108
+ },
109
+ service: {
110
+ resource: 'users',
111
+ },
112
+ },
113
+ },
114
+ },
115
+ {
116
+ type: 'belongsTo',
117
+ name: 'node',
118
+ target: 'flow_nodes',
119
+ foreignKey: 'nodeId',
120
+ interface: 'm2o',
121
+ isAssociation: true,
122
+ uiSchema: {
123
+ type: 'number',
124
+ title: `{{t("Task", { ns: "${NAMESPACE}" })}}`,
125
+ 'x-component': 'RemoteSelect',
126
+ 'x-component-props': {
127
+ fieldNames: {
128
+ label: 'title',
129
+ value: 'id',
130
+ },
131
+ service: {
132
+ resource: 'flow_nodes',
133
+ },
134
+ },
135
+ },
136
+ },
137
+ {
138
+ type: 'belongsTo',
139
+ name: 'workflow',
140
+ target: 'workflows',
141
+ foreignKey: 'workflowId',
142
+ interface: 'm2o',
143
+ uiSchema: {
144
+ type: 'number',
145
+ title: `{{t("Workflow", { ns: "${NAMESPACE}" })}}`,
146
+ 'x-component': 'RemoteSelect',
147
+ 'x-component-props': {
148
+ fieldNames: {
149
+ label: 'title',
150
+ value: 'id',
151
+ },
152
+ service: {
153
+ resource: 'workflows',
154
+ },
155
+ },
156
+ },
157
+ },
158
+ {
159
+ type: 'integer',
160
+ name: 'status',
161
+ interface: 'select',
162
+ uiSchema: {
163
+ type: 'number',
164
+ title: `{{t("Status", { ns: "${NAMESPACE}" })}}`,
165
+ 'x-component': 'Select',
166
+ enum: JobStatusOptions,
167
+ },
168
+ },
169
+ {
170
+ name: 'createdAt',
171
+ type: 'date',
172
+ interface: 'createdAt',
173
+ uiSchema: {
174
+ type: 'datetime',
175
+ title: '{{t("Created at")}}',
176
+ 'x-component': 'DatePicker',
177
+ 'x-component-props': {
178
+ showTime: true,
179
+ },
180
+ 'x-read-pretty': true,
181
+ },
182
+ },
183
+ ],
184
+ };
185
+
186
+ const NodeColumn = observer(
187
+ () => {
188
+ const field = useField<any>();
189
+ return field?.value?.title ?? `#${field.value?.id}`;
190
+ },
191
+ { displayName: 'NodeColumn' },
192
+ );
193
+
194
+ const WorkflowColumn = observer(
195
+ () => {
196
+ const field = useField<any>();
197
+ return field?.value?.title ?? `#${field.value?.id}`;
198
+ },
199
+ { displayName: 'WorkflowColumn' },
200
+ );
201
+
202
+ const UserColumn = observer(
203
+ () => {
204
+ const field = useField<any>();
205
+ return field?.value?.nickname ?? field.value?.id;
206
+ },
207
+ { displayName: 'UserColumn' },
208
+ );
209
+
210
+ export const WorkflowTodo: React.FC & { Drawer: React.FC; Decorator: React.FC } = () => {
211
+ return (
212
+ <SchemaComponent
213
+ components={{
214
+ NodeColumn,
215
+ WorkflowColumn,
216
+ UserColumn,
217
+ }}
218
+ schema={{
219
+ type: 'void',
220
+ name: uid(),
221
+ 'x-component': 'div',
222
+ properties: {
223
+ actions: {
224
+ type: 'void',
225
+ 'x-component': 'ActionBar',
226
+ 'x-component-props': {
227
+ style: {
228
+ marginBottom: 16,
229
+ },
230
+ },
231
+ properties: {
232
+ filter: {
233
+ type: 'void',
234
+ title: '{{ t("Filter") }}',
235
+ 'x-action': 'filter',
236
+ 'x-designer': 'Filter.Action.Designer',
237
+ 'x-component': 'Filter.Action',
238
+ 'x-component-props': {
239
+ icon: 'FilterOutlined',
240
+ useProps: '{{ useFilterActionProps }}',
241
+ },
242
+ 'x-align': 'left',
243
+ },
244
+ refresher: {
245
+ type: 'void',
246
+ title: '{{ t("Refresh") }}',
247
+ 'x-action': 'refresh',
248
+ 'x-component': 'Action',
249
+ 'x-designer': 'Action.Designer',
250
+ 'x-component-props': {
251
+ icon: 'ReloadOutlined',
252
+ useProps: '{{ useRefreshActionProps }}',
253
+ },
254
+ 'x-align': 'right',
255
+ },
256
+ },
257
+ },
258
+ table: {
259
+ type: 'array',
260
+ 'x-component': 'TableV2',
261
+ 'x-component-props': {
262
+ rowKey: 'id',
263
+ useProps: '{{ useTableBlockProps }}',
264
+ },
265
+ properties: {
266
+ node: {
267
+ type: 'void',
268
+ 'x-decorator': 'TableV2.Column.Decorator',
269
+ 'x-component': 'TableV2.Column',
270
+ title: `{{t("Task", { ns: "${NAMESPACE}" })}}`,
271
+ properties: {
272
+ node: {
273
+ 'x-component': 'NodeColumn',
274
+ 'x-read-pretty': true,
275
+ },
276
+ },
277
+ },
278
+ workflow: {
279
+ type: 'void',
280
+ 'x-decorator': 'TableV2.Column.Decorator',
281
+ 'x-component': 'TableV2.Column',
282
+ title: `{{t("Workflow", { ns: "${NAMESPACE}" })}}`,
283
+ properties: {
284
+ workflow: {
285
+ 'x-component': 'WorkflowColumn',
286
+ 'x-read-pretty': true,
287
+ },
288
+ },
289
+ },
290
+ createdAt: {
291
+ type: 'void',
292
+ 'x-decorator': 'TableV2.Column.Decorator',
293
+ 'x-component': 'TableV2.Column',
294
+ properties: {
295
+ createdAt: {
296
+ type: 'number',
297
+ 'x-component': 'CollectionField',
298
+ 'x-read-pretty': true,
299
+ },
300
+ },
301
+ },
302
+ user: {
303
+ type: 'void',
304
+ 'x-decorator': 'TableV2.Column.Decorator',
305
+ 'x-component': 'TableV2.Column',
306
+ title: `{{t("Assignee", { ns: "${NAMESPACE}" })}}`,
307
+ properties: {
308
+ user: {
309
+ 'x-component': 'UserColumn',
310
+ 'x-read-pretty': true,
311
+ },
312
+ },
313
+ },
314
+ status: {
315
+ type: 'void',
316
+ 'x-decorator': 'TableV2.Column.Decorator',
317
+ 'x-component': 'TableV2.Column',
318
+ properties: {
319
+ status: {
320
+ type: 'number',
321
+ 'x-component': 'CollectionField',
322
+ 'x-read-pretty': true,
323
+ },
324
+ },
325
+ },
326
+ actions: {
327
+ type: 'void',
328
+ 'x-decorator': 'TableV2.Column.Decorator',
329
+ 'x-component': 'TableV2.Column',
330
+ title: '{{t("Actions")}}',
331
+ properties: {
332
+ view: {
333
+ type: 'void',
334
+ 'x-component': 'Action.Link',
335
+ title: '{{t("View")}}',
336
+ properties: {
337
+ drawer: {
338
+ 'x-component': 'WorkflowTodo.Drawer',
339
+ },
340
+ },
341
+ },
342
+ },
343
+ },
344
+ },
345
+ },
346
+ },
347
+ }}
348
+ />
349
+ );
350
+ };
351
+
352
+ function ActionBarProvider(props) {
353
+ // * status is done:
354
+ // 1. form is this form: show action button, and emphasis used status button
355
+ // 2. form is not this form: hide action bar
356
+ // * status is not done:
357
+ // 1. current user: show action bar
358
+ // 2. not current user: disabled action bar
359
+
360
+ const { data: user } = useCurrentUserContext();
361
+ const { userJob } = useFlowContext();
362
+ const { status, result, userId } = userJob;
363
+ const buttonSchema = useFieldSchema();
364
+ const { name } = buttonSchema.parent.toJSON();
365
+
366
+ let { children: content } = props;
367
+ if (status) {
368
+ if (!result[name]) {
369
+ content = null;
370
+ }
371
+ } else {
372
+ if (user?.data?.id !== userId) {
373
+ content = null;
374
+ }
375
+ }
376
+
377
+ return content;
378
+ }
379
+
380
+ const ManualActionStatusContext = createContext<number | null>(null);
381
+
382
+ function ManualActionStatusProvider({ value, children }) {
383
+ const { userJob } = useFlowContext();
384
+ const button = useField();
385
+
386
+ useEffect(() => {
387
+ if (userJob.status) {
388
+ button.disabled = true;
389
+ button.visible = userJob.status === value;
390
+ }
391
+ }, [userJob.status, value, button]);
392
+
393
+ return <ManualActionStatusContext.Provider value={value}>{children}</ManualActionStatusContext.Provider>;
394
+ }
395
+
396
+ function useSubmit() {
397
+ const api = useAPIClient();
398
+ const { setVisible } = useActionContext();
399
+ const { values, submit } = useForm();
400
+ const buttonSchema = useFieldSchema();
401
+ const nextStatus = useContext(ManualActionStatusContext);
402
+ const { service } = useTableBlockContext();
403
+ const { userJob } = useFlowContext();
404
+ const { updateAssociationValues } = useContext(FormBlockContext);
405
+ return {
406
+ async run() {
407
+ await submit();
408
+ const { name } = buttonSchema.parent.parent.toJSON();
409
+ await api.resource('users_jobs').submit({
410
+ filterByTk: userJob.id,
411
+ values: {
412
+ status: nextStatus,
413
+ result: { [name]: values },
414
+ },
415
+ updateAssociationValues,
416
+ });
417
+ setVisible(false);
418
+ service.refresh();
419
+ },
420
+ };
421
+ }
422
+
423
+ function FlowContextProvider(props) {
424
+ const api = useAPIClient();
425
+ const { id } = useRecord();
426
+ const [flowContext, setFlowContext] = useState<any>(null);
427
+ const [node, setNode] = useState<any>(null);
428
+
429
+ useEffect(() => {
430
+ if (!id) {
431
+ return;
432
+ }
433
+ api
434
+ .resource('users_jobs')
435
+ .get?.({
436
+ filterByTk: id,
437
+ appends: ['node', 'workflow', 'workflow.nodes', 'execution', 'execution.jobs'],
438
+ })
439
+ .then(({ data }) => {
440
+ const { node, workflow: { nodes = [], ...workflow } = {}, execution, ...userJob } = data?.data ?? {};
441
+ linkNodes(nodes);
442
+ setNode(node);
443
+ setFlowContext({
444
+ userJob,
445
+ workflow,
446
+ nodes,
447
+ execution,
448
+ });
449
+ return;
450
+ });
451
+ }, [id]);
452
+
453
+ const upstreams = useAvailableUpstreams(flowContext?.nodes.find((item) => item.id === node.id));
454
+ const nodeComponents = upstreams.reduce(
455
+ (components, { type }) => Object.assign(components, instructions.get(type).components),
456
+ {},
457
+ );
458
+
459
+ return node && flowContext ? (
460
+ <FlowContext.Provider value={flowContext}>
461
+ <SchemaComponent
462
+ components={{
463
+ FormBlockProvider,
464
+ DetailsBlockProvider,
465
+ ActionBarProvider,
466
+ ManualActionStatusProvider,
467
+ ...Array.from(manualFormTypes.getValues()).reduce(
468
+ (result, item) => Object.assign(result, item.block.components),
469
+ {},
470
+ ),
471
+ ...nodeComponents,
472
+ }}
473
+ scope={{
474
+ useSubmit,
475
+ useFormBlockProps,
476
+ useDetailsBlockProps,
477
+ ...Array.from(manualFormTypes.getValues()).reduce(
478
+ (result, item) => Object.assign(result, item.block.scope),
479
+ {},
480
+ ),
481
+ }}
482
+ schema={{
483
+ type: 'void',
484
+ name: 'tabs',
485
+ 'x-component': 'Tabs',
486
+ properties: node.config?.schema,
487
+ }}
488
+ />
489
+ </FlowContext.Provider>
490
+ ) : (
491
+ <Spin />
492
+ );
493
+ }
494
+
495
+ function useFormBlockProps() {
496
+ const { userJob } = useFlowContext();
497
+ const record = useRecord();
498
+ const { data: user } = useCurrentUserContext();
499
+ const { form } = useFormBlockContext();
500
+
501
+ const pattern = userJob.status
502
+ ? record
503
+ ? 'readPretty'
504
+ : 'disabled'
505
+ : user?.data?.id !== userJob.userId
506
+ ? 'disabled'
507
+ : 'editable';
508
+
509
+ useEffect(() => {
510
+ form?.setPattern(pattern);
511
+ }, [pattern, form]);
512
+
513
+ return { form };
514
+ }
515
+
516
+ function useDetailsBlockProps() {
517
+ const { form } = useFormBlockContext();
518
+ return { form };
519
+ }
520
+
521
+ function Drawer() {
522
+ const ctx = useContext(SchemaComponentContext);
523
+ const { id, node, workflow, status, updatedAt } = useRecord();
524
+
525
+ const statusOption = JobStatusOptionsMap[status];
526
+ const footerSchema = status
527
+ ? {
528
+ date: {
529
+ type: 'void',
530
+ 'x-component': 'time',
531
+ 'x-component-props': {
532
+ className: css`
533
+ margin-right: 0.5em;
534
+ `,
535
+ },
536
+ 'x-content': dayjs(updatedAt).format('YYYY-MM-DD HH:mm:ss'),
537
+ },
538
+ status: {
539
+ type: 'void',
540
+ 'x-component': 'Tag',
541
+ 'x-component-props': {
542
+ icon: statusOption.icon,
543
+ color: statusOption.color,
544
+ },
545
+ 'x-content': statusOption.label,
546
+ },
547
+ }
548
+ : null;
549
+
550
+ return (
551
+ <SchemaComponentContext.Provider value={{ ...ctx, reset() {}, designable: false }}>
552
+ <SchemaComponent
553
+ components={{
554
+ Tag,
555
+ FlowContextProvider,
556
+ }}
557
+ schema={{
558
+ type: 'void',
559
+ name: `drawer-${id}-${status}`,
560
+ 'x-component': 'Action.Drawer',
561
+ 'x-component-props': {
562
+ className: 'nb-action-popup',
563
+ },
564
+ title: `${workflow.title} - ${node.title ?? `#${node.id}`}`,
565
+ properties: {
566
+ tabs: {
567
+ type: 'void',
568
+ 'x-component': 'FlowContextProvider',
569
+ },
570
+ footer: {
571
+ type: 'void',
572
+ 'x-component': 'Action.Drawer.Footer',
573
+ properties: footerSchema,
574
+ },
575
+ },
576
+ }}
577
+ />
578
+ </SchemaComponentContext.Provider>
579
+ );
580
+ }
581
+
582
+ function Decorator({ params = {}, children }) {
583
+ const { collections, ...cm } = useCollectionManager();
584
+ const blockProps = {
585
+ collection: 'users_jobs',
586
+ resource: 'users_jobs',
587
+ action: 'list',
588
+ params: {
589
+ pageSize: 20,
590
+ sort: ['-createdAt'],
591
+ ...params,
592
+ appends: ['user', 'node', 'workflow'],
593
+ except: ['node.config', 'workflow.config'],
594
+ },
595
+ rowKey: 'id',
596
+ showIndex: true,
597
+ dragSort: false,
598
+ };
599
+
600
+ return (
601
+ <CollectionManagerProvider
602
+ {...cm}
603
+ collections={[...collections, nodeCollection, workflowCollection, todoCollection]}
604
+ >
605
+ <TableBlockProvider {...blockProps}>{children}</TableBlockProvider>
606
+ </CollectionManagerProvider>
607
+ );
608
+ }
609
+
610
+ WorkflowTodo.Drawer = Drawer;
611
+ WorkflowTodo.Decorator = Decorator;
@@ -0,0 +1,28 @@
1
+ import React, { FC } from 'react';
2
+ import { TableOutlined } from '@ant-design/icons';
3
+
4
+ import { SchemaInitializer, useCollectionManager } from '@nocobase/client';
5
+
6
+ export const WorkflowTodoBlockInitializer: FC<any> = ({ insert, ...rest }) => {
7
+ return (
8
+ <SchemaInitializer.Item
9
+ icon={<TableOutlined />}
10
+ {...rest}
11
+ onClick={() => {
12
+ insert({
13
+ type: 'void',
14
+ 'x-decorator': 'WorkflowTodo.Decorator',
15
+ 'x-decorator-props': {},
16
+ 'x-component': 'CardItem',
17
+ 'x-designer': 'TableBlockDesigner',
18
+ properties: {
19
+ todos: {
20
+ type: 'void',
21
+ 'x-component': 'WorkflowTodo',
22
+ },
23
+ },
24
+ });
25
+ }}
26
+ />
27
+ );
28
+ }