diff --git a/packages/core/client/src/locale/zh_CN.ts b/packages/core/client/src/locale/zh_CN.ts
index 77f918b13..f4e9c53ce 100644
--- a/packages/core/client/src/locale/zh_CN.ts
+++ b/packages/core/client/src/locale/zh_CN.ts
@@ -540,6 +540,9 @@ export default {
'Load failed': '加载失败',
'Trigger': '触发器',
+ 'Trigger context': '触发数据',
+ 'Trigger data': '触发数据',
+ 'Trigger time': '触发时间',
'Triggered at': '触发时间',
'Collection event': '数据表事件',
'Trigger on': '触发时机',
@@ -585,7 +588,6 @@ export default {
'End': '结束',
- 'Trigger context': '触发数据',
'Node result': '节点数据',
'Constant': '常量',
diff --git a/packages/plugins/workflow/src/client/nodes/calculation.tsx b/packages/plugins/workflow/src/client/nodes/calculation.tsx
index 2fe7fd364..c2e2a1bc6 100644
--- a/packages/plugins/workflow/src/client/nodes/calculation.tsx
+++ b/packages/plugins/workflow/src/client/nodes/calculation.tsx
@@ -1,5 +1,5 @@
-import { css } from '@emotion/css';
import React from 'react';
+import { css } from '@emotion/css';
import { useTranslation } from 'react-i18next';
import { Calculation } from '../calculators';
diff --git a/packages/plugins/workflow/src/client/triggers/collection.tsx b/packages/plugins/workflow/src/client/triggers/collection.tsx
index 742720226..16755e32b 100644
--- a/packages/plugins/workflow/src/client/triggers/collection.tsx
+++ b/packages/plugins/workflow/src/client/triggers/collection.tsx
@@ -42,6 +42,20 @@ const FieldsSelect = observer((props) => {
);
});
+const COLLECTION_TRIGGER_MODE = {
+ CREATED: 1,
+ UPDATED: 2,
+ SAVED: 3,
+ DELETED: 4,
+};
+
+const collectionModeOptions = [
+ { label: '{{t("After record added")}}', value: COLLECTION_TRIGGER_MODE.CREATED },
+ { label: '{{t("After record updated")}}', value: COLLECTION_TRIGGER_MODE.UPDATED },
+ { label: '{{t("After record added or updated")}}', value: COLLECTION_TRIGGER_MODE.SAVED },
+ { label: '{{t("After record deleted")}}', value: COLLECTION_TRIGGER_MODE.DELETED },
+];
+
export default {
@@ -85,12 +99,7 @@ export default {
'x-decorator': 'FormItem',
'x-component': 'Select',
'x-component-props': {
- options: [
- { value: 1, label: '{{t("After record added")}}' },
- { value: 2, label: '{{t("After record updated")}}' },
- { value: 3, label: '{{t("After record added or updated")}}' },
- { value: 4, label: '{{t("After record deleted")}}' }
- ],
+ options: collectionModeOptions,
placeholder: '{{t("Trigger on")}}'
},
required: true,
@@ -99,7 +108,7 @@ export default {
target: 'config.changed',
fulfill: {
state: {
- disabled: '{{!($self.value & 0b010)}}',
+ disabled: `{{!($self.value & ${COLLECTION_TRIGGER_MODE.UPDATED})}}`,
},
}
},
diff --git a/packages/plugins/workflow/src/client/triggers/schedule/ScheduleConfig.tsx b/packages/plugins/workflow/src/client/triggers/schedule/ScheduleConfig.tsx
index 0b3013f48..0d5fa8c53 100644
--- a/packages/plugins/workflow/src/client/triggers/schedule/ScheduleConfig.tsx
+++ b/packages/plugins/workflow/src/client/triggers/schedule/ScheduleConfig.tsx
@@ -9,9 +9,10 @@ import { collection } from '../../schemas/collection';
import { OnField } from './OnField';
import { EndsByField } from './EndsByField';
import { RepeatField } from './RepeatField';
+import { SCHEDULE_MODE } from './constants';
const ModeFieldsets = {
- 0: {
+ [SCHEDULE_MODE.STATIC]: {
startsOn: {
type: 'datetime',
name: 'startsOn',
@@ -70,7 +71,7 @@ const ModeFieldsets = {
}
}
},
- 1: {
+ [SCHEDULE_MODE.COLLECTION_FIELD]: {
collection: {
...collection,
'x-reactions': [
@@ -148,6 +149,11 @@ const ModeFieldsets = {
}
};
+const scheduleModeOptions = [
+ { value: SCHEDULE_MODE.STATIC, label: '{{t("Based on certain date")}}' },
+ { value: SCHEDULE_MODE.COLLECTION_FIELD, label: '{{t("Based on date field of collection")}}' },
+]
+
export const ScheduleConfig = () => {
const { values = {}, clearFormGraph } = useForm();
const { config = {} } = values;
@@ -173,10 +179,7 @@ export const ScheduleConfig = () => {
'x-decorator': 'FormItem',
'x-component': 'Radio.Group',
'x-component-props': {
- options: [
- { value: 0, label: '{{t("Based on certain date")}}' },
- { value: 1, label: '{{t("Based on date field of collection")}}' },
- ]
+ options: scheduleModeOptions
},
required: true
}}
diff --git a/packages/plugins/workflow/src/client/triggers/schedule/constants.ts b/packages/plugins/workflow/src/client/triggers/schedule/constants.ts
new file mode 100644
index 000000000..1fb952059
--- /dev/null
+++ b/packages/plugins/workflow/src/client/triggers/schedule/constants.ts
@@ -0,0 +1,4 @@
+export const SCHEDULE_MODE = {
+ STATIC: 0,
+ COLLECTION_FIELD: 1
+};
diff --git a/packages/plugins/workflow/src/client/triggers/schedule/index.tsx b/packages/plugins/workflow/src/client/triggers/schedule/index.tsx
index 8aa2ad6e1..12f788b8c 100644
--- a/packages/plugins/workflow/src/client/triggers/schedule/index.tsx
+++ b/packages/plugins/workflow/src/client/triggers/schedule/index.tsx
@@ -1,12 +1,14 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
-import { Select } from 'antd';
+import { css } from '@emotion/css';
+import { Cascader } from 'antd';
import { useCompile, useCollectionDataSource, useCollectionManager } from '@nocobase/client';
import { ScheduleConfig } from './ScheduleConfig';
import { useFlowContext } from '../../FlowContext';
import { BaseTypeSet } from '../../calculators';
+import { SCHEDULE_MODE } from './constants';
export default {
title: '{{t("Schedule event")}}',
@@ -29,24 +31,35 @@ export default {
getter({ type, options, onChange }) {
const { t } = useTranslation();
const compile = useCompile();
- const { collections = [] } = useCollectionManager();
const { workflow } = useFlowContext();
- const collection = collections.find(item => item.name === workflow.config.collection) ?? { fields: [] };
-
- return (
-
+ .map(field => ({
+ value: field.name,
+ label: compile(field.uiSchema?.title),
+ }))
+ });
+ }
+ return (
+ {
+ onChange({ type, options: { ...options, path: next.join('.') } });
+ }}
+ allowClear={false}
+ />
);
}
};
diff --git a/packages/plugins/workflow/src/server/Plugin.ts b/packages/plugins/workflow/src/server/Plugin.ts
index 918527692..63ad67e44 100644
--- a/packages/plugins/workflow/src/server/Plugin.ts
+++ b/packages/plugins/workflow/src/server/Plugin.ts
@@ -156,7 +156,7 @@ export default class WorkflowPlugin extends Plugin {
key: workflow.key,
status: EXECUTION_STATUS.STARTED,
useTransaction: workflow.useTransaction,
- transaction: transaction.id
+ transaction: transaction?.id
}, { transaction });
console.log('workflow triggered:', new Date(), workflow.id, execution.id);
diff --git a/packages/plugins/workflow/src/server/__tests__/instructions/delay.test.ts b/packages/plugins/workflow/src/server/__tests__/instructions/delay.test.ts
index 0fa83ea2e..d8351e849 100644
--- a/packages/plugins/workflow/src/server/__tests__/instructions/delay.test.ts
+++ b/packages/plugins/workflow/src/server/__tests__/instructions/delay.test.ts
@@ -79,6 +79,44 @@ describe('workflow > instructions > delay', () => {
const [j2] = await e2.getJobs();
expect(j2.status).toBe(JOB_STATUS.REJECTED);
});
+
+ it('delay to resolve and rollback in downstream node', async () => {
+ const n1 = await workflow.createNode({
+ type: 'delay',
+ config: {
+ duration: 1000,
+ endStatus: JOB_STATUS.RESOLVED
+ }
+ });
+ const n2 = await workflow.createNode({
+ type: 'create',
+ config: {
+ collection: 'comment',
+ params: {
+ values: {
+ status: 'should be number but use string to raise an error'
+ }
+ }
+ },
+ upstreamId: n1.id
+ });
+ await n1.setDownstream(n2);
+
+ const post = await PostRepo.create({ values: { title: 't1' } });
+
+ const [e1] = await workflow.getExecutions();
+ expect(e1.status).toEqual(EXECUTION_STATUS.STARTED);
+ const [j1] = await e1.getJobs();
+ expect(j1.status).toBe(JOB_STATUS.PENDING);
+
+ await sleep(2000);
+
+ const [e2] = await workflow.getExecutions();
+ expect(e2.status).toEqual(EXECUTION_STATUS.REJECTED);
+ const [j2, j3] = await e2.getJobs({ order: [['id', 'ASC']] });
+ expect(j2.status).toBe(JOB_STATUS.RESOLVED);
+ expect(j3.status).toBe(JOB_STATUS.REJECTED);
+ });
});
describe('app lifecycle', () => {