@nocobase/plugin-workflow-manual 0.17.0-alpha.4

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 (84) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +9 -0
  3. package/README.zh-CN.md +9 -0
  4. package/client.d.ts +2 -0
  5. package/client.js +1 -0
  6. package/dist/client/WorkflowTodo.d.ts +5 -0
  7. package/dist/client/WorkflowTodoBlockInitializer.d.ts +2 -0
  8. package/dist/client/index.d.ts +6 -0
  9. package/dist/client/index.js +13 -0
  10. package/dist/client/instruction/AssigneesSelect.d.ts +6 -0
  11. package/dist/client/instruction/DetailsBlockProvider.d.ts +2 -0
  12. package/dist/client/instruction/FormBlockInitializer.d.ts +2 -0
  13. package/dist/client/instruction/FormBlockProvider.d.ts +2 -0
  14. package/dist/client/instruction/ModeConfig.d.ts +5 -0
  15. package/dist/client/instruction/SchemaConfig.d.ts +49 -0
  16. package/dist/client/instruction/forms/create.d.ts +3 -0
  17. package/dist/client/instruction/forms/custom.d.ts +5 -0
  18. package/dist/client/instruction/forms/update.d.ts +3 -0
  19. package/dist/client/instruction/index.d.ts +83 -0
  20. package/dist/client/instruction/utils.d.ts +1 -0
  21. package/dist/externalVersion.js +18 -0
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.js +39 -0
  24. package/dist/locale/en-US.json +30 -0
  25. package/dist/locale/index.d.ts +3 -0
  26. package/dist/locale/index.js +39 -0
  27. package/dist/locale/zh-CN.json +30 -0
  28. package/dist/server/ManualInstruction.d.ts +28 -0
  29. package/dist/server/ManualInstruction.js +150 -0
  30. package/dist/server/Plugin.d.ts +6 -0
  31. package/dist/server/Plugin.js +73 -0
  32. package/dist/server/actions.d.ts +2 -0
  33. package/dist/server/actions.js +94 -0
  34. package/dist/server/collecions/jobs.d.ts +19 -0
  35. package/dist/server/collecions/jobs.js +39 -0
  36. package/dist/server/collecions/users.d.ts +15 -0
  37. package/dist/server/collecions/users.js +37 -0
  38. package/dist/server/collecions/users_jobs.d.ts +3 -0
  39. package/dist/server/collecions/users_jobs.js +70 -0
  40. package/dist/server/forms/create.d.ts +5 -0
  41. package/dist/server/forms/create.js +41 -0
  42. package/dist/server/forms/index.d.ts +6 -0
  43. package/dist/server/forms/index.js +38 -0
  44. package/dist/server/forms/update.d.ts +6 -0
  45. package/dist/server/forms/update.js +41 -0
  46. package/dist/server/index.d.ts +1 -0
  47. package/dist/server/index.js +33 -0
  48. package/package.json +33 -0
  49. package/server.d.ts +2 -0
  50. package/server.js +1 -0
  51. package/src/client/WorkflowTodo.tsx +618 -0
  52. package/src/client/WorkflowTodoBlockInitializer.tsx +30 -0
  53. package/src/client/index.ts +44 -0
  54. package/src/client/instruction/AssigneesSelect.tsx +39 -0
  55. package/src/client/instruction/DetailsBlockProvider.tsx +85 -0
  56. package/src/client/instruction/FormBlockInitializer.tsx +72 -0
  57. package/src/client/instruction/FormBlockProvider.tsx +84 -0
  58. package/src/client/instruction/ModeConfig.tsx +85 -0
  59. package/src/client/instruction/SchemaConfig.tsx +538 -0
  60. package/src/client/instruction/forms/create.tsx +112 -0
  61. package/src/client/instruction/forms/custom.tsx +403 -0
  62. package/src/client/instruction/forms/update.tsx +150 -0
  63. package/src/client/instruction/index.tsx +157 -0
  64. package/src/client/instruction/utils.ts +19 -0
  65. package/src/index.ts +2 -0
  66. package/src/locale/en-US.json +30 -0
  67. package/src/locale/index.ts +12 -0
  68. package/src/locale/zh-CN.json +30 -0
  69. package/src/server/ManualInstruction.ts +151 -0
  70. package/src/server/Plugin.ts +48 -0
  71. package/src/server/__tests__/collections/categories.ts +15 -0
  72. package/src/server/__tests__/collections/comments.ts +24 -0
  73. package/src/server/__tests__/collections/posts.ts +40 -0
  74. package/src/server/__tests__/collections/replies.ts +9 -0
  75. package/src/server/__tests__/collections/tags.ts +15 -0
  76. package/src/server/__tests__/instruction.test.ts +1154 -0
  77. package/src/server/actions.ts +100 -0
  78. package/src/server/collecions/jobs.ts +17 -0
  79. package/src/server/collecions/users.ts +15 -0
  80. package/src/server/collecions/users_jobs.ts +50 -0
  81. package/src/server/forms/create.ts +23 -0
  82. package/src/server/forms/index.ts +13 -0
  83. package/src/server/forms/update.ts +23 -0
  84. package/src/server/index.ts +1 -0
