mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
fix(plugin-workflow-manual): support to continue manual job when workflow disabled
This commit is contained in:
parent
a2002d8329
commit
6a3329ce3d
@ -338,7 +338,8 @@ function FlowContextProvider(props) {
|
|||||||
appends: ['node', 'job', 'workflow', 'workflow.nodes', 'execution', 'execution.jobs'],
|
appends: ['node', 'job', 'workflow', 'workflow.nodes', 'execution', 'execution.jobs'],
|
||||||
})
|
})
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
const { node, workflow: { nodes = [], ...workflow } = {}, execution, ...userJob } = data?.data ?? {};
|
const { node, workflow: workflowWithNodes, execution, ...userJob } = data?.data ?? {};
|
||||||
|
const { nodes = [], ...workflow } = workflowWithNodes || {};
|
||||||
linkNodes(nodes);
|
linkNodes(nodes);
|
||||||
setNode(node);
|
setNode(node);
|
||||||
setFlowContext({
|
setFlowContext({
|
||||||
@ -682,6 +683,9 @@ function useTodoActionParams(status) {
|
|||||||
filter: {
|
filter: {
|
||||||
...filter,
|
...filter,
|
||||||
userId: user?.data?.id,
|
userId: user?.data?.id,
|
||||||
|
workflowId: {
|
||||||
|
$ne: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
appends: [
|
appends: [
|
||||||
'job.id',
|
'job.id',
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Plugin } from '@nocobase/server';
|
import { Plugin } from '@nocobase/server';
|
||||||
import actions from '@nocobase/actions';
|
import WorkflowPlugin from '@nocobase/plugin-workflow';
|
||||||
import { HandlerType } from '@nocobase/resourcer';
|
|
||||||
import WorkflowPlugin, { JOB_STATUS } from '@nocobase/plugin-workflow';
|
|
||||||
|
|
||||||
import * as jobActions from './actions';
|
import { submit } from './actions';
|
||||||
|
|
||||||
import ManualInstruction from './ManualInstruction';
|
import ManualInstruction from './ManualInstruction';
|
||||||
import { MANUAL_TASK_TYPE } from '../common/constants';
|
import { MANUAL_TASK_TYPE } from '../common/constants';
|
||||||
@ -27,28 +25,7 @@ interface WorkflowManualTaskModel {
|
|||||||
|
|
||||||
export default class extends Plugin {
|
export default class extends Plugin {
|
||||||
async load() {
|
async load() {
|
||||||
this.app.resourceManager.define({
|
this.app.resourceManager.registerActionHandler('workflowManualTasks:submit', submit);
|
||||||
name: 'workflowManualTasks',
|
|
||||||
actions: {
|
|
||||||
list: {
|
|
||||||
filter: {
|
|
||||||
$or: [
|
|
||||||
{
|
|
||||||
'workflow.enabled': true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'workflow.enabled': false,
|
|
||||||
status: {
|
|
||||||
$ne: JOB_STATUS.PENDING,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
handler: actions.list as HandlerType,
|
|
||||||
},
|
|
||||||
...jobActions,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.app.acl.allow('workflowManualTasks', ['list', 'get', 'submit'], 'loggedIn');
|
this.app.acl.allow('workflowManualTasks', ['list', 'get', 'submit'], 'loggedIn');
|
||||||
|
|
||||||
|
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Database from '@nocobase/database';
|
||||||
|
import { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow';
|
||||||
|
import { getApp, sleep } from '@nocobase/plugin-workflow-test';
|
||||||
|
import { MockServer } from '@nocobase/test';
|
||||||
|
|
||||||
|
// NOTE: skipped because time is not stable on github ci, but should work in local
|
||||||
|
describe('workflow > instructions > manual > assignees', () => {
|
||||||
|
let app: MockServer;
|
||||||
|
let agent;
|
||||||
|
let userAgents;
|
||||||
|
let db: Database;
|
||||||
|
let PostRepo;
|
||||||
|
let CommentRepo;
|
||||||
|
let WorkflowModel;
|
||||||
|
let workflow;
|
||||||
|
let UserModel;
|
||||||
|
let users;
|
||||||
|
let UserJobModel;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = await getApp({
|
||||||
|
plugins: ['users', 'auth', 'workflow-manual'],
|
||||||
|
});
|
||||||
|
// await app.getPlugin('auth').install();
|
||||||
|
agent = app.agent();
|
||||||
|
db = app.db;
|
||||||
|
WorkflowModel = db.getCollection('workflows').model;
|
||||||
|
PostRepo = db.getCollection('posts').repository;
|
||||||
|
CommentRepo = db.getCollection('comments').repository;
|
||||||
|
UserModel = db.getCollection('users').model;
|
||||||
|
UserJobModel = db.getModel('workflowManualTasks');
|
||||||
|
|
||||||
|
users = await UserModel.bulkCreate([
|
||||||
|
{ id: 2, nickname: 'a' },
|
||||||
|
{ id: 3, nickname: 'b' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
userAgents = await Promise.all(users.map((user) => app.agent().login(user)));
|
||||||
|
|
||||||
|
workflow = await WorkflowModel.create({
|
||||||
|
enabled: true,
|
||||||
|
type: 'collection',
|
||||||
|
config: {
|
||||||
|
mode: 1,
|
||||||
|
collection: 'posts',
|
||||||
|
appends: ['category', 'category.posts'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => app.destroy());
|
||||||
|
|
||||||
|
describe('workflow status', () => {
|
||||||
|
it('enabled', async () => {
|
||||||
|
const n1 = await workflow.createNode({
|
||||||
|
type: 'manual',
|
||||||
|
config: {
|
||||||
|
assignees: [users[0].id],
|
||||||
|
forms: {
|
||||||
|
f1: {
|
||||||
|
actions: [{ status: JOB_STATUS.RESOLVED, key: 'resolve' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const post = await PostRepo.create({
|
||||||
|
values: { title: 't1', category: { title: 'c1' } },
|
||||||
|
context: { state: { currentUser: users[0] } },
|
||||||
|
});
|
||||||
|
|
||||||
|
await sleep(500);
|
||||||
|
|
||||||
|
const [pending] = await workflow.getExecutions();
|
||||||
|
expect(pending.status).toBe(EXECUTION_STATUS.STARTED);
|
||||||
|
|
||||||
|
const usersJobs = await UserJobModel.findAll();
|
||||||
|
expect(usersJobs.length).toBe(1);
|
||||||
|
|
||||||
|
const res1 = await userAgents[0].resource('workflowManualTasks').submit({
|
||||||
|
filterByTk: usersJobs[0].id,
|
||||||
|
values: { result: { f1: {}, _: 'resolve' } },
|
||||||
|
});
|
||||||
|
expect(res1.status).toBe(202);
|
||||||
|
|
||||||
|
await sleep(500);
|
||||||
|
|
||||||
|
const [resolved] = await workflow.getExecutions();
|
||||||
|
expect(resolved.status).toBe(EXECUTION_STATUS.RESOLVED);
|
||||||
|
const [j1] = await resolved.getJobs();
|
||||||
|
expect(j1.status).toBe(JOB_STATUS.RESOLVED);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disabled after triggered', async () => {
|
||||||
|
const n1 = await workflow.createNode({
|
||||||
|
type: 'manual',
|
||||||
|
config: {
|
||||||
|
assignees: [users[0].id],
|
||||||
|
forms: {
|
||||||
|
f1: {
|
||||||
|
actions: [{ status: JOB_STATUS.RESOLVED, key: 'resolve' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const post = await PostRepo.create({
|
||||||
|
values: { title: 't1', category: { title: 'c1' } },
|
||||||
|
context: { state: { currentUser: users[0] } },
|
||||||
|
});
|
||||||
|
|
||||||
|
await sleep(500);
|
||||||
|
|
||||||
|
const [pending] = await workflow.getExecutions();
|
||||||
|
expect(pending.status).toBe(EXECUTION_STATUS.STARTED);
|
||||||
|
|
||||||
|
const usersJobs = await UserJobModel.findAll();
|
||||||
|
expect(usersJobs.length).toBe(1);
|
||||||
|
|
||||||
|
await workflow.update({
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const res1 = await userAgents[0].resource('workflowManualTasks').submit({
|
||||||
|
filterByTk: usersJobs[0].id,
|
||||||
|
values: { result: { f1: {}, _: 'resolve' } },
|
||||||
|
});
|
||||||
|
expect(res1.status).toBe(202);
|
||||||
|
|
||||||
|
await sleep(500);
|
||||||
|
|
||||||
|
const [resolved] = await workflow.getExecutions();
|
||||||
|
expect(resolved.status).toBe(EXECUTION_STATUS.RESOLVED);
|
||||||
|
const [j1] = await resolved.getJobs();
|
||||||
|
expect(j1.status).toBe(JOB_STATUS.RESOLVED);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -47,7 +47,7 @@ export async function submit(context: Context, next) {
|
|||||||
task.status !== JOB_STATUS.PENDING ||
|
task.status !== JOB_STATUS.PENDING ||
|
||||||
task.job.status !== JOB_STATUS.PENDING ||
|
task.job.status !== JOB_STATUS.PENDING ||
|
||||||
task.execution.status !== EXECUTION_STATUS.STARTED ||
|
task.execution.status !== EXECUTION_STATUS.STARTED ||
|
||||||
!task.workflow.enabled ||
|
// !task.workflow.enabled ||
|
||||||
!actionKey ||
|
!actionKey ||
|
||||||
actionItem?.status == null
|
actionItem?.status == null
|
||||||
) {
|
) {
|
||||||
|
@ -74,6 +74,7 @@ export default defineCollection({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
onDelete: 'SET NULL',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user