refactor(plugin-workflow): migrate directly action trigger to custom action trigger (#4253)

* refactor(plugin-workflow): migrate directly action trigger to custom action trigger

* test(plugin-workflow-action-trigger): skip legacy test case

* chore(plugin-workflow-action-trigger): adjust locale

* chore(plugin-workflow-action-trigger): adjust locale

* chore(plugin-workflow-action-trigger): match version for migration
This commit is contained in:
Junyi 2024-05-09 08:34:29 +08:00 committed by GitHub
parent 077efebdf0
commit cafaa82a94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 105 additions and 93 deletions

View File

@ -335,7 +335,7 @@ export function RemoveButton(
);
}
function WorkflowSelect({ actionType, direct = false, ...props }) {
function WorkflowSelect({ formAction, buttonAction, actionType, ...props }) {
const { t } = useTranslation();
const index = ArrayTable.useIndex();
const { setValuesIn } = useForm();
@ -376,17 +376,28 @@ function WorkflowSelect({ actionType, direct = false, ...props }) {
});
const optionFilter = useCallback(
({ type, config }) => {
({ key, type, config }) => {
if (key === props.value) {
return true;
}
const trigger = workflowPlugin.triggers.get(type);
if (trigger.isActionTriggerable === true) {
return true;
}
if (typeof trigger.isActionTriggerable === 'function') {
return trigger.isActionTriggerable(config, { action: actionType, direct });
return trigger.isActionTriggerable(config, {
action: actionType,
formAction,
buttonAction,
/**
* @deprecated
*/
direct: buttonAction === 'customize:triggerWorkflows',
});
}
return false;
},
[workflowPlugin.triggers, actionType, direct],
[props.value, workflowPlugin.triggers, formAction, buttonAction, actionType],
);
return (
@ -434,7 +445,12 @@ export function WorkflowConfig() {
const collection = useCollection_deprecated();
// TODO(refactor): should refactor for getting certain action type, better from 'x-action'.
const formBlock = useFormBlockContext();
/**
* @deprecated
*/
const actionType = formBlock?.type || fieldSchema['x-action'];
const formAction = formBlock?.type;
const buttonAction = fieldSchema['x-action'];
const description = {
submit: t('Workflow will be triggered before or after submitting succeeded based on workflow type.', {
@ -444,7 +460,11 @@ export function WorkflowConfig() {
ns: 'workflow',
}),
'customize:triggerWorkflows': t(
'Workflow will be triggered directly once the button clicked, without data saving. Only supports "Post-action event" for now.',
'Workflow will be triggered directly once the button clicked, without data saving. Only supports to be bound with "Custom action event".',
{ ns: 'workflow' },
),
'customize:triggerWorkflows_deprecated': t(
'"Submit to workflow" to "Post-action event" is deprecated, please use "Custom action event" instead.',
{ ns: 'workflow' },
),
destroy: t('Workflow will be triggered before deleting succeeded.', { ns: 'workflow' }),
@ -509,7 +529,7 @@ export function WorkflowConfig() {
value: '',
},
allowClear: false,
loadData: actionType === 'destroy' ? null : undefined,
loadData: buttonAction === 'destroy' ? null : undefined,
},
default: '',
},
@ -529,7 +549,8 @@ export function WorkflowConfig() {
'x-component-props': {
placeholder: t('Select workflow', { ns: 'workflow' }),
actionType,
direct: fieldSchema['x-action'] === 'customize:triggerWorkflows',
formAction,
buttonAction,
},
required: true,
},

View File

@ -34,7 +34,7 @@ const COLLECTION_TRIGGER_ACTION = {
export default class extends Trigger {
title = `{{t("Post-action event", { ns: "${NAMESPACE}" })}}`;
description = `{{t('Triggered after the completion of a request initiated through an action button or API, such as after adding, updating, deleting data, or "submit to workflow". Suitable for data processing, sending notifications, etc., after actions are completed.', { ns: "${NAMESPACE}" })}}`;
description = `{{t('Triggered after the completion of a request initiated through an action button or API, such as after adding, updating, or deleting data. Suitable for data processing, sending notifications, etc., after actions are completed.', { ns: "${NAMESPACE}" })}}`;
fieldset = {
collection: {
type: 'string',
@ -153,8 +153,9 @@ export default class extends Trigger {
};
isActionTriggerable = (config, context) => {
return (
context.action === 'customize:triggerWorkflows' ||
(['create', 'update', 'customize:update'].includes(context.action) && !config.global)
['create', 'update'].includes(context.formAction) &&
['submit', 'customize:save'].includes(context.buttonAction) &&
!config.global
);
};
useVariables(config, options) {

View File

@ -126,7 +126,13 @@ test.describe('Configuration page to configure the Trigger node', () => {
await apiDeleteWorkflow(workflowId);
});
test('Form Submit to Workflow Button Add Data Trigger', async ({ page, mockPage, mockCollections, mockRecords }) => {
// TODO: 需要转移到新事件中
test.skip('Form Submit to Workflow Button Add Data Trigger', async ({
page,
mockPage,
mockCollections,
mockRecords,
}) => {
//数据表后缀标识
const triggerNodeAppendText = faker.string.alphanumeric(5);

View File

@ -7,7 +7,7 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Plugin, SchemaInitializerItemType } from '@nocobase/client';
import { Plugin } from '@nocobase/client';
import WorkflowPlugin, {
useRecordTriggerWorkflowsActionProps,
useTriggerWorkflowsActionProps,
@ -15,59 +15,6 @@ import WorkflowPlugin, {
import ActionTrigger from './ActionTrigger';
const submitToWorkflowActionInitializer: SchemaInitializerItemType = {
name: 'submitToWorkflow',
title: '{{t("Submit to workflow", { ns: "workflow" })}}',
Component: 'CustomizeActionInitializer',
schema: {
title: '{{t("Submit to workflow", { ns: "workflow" })}}',
'x-component': 'Action',
'x-use-component-props': 'useTriggerWorkflowsActionProps',
'x-designer': 'Action.Designer',
'x-action-settings': {
// assignedValues: {},
skipValidator: false,
onSuccess: {
manualClose: true,
redirecting: false,
successMessage: '{{t("Submitted successfully")}}',
},
triggerWorkflows: [],
},
'x-action': 'customize:triggerWorkflows',
},
};
const recordTriggerWorkflowActionInitializer: SchemaInitializerItemType = {
name: 'submitToWorkflow',
title: '{{t("Submit to workflow", { ns: "workflow" })}}',
Component: 'CustomizeActionInitializer',
schema: {
title: '{{t("Submit to workflow", { ns: "workflow" })}}',
'x-component': 'Action',
'x-use-component-props': 'useRecordTriggerWorkflowsActionProps',
'x-designer': 'Action.Designer',
'x-action-settings': {
// assignedValues: {},
onSuccess: {
manualClose: true,
redirecting: false,
successMessage: '{{t("Submitted successfully")}}',
},
triggerWorkflows: [],
},
'x-action': 'customize:triggerWorkflows',
},
};
const recordTriggerWorkflowActionLinkInitializer = {
...recordTriggerWorkflowActionInitializer,
schema: {
...recordTriggerWorkflowActionInitializer.schema,
'x-component': 'Action.Link',
},
};
export default class extends Plugin {
async load() {
const workflow = this.app.pm.get('workflow') as WorkflowPlugin;
@ -77,29 +24,5 @@ export default class extends Plugin {
useTriggerWorkflowsActionProps,
useRecordTriggerWorkflowsActionProps,
});
const FormActionInitializers = this.app.schemaInitializerManager.get('FormActionInitializers');
FormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
const CreateFormActionInitializers = this.app.schemaInitializerManager.get('createForm:configureActions');
CreateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
const UpdateFormActionInitializers = this.app.schemaInitializerManager.get('editForm:configureActions');
UpdateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
const DetailsActionInitializers = this.app.schemaInitializerManager.get('detailsWithPaging:configureActions');
DetailsActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
const ReadPrettyFormActionInitializers = this.app.schemaInitializerManager.get('details:configureActions');
ReadPrettyFormActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
const TableActionColumnInitializers = this.app.schemaInitializerManager.get('table:configureItemActions');
TableActionColumnInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
const GridCardItemActionInitializers = this.app.schemaInitializerManager.get('gridCard:configureItemActions');
GridCardItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
const ListItemActionInitializers = this.app.schemaInitializerManager.get('list:configureItemActions');
ListItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
}
}

View File

@ -1,13 +1,12 @@
{
"Post-action event": "操作后事件",
"Triggered after the completion of a request initiated through an action button or API, such as after adding, updating, deleting data, or \"submit to workflow\". Suitable for data processing, sending notifications, etc., after actions are completed.":
"通过操作按钮或 API 发起请求并在执行完成后触发,比如新增、更新、删除数据或者“提交至工作流”之后。适用于在操作完成后进行数据处理、发送通知等。",
"Triggered after the completion of a request initiated through an action button or API, such as after adding, updating, or deleting data. Suitable for data processing, sending notifications, etc., after actions are completed.":
"通过操作按钮或 API 发起请求时,在请求执行成功后触发该事件,比如新增、更新、删除操作之后。适用于在操作完成后进行数据处理、发送通知等。",
"Collection": "数据表",
"The collection to which the triggered data belongs.": "触发数据所属的数据表。",
"Trigger mode": "触发模式",
"Local mode, triggered after the completion of actions bound to this workflow": "局部模式,绑定该工作流的操作执行完成后触发",
"Global mode, triggered after the completion of the following actions": "全局模式,以下操作执行完成后都触发",
"Action to submit to workflow directly is only supported on bound buttons, and will not be affected under global mode.": "直接提交至工作流的操作仅支持使用按钮绑定,不受全局模式的影响。",
"Select actions": "选择操作",
"Create record action": "创建记录操作",
"Update record action": "更新记录操作",

View File

@ -27,6 +27,9 @@ export default class extends Trigger {
workflow.app.use(this.middleware, { after: 'dataSource' });
}
/**
* @deprecated
*/
async workflowTriggerAction(context: Context, next: Next) {
const { triggerWorkflows } = context.action.params;

View File

@ -0,0 +1,52 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Migration } from '@nocobase/server';
export default class extends Migration {
appVersion = '<1.0.0-alpha.7';
on = 'afterSync';
async up() {
const { db } = this.context;
const UiSchemaRepo = db.getRepository('uiSchemas');
await db.sequelize.transaction(async (transaction) => {
const nodes = await UiSchemaRepo.find({
filter: {
'schema.x-component': 'Action',
'schema.x-designer': 'Action.Designer',
'schema.x-action': 'customize:triggerWorkflows',
$or: [
{
'schema.x-component-props.useProps': 'useTriggerWorkflowsActionProps',
},
{
'schema.x-component-props.useProps': 'useRecordTriggerWorkflowsActionProps',
},
{
'schema.x-use-component-props': 'useTriggerWorkflowsActionProps',
},
{
'schema.x-use-component-props': 'useRecordTriggerWorkflowsActionProps',
},
],
},
transaction,
});
for (const node of nodes) {
const schema = node.get('schema');
schema['x-action'] = 'customize:triggerWorkflows_deprecated';
node.set('schema', { ...schema });
node.changed('schema', true);
await node.save({ transaction });
}
});
}
}

View File

@ -21,6 +21,9 @@ import {
} from '@nocobase/client';
import { isURL } from '@nocobase/utils/client';
/**
* @deprecated
*/
export function useTriggerWorkflowsActionProps() {
const api = useAPIClient();
const form = useForm();
@ -84,6 +87,9 @@ export function useTriggerWorkflowsActionProps() {
};
}
/**
* @deprecated
*/
export function useRecordTriggerWorkflowsActionProps() {
const compile = useCompile();
const api = useAPIClient();

View File

@ -38,7 +38,8 @@
"Go back": "返回",
"Bind workflows": "绑定工作流",
"Workflow will be triggered before or after submitting succeeded based on workflow type.": "工作流会基于其类型在提交成功之前或之后触发。",
"Workflow will be triggered directly once the button clicked, without data saving. Only supports \"Post-action event\" for now.": "按钮点击后直接触发工作流,但不会保存数据。目前仅支持“操作后事件”。",
"Workflow will be triggered directly once the button clicked, without data saving. Only supports to be bound with \"Custom action event\".": "按钮点击后直接触发工作流,但不会保存数据。仅支持绑定“自定义操作事件”。",
"\"Submit to workflow\" to \"Post-action event\" is deprecated, please use \"Custom action event\" instead.": "“提交至工作流”到“操作后事件”的方式已被弃用,请使用“自定义操作事件”代替。",
"Workflow will be triggered before deleting succeeded.": "删除成功之前触发工作流。",
"Submit to workflow": "提交至工作流",
"Add workflow": "添加工作流",