@@ -0,0 +1,538 @@
1
+ import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
2
+ import { FormLayout } from '@formily/antd-v5';
3
+ import { createForm } from '@formily/core';
4
+ import { FormProvider, ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
5
+ import { Alert, Button, Modal, Space } from 'antd';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ import {
9
+ Action,
10
+ ActionContextProvider,
11
+ DefaultValueProvider,
12
+ FormActiveFieldsProvider,
13
+ GeneralSchemaDesigner,
14
+ InitializerWithSwitch,
15
+ SchemaComponent,
16
+ SchemaComponentContext,
17
+ SchemaInitializer,
18
+ SchemaInitializerItem,
19
+ SchemaInitializerItemType,
20
+ SchemaSettingsBlockTitleItem,
21
+ SchemaSettingsDivider,
22
+ SchemaSettingsItem,
23
+ SchemaSettingsRemove,
24
+ VariableScopeProvider,
25
+ css,
26
+ gridRowColWrap,
27
+ useCollectionManager,
28
+ useCompile,
29
+ useFormActiveFields,
30
+ useFormBlockContext,
31
+ usePlugin,
32
+ useSchemaInitializer,
33
+ useSchemaInitializerItem,
34
+ useSchemaOptionsContext,
35
+ } from '@nocobase/client';
36
+ import { Registry, lodash } from '@nocobase/utils/client';
37
+ import WorkflowPlugin, {
38
+ useAvailableUpstreams,
39
+ useNodeContext,
40
+ useFlowContext,
41
+ JOB_STATUS,
42
+ useTrigger,
43
+ useWorkflowVariableOptions,
44
+ } from '@nocobase/plugin-workflow/client';
45
+
46
+ import { NAMESPACE, useLang } from '../../locale';
47
+ import { DetailsBlockProvider } from './DetailsBlockProvider';
48
+ import { FormBlockProvider } from './FormBlockProvider';
49
+ import createRecordForm from './forms/create';
50
+ import customRecordForm from './forms/custom';
51
+ import updateRecordForm from './forms/update';
52
+
53
+ type ValueOf<T> = T[keyof T];
54
+
55
+ export type FormType = {
56
+ type: 'create' | 'update' | 'custom';
57
+ title: string;
58
+ actions: ValueOf<typeof JOB_STATUS>[];
59
+ collection:
60
+ | string
61
+ | {
62
+ name: string;
63
+ fields: any[];
64
+ [key: string]: any;
65
+ };
66
+ };
67
+
68
+ export type ManualFormType = {
69
+ title: string;
70
+ config: {
71
+ useInitializer: ({ collections }?: { collections: any[] }) => SchemaInitializerItemType;
72
+ initializers?: {
73
+ [key: string]: React.FC;
74
+ };
75
+ components?: {
76
+ [key: string]: React.FC;
77
+ };
78
+ parseFormOptions(root: ISchema): { [key: string]: FormType };
79
+ };
80
+ block: {
81
+ scope?: {
82
+ [key: string]: () => any;
83
+ };
84
+ components?: {
85
+ [key: string]: React.FC;
86
+ };
87
+ };
88
+ };
89
+
90
+ export const manualFormTypes = new Registry<ManualFormType>();
91
+
92
+ manualFormTypes.register('customForm', customRecordForm);
93
+ manualFormTypes.register('createForm', createRecordForm);
94
+ manualFormTypes.register('updateForm', updateRecordForm);
95
+
96
+ function useTriggerInitializers(): SchemaInitializerItemType | null {
97
+ const { workflow } = useFlowContext();
98
+ const trigger = useTrigger();
99
+ return trigger.useInitializers ? trigger.useInitializers(workflow.config) : null;
100
+ }
101
+
102
+ const blockTypeNames = {
103
+ customForm: customRecordForm.title,
104
+ record: `{{t("Data record", { ns: "${NAMESPACE}" })}}`,
105
+ };
106
+
107
+ function SimpleDesigner() {
108
+ const schema = useFieldSchema();
109
+ const title = blockTypeNames[schema['x-designer-props']?.type] ?? '{{t("Block")}}';
110
+ const compile = useCompile();
111
+ return (
112
+ <GeneralSchemaDesigner title={compile(title)}>
113
+ <SchemaSettingsBlockTitleItem />
114
+ <SchemaSettingsDivider />
115
+ <SchemaSettingsRemove
116
+ removeParentsIfNoChildren
117
+ breakRemoveOn={{
118
+ 'x-component': 'Grid',
119
+ }}
120
+ />
121
+ </GeneralSchemaDesigner>
122
+ );
123
+ }
124
+
125
+ export const addBlockButton = new SchemaInitializer({
126
+ name: 'AddBlockButton',
127
+ wrap: gridRowColWrap,
128
+ title: '{{t("Add block")}}',
129
+ items: [
130
+ {
131
+ type: 'itemGroup',
132
+ name: 'dataBlocks',
133
+ title: '{{t("Data blocks")}}',
134
+ checkChildrenLength: true,
135
+ useChildren() {
136
+ const workflowPlugin = usePlugin(WorkflowPlugin);
137
+ const current = useNodeContext();
138
+ const nodes = useAvailableUpstreams(current);
139
+ const triggerInitializers = [useTriggerInitializers()].filter(Boolean);
140
+ const nodeBlockInitializers = nodes
141
+ .map((node) => {
142
+ const instruction = workflowPlugin.instructions.get(node.type);
143
+ return instruction?.useInitializers?.(node);
144
+ })
145
+ .filter(Boolean);
146
+ const dataBlockInitializers: any = [
147
+ ...triggerInitializers,
148
+ ...(nodeBlockInitializers.length
149
+ ? [
150
+ {
151
+ name: 'nodes',
152
+ type: 'subMenu',
153
+ title: `{{t("Node result", { ns: "${NAMESPACE}" })}}`,
154
+ children: nodeBlockInitializers,
155
+ },
156
+ ]
157
+ : []),
158
+ ].filter(Boolean);
159
+ return dataBlockInitializers;
160
+ },
161
+ },
162
+ {
163
+ type: 'itemGroup',
164
+ name: 'form',
165
+ title: '{{t("Form")}}',
166
+ useChildren() {
167
+ const { collections } = useCollectionManager();
168
+ return Array.from(manualFormTypes.getValues()).map((item: ManualFormType) => {
169
+ const { useInitializer: getInitializer } = item.config;
170
+ return getInitializer({ collections });
171
+ });
172
+ },
173
+ },
174
+ {
175
+ type: 'itemGroup',
176
+ name: 'otherBlocks',
177
+ title: '{{t("Other blocks")}}',
178
+ children: [
179
+ {
180
+ name: 'markdown',
181
+ title: '{{t("Markdown")}}',
182
+ Component: 'MarkdownBlockInitializer',
183
+ },
184
+ ],
185
+ },
186
+ ],
187
+ });
188
+
189
+ function AssignedFieldValues() {
190
+ const ctx = useContext(SchemaComponentContext);
191
+ const { t } = useTranslation();
192
+ const fieldSchema = useFieldSchema();
193
+ const scope = useWorkflowVariableOptions();
194
+ const [open, setOpen] = useState(false);
195
+ const [initialSchema, setInitialSchema] = useState(
196
+ fieldSchema?.['x-action-settings']?.assignedValues?.schema ?? {
197
+ type: 'void',
198
+ 'x-component': 'Grid',
199
+ 'x-initializer': 'CustomFormItemInitializers',
200
+ properties: {},
201
+ },
202
+ );
203
+ const [schema, setSchema] = useState<Schema>(null);
204
+ const { components } = useSchemaOptionsContext();
205
+ useEffect(() => {
206
+ setSchema(
207
+ new Schema({
208
+ properties: {
209
+ grid: initialSchema,
210
+ },
211
+ }),
212
+ );
213
+ }, [initialSchema]);
214
+ const form = useMemo(() => {
215
+ const initialValues = fieldSchema?.['x-action-settings']?.assignedValues?.values;
216
+ return createForm({
217
+ initialValues: lodash.cloneDeep(initialValues),
218
+ values: lodash.cloneDeep(initialValues),
219
+ });
220
+ }, [fieldSchema]);
221
+ const upLevelActiveFields = useFormActiveFields();
222
+
223
+ const title = t('Assign field values');
224
+
225
+ function onCancel() {
226
+ setOpen(false);
227
+ }
228
+
229
+ function onSubmit() {
230
+ if (!fieldSchema['x-action-settings']) {
231
+ fieldSchema['x-action-settings'] = {};
232
+ }
233
+ if (!fieldSchema['x-action-settings'].assignedValues) {
234
+ fieldSchema['x-action-settings'].assignedValues = {};
235
+ }
236
+ fieldSchema['x-action-settings'].assignedValues.schema = initialSchema;
237
+ fieldSchema['x-action-settings'].assignedValues.values = form.values;
238
+ setOpen(false);
239
+ setTimeout(() => {
240
+ ctx.refresh?.();
241
+ }, 300);
242
+ }
243
+
244
+ return (
245
+ <>
246
+ <SchemaSettingsItem title={title} onClick={() => setOpen(true)}>
247
+ {title}
248
+ </SchemaSettingsItem>
249
+ <Modal
250
+ width={'50%'}
251
+ title={title}
252
+ open={open}
253
+ onCancel={onCancel}
254
+ footer={
255
+ <Space>
256
+ <Button onClick={onCancel}>{t('Cancel')}</Button>
257
+ <Button type="primary" onClick={onSubmit}>
258
+ {t('Submit')}
259
+ </Button>
260
+ </Space>
261
+ }
262
+ >
263
+ <DefaultValueProvider isAllowToSetDefaultValue={() => false}>
264
+ <VariableScopeProvider scope={scope}>
265
+ <FormActiveFieldsProvider name="form" getActiveFieldsName={upLevelActiveFields?.getActiveFieldsName}>
266
+ <FormProvider form={form}>
267
+ <FormLayout layout={'vertical'}>
268
+ <Alert
269
+ message={useLang(
270
+ 'Values preset in this form will override user submitted ones when continue or reject.',
271
+ )}
272
+ />
273
+ <br />
274
+ {open && schema && (
275
+ <SchemaComponentContext.Provider
276
+ value={{
277
+ ...ctx,
278
+ refresh() {
279
+ setInitialSchema(lodash.get(schema.toJSON(), 'properties.grid'));
280
+ },
281
+ }}
282
+ >
283
+ <SchemaComponent schema={schema} components={components} />
284
+ </SchemaComponentContext.Provider>
285
+ )}
286
+ </FormLayout>
287
+ </FormProvider>
288
+ </FormActiveFieldsProvider>
289
+ </VariableScopeProvider>
290
+ </DefaultValueProvider>
291
+ </Modal>
292
+ </>
293
+ );
294
+ }
295
+
296
+ function ManualActionDesigner(props) {
297
+ return (
298
+ <GeneralSchemaDesigner {...props} disableInitializer>
299
+ <Action.Designer.ButtonEditor />
300
+ <AssignedFieldValues />
301
+ <SchemaSettingsDivider />
302
+ <SchemaSettingsRemove
303
+ removeParentsIfNoChildren
304
+ breakRemoveOn={{
305
+ 'x-component': 'ActionBar',
306
+ }}
307
+ />
308
+ </GeneralSchemaDesigner>
309
+ );
310
+ }
311
+
312
+ function ContinueInitializer() {
313
+ const itemConfig = useSchemaInitializerItem();
314
+ const { action, actionProps, ...others } = itemConfig;
315
+ const { insert } = useSchemaInitializer();
316
+ return (
317
+ <SchemaInitializerItem
318
+ {...others}
319
+ onClick={() => {
320
+ insert({
321
+ type: 'void',
322
+ title: others.title,
323
+ 'x-decorator': 'ManualActionStatusProvider',
324
+ 'x-decorator-props': {
325
+ value: action,
326
+ },
327
+ 'x-component': 'Action',
328
+ 'x-component-props': {
329
+ ...actionProps,
330
+ useAction: '{{ useSubmit }}',
331
+ },
332
+ 'x-designer': 'ManualActionDesigner',
333
+ 'x-action-settings': {},
334
+ });
335
+ }}
336
+ />
337
+ );
338
+ }
339
+
340
+ function ActionInitializer() {
341
+ const itemConfig = useSchemaInitializerItem();
342
+ const { action, actionProps, ...others } = itemConfig;
343
+ return (
344
+ <InitializerWithSwitch
345
+ {...others}
346
+ item={itemConfig}
347
+ schema={{
348
+ type: 'void',
349
+ title: others.title,
350
+ 'x-decorator': 'ManualActionStatusProvider',
351
+ 'x-decorator-props': {
352
+ value: action,
353
+ },
354
+ 'x-component': 'Action',
355
+ 'x-component-props': {
356
+ ...actionProps,
357
+ useAction: '{{ useSubmit }}',
358
+ },
359
+ 'x-designer': 'Action.Designer',
360
+ 'x-action': `${action}`,
361
+ }}
362
+ type="x-action"
363
+ />
364
+ );
365
+ }
366
+
367
+ export const addActionButton = new SchemaInitializer({
368
+ name: 'AddActionButton',
369
+ title: '{{t("Configure actions")}}',
370
+ items: [
371
+ {
372
+ name: 'jobStatusResolved',
373
+ title: `{{t("Continue the process", { ns: "${NAMESPACE}" })}}`,
374
+ Component: ContinueInitializer,
375
+ action: JOB_STATUS.RESOLVED,
376
+ actionProps: {
377
+ type: 'primary',
378
+ },
379
+ },
380
+ {
381
+ name: 'jobStatusRejected',
382
+ title: `{{t("Terminate the process", { ns: "${NAMESPACE}" })}}`,
383
+ Component: ActionInitializer,
384
+ action: JOB_STATUS.REJECTED,
385
+ actionProps: {
386
+ danger: true,
387
+ },
388
+ },
389
+ {
390
+ name: 'jobStatusPending',
391
+ title: `{{t("Save temporarily", { ns: "${NAMESPACE}" })}}`,
392
+ Component: ActionInitializer,
393
+ action: JOB_STATUS.PENDING,
394
+ },
395
+ ],
396
+ });
397
+
398
+ // NOTE: fake useAction for ui configuration
399
+ function useSubmit() {
400
+ // const { values, submit, id: formId } = useForm();
401
+ // const formSchema = useFieldSchema();
402
+ return {
403
+ run() {},
404
+ };
405
+ }
406
+
407
+ export function SchemaConfig({ value, onChange }) {
408
+ const workflowPlugin = usePlugin(WorkflowPlugin);
409
+ const ctx = useContext(SchemaComponentContext);
410
+ const node = useNodeContext();
411
+ const nodes = useAvailableUpstreams(node);
412
+ const form = useForm();
413
+ const { workflow } = useFlowContext();
414
+
415
+ const nodeInitializers = {};
416
+ const nodeComponents = {};
417
+ nodes.forEach((item) => {
418
+ const instruction = workflowPlugin.instructions.get(item.type);
419
+ Object.assign(nodeInitializers, instruction.initializers);
420
+ Object.assign(nodeComponents, instruction.components);
421
+ });
422
+
423
+ const schema = useMemo(
424
+ () =>
425
+ new Schema({
426
+ properties: {
427
+ drawer: {
428
+ type: 'void',
429
+ title: `{{t("User interface", { ns: "${NAMESPACE}" })}}`,
430
+ 'x-decorator': 'Form',
431
+ 'x-component': 'Action.Drawer',
432
+ 'x-component-props': {
433
+ className: css`
434
+ .ant-drawer-body {
435
+ background: var(--nb-box-bg);
436
+ }
437
+ `,
438
+ },
439
+ properties: {
440
+ tabs: {
441
+ type: 'void',
442
+ 'x-component': 'Tabs',
443
+ 'x-component-props': {},
444
+ 'x-initializer': 'TabPaneInitializers',
445
+ 'x-initializer-props': {
446
+ gridInitializer: 'AddBlockButton',
447
+ },
448
+ properties: value ?? {
449
+ tab1: {
450
+ type: 'void',
451
+ title: `{{t("Manual", { ns: "${NAMESPACE}" })}}`,
452
+ 'x-component': 'Tabs.TabPane',
453
+ 'x-designer': 'Tabs.Designer',
454
+ properties: {
455
+ grid: {
456
+ type: 'void',
457
+ 'x-component': 'Grid',
458
+ 'x-initializer': 'AddBlockButton',
459
+ properties: {},
460
+ },
461
+ },
462
+ },
463
+ },
464
+ },
465
+ },
466
+ },
467
+ },
468
+ }),
469
+ [value],
470
+ );
471
+
472
+ const refresh = useCallback(
473
+ function refresh() {
474
+ // ctx.refresh?.();
475
+ const { tabs } = lodash.get(schema.toJSON(), 'properties.drawer.properties') as { tabs: ISchema };
476
+ const forms = Array.from(manualFormTypes.getValues()).reduce(
477
+ (result, item: ManualFormType) => Object.assign(result, item.config.parseFormOptions(tabs)),
478
+ {},
479
+ );
480
+ form.setValuesIn('forms', forms);
481
+
482
+ onChange(tabs.properties);
483
+ },
484
+ [form, onChange, schema],
485
+ );
486
+
487
+ return (
488
+ <SchemaComponentContext.Provider
489
+ value={{
490
+ ...ctx,
491
+ designable: !workflow.executed,
492
+ refresh,
493
+ }}
494
+ >
495
+ <SchemaComponent
496
+ schema={schema}
497
+ components={{
498
+ ...nodeComponents,
499
+ // @ts-ignore
500
+ ...Array.from(manualFormTypes.getValues()).reduce(
501
+ (result, item: ManualFormType) => Object.assign(result, item.config.components),
502
+ {},
503
+ ),
504
+ FormBlockProvider,
505
+ DetailsBlockProvider,
506
+ // NOTE: fake provider component
507
+ ManualActionStatusProvider(props) {
508
+ return props.children;
509
+ },
510
+ ActionBarProvider(props) {
511
+ return props.children;
512
+ },
513
+ SimpleDesigner,
514
+ ManualActionDesigner,
515
+ }}
516
+ scope={{
517
+ useSubmit,
518
+ useDetailsBlockProps: useFormBlockContext,
519
+ }}
520
+ />
521
+ </SchemaComponentContext.Provider>
522
+ );
523
+ }
524
+
525
+ export function SchemaConfigButton(props) {
526
+ const { workflow } = useFlowContext();
527
+ const [visible, setVisible] = useState(false);
528
+ return (
529
+ <>
530
+ <Button type="primary" onClick={() => setVisible(true)} disabled={false}>
531
+ {useLang(workflow.executed ? 'View user interface' : 'Configure user interface')}
532
+ </Button>
533
+ <ActionContextProvider value={{ visible, setVisible, formValueChanged: false }}>
534
+ {props.children}
535
+ </ActionContextProvider>
536
+ </>
537
+ );
538
+ }
@@ -0,0 +1,112 @@
1
+ import React, { useMemo, useState } from 'react';
2
+
3
+ import {
4
+ GeneralSchemaDesigner,
5
+ SchemaSettingsBlockTitleItem,
6
+ SchemaSettingsDataTemplates,
7
+ SchemaSettingsDivider,
8
+ SchemaSettingsLinkageRules,
9
+ SchemaSettingsRemove,
10
+ useCollection,
11
+ useMenuSearch,
12
+ } from '@nocobase/client';
13
+
14
+ import _ from 'lodash';
15
+ import { NAMESPACE } from '../../../locale';
16
+ import { FormBlockInitializer } from '../FormBlockInitializer';
17
+ import { ManualFormType } from '../SchemaConfig';
18
+ import { findSchema } from '../utils';
19
+
20
+ function CreateFormDesigner() {
21
+ const { name, title } = useCollection();
22
+
23
+ return (
24
+ <GeneralSchemaDesigner title={title || name}>
25
+ <SchemaSettingsBlockTitleItem />
26
+ <SchemaSettingsLinkageRules collectionName={name} />
27
+ <SchemaSettingsDataTemplates collectionName={name} />
28
+ <SchemaSettingsDivider />
29
+ <SchemaSettingsRemove
30
+ removeParentsIfNoChildren
31
+ breakRemoveOn={{
32
+ 'x-component': 'Grid',
33
+ }}
34
+ />
35
+ </GeneralSchemaDesigner>
36
+ );
37
+ }
38
+
39
+ export default {
40
+ title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
41
+ config: {
42
+ useInitializer({ collections }) {
43
+ const childItems = useMemo(
44
+ () =>
45
+ collections.map((item) => ({
46
+ name: _.camelCase(`createRecordForm-child-${item.name}`),
47
+ type: 'item',
48
+ title: item.title,
49
+ label: item.label,
50
+ schema: {
51
+ collection: item.name,
52
+ title: `{{t("Create record", { ns: "${NAMESPACE}" })}}`,
53
+ formType: 'create',
54
+ 'x-designer': 'CreateFormDesigner',
55
+ },
56
+ Component: FormBlockInitializer,
57
+ })),
58
+ [collections],
59
+ );
60
+ const [isOpenSubMenu, setIsOpenSubMenu] = useState(false);
61
+ const searchedChildren = useMenuSearch(childItems, isOpenSubMenu, true);
62
+ return {
63
+ name: 'createRecordForm',
64
+ key: 'createRecordForm',
65
+ type: 'subMenu',
66
+ title: `{{t("Create record form", { ns: "${NAMESPACE}" })}}`,
67
+ componentProps: {
68
+ onOpenChange(keys) {
69
+ setIsOpenSubMenu(keys.length > 0);
70
+ },
71
+ },
72
+ children: searchedChildren,
73
+ } as any;
74
+ },
75
+ initializers: {
76
+ // AddCustomFormField
77
+ },
78
+ components: {
79
+ CreateFormDesigner,
80
+ },
81
+ parseFormOptions(root) {
82
+ const forms = {};
83
+ const formBlocks: any[] = findSchema(
84
+ root,
85
+ (item) => item['x-decorator'] === 'FormBlockProvider' && item['x-decorator-props'].formType === 'create',
86
+ );
87
+ formBlocks.forEach((formBlock) => {
88
+ const [formKey] = Object.keys(formBlock.properties);
89
+ const formSchema = formBlock.properties[formKey];
90
+ forms[formKey] = {
91
+ type: 'create',
92
+ title: formBlock['x-component-props']?.title || formKey,
93
+ actions: findSchema(formSchema.properties.actions, (item) => item['x-component'] === 'Action').map(
94
+ (item) => ({
95
+ status: item['x-decorator-props'].value,
96
+ values: item['x-action-settings']?.assignedValues?.values,
97
+ key: item.name,
98
+ }),
99
+ ),
100
+ collection: formBlock['x-decorator-props'].collection,
101
+ };
102
+ });
103
+ return forms;
104
+ },
105
+ },
106
+ block: {
107
+ scope: {
108
+ // useFormBlockProps
109
+ },
110
+ components: {},
111
+ },
112
+ } as ManualFormType;