@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,92 @@
1
+ import React from 'react';
2
+ import { useFieldSchema } from '@formily/react';
3
+
4
+ import { GeneralSchemaDesigner, SchemaSettings, useCollection, useCollectionManager } from '@nocobase/client';
5
+
6
+ import { NAMESPACE } from '../../../locale';
7
+ import { findSchema } from '../utils';
8
+ import { ManualFormType } from '../SchemaConfig';
9
+ import { FormBlockInitializer } from '../FormBlockInitializer';
10
+
11
+ function CreateFormDesigner() {
12
+ const { name, title } = useCollection();
13
+
14
+ return (
15
+ <GeneralSchemaDesigner title={title || name}>
16
+ <SchemaSettings.BlockTitleItem />
17
+ <SchemaSettings.LinkageRules collectionName={name} />
18
+ <SchemaSettings.DataTemplates collectionName={name} />
19
+ <SchemaSettings.Divider />
20
+ <SchemaSettings.Remove
21
+ removeParentsIfNoChildren
22
+ breakRemoveOn={{
23
+ 'x-component': 'Grid',
24
+ }}
25
+ />
26
+ </GeneralSchemaDesigner>
27
+ );
28
+ }
29
+
30
+ export default {
31
+ title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
32
+ config: {
33
+ useInitializer() {
34
+ const { collections } = useCollectionManager();
35
+ return {
36
+ key: 'createRecordForm',
37
+ type: 'subMenu',
38
+ title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
39
+ children: collections
40
+ .filter((item) => !item.hidden)
41
+ .map((item) => ({
42
+ key: `createForm-${item.name}`,
43
+ type: 'item',
44
+ title: item.title,
45
+ schema: {
46
+ collection: item.name,
47
+ title: `{{t("Create record", { ns: "${NAMESPACE}" })}}`,
48
+ formType: 'create',
49
+ 'x-designer': 'CreateFormDesigner',
50
+ },
51
+ component: FormBlockInitializer,
52
+ })),
53
+ };
54
+ },
55
+ initializers: {
56
+ // AddCustomFormField
57
+ },
58
+ components: {
59
+ CreateFormDesigner,
60
+ },
61
+ parseFormOptions(root) {
62
+ const forms = {};
63
+ const formBlocks: any[] = findSchema(
64
+ root,
65
+ (item) => item['x-decorator'] === 'FormBlockProvider' && item['x-decorator-props'].formType === 'create',
66
+ );
67
+ formBlocks.forEach((formBlock) => {
68
+ const [formKey] = Object.keys(formBlock.properties);
69
+ const formSchema = formBlock.properties[formKey];
70
+ forms[formKey] = {
71
+ type: 'create',
72
+ title: formBlock['x-component-props']?.title || formKey,
73
+ actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
74
+ (item) => ({
75
+ status: item['x-decorator-props'].value,
76
+ values: item['x-action-settings']?.assignedValues?.values,
77
+ key: item.name,
78
+ }),
79
+ ),
80
+ collection: formBlock['x-decorator-props'].collection,
81
+ };
82
+ });
83
+ return forms;
84
+ },
85
+ },
86
+ block: {
87
+ scope: {
88
+ // useFormBlockProps
89
+ },
90
+ components: {},
91
+ },
92
+ } as ManualFormType;
@@ -0,0 +1,392 @@
1
+ import React, { useContext, useMemo, useState } from 'react';
2
+
3
+ import { ArrayTable } from '@formily/antd-v5';
4
+ import { Field, createForm } from '@formily/core';
5
+ import { useField, useFieldSchema, useForm } from '@formily/react';
6
+
7
+ import {
8
+ ActionContextProvider,
9
+ CollectionContext,
10
+ CollectionProvider,
11
+ FormBlockContext,
12
+ RecordProvider,
13
+ SchemaComponent,
14
+ SchemaInitializer,
15
+ SchemaInitializerItemOptions,
16
+ gridRowColWrap,
17
+ useCollectionManager,
18
+ useRecord,
19
+ } from '@nocobase/client';
20
+ import { lodash, merge, uid } from '@nocobase/utils/client';
21
+ import { JOB_STATUS } from '../../../constants';
22
+ import { NAMESPACE, lang } from '../../../locale';
23
+ import { ManualFormType } from '../SchemaConfig';
24
+ import { findSchema } from '../utils';
25
+
26
+ function CustomFormBlockProvider(props) {
27
+ const [fields, setCollectionFields] = useState(props.collection?.fields ?? []);
28
+ const userJob = useRecord();
29
+ const field = useField();
30
+ const fieldSchema = useFieldSchema();
31
+ const [formKey] = Object.keys(fieldSchema.toJSON().properties ?? {});
32
+ const values = userJob?.result?.[formKey];
33
+
34
+ const form = useMemo(
35
+ () =>
36
+ createForm({
37
+ initialValues: values,
38
+ }),
39
+ [values],
40
+ );
41
+
42
+ return (
43
+ <CollectionProvider
44
+ collection={{
45
+ ...props.collection,
46
+ fields,
47
+ }}
48
+ >
49
+ <RecordProvider record={values} parent={false}>
50
+ <FormBlockContext.Provider
51
+ value={{
52
+ form,
53
+ field,
54
+ setCollectionFields,
55
+ }}
56
+ >
57
+ {props.children}
58
+ </FormBlockContext.Provider>
59
+ </RecordProvider>
60
+ </CollectionProvider>
61
+ );
62
+ }
63
+
64
+ function CustomFormBlockInitializer({ insert, ...props }) {
65
+ return (
66
+ <SchemaInitializer.Item
67
+ {...props}
68
+ onClick={() => {
69
+ insert({
70
+ type: 'void',
71
+ 'x-decorator': 'CustomFormBlockProvider',
72
+ 'x-decorator-props': {
73
+ collection: {
74
+ name: uid(),
75
+ fields: [],
76
+ },
77
+ },
78
+ 'x-component': 'CardItem',
79
+ 'x-component-props': {
80
+ title: '{{t("Form")}}',
81
+ },
82
+ 'x-designer': 'SimpleDesigner',
83
+ 'x-designer-props': {
84
+ type: 'customForm',
85
+ },
86
+ properties: {
87
+ [uid()]: {
88
+ type: 'void',
89
+ 'x-component': 'FormV2',
90
+ 'x-component-props': {
91
+ // disabled / read-pretty / initialValues
92
+ useProps: '{{ useFormBlockProps }}',
93
+ },
94
+ properties: {
95
+ grid: {
96
+ type: 'void',
97
+ 'x-component': 'Grid',
98
+ 'x-initializer': 'AddCustomFormField',
99
+ },
100
+ actions: {
101
+ type: 'void',
102
+ 'x-decorator': 'ActionBarProvider',
103
+ 'x-component': 'ActionBar',
104
+ 'x-component-props': {
105
+ layout: 'one-column',
106
+ style: {
107
+ marginTop: '1.5em',
108
+ flexWrap: 'wrap',
109
+ },
110
+ },
111
+ 'x-initializer': 'AddActionButton',
112
+ properties: {
113
+ resolve: {
114
+ type: 'void',
115
+ title: `{{t("Continue the process", { ns: "${NAMESPACE}" })}}`,
116
+ 'x-decorator': 'ManualActionStatusProvider',
117
+ 'x-decorator-props': {
118
+ value: JOB_STATUS.RESOLVED,
119
+ },
120
+ 'x-component': 'Action',
121
+ 'x-component-props': {
122
+ type: 'primary',
123
+ useAction: '{{ useSubmit }}',
124
+ },
125
+ 'x-designer': 'ManualActionDesigner',
126
+ },
127
+ },
128
+ },
129
+ },
130
+ },
131
+ },
132
+ });
133
+ }}
134
+ />
135
+ );
136
+ }
137
+
138
+ const GroupLabels = {
139
+ basic: '{{t("Basic")}}',
140
+ choices: '{{t("Choices")}}',
141
+ media: '{{t("Media")}}',
142
+ datetime: '{{t("Date & Time")}}',
143
+ relation: '{{t("Relation")}}',
144
+ advanced: '{{t("Advanced type")}}',
145
+ systemInfo: '{{t("System info")}}',
146
+ others: '{{t("Others")}}',
147
+ };
148
+
149
+ function getOptions(interfaces) {
150
+ const fields = {};
151
+
152
+ Object.keys(interfaces).forEach((type) => {
153
+ const schema = interfaces[type];
154
+ const { group = 'others' } = schema;
155
+ fields[group] = fields[group] || {};
156
+ lodash.set(fields, [group, type], schema);
157
+ });
158
+
159
+ return Object.keys(GroupLabels)
160
+ .filter((groupName) => ['basic', 'choices', 'datetime', 'media'].includes(groupName))
161
+ .map((groupName) => ({
162
+ title: GroupLabels[groupName],
163
+ children: Object.keys(fields[groupName] || {})
164
+ .map((type) => {
165
+ const field = fields[groupName][type];
166
+ return {
167
+ value: type,
168
+ title: field.title,
169
+ name: type,
170
+ ...fields[groupName][type],
171
+ };
172
+ })
173
+ .sort((a, b) => a.order - b.order),
174
+ }));
175
+ }
176
+
177
+ function useCommonInterfaceInitializers(): SchemaInitializerItemOptions[] {
178
+ const { interfaces } = useCollectionManager();
179
+ const options = getOptions(interfaces);
180
+
181
+ return options.map((group) => ({
182
+ key: group.title,
183
+ type: 'itemGroup',
184
+ title: group.title,
185
+ children: group.children.map((item) => ({
186
+ key: item.name,
187
+ type: 'item',
188
+ title: item.title,
189
+ component: CustomFormFieldInitializer,
190
+ fieldInterface: item.name,
191
+ })),
192
+ }));
193
+ }
194
+
195
+ const AddCustomFormFieldButtonContext = React.createContext<any>({});
196
+
197
+ function AddCustomFormField(props) {
198
+ const { insertPosition = 'beforeEnd', component } = props;
199
+ const items = useCommonInterfaceInitializers();
200
+ const collection = useContext(CollectionContext);
201
+ const [interfaceOptions, setInterface] = useState<any>(null);
202
+ const [insert, setCallback] = useState<any>();
203
+ const { setCollectionFields } = useContext(FormBlockContext);
204
+
205
+ return (
206
+ <AddCustomFormFieldButtonContext.Provider
207
+ value={{
208
+ onAddField(item) {
209
+ const {
210
+ properties: { unique, type, ...properties },
211
+ ...options
212
+ } = lodash.cloneDeep(item);
213
+ delete properties.name['x-disabled'];
214
+ setInterface({
215
+ ...options,
216
+ properties,
217
+ });
218
+ },
219
+ setCallback,
220
+ }}
221
+ >
222
+ <SchemaInitializer.Button
223
+ wrap={gridRowColWrap}
224
+ insertPosition={insertPosition}
225
+ items={items}
226
+ component={component}
227
+ title="{{t('Configure fields')}}"
228
+ />
229
+ <ActionContextProvider value={{ visible: Boolean(interfaceOptions) }}>
230
+ {interfaceOptions ? (
231
+ <SchemaComponent
232
+ schema={{
233
+ type: 'void',
234
+ name: 'drawer',
235
+ title: '{{t("Configure field")}}',
236
+ 'x-decorator': 'Form',
237
+ 'x-component': 'Action.Drawer',
238
+ properties: {
239
+ ...interfaceOptions.properties,
240
+ footer: {
241
+ type: 'void',
242
+ 'x-component': 'Action.Drawer.Footer',
243
+ properties: {
244
+ cancel: {
245
+ type: 'void',
246
+ title: '{{t("Cancel")}}',
247
+ 'x-component': 'Action',
248
+ 'x-component-props': {
249
+ useAction() {
250
+ const form = useForm();
251
+ return {
252
+ async run() {
253
+ setCallback(null);
254
+ setInterface(null);
255
+ form.reset();
256
+ },
257
+ };
258
+ },
259
+ },
260
+ },
261
+ submit: {
262
+ type: 'void',
263
+ title: '{{t("Submit")}}',
264
+ 'x-component': 'Action',
265
+ 'x-component-props': {
266
+ type: 'primary',
267
+ useAction() {
268
+ const { values, query } = useForm();
269
+ return {
270
+ async run() {
271
+ const { default: options } = interfaceOptions;
272
+ const defaultName = uid();
273
+ options.name = values.name ?? defaultName;
274
+ options.uiSchema.title = values.uiSchema?.title ?? defaultName;
275
+ options.interface = interfaceOptions.name;
276
+ const existed = collection.fields?.find((item) => item.name === options.name);
277
+ if (existed) {
278
+ const field = query('name').take() as Field;
279
+ field.setFeedback({
280
+ type: 'error',
281
+ // code: 'FormulaError',
282
+ messages: [lang('Field name existed in form')],
283
+ });
284
+ return;
285
+ }
286
+ const newField = merge(options, values) as any;
287
+ setCollectionFields([...collection.fields, newField]);
288
+
289
+ insert({
290
+ name: options.name,
291
+ type: options.uiSchema.type,
292
+ 'x-decorator': 'FormItem',
293
+ 'x-component': 'CollectionField',
294
+ 'x-component-props': {
295
+ field: newField,
296
+ },
297
+ 'x-collection-field': `${collection.name}.${options.name}`,
298
+ 'x-designer': 'FormItem.Designer',
299
+ });
300
+ setCallback(null);
301
+ setInterface(null);
302
+ },
303
+ };
304
+ },
305
+ },
306
+ },
307
+ },
308
+ },
309
+ },
310
+ }}
311
+ components={{
312
+ ArrayTable,
313
+ }}
314
+ />
315
+ ) : null}
316
+ </ActionContextProvider>
317
+ </AddCustomFormFieldButtonContext.Provider>
318
+ );
319
+ }
320
+
321
+ function CustomFormFieldInitializer(props) {
322
+ const { item, insert } = props;
323
+ const { onAddField, setCallback } = useContext(AddCustomFormFieldButtonContext);
324
+ const { getInterface } = useCollectionManager();
325
+
326
+ const interfaceOptions = getInterface(item.fieldInterface);
327
+
328
+ return (
329
+ <SchemaInitializer.Item
330
+ key={item.fieldInterface}
331
+ onClick={() => {
332
+ setCallback(() => insert);
333
+ onAddField(interfaceOptions);
334
+ }}
335
+ />
336
+ );
337
+ }
338
+
339
+ export default {
340
+ title: `{{t("Custom form", { ns: "${NAMESPACE}" })}}`,
341
+ config: {
342
+ useInitializer() {
343
+ return {
344
+ key: 'customForm',
345
+ type: 'item',
346
+ title: `{{t("Custom form", { ns: "${NAMESPACE}" })}}`,
347
+ component: CustomFormBlockInitializer,
348
+ };
349
+ },
350
+ initializers: {
351
+ AddCustomFormField,
352
+ },
353
+ components: {
354
+ CustomFormBlockProvider,
355
+ },
356
+ parseFormOptions(root) {
357
+ const forms = {};
358
+ const formBlocks: any[] = findSchema(root, (item) => item['x-decorator'] === 'CustomFormBlockProvider');
359
+ formBlocks.forEach((formBlock) => {
360
+ const [formKey] = Object.keys(formBlock.properties);
361
+ const formSchema = formBlock.properties[formKey];
362
+ const fields = findSchema(
363
+ formSchema.properties.grid,
364
+ (item) => item['x-component'] === 'CollectionField',
365
+ true,
366
+ );
367
+ formBlock['x-decorator-props'].collection.fields = fields.map(
368
+ (field) => field['x-component-props']?.field ?? field['x-interface-options'],
369
+ );
370
+ forms[formKey] = {
371
+ type: 'custom',
372
+ title: formBlock['x-component-props']?.title || formKey,
373
+ actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
374
+ (item) => ({
375
+ status: item['x-decorator-props'].value,
376
+ values: item['x-action-settings']?.assignedValues?.values,
377
+ key: item.name,
378
+ }),
379
+ ),
380
+ collection: formBlock['x-decorator-props'].collection,
381
+ };
382
+ });
383
+ return forms;
384
+ },
385
+ },
386
+ block: {
387
+ scope: {},
388
+ components: {
389
+ CustomFormBlockProvider,
390
+ },
391
+ },
392
+ } as ManualFormType;
@@ -0,0 +1,134 @@
1
+ import React from 'react';
2
+ import { useFieldSchema } from '@formily/react';
3
+ import { useTranslation } from 'react-i18next';
4
+
5
+ import {
6
+ GeneralSchemaDesigner,
7
+ SchemaSettings,
8
+ useCollection,
9
+ useCollectionFilterOptions,
10
+ useCollectionManager,
11
+ useDesignable,
12
+ } from '@nocobase/client';
13
+
14
+ import { NAMESPACE } from '../../../locale';
15
+ import { findSchema } from '../utils';
16
+ import { ManualFormType } from '../SchemaConfig';
17
+ import { FilterDynamicComponent } from '../../../components/FilterDynamicComponent';
18
+ import { FormBlockInitializer } from '../FormBlockInitializer';
19
+
20
+ function UpdateFormDesigner() {
21
+ const { name, title } = useCollection();
22
+ const fieldSchema = useFieldSchema();
23
+ const { t } = useTranslation();
24
+ const { dn } = useDesignable();
25
+
26
+ return (
27
+ <GeneralSchemaDesigner title={title || name}>
28
+ <SchemaSettings.BlockTitleItem />
29
+ <SchemaSettings.ActionModalItem
30
+ title={t('Filter settings', { ns: NAMESPACE })}
31
+ schema={{
32
+ name: 'filter',
33
+ type: 'object',
34
+ title: `{{t("Filter")}}`,
35
+ // 'x-decorator': 'FormItem',
36
+ 'x-component': 'Filter',
37
+ 'x-component-props': {
38
+ useProps() {
39
+ const options = useCollectionFilterOptions(fieldSchema?.['x-decorator-props']?.collection);
40
+ return {
41
+ options,
42
+ };
43
+ },
44
+ dynamicComponent: 'FilterDynamicComponent',
45
+ },
46
+ }}
47
+ initialValues={fieldSchema?.['x-decorator-props']}
48
+ onSubmit={({ filter }) => {
49
+ fieldSchema['x-decorator-props'].filter = filter;
50
+ dn.emit('patch', {
51
+ schema: {
52
+ // ['x-uid']: fieldSchema['x-uid'],
53
+ 'x-decorator-props': fieldSchema['x-decorator-props'],
54
+ },
55
+ });
56
+ dn.refresh();
57
+ }}
58
+ />
59
+ <SchemaSettings.LinkageRules collectionName={name} />
60
+ <SchemaSettings.Divider />
61
+ <SchemaSettings.Remove
62
+ removeParentsIfNoChildren
63
+ breakRemoveOn={{
64
+ 'x-component': 'Grid',
65
+ }}
66
+ />
67
+ </GeneralSchemaDesigner>
68
+ );
69
+ }
70
+
71
+ export default {
72
+ title: `{{t("Update record form", { ns: "${NAMESPACE}" })}}`,
73
+ config: {
74
+ useInitializer() {
75
+ const { collections } = useCollectionManager();
76
+ return {
77
+ key: 'updateRecordForm',
78
+ type: 'subMenu',
79
+ title: `{{t("Update record form", { ns: "${NAMESPACE}" })}}`,
80
+ children: collections
81
+ .filter((item) => !item.hidden)
82
+ .map((item) => ({
83
+ key: `updateForm-${item.name}`,
84
+ type: 'item',
85
+ title: item.title,
86
+ schema: {
87
+ collection: item.name,
88
+ title: `{{t("Update record", { ns: "${NAMESPACE}" })}}`,
89
+ formType: 'update',
90
+ 'x-designer': 'UpdateFormDesigner',
91
+ },
92
+ component: FormBlockInitializer,
93
+ })),
94
+ };
95
+ },
96
+ initializers: {
97
+ // AddCustomFormField
98
+ },
99
+ components: {
100
+ FilterDynamicComponent,
101
+ UpdateFormDesigner,
102
+ },
103
+ parseFormOptions(root) {
104
+ const forms = {};
105
+ const formBlocks: any[] = findSchema(
106
+ root,
107
+ (item) => item['x-decorator'] === 'FormBlockProvider' && item['x-decorator-props'].formType === 'update',
108
+ );
109
+ formBlocks.forEach((formBlock) => {
110
+ const [formKey] = Object.keys(formBlock.properties);
111
+ const formSchema = formBlock.properties[formKey];
112
+ forms[formKey] = {
113
+ ...formBlock['x-decorator-props'],
114
+ type: 'update',
115
+ title: formBlock['x-component-props']?.title || formKey,
116
+ actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
117
+ (item) => ({
118
+ status: item['x-decorator-props'].value,
119
+ values: item['x-action-settings']?.assignedValues?.values,
120
+ key: item.name,
121
+ }),
122
+ ),
123
+ };
124
+ });
125
+ return forms;
126
+ },
127
+ },
128
+ block: {
129
+ scope: {
130
+ // useFormBlockProps
131
+ },
132
+ components: {},
133
+ },
134
+ } as ManualFormType;