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