fix(plugin-workflow): fix trigger getter (#1060)
This commit is contained in:
parent
2aa4468763
commit
1bd3e93588
@ -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': '常量',
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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})}}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -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
|
||||
}}
|
||||
|
@ -0,0 +1,4 @@
|
||||
export const SCHEDULE_MODE = {
|
||||
STATIC: 0,
|
||||
COLLECTION_FIELD: 1
|
||||
};
|
@ -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 (
|
||||
<Select
|
||||
placeholder={t('Fields')}
|
||||
value={options?.path?.replace(/^data\./, '')}
|
||||
onChange={(path) => {
|
||||
onChange({ type, options: { ...options, path: `data.${path}` } });
|
||||
}}
|
||||
>
|
||||
{collection.fields
|
||||
const { collections = [] } = useCollectionManager();
|
||||
const path = options?.path ? options.path.split('.') : [];
|
||||
const varOptions: any[] = [
|
||||
{ value: 'date', label: t('Trigger time') },
|
||||
];
|
||||
if (workflow.config.mode === SCHEDULE_MODE.COLLECTION_FIELD) {
|
||||
const collection = collections.find(item => item.name === workflow.config.collection) ?? { fields: [] };
|
||||
varOptions.push({
|
||||
value: 'data',
|
||||
label: t('Trigger data'),
|
||||
children: collection.fields
|
||||
.filter(field => BaseTypeSet.has(field?.uiSchema?.type))
|
||||
.map(field => (
|
||||
<Select.Option key={field.name} value={field.name}>{compile(field.uiSchema.title)}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
.map(field => ({
|
||||
value: field.name,
|
||||
label: compile(field.uiSchema?.title),
|
||||
}))
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Cascader
|
||||
placeholder={t('Trigger context')}
|
||||
value={path}
|
||||
options={varOptions}
|
||||
onChange={(next) => {
|
||||
onChange({ type, options: { ...options, path: next.join('.') } });
|
||||
}}
|
||||
allowClear={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user