@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.
@@ -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-component-props': {
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[];
@@ -1 +1 @@
1
- (function(t,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):(t=typeof globalThis!="undefined"?globalThis:t||self,e(t["@nocobase/plugin-workflow-action-trigger"]={},t["@nocobase/client"],t["@nocobase/plugin-workflow"],t["@formily/react"],t["react-i18next"]))})(this,function(t,e,i,w,m){"use strict";var M=Object.defineProperty,D=Object.defineProperties;var R=Object.getOwnPropertyDescriptors;var y=Object.getOwnPropertySymbols;var q=Object.prototype.hasOwnProperty,L=Object.prototype.propertyIsEnumerable;var A=(t,e,i)=>e in t?M(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i,g=(t,e)=>{for(var i in e||(e={}))q.call(e,i)&&A(t,i,e[i]);if(y)for(var i of y(e))L.call(e,i)&&A(t,i,e[i]);return t},f=(t,e)=>D(t,R(e));var a=(t,e,i)=>(A(t,typeof e!="symbol"?e+"":e,i),i);var S=(t,e,i)=>new Promise((w,m)=>{var s=r=>{try{l(i.next(r))}catch(n){m(n)}},c=r=>{try{l(i.throw(r))}catch(n){m(n)}},l=r=>r.done?w(r.value):Promise.resolve(r.value).then(s,c);l((i=i.apply(t,e)).next())});const s="workflow-action-trigger";function c(u,k={}){const{t:o}=l(k);return o(u)}function l(u){return m.useTranslation(s,u)}class r extends i.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":"CollectionSelect","x-component-props":{className:"auto-width"},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:o}=w.useForm();return o==null?void 0:o.collection}},"x-reactions":[{dependencies:["collection"],fulfill:{state:{visible:"{{!!$deps[0]}}"}}}]}});a(this,"scope",{useCollectionDataSource:e.useCollectionDataSource});a(this,"isActionTriggerable",(o,p)=>["create","update","customize:update","customize:triggerWorkflows"].includes(p.action))}useVariables(o,p){var W;const I=e.useCompile(),{getCollectionFields:h}=e.useCollectionManager_deprecated(),b=c("Trigger data"),T=c("User submitted action"),x=c("Role of user submitted action"),C=[{collectionName:o.collection,name:"data",type:"hasOne",target:o.collection,uiSchema:{title:b}},{collectionName:"users",name:"user",type:"hasOne",target:"users",uiSchema:{title:T}},{name:"roleName",uiSchema:{title:x}}];return i.getCollectionFieldOptions(f(g({appends:["data","user",...((W=o.appends)==null?void 0:W.map(P=>`data.${P}`))||[]]},p),{fields:C,compile:I,getCollectionFields:h}))}useInitializers(o){return o.collection?{name:"triggerData",type:"item",key:"triggerData",title:`{{t("Trigger data", { ns: "${s}" })}}`,Component:i.CollectionBlockInitializer,collection:o.collection,dataSource:"{{$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"}},z=f(g({},d),{schema:f(g({},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:i.useTriggerWorkflowsActionProps,useRecordTriggerWorkflowsActionProps:i.useRecordTriggerWorkflowsActionProps}),this.app.schemaInitializerManager.get("FormActionInitializers").add("customize.submitToWorkflow",n),this.app.schemaInitializerManager.get("CreateFormActionInitializers").add("customize.submitToWorkflow",n),this.app.schemaInitializerManager.get("UpdateFormActionInitializers").add("customize.submitToWorkflow",n),this.app.schemaInitializerManager.get("DetailsActionInitializers").add("customize.submitToWorkflow",d),this.app.schemaInitializerManager.get("ReadPrettyFormActionInitializers").add("customize.submitToWorkflow",d),this.app.schemaInitializerManager.get("TableActionColumnInitializers").add("customize.submitToWorkflow",z),this.app.schemaInitializerManager.get("GridCardItemActionInitializers").add("customize.submitToWorkflow",z),this.app.schemaInitializerManager.get("ListItemActionInitializers").add("customize.submitToWorkflow",z)})}}t.default=F,Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
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"}})});
@@ -1,15 +1,15 @@
1
1
  module.exports = {
2
2
  "@formily/react": "2.3.0",
3
- "@nocobase/client": "0.20.0-alpha.9",
4
- "@nocobase/plugin-workflow": "0.20.0-alpha.9",
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.20.0-alpha.9",
9
- "@nocobase/server": "0.20.0-alpha.9",
10
- "@nocobase/resourcer": "0.20.0-alpha.9",
11
- "@nocobase/actions": "0.20.0-alpha.9",
12
- "@nocobase/plugin-workflow-test": "0.20.0-alpha.9",
13
- "@nocobase/test": "0.20.0-alpha.9",
14
- "@nocobase/utils": "0.20.0-alpha.9"
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/resourcer';
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<any>;
10
- middleware: (context: Context, next: Next) => Promise<any>;
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.resourcer.use(this.middleware);
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: (0, import_plugin_workflow.toJSON)(currentUser),
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 (collection !== model.collection.name) {
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.db.getCollection(collection);
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.20.0-alpha.9",
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": "5473d9039cfdb649a8c8c625edefc9a3ac464be5",
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 { Trigger, CollectionBlockInitializer, getCollectionFieldOptions } from '@nocobase/plugin-workflow/client';
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': 'CollectionSelect',
21
- 'x-component-props': {
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
- dataSource: '{{$context.data}}',
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('option', { name: triggerNodeCollectionDisplayName }).click();
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-BlockInitializers').hover();
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-CreateFormBlockInitializers-${triggerNodeCollectionName}`).hover();
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-CreateFormActionInitializers-${triggerNodeCollectionName}`)
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-FormItemInitializers-${triggerNodeCollectionName}`).hover();
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('option', { name: triggerNodeCollectionDisplayName }).click();
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-BlockInitializers').hover();
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-CreateFormBlockInitializers-${triggerNodeCollectionName}`).hover();
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-CreateFormActionInitializers-${triggerNodeCollectionName}`)
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-FormItemInitializers-${triggerNodeCollectionName}`).hover();
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(page.getByRole('button', { name: triggerNodeCollectionDisplayName })).toBeVisible();
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
  });
@@ -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('CreateFormActionInitializers');
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('UpdateFormActionInitializers');
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('DetailsActionInitializers');
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('ReadPrettyFormActionInitializers');
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('TableActionColumnInitializers');
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('GridCardItemActionInitializers');
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('ListItemActionInitializers');
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/resourcer';
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.resourcer.use(this.middleware);
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: toJSON(currentUser),
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 (collection !== model.collection.name) {
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.db.getCollection(collection);
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 UserModel;
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
- UserModel = db.getCollection('users').model;
29
+ UserRepo = db.getCollection('users').repository;
30
30
 
31
- users = await UserModel.bulkCreate([
32
- { id: 2, nickname: 'a' },
33
- { id: 3, nickname: 'b' },
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
  });