@nocobase/plugin-workflow-action-trigger 0.20.0-alpha.9 → 0.21.0-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.
- package/dist/client/ActionTrigger.d.ts +3 -4
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +9 -9
- package/dist/server/ActionTrigger.d.ts +3 -4
- package/dist/server/ActionTrigger.js +11 -4
- package/package.json +2 -2
- package/src/client/ActionTrigger.tsx +10 -6
- package/src/client/__e2e__/configuration.test.ts +26 -12
- package/src/client/index.ts +8 -8
- package/src/server/ActionTrigger.ts +15 -7
- package/src/server/__tests__/trigger.test.ts +53 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SchemaInitializerItemType, useCollectionDataSource } from '@nocobase/client';
|
|
2
|
-
import { Trigger } from '@nocobase/plugin-workflow/client';
|
|
2
|
+
import { Trigger, useWorkflowAnyExecuted } from '@nocobase/plugin-workflow/client';
|
|
3
3
|
export default class extends Trigger {
|
|
4
4
|
title: string;
|
|
5
5
|
description: string;
|
|
@@ -9,9 +9,7 @@ export default class extends Trigger {
|
|
|
9
9
|
required: boolean;
|
|
10
10
|
'x-decorator': string;
|
|
11
11
|
'x-component': string;
|
|
12
|
-
'x-
|
|
13
|
-
className: string;
|
|
14
|
-
};
|
|
12
|
+
'x-disabled': string;
|
|
15
13
|
title: string;
|
|
16
14
|
description: string;
|
|
17
15
|
'x-reactions': {
|
|
@@ -47,6 +45,7 @@ export default class extends Trigger {
|
|
|
47
45
|
};
|
|
48
46
|
scope: {
|
|
49
47
|
useCollectionDataSource: typeof useCollectionDataSource;
|
|
48
|
+
useWorkflowAnyExecuted: typeof useWorkflowAnyExecuted;
|
|
50
49
|
};
|
|
51
50
|
isActionTriggerable: (config: any, context: any) => boolean;
|
|
52
51
|
useVariables(config: any, options: any): import("@nocobase/plugin-workflow/client").VariableOption[];
|
package/dist/client/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(o,e){typeof exports=="object"&&typeof module!="undefined"?e(exports,require("@nocobase/client"),require("@nocobase/plugin-workflow/client"),require("@formily/react"),require("react-i18next")):typeof define=="function"&&define.amd?define(["exports","@nocobase/client","@nocobase/plugin-workflow/client","@formily/react","react-i18next"],e):(o=typeof globalThis!="undefined"?globalThis:o||self,e(o["@nocobase/plugin-workflow-action-trigger"]={},o["@nocobase/client"],o["@nocobase/plugin-workflow"],o["@formily/react"],o["react-i18next"]))})(this,function(o,e,t,w,m){"use strict";var M=Object.defineProperty,D=Object.defineProperties;var R=Object.getOwnPropertyDescriptors;var y=Object.getOwnPropertySymbols;var q=Object.prototype.hasOwnProperty,$=Object.prototype.propertyIsEnumerable;var z=(o,e,t)=>e in o?M(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,p=(o,e)=>{for(var t in e||(e={}))q.call(e,t)&&z(o,t,e[t]);if(y)for(var t of y(e))$.call(e,t)&&z(o,t,e[t]);return o},f=(o,e)=>D(o,R(e));var a=(o,e,t)=>(z(o,typeof e!="symbol"?e+"":e,t),t);var S=(o,e,t)=>new Promise((w,m)=>{var s=r=>{try{l(t.next(r))}catch(n){m(n)}},c=r=>{try{l(t.throw(r))}catch(n){m(n)}},l=r=>r.done?w(r.value):Promise.resolve(r.value).then(s,c);l((t=t.apply(o,e)).next())});const s="workflow-action-trigger";function c(u,A={}){const{t:i}=l(A);return i(u)}function l(u){return m.useTranslation(s,u)}class r extends t.Trigger{constructor(){super(...arguments);a(this,"title",`{{t("Action event", { ns: "${s}" })}}`);a(this,"description",`{{t("Triggers after specific operations on data are submitted, such as create, update, delete, etc., or directly submitting a record to the workflow.", { ns: "${s}" })}}`);a(this,"fieldset",{collection:{type:"string",required:!0,"x-decorator":"FormItem","x-component":"DataSourceCollectionCascader","x-disabled":"{{ useWorkflowAnyExecuted() }}",title:`{{t("Collection", { ns: "${s}" })}}`,description:`{{t("Which collection record belongs to.", { ns: "${s}" })}}`,"x-reactions":[{target:"appends",effects:["onFieldValueChange"],fulfill:{state:{value:[]}}}]},appends:{type:"array",title:`{{t("Associations to use", { ns: "${s}" })}}`,description:'{{t("Please select the associated fields that need to be accessed in subsequent nodes. With more than two levels of to-many associations may cause performance issue, please use with caution.", { ns: "workflow" })}}',"x-decorator":"FormItem","x-component":"AppendsTreeSelect","x-component-props":{title:"Preload associations",multiple:!0,useCollection(){const{values:i}=w.useForm();return i==null?void 0:i.collection}},"x-reactions":[{dependencies:["collection"],fulfill:{state:{visible:"{{!!$deps[0]}}"}}}]}});a(this,"scope",{useCollectionDataSource:e.useCollectionDataSource,useWorkflowAnyExecuted:t.useWorkflowAnyExecuted});a(this,"isActionTriggerable",(i,g)=>["create","update","customize:update","customize:triggerWorkflows"].includes(g.action))}useVariables(i,g){var C;const h=e.useCompile(),{getCollectionFields:I}=e.useCollectionManager_deprecated(),b=c("Trigger data"),T=c("User submitted action"),x=c("Role of user submitted action"),W=[{collectionName:i.collection,name:"data",type:"hasOne",target:i.collection,uiSchema:{title:b}},{collectionName:"users",name:"user",type:"hasOne",target:"users",uiSchema:{title:T}},{name:"roleName",uiSchema:{title:x}}];return t.getCollectionFieldOptions(f(p({appends:["data","user",...((C=i.appends)==null?void 0:C.map(P=>`data.${P}`))||[]]},g),{fields:W,compile:h,getCollectionFields:I}))}useInitializers(i){return i.collection?{name:"triggerData",type:"item",key:"triggerData",title:`{{t("Trigger data", { ns: "${s}" })}}`,Component:t.CollectionBlockInitializer,collection:i.collection,dataPath:"$context.data"}:null}}const n={name:"submitToWorkflow",title:'{{t("Submit to workflow", { ns: "workflow" })}}',Component:"CustomizeActionInitializer",schema:{title:'{{t("Submit to workflow", { ns: "workflow" })}}',"x-component":"Action","x-component-props":{useProps:"{{ useTriggerWorkflowsActionProps }}"},"x-designer":"Action.Designer","x-action-settings":{skipValidator:!1,onSuccess:{manualClose:!0,redirecting:!1,successMessage:'{{t("Submitted successfully")}}'},triggerWorkflows:[]},"x-action":"customize:triggerWorkflows"}},d={name:"submitToWorkflow",title:'{{t("Submit to workflow", { ns: "workflow" })}}',Component:"CustomizeActionInitializer",schema:{title:'{{t("Submit to workflow", { ns: "workflow" })}}',"x-component":"Action","x-component-props":{useProps:"{{ useRecordTriggerWorkflowsActionProps }}"},"x-designer":"Action.Designer","x-action-settings":{onSuccess:{manualClose:!0,redirecting:!1,successMessage:'{{t("Submitted successfully")}}'},triggerWorkflows:[]},"x-action":"customize:triggerWorkflows"}},k=f(p({},d),{schema:f(p({},d.schema),{"x-component":"Action.Link"})});class F extends e.Plugin{load(){return S(this,null,function*(){this.app.pm.get("workflow").registerTrigger("action",r),this.app.addScopes({useTriggerWorkflowsActionProps:t.useTriggerWorkflowsActionProps,useRecordTriggerWorkflowsActionProps:t.useRecordTriggerWorkflowsActionProps}),this.app.schemaInitializerManager.get("FormActionInitializers").add("customize.submitToWorkflow",n),this.app.schemaInitializerManager.get("createForm:configureActions").add("customize.submitToWorkflow",n),this.app.schemaInitializerManager.get("editForm:configureActions").add("customize.submitToWorkflow",n),this.app.schemaInitializerManager.get("detailsWithPaging:configureActions").add("customize.submitToWorkflow",d),this.app.schemaInitializerManager.get("details:configureActions").add("customize.submitToWorkflow",d),this.app.schemaInitializerManager.get("table:configureItemActions").add("customize.submitToWorkflow",k),this.app.schemaInitializerManager.get("gridCard:configureItemActions").add("customize.submitToWorkflow",k),this.app.schemaInitializerManager.get("list:configureItemActions").add("customize.submitToWorkflow",k)})}}o.default=F,Object.defineProperties(o,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
"@formily/react": "2.3.0",
|
|
3
|
-
"@nocobase/client": "0.
|
|
4
|
-
"@nocobase/plugin-workflow": "0.
|
|
3
|
+
"@nocobase/client": "0.21.0-alpha.1",
|
|
4
|
+
"@nocobase/plugin-workflow": "0.21.0-alpha.1",
|
|
5
5
|
"react-i18next": "11.18.6",
|
|
6
6
|
"lodash": "4.17.21",
|
|
7
7
|
"sequelize": "6.35.2",
|
|
8
|
-
"@nocobase/database": "0.
|
|
9
|
-
"@nocobase/server": "0.
|
|
10
|
-
"@nocobase/
|
|
11
|
-
"@nocobase/
|
|
12
|
-
"@nocobase/plugin-workflow-test": "0.
|
|
13
|
-
"@nocobase/test": "0.
|
|
14
|
-
"@nocobase/utils": "0.
|
|
8
|
+
"@nocobase/database": "0.21.0-alpha.1",
|
|
9
|
+
"@nocobase/server": "0.21.0-alpha.1",
|
|
10
|
+
"@nocobase/actions": "0.21.0-alpha.1",
|
|
11
|
+
"@nocobase/data-source-manager": "0.21.0-alpha.1",
|
|
12
|
+
"@nocobase/plugin-workflow-test": "0.21.0-alpha.1",
|
|
13
|
+
"@nocobase/test": "0.21.0-alpha.1",
|
|
14
|
+
"@nocobase/utils": "0.21.0-alpha.1"
|
|
15
15
|
};
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { DefaultContext } from '@nocobase/server';
|
|
2
|
-
import { ActionContext } from '@nocobase/
|
|
3
|
-
import { Next } from '@nocobase/actions';
|
|
2
|
+
import { Context as ActionContext, Next } from '@nocobase/actions';
|
|
4
3
|
import WorkflowPlugin, { Trigger, WorkflowModel } from '@nocobase/plugin-workflow';
|
|
5
4
|
interface Context extends ActionContext, DefaultContext {
|
|
6
5
|
}
|
|
7
6
|
export default class extends Trigger {
|
|
8
7
|
constructor(workflow: WorkflowPlugin);
|
|
9
|
-
triggerAction(context: Context, next: Next): Promise<
|
|
10
|
-
middleware: (context: Context, next: Next) => Promise<
|
|
8
|
+
triggerAction(context: Context, next: Next): Promise<never>;
|
|
9
|
+
middleware: (context: Context, next: Next) => Promise<void>;
|
|
11
10
|
private trigger;
|
|
12
11
|
on(workflow: WorkflowModel): void;
|
|
13
12
|
off(workflow: WorkflowModel): void;
|
|
@@ -23,10 +23,11 @@ module.exports = __toCommonJS(ActionTrigger_exports);
|
|
|
23
23
|
var import_lodash = require("lodash");
|
|
24
24
|
var import_database = require("@nocobase/database");
|
|
25
25
|
var import_plugin_workflow = require("@nocobase/plugin-workflow");
|
|
26
|
+
var import_data_source_manager = require("@nocobase/data-source-manager");
|
|
26
27
|
class ActionTrigger_default extends import_plugin_workflow.Trigger {
|
|
27
28
|
constructor(workflow) {
|
|
28
29
|
super(workflow);
|
|
29
|
-
workflow.app.
|
|
30
|
+
workflow.app.use(this.middleware, { after: "dataSource" });
|
|
30
31
|
}
|
|
31
32
|
async triggerAction(context, next) {
|
|
32
33
|
const { triggerWorkflows } = context.action.params;
|
|
@@ -57,9 +58,11 @@ class ActionTrigger_default extends import_plugin_workflow.Trigger {
|
|
|
57
58
|
};
|
|
58
59
|
async trigger(context) {
|
|
59
60
|
const { triggerWorkflows = "", values } = context.action.params;
|
|
61
|
+
const dataSourceHeader = context.get("x-data-source") || "main";
|
|
60
62
|
const { currentUser, currentRole } = context.state;
|
|
63
|
+
const { model: UserModel } = this.workflow.db.getCollection("users");
|
|
61
64
|
const userInfo = {
|
|
62
|
-
user:
|
|
65
|
+
user: UserModel.build(currentUser).desensitize(),
|
|
63
66
|
roleName: currentRole
|
|
64
67
|
};
|
|
65
68
|
const triggers = triggerWorkflows.split(",").map((trigger) => trigger.split("!"));
|
|
@@ -76,12 +79,16 @@ class ActionTrigger_default extends import_plugin_workflow.Trigger {
|
|
|
76
79
|
const asyncGroup = [];
|
|
77
80
|
for (const workflow of workflows) {
|
|
78
81
|
const { collection, appends = [] } = workflow.config;
|
|
82
|
+
const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
|
|
79
83
|
const trigger = triggers.find((trigger2) => trigger2[0] == workflow.key);
|
|
80
84
|
const event = [workflow];
|
|
81
85
|
if (context.action.resourceName !== "workflows") {
|
|
82
86
|
if (!context.body) {
|
|
83
87
|
continue;
|
|
84
88
|
}
|
|
89
|
+
if (dataSourceName !== dataSourceHeader) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
85
92
|
const { body: data } = context;
|
|
86
93
|
for (const row of Array.isArray(data) ? data : [data]) {
|
|
87
94
|
let payload = row;
|
|
@@ -98,7 +105,7 @@ class ActionTrigger_default extends import_plugin_workflow.Trigger {
|
|
|
98
105
|
}
|
|
99
106
|
const model = payload.constructor;
|
|
100
107
|
if (payload instanceof import_database.Model) {
|
|
101
|
-
if (
|
|
108
|
+
if (collectionName !== model.collection.name) {
|
|
102
109
|
continue;
|
|
103
110
|
}
|
|
104
111
|
if (appends.length) {
|
|
@@ -111,7 +118,7 @@ class ActionTrigger_default extends import_plugin_workflow.Trigger {
|
|
|
111
118
|
event.push({ data: (0, import_plugin_workflow.toJSON)(payload), ...userInfo });
|
|
112
119
|
}
|
|
113
120
|
} else {
|
|
114
|
-
const { model, repository } = context.
|
|
121
|
+
const { model, repository } = context.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
|
|
115
122
|
let data = trigger[1] ? (0, import_lodash.get)(values, trigger[1]) : values;
|
|
116
123
|
const pk = (0, import_lodash.get)(data, model.primaryKeyAttribute);
|
|
117
124
|
if (appends.length && pk != null) {
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName.zh-CN": "工作流:数据操作触发器",
|
|
5
5
|
"description": "Bind action buttons to trigger workflow events when clicked.",
|
|
6
6
|
"description.zh-CN": "可对数据操作按钮绑定,在点击后触发对应的工作流事件。",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.21.0-alpha.1",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
9
|
"main": "./dist/server/index.js",
|
|
10
10
|
"homepage": "https://docs.nocobase.com/plugins/workflow-action-trigger",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@nocobase/server": "0.x",
|
|
22
22
|
"@nocobase/test": "0.x"
|
|
23
23
|
},
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "afd2f3d1341b85ea9daa7b2667dd4ace1fafb7ff",
|
|
25
25
|
"keywords": [
|
|
26
26
|
"Workflow"
|
|
27
27
|
]
|
|
@@ -6,7 +6,12 @@ import {
|
|
|
6
6
|
useCollectionManager_deprecated,
|
|
7
7
|
useCompile,
|
|
8
8
|
} from '@nocobase/client';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Trigger,
|
|
11
|
+
CollectionBlockInitializer,
|
|
12
|
+
getCollectionFieldOptions,
|
|
13
|
+
useWorkflowAnyExecuted,
|
|
14
|
+
} from '@nocobase/plugin-workflow/client';
|
|
10
15
|
import { NAMESPACE, useLang } from '../locale';
|
|
11
16
|
|
|
12
17
|
export default class extends Trigger {
|
|
@@ -17,10 +22,8 @@ export default class extends Trigger {
|
|
|
17
22
|
type: 'string',
|
|
18
23
|
required: true,
|
|
19
24
|
'x-decorator': 'FormItem',
|
|
20
|
-
'x-component': '
|
|
21
|
-
'x-
|
|
22
|
-
className: 'auto-width',
|
|
23
|
-
},
|
|
25
|
+
'x-component': 'DataSourceCollectionCascader',
|
|
26
|
+
'x-disabled': '{{ useWorkflowAnyExecuted() }}',
|
|
24
27
|
title: `{{t("Collection", { ns: "${NAMESPACE}" })}}`,
|
|
25
28
|
description: `{{t("Which collection record belongs to.", { ns: "${NAMESPACE}" })}}`,
|
|
26
29
|
'x-reactions': [
|
|
@@ -63,6 +66,7 @@ export default class extends Trigger {
|
|
|
63
66
|
};
|
|
64
67
|
scope = {
|
|
65
68
|
useCollectionDataSource,
|
|
69
|
+
useWorkflowAnyExecuted,
|
|
66
70
|
};
|
|
67
71
|
isActionTriggerable = (config, context) => {
|
|
68
72
|
return ['create', 'update', 'customize:update', 'customize:triggerWorkflows'].includes(context.action);
|
|
@@ -126,7 +130,7 @@ export default class extends Trigger {
|
|
|
126
130
|
title: `{{t("Trigger data", { ns: "${NAMESPACE}" })}}`,
|
|
127
131
|
Component: CollectionBlockInitializer,
|
|
128
132
|
collection: config.collection,
|
|
129
|
-
|
|
133
|
+
dataPath: '$context.data',
|
|
130
134
|
};
|
|
131
135
|
}
|
|
132
136
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
apiUpdateWorkflowTrigger,
|
|
10
10
|
appendJsonCollectionName,
|
|
11
11
|
generalWithNoRelationalFields,
|
|
12
|
+
apiGetDataSourceCount,
|
|
12
13
|
} from '@nocobase/plugin-workflow-test/e2e';
|
|
13
14
|
import { expect, test } from '@nocobase/test/e2e';
|
|
14
15
|
import { dayjs } from '@nocobase/utils';
|
|
@@ -51,15 +52,20 @@ test.describe('Configuration page to configure the Trigger node', () => {
|
|
|
51
52
|
const formEventTriggerNode = new FormEventTriggerNode(page, workFlowName, triggerNodeCollectionName);
|
|
52
53
|
await formEventTriggerNode.nodeConfigure.click();
|
|
53
54
|
await formEventTriggerNode.collectionDropDown.click();
|
|
54
|
-
await page.getByRole('
|
|
55
|
+
await page.getByRole('menuitemcheckbox', { name: 'Main right' }).click();
|
|
56
|
+
await page.getByRole('menuitemcheckbox', { name: triggerNodeCollectionDisplayName }).click();
|
|
55
57
|
await formEventTriggerNode.submitButton.click();
|
|
56
58
|
|
|
57
59
|
//配置录入数据区块
|
|
58
60
|
const newPage = mockPage();
|
|
59
61
|
await newPage.goto();
|
|
60
62
|
await page.waitForLoadState('networkidle');
|
|
61
|
-
await page.getByLabel('schema-initializer-Grid-
|
|
63
|
+
await page.getByLabel('schema-initializer-Grid-page:addBlock').hover();
|
|
62
64
|
await page.getByRole('menuitem', { name: 'table Table' }).hover();
|
|
65
|
+
const dataSourcesCount = await apiGetDataSourceCount();
|
|
66
|
+
if (dataSourcesCount > 1) {
|
|
67
|
+
await page.getByRole('menuitem', { name: 'Main right' }).hover();
|
|
68
|
+
}
|
|
63
69
|
await page.getByRole('menuitem', { name: `${triggerNodeCollectionDisplayName}` }).click();
|
|
64
70
|
|
|
65
71
|
// 移开鼠标,关闭菜单
|
|
@@ -71,16 +77,16 @@ test.describe('Configuration page to configure the Trigger node', () => {
|
|
|
71
77
|
await page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch').click();
|
|
72
78
|
await expect(page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch')).toBeEnabled();
|
|
73
79
|
await page.getByLabel(`action-Action-Add new-create-${triggerNodeCollectionName}-table`).click();
|
|
74
|
-
await page.getByLabel(`schema-initializer-Grid-
|
|
80
|
+
await page.getByLabel(`schema-initializer-Grid-popup:addNew:addBlock-${triggerNodeCollectionName}`).hover();
|
|
75
81
|
await page.getByRole('menuitem', { name: 'form Form' }).click();
|
|
76
82
|
// 移开鼠标,关闭菜单
|
|
77
83
|
await page.mouse.move(300, 0);
|
|
78
84
|
await page
|
|
79
|
-
.getByLabel(`schema-initializer-ActionBar-
|
|
85
|
+
.getByLabel(`schema-initializer-ActionBar-createForm:configureActions-${triggerNodeCollectionName}`)
|
|
80
86
|
.hover();
|
|
81
87
|
await page.getByRole('menuitem', { name: 'Submit' }).click();
|
|
82
88
|
// 绑定工作流
|
|
83
|
-
await page.getByLabel(`schema-initializer-Grid-
|
|
89
|
+
await page.getByLabel(`schema-initializer-Grid-form:configureFields-${triggerNodeCollectionName}`).hover();
|
|
84
90
|
await page.getByRole('menuitem', { name: `${triggerNodeFieldDisplayName}` }).click();
|
|
85
91
|
await page.mouse.move(300, 0);
|
|
86
92
|
await page.getByLabel(`action-Action-Submit-submit-${triggerNodeCollectionName}-form`).hover();
|
|
@@ -143,15 +149,20 @@ test.describe('Configuration page to configure the Trigger node', () => {
|
|
|
143
149
|
const formEventTriggerNode = new FormEventTriggerNode(page, workFlowName, triggerNodeCollectionName);
|
|
144
150
|
await formEventTriggerNode.nodeConfigure.click();
|
|
145
151
|
await formEventTriggerNode.collectionDropDown.click();
|
|
146
|
-
await page.getByRole('
|
|
152
|
+
await page.getByRole('menuitemcheckbox', { name: 'Main right' }).click();
|
|
153
|
+
await page.getByRole('menuitemcheckbox', { name: triggerNodeCollectionDisplayName }).click();
|
|
147
154
|
await formEventTriggerNode.submitButton.click();
|
|
148
155
|
|
|
149
156
|
//配置录入数据区块
|
|
150
157
|
const newPage = mockPage();
|
|
151
158
|
await newPage.goto();
|
|
152
159
|
await page.waitForLoadState('networkidle');
|
|
153
|
-
await page.getByLabel('schema-initializer-Grid-
|
|
160
|
+
await page.getByLabel('schema-initializer-Grid-page:addBlock').hover();
|
|
154
161
|
await page.getByRole('menuitem', { name: 'table Table' }).hover();
|
|
162
|
+
const dataSourcesCount = await apiGetDataSourceCount();
|
|
163
|
+
if (dataSourcesCount > 1) {
|
|
164
|
+
await page.getByRole('menuitem', { name: 'Main right' }).hover();
|
|
165
|
+
}
|
|
155
166
|
await page.getByRole('menuitem', { name: `${triggerNodeCollectionDisplayName}` }).click();
|
|
156
167
|
|
|
157
168
|
// 移开鼠标,关闭菜单
|
|
@@ -164,7 +175,7 @@ test.describe('Configuration page to configure the Trigger node', () => {
|
|
|
164
175
|
await expect(page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch')).toBeEnabled();
|
|
165
176
|
|
|
166
177
|
await page.getByLabel(`action-Action-Add new-create-${triggerNodeCollectionName}-table`).click();
|
|
167
|
-
await page.getByLabel(`schema-initializer-Grid-
|
|
178
|
+
await page.getByLabel(`schema-initializer-Grid-popup:addNew:addBlock-${triggerNodeCollectionName}`).hover();
|
|
168
179
|
await page.getByRole('menuitem', { name: 'form Form' }).click();
|
|
169
180
|
|
|
170
181
|
// 移开鼠标,关闭菜单
|
|
@@ -172,11 +183,11 @@ test.describe('Configuration page to configure the Trigger node', () => {
|
|
|
172
183
|
|
|
173
184
|
// 绑定工作流
|
|
174
185
|
await page
|
|
175
|
-
.getByLabel(`schema-initializer-ActionBar-
|
|
186
|
+
.getByLabel(`schema-initializer-ActionBar-createForm:configureActions-${triggerNodeCollectionName}`)
|
|
176
187
|
.hover();
|
|
177
188
|
await page.getByRole('menuitem', { name: 'Customize' }).hover();
|
|
178
189
|
await page.getByRole('menuitem', { name: 'Submit to workflow' }).click();
|
|
179
|
-
await page.getByLabel(`schema-initializer-Grid-
|
|
190
|
+
await page.getByLabel(`schema-initializer-Grid-form:configureFields-${triggerNodeCollectionName}`).hover();
|
|
180
191
|
await page.getByRole('menuitem', { name: `${triggerNodeFieldDisplayName}` }).click();
|
|
181
192
|
await page.mouse.move(300, 0);
|
|
182
193
|
await page.getByRole('button', { name: 'Submit to workflow' }).hover();
|
|
@@ -649,8 +660,11 @@ test.describe('Configuration page copy to new version', () => {
|
|
|
649
660
|
// 3、预期结果:新版本工作流配置内容同旧版本一样
|
|
650
661
|
const formEventTriggerNode = new FormEventTriggerNode(page, workFlowName, triggerNodeCollectionName);
|
|
651
662
|
await formEventTriggerNode.nodeConfigure.click();
|
|
652
|
-
await expect(
|
|
653
|
-
|
|
663
|
+
await expect(
|
|
664
|
+
page
|
|
665
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
666
|
+
.getByText(`Main / ${triggerNodeCollectionDisplayName}`),
|
|
667
|
+
).toBeVisible();
|
|
654
668
|
// 4、后置处理:删除工作流
|
|
655
669
|
await apiDeleteWorkflow(workflowId);
|
|
656
670
|
});
|
package/src/client/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Plugin, SchemaInitializerItemType } from '@nocobase/client';
|
|
2
2
|
import WorkflowPlugin, {
|
|
3
|
-
useTriggerWorkflowsActionProps,
|
|
4
3
|
useRecordTriggerWorkflowsActionProps,
|
|
4
|
+
useTriggerWorkflowsActionProps,
|
|
5
5
|
} from '@nocobase/plugin-workflow/client';
|
|
6
6
|
|
|
7
7
|
import ActionTrigger from './ActionTrigger';
|
|
@@ -76,25 +76,25 @@ export default class extends Plugin {
|
|
|
76
76
|
const FormActionInitializers = this.app.schemaInitializerManager.get('FormActionInitializers');
|
|
77
77
|
FormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
|
78
78
|
|
|
79
|
-
const CreateFormActionInitializers = this.app.schemaInitializerManager.get('
|
|
79
|
+
const CreateFormActionInitializers = this.app.schemaInitializerManager.get('createForm:configureActions');
|
|
80
80
|
CreateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
|
81
81
|
|
|
82
|
-
const UpdateFormActionInitializers = this.app.schemaInitializerManager.get('
|
|
82
|
+
const UpdateFormActionInitializers = this.app.schemaInitializerManager.get('editForm:configureActions');
|
|
83
83
|
UpdateFormActionInitializers.add('customize.submitToWorkflow', submitToWorkflowActionInitializer);
|
|
84
84
|
|
|
85
|
-
const DetailsActionInitializers = this.app.schemaInitializerManager.get('
|
|
85
|
+
const DetailsActionInitializers = this.app.schemaInitializerManager.get('detailsWithPaging:configureActions');
|
|
86
86
|
DetailsActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
|
|
87
87
|
|
|
88
|
-
const ReadPrettyFormActionInitializers = this.app.schemaInitializerManager.get('
|
|
88
|
+
const ReadPrettyFormActionInitializers = this.app.schemaInitializerManager.get('details:configureActions');
|
|
89
89
|
ReadPrettyFormActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionInitializer);
|
|
90
90
|
|
|
91
|
-
const TableActionColumnInitializers = this.app.schemaInitializerManager.get('
|
|
91
|
+
const TableActionColumnInitializers = this.app.schemaInitializerManager.get('table:configureItemActions');
|
|
92
92
|
TableActionColumnInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
|
93
93
|
|
|
94
|
-
const GridCardItemActionInitializers = this.app.schemaInitializerManager.get('
|
|
94
|
+
const GridCardItemActionInitializers = this.app.schemaInitializerManager.get('gridCard:configureItemActions');
|
|
95
95
|
GridCardItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
|
96
96
|
|
|
97
|
-
const ListItemActionInitializers = this.app.schemaInitializerManager.get('
|
|
97
|
+
const ListItemActionInitializers = this.app.schemaInitializerManager.get('list:configureItemActions');
|
|
98
98
|
ListItemActionInitializers.add('customize.submitToWorkflow', recordTriggerWorkflowActionLinkInitializer);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { get } from 'lodash';
|
|
2
2
|
import { BelongsTo, HasOne } from 'sequelize';
|
|
3
3
|
import { Model, modelAssociationByKey } from '@nocobase/database';
|
|
4
|
-
import { DefaultContext } from '@nocobase/server';
|
|
5
|
-
import { ActionContext } from '@nocobase/
|
|
6
|
-
import { Next } from '@nocobase/actions';
|
|
4
|
+
import Application, { DefaultContext } from '@nocobase/server';
|
|
5
|
+
import { Context as ActionContext, Next } from '@nocobase/actions';
|
|
7
6
|
|
|
8
7
|
import WorkflowPlugin, { Trigger, WorkflowModel, toJSON } from '@nocobase/plugin-workflow';
|
|
8
|
+
import { parseCollectionName } from '@nocobase/data-source-manager';
|
|
9
9
|
|
|
10
10
|
interface Context extends ActionContext, DefaultContext {}
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ export default class extends Trigger {
|
|
|
13
13
|
constructor(workflow: WorkflowPlugin) {
|
|
14
14
|
super(workflow);
|
|
15
15
|
|
|
16
|
-
workflow.app.
|
|
16
|
+
workflow.app.use(this.middleware, { after: 'dataSource' });
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
async triggerAction(context: Context, next: Next) {
|
|
@@ -55,10 +55,12 @@ export default class extends Trigger {
|
|
|
55
55
|
|
|
56
56
|
private async trigger(context: Context) {
|
|
57
57
|
const { triggerWorkflows = '', values } = context.action.params;
|
|
58
|
+
const dataSourceHeader = context.get('x-data-source') || 'main';
|
|
58
59
|
|
|
59
60
|
const { currentUser, currentRole } = context.state;
|
|
61
|
+
const { model: UserModel } = this.workflow.db.getCollection('users');
|
|
60
62
|
const userInfo = {
|
|
61
|
-
user:
|
|
63
|
+
user: UserModel.build(currentUser).desensitize(),
|
|
62
64
|
roleName: currentRole,
|
|
63
65
|
};
|
|
64
66
|
|
|
@@ -78,12 +80,16 @@ export default class extends Trigger {
|
|
|
78
80
|
const asyncGroup = [];
|
|
79
81
|
for (const workflow of workflows) {
|
|
80
82
|
const { collection, appends = [] } = workflow.config;
|
|
83
|
+
const [dataSourceName, collectionName] = parseCollectionName(collection);
|
|
81
84
|
const trigger = triggers.find((trigger) => trigger[0] == workflow.key);
|
|
82
85
|
const event = [workflow];
|
|
83
86
|
if (context.action.resourceName !== 'workflows') {
|
|
84
87
|
if (!context.body) {
|
|
85
88
|
continue;
|
|
86
89
|
}
|
|
90
|
+
if (dataSourceName !== dataSourceHeader) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
87
93
|
const { body: data } = context;
|
|
88
94
|
for (const row of Array.isArray(data) ? data : [data]) {
|
|
89
95
|
let payload = row;
|
|
@@ -100,7 +106,7 @@ export default class extends Trigger {
|
|
|
100
106
|
}
|
|
101
107
|
const model = payload.constructor;
|
|
102
108
|
if (payload instanceof Model) {
|
|
103
|
-
if (
|
|
109
|
+
if (collectionName !== model.collection.name) {
|
|
104
110
|
continue;
|
|
105
111
|
}
|
|
106
112
|
if (appends.length) {
|
|
@@ -114,7 +120,9 @@ export default class extends Trigger {
|
|
|
114
120
|
event.push({ data: toJSON(payload), ...userInfo });
|
|
115
121
|
}
|
|
116
122
|
} else {
|
|
117
|
-
const { model, repository } = context.
|
|
123
|
+
const { model, repository } = (<Application>context.app).dataSourceManager.dataSources
|
|
124
|
+
.get(dataSourceName)
|
|
125
|
+
.collectionManager.getCollection(collectionName);
|
|
118
126
|
let data = trigger[1] ? get(values, trigger[1]) : values;
|
|
119
127
|
const pk = get(data, model.primaryKeyAttribute);
|
|
120
128
|
if (appends.length && pk != null) {
|
|
@@ -12,7 +12,7 @@ describe('workflow > action-trigger', () => {
|
|
|
12
12
|
let PostRepo;
|
|
13
13
|
let CommentRepo;
|
|
14
14
|
let WorkflowModel;
|
|
15
|
-
let
|
|
15
|
+
let UserRepo;
|
|
16
16
|
let users;
|
|
17
17
|
let userAgents;
|
|
18
18
|
|
|
@@ -26,12 +26,14 @@ describe('workflow > action-trigger', () => {
|
|
|
26
26
|
WorkflowModel = db.getCollection('workflows').model;
|
|
27
27
|
PostRepo = db.getCollection('posts').repository;
|
|
28
28
|
CommentRepo = db.getCollection('comments').repository;
|
|
29
|
-
|
|
29
|
+
UserRepo = db.getCollection('users').repository;
|
|
30
30
|
|
|
31
|
-
users = await
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
users = await UserRepo.create({
|
|
32
|
+
values: [
|
|
33
|
+
{ id: 2, nickname: 'a', roles: [{ name: 'root' }] },
|
|
34
|
+
{ id: 3, nickname: 'b' },
|
|
35
|
+
],
|
|
36
|
+
});
|
|
35
37
|
|
|
36
38
|
userAgents = users.map((user) => app.agent().login(user));
|
|
37
39
|
});
|
|
@@ -569,4 +571,49 @@ describe('workflow > action-trigger', () => {
|
|
|
569
571
|
expect(e3s[0].status).toBe(EXECUTION_STATUS.RESOLVED);
|
|
570
572
|
});
|
|
571
573
|
});
|
|
574
|
+
|
|
575
|
+
describe('multiple data source', () => {
|
|
576
|
+
it('trigger on different data source', async () => {
|
|
577
|
+
const workflow = await WorkflowModel.create({
|
|
578
|
+
enabled: true,
|
|
579
|
+
type: 'action',
|
|
580
|
+
config: {
|
|
581
|
+
collection: 'another:posts',
|
|
582
|
+
},
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const res1 = await userAgents[0].resource('posts').create({
|
|
586
|
+
values: { title: 't1' },
|
|
587
|
+
triggerWorkflows: `${workflow.key}`,
|
|
588
|
+
});
|
|
589
|
+
expect(res1.status).toBe(200);
|
|
590
|
+
|
|
591
|
+
await sleep(500);
|
|
592
|
+
|
|
593
|
+
const e1s = await workflow.getExecutions();
|
|
594
|
+
expect(e1s.length).toBe(0);
|
|
595
|
+
|
|
596
|
+
// const res2 = await userAgents[0]
|
|
597
|
+
// .set('x-data-source', 'another')
|
|
598
|
+
// .resource('posts')
|
|
599
|
+
// .create({
|
|
600
|
+
// values: { title: 't2' },
|
|
601
|
+
// triggerWorkflows: `${workflow.key}`,
|
|
602
|
+
// });
|
|
603
|
+
const res2 = await agent
|
|
604
|
+
.login(users[0])
|
|
605
|
+
.set('x-data-source', 'another')
|
|
606
|
+
.post('/api/posts:create')
|
|
607
|
+
.query({ triggerWorkflows: `${workflow.key}` })
|
|
608
|
+
.send({ title: 't2' });
|
|
609
|
+
|
|
610
|
+
expect(res2.status).toBe(200);
|
|
611
|
+
|
|
612
|
+
await sleep(500);
|
|
613
|
+
|
|
614
|
+
const e2s = await workflow.getExecutions();
|
|
615
|
+
expect(e2s.length).toBe(1);
|
|
616
|
+
expect(e2s[0].status).toBe(EXECUTION_STATUS.RESOLVED);
|
|
617
|
+
});
|
|
618
|
+
});
|
|
572
619
|
});
|