import { BlockInitializers, SchemaInitializerItemOptions, useCollectionManager } from '@nocobase/client'; import { CollectionBlockInitializer } from '../../components/CollectionBlockInitializer'; import { CollectionFieldInitializers } from '../../components/CollectionFieldInitializers'; import { filterTypedFields, useCollectionFieldOptions } from '../../variable'; import { NAMESPACE } from '../../locale'; import { SchemaConfig, SchemaConfigButton } from './SchemaConfig'; import { ModeConfig } from './ModeConfig'; import { AssigneesSelect } from './AssigneesSelect'; const MULTIPLE_ASSIGNED_MODE = { SINGLE: Symbol('single'), ALL: Symbol('all'), ANY: Symbol('any'), ALL_PERCENTAGE: Symbol('all percentage'), ANY_PERCENTAGE: Symbol('any percentage'), }; // TODO(optimize): change to register way const initializerGroup = BlockInitializers.items.find((group) => group.key === 'media'); if (!initializerGroup.children.find((item) => item.key === 'workflowTodos')) { initializerGroup.children.push({ key: 'workflowTodos', type: 'item', title: `{{t("Workflow todos", { ns: "${NAMESPACE}" })}}`, component: 'WorkflowTodoBlockInitializer', icon: 'CheckSquareOutlined', } as any); } export default { title: `{{t("Manual", { ns: "${NAMESPACE}" })}}`, type: 'manual', group: 'manual', description: `{{t("Could be used for manually submitting data, and determine whether to continue or exit. Workflow will generate a todo item for assigned user when it reaches a manual node, and continue processing after user submits the form.", { ns: "${NAMESPACE}" })}}`, fieldset: { assignees: { type: 'array', title: `{{t("Assignees", { ns: "${NAMESPACE}" })}}`, 'x-decorator': 'FormItem', 'x-component': 'AssigneesSelect', 'x-component-props': { // multiple: true, }, required: true, default: [], }, mode: { type: 'number', title: `{{t("Mode", { ns: "${NAMESPACE}" })}}`, 'x-decorator': 'FormItem', 'x-component': 'ModeConfig', default: 1, 'x-reactions': { dependencies: ['assignees'], fulfill: { state: { visible: '{{$deps[0].length > 1}}', }, }, }, }, schema: { type: 'void', title: `{{t("User interface", { ns: "${NAMESPACE}" })}}`, 'x-decorator': 'FormItem', 'x-component': 'SchemaConfigButton', properties: { schema: { type: 'object', 'x-component': 'SchemaConfig', default: null, }, }, }, forms: { type: 'object', default: {}, }, }, view: {}, scope: {}, components: { SchemaConfigButton, SchemaConfig, ModeConfig, AssigneesSelect, }, useVariables({ config }, { types }) { const formKeys = Object.keys(config.forms ?? {}); if (!formKeys.length) { return null; } const options = formKeys .map((formKey) => { const form = config.forms[formKey]; // eslint-disable-next-line react-hooks/rules-of-hooks const options = useCollectionFieldOptions({ fields: form.collection?.fields, collection: form.collection, types, }); return options.length ? { key: formKey, value: formKey, label: form.title || formKey, title: form.title || formKey, children: options, } : null; }) .filter(Boolean); return options.length ? options : null; }, useInitializers(node): SchemaInitializerItemOptions | null { const { getCollection } = useCollectionManager(); const formKeys = Object.keys(node.config.forms ?? {}); if (!formKeys.length || node.config.mode) { return null; } const forms = formKeys .map((formKey) => { const form = node.config.forms[formKey]; const { fields = [] } = getCollection(form.collection); return fields.length ? ({ type: 'item', title: form.title ?? formKey, component: CollectionBlockInitializer, collection: form.collection, dataSource: `{{$jobsMapByNodeId.${node.id}.${formKey}}}`, } as SchemaInitializerItemOptions) : null; }) .filter(Boolean); return forms.length ? { key: 'forms', type: 'subMenu', title: node.title, children: forms, } : null; }, initializers: { CollectionFieldInitializers, }, };