mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-07 06:29:25 +08:00
* feat(plugin-workflow): add create record form for manual node * feat(plugin-workflow): add update form for manual node * fix(plugin-workflow): fix antd version and menu * refactor(plugin-workflow): change collection config modal to initializer sub-menu * test(plugin-workflow): add test case * fix(plugin-workflow): fix todo components based on forms * fix(plugin-workflow): fix cycling trigger when create or update * fix(plugin-workflow): fix transaction in manual processor * refactor(plugin-workflow): optimize todo list data loading * fix(plugin-workflow): fix uncommitted manual action effects * fix(plugin-workflow): fix save multiple forms and only submit one * chore(plugin-workflow): fix lint * fix(plugin-workflow): fix lint error * refactor(plugin-workflow): abstract workflow scoped FormBlockProvider * fix(plugin-workflow): adjust designable api to use current schema in refresh * fix(plugin-workflow): fix schema config and support block template * fix(plugin-workflow): fix lint and build error * fix(plugin-workflow): adjust components and scope to inner schema component * fix(plugin-workflow): fix ref template in todo drawer * fix(plugin-workflow): fix todo form undefined * fix(plugin-workflow): fix manual form schema * fix(plugin-workflow): fix manual createdBy/updatedBy user * fix(plugin-workflow): disable save to template on create form * fix(plugin-workflow): fix manual form variables * fix(plugin-workflow): fix FormBlockProvider for default field value * fix(plugin-workflow): fix manual node variables
156 lines
4.5 KiB
TypeScript
156 lines
4.5 KiB
TypeScript
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,
|
|
},
|
|
};
|