diff --git a/packages/core/database/src/model.ts b/packages/core/database/src/model.ts index 93bb0d15d..84f94b479 100644 --- a/packages/core/database/src/model.ts +++ b/packages/core/database/src/model.ts @@ -24,6 +24,38 @@ export class Model 0) { + return Array.from(this._changedWithAssociations); + } + return false; + } + if (value === true) { + this._changedWithAssociations.add(key); + return this; + } + if (value === false) { + this._changedWithAssociations.delete(key); + return this; + } + return this._changedWithAssociations.has(key); + } + + public clearChangedWithAssociations() { + this._changedWithAssociations = new Set(); + } public toJSON(): T { const handleObj = (obj, options: JSONTransformerOptions) => { diff --git a/packages/plugins/workflow/src/client/triggers/collection.tsx b/packages/plugins/workflow/src/client/triggers/collection.tsx index a3bdd97aa..a5a084ab0 100644 --- a/packages/plugins/workflow/src/client/triggers/collection.tsx +++ b/packages/plugins/workflow/src/client/triggers/collection.tsx @@ -33,6 +33,7 @@ const FieldsSelect = observer((props) => { .filter(field => ( !field.hidden && (field.uiSchema ? !field.uiSchema['x-read-pretty'] : true) + && !['linkTo', 'hasOne', 'hasMany', 'belongsToMany'].includes(field.type) )) .map(field => ( {compile(field.uiSchema?.title)} diff --git a/packages/plugins/workflow/src/server/__tests__/triggers/collection.test.ts b/packages/plugins/workflow/src/server/__tests__/triggers/collection.test.ts index c83303eb6..4ec8b5e14 100644 --- a/packages/plugins/workflow/src/server/__tests__/triggers/collection.test.ts +++ b/packages/plugins/workflow/src/server/__tests__/triggers/collection.test.ts @@ -45,4 +45,62 @@ describe('workflow > triggers > collection', () => { expect(executions.length).toBe(0); }); }); + + describe('config.changed', () => { + it('no changed config', async () => { + const workflow = await WorkflowModel.create({ + enabled: true, + type: 'collection', + config: { + mode: 2, + collection: 'posts' + } + }); + + const post = await PostRepo.create({ values: { title: 't1' } }); + await PostRepo.update({ filterByTk: post.id, values: { title: 't2' } }); + + const executions = await workflow.getExecutions(); + expect(executions.length).toBe(1); + expect(executions[0].context.data.title).toBe('t2'); + }); + + it('field in changed config', async () => { + const workflow = await WorkflowModel.create({ + enabled: true, + type: 'collection', + config: { + mode: 2, + collection: 'posts', + changed: ['title'] + } + }); + + const post = await PostRepo.create({ values: { title: 't1' } }); + await PostRepo.update({ filterByTk: post.id, values: { title: 't2' } }); + + const executions = await workflow.getExecutions(); + expect(executions.length).toBe(1); + expect(executions[0].status).toBe(EXECUTION_STATUS.RESOLVED); + expect(executions[0].context.data.title).toBe('t2'); + }); + + it('field not in changed config', async () => { + const workflow = await WorkflowModel.create({ + enabled: true, + type: 'collection', + config: { + mode: 2, + collection: 'posts', + changed: ['published'] + } + }); + + const post = await PostRepo.create({ values: { title: 't1' } }); + await PostRepo.update({ filterByTk: post.id, values: { title: 't2' } }); + + const executions = await workflow.getExecutions(); + expect(executions.length).toBe(0); + }); + }); }); diff --git a/packages/plugins/workflow/src/server/triggers/collection.ts b/packages/plugins/workflow/src/server/triggers/collection.ts index e482a4db8..584286039 100644 --- a/packages/plugins/workflow/src/server/triggers/collection.ts +++ b/packages/plugins/workflow/src/server/triggers/collection.ts @@ -1,5 +1,5 @@ -import { Model } from "@nocobase/database"; -import Plugin, { Trigger } from ".."; +import { Collection, Model } from "@nocobase/database"; +import { Trigger } from ".."; import WorkflowModel from "../models/Workflow"; export interface CollectionChangeTriggerConfig { @@ -26,19 +26,34 @@ function getHookId(workflow, type) { return `${type}#${workflow.id}`; } +function getFieldRawName(collection: Collection, name: string) { + const field = collection.getField(name); + if (field && field.type === 'belongsTo') { + return field.foreignKey; + } + return name; +} + // async function, should return promise async function handler(this: CollectionTrigger, workflow: WorkflowModel, data: Model, options) { - const { collection, condition, changed } = workflow.config; + const { collection: collectionName, condition, changed } = workflow.config; + const collection = (data.constructor).database.getCollection(collectionName); + // NOTE: if no configured fields changed, do not trigger - if (changed && changed.length && changed.every(name => !data.changed(name))) { + if (changed + && changed.length + && changed + .filter(name => !['linkTo', 'hasOne', 'hasMany', 'belongsToMany'].includes(collection.getField(name).type)) + .every(name => !data.changedWithAssociations(getFieldRawName(collection, name))) + ) { // TODO: temp comment out - // return; + return; } // NOTE: if no configured condition match, do not trigger if (condition && condition.$and?.length) { // TODO: change to map filter format to calculation format // const calculation = toCalculation(condition); - const { repository, model } = (data.constructor).database.getCollection(collection); + const { repository, model } = collection; const { transaction, context } = options; const count = await repository.count({ filter: {