mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 05:29:26 +08:00
fix(plugin-workflow): fix tasks count (#6474)
* fix(plugin-workflow): fix tasks count * fix(plugin-workflow): add filter * fix(plugin-workflow): always refresh all counts * refactor(plugin-workflow): change to delete tasks when workflow deleted * feat(plugin-workflow): add reload when click menu link
This commit is contained in:
parent
fd7c839228
commit
cba610ecc8
@ -64,7 +64,11 @@ export interface TaskTypeOptions {
|
|||||||
// children?: TaskTypeOptions[];
|
// children?: TaskTypeOptions[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const TasksCountsContext = createContext<{ counts: Record<string, number>; total: number }>({ counts: {}, total: 0 });
|
const TasksCountsContext = createContext<{ reload: () => void; counts: Record<string, number>; total: number }>({
|
||||||
|
reload() {},
|
||||||
|
counts: {},
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
|
||||||
function MenuLink({ type }: any) {
|
function MenuLink({ type }: any) {
|
||||||
const workflowPlugin = usePlugin(PluginWorkflowClient);
|
const workflowPlugin = usePlugin(PluginWorkflowClient);
|
||||||
@ -299,13 +303,13 @@ export function WorkflowTasks() {
|
|||||||
|
|
||||||
function WorkflowTasksLink() {
|
function WorkflowTasksLink() {
|
||||||
const workflowPlugin = usePlugin(PluginWorkflowClient);
|
const workflowPlugin = usePlugin(PluginWorkflowClient);
|
||||||
const { total } = useContext(TasksCountsContext);
|
const { reload, total } = useContext(TasksCountsContext);
|
||||||
|
|
||||||
const types = Array.from(workflowPlugin.taskTypes.getKeys());
|
const types = Array.from(workflowPlugin.taskTypes.getKeys());
|
||||||
return types.length ? (
|
return types.length ? (
|
||||||
<Tooltip title={lang('Workflow todos')}>
|
<Tooltip title={lang('Workflow todos')}>
|
||||||
<Button>
|
<Button>
|
||||||
<Link to={`/admin/workflow/tasks/${types[0]}`}>
|
<Link to={`/admin/workflow/tasks/${types[0]}`} onClick={reload}>
|
||||||
<Badge count={total} size="small">
|
<Badge count={total} size="small">
|
||||||
<CheckCircleOutlined />
|
<CheckCircleOutlined />
|
||||||
</Badge>
|
</Badge>
|
||||||
@ -326,12 +330,7 @@ function TasksCountsProvider(props: any) {
|
|||||||
const app = useApp();
|
const app = useApp();
|
||||||
const [counts, setCounts] = useState<Record<string, number>>({});
|
const [counts, setCounts] = useState<Record<string, number>>({});
|
||||||
const onTaskUpdate = useCallback(({ detail = [] }: CustomEvent) => {
|
const onTaskUpdate = useCallback(({ detail = [] }: CustomEvent) => {
|
||||||
setCounts((prev) => {
|
setCounts(transform(detail));
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
...transform(detail),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { runAsync } = useRequest(
|
const { runAsync } = useRequest(
|
||||||
@ -344,21 +343,20 @@ function TasksCountsProvider(props: any) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
const reload = useCallback(() => {
|
||||||
runAsync()
|
runAsync()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setCounts((prev) => {
|
setCounts(transform(res['data']));
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
...transform(res['data']),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
}, [runAsync]);
|
}, [runAsync]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
reload();
|
||||||
|
}, [reload]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
app.eventBus.addEventListener('ws:message:workflow:tasks:updated', onTaskUpdate);
|
app.eventBus.addEventListener('ws:message:workflow:tasks:updated', onTaskUpdate);
|
||||||
|
|
||||||
@ -369,7 +367,7 @@ function TasksCountsProvider(props: any) {
|
|||||||
|
|
||||||
const total = Object.values(counts).reduce((a, b) => a + b, 0) || 0;
|
const total = Object.values(counts).reduce((a, b) => a + b, 0) || 0;
|
||||||
|
|
||||||
return <TasksCountsContext.Provider value={{ total, counts }}>{props.children}</TasksCountsContext.Provider>;
|
return <TasksCountsContext.Provider value={{ reload, total, counts }}>{props.children}</TasksCountsContext.Provider>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TasksProvider = (props: any) => {
|
export const TasksProvider = (props: any) => {
|
||||||
|
@ -283,9 +283,17 @@ export default class PluginWorkflowServer extends Plugin {
|
|||||||
db.on('workflows.afterUpdate', (model: WorkflowModel, { transaction }) =>
|
db.on('workflows.afterUpdate', (model: WorkflowModel, { transaction }) =>
|
||||||
this.toggle(model, model.enabled, { transaction }),
|
this.toggle(model, model.enabled, { transaction }),
|
||||||
);
|
);
|
||||||
db.on('workflows.afterDestroy', (model: WorkflowModel, { transaction }) =>
|
db.on('workflows.afterDestroy', async (model: WorkflowModel, { transaction }) => {
|
||||||
this.toggle(model, false, { transaction }),
|
this.toggle(model, false, { transaction });
|
||||||
);
|
|
||||||
|
const TaskRepo = this.db.getRepository('workflowTasks');
|
||||||
|
await TaskRepo.destroy({
|
||||||
|
filter: {
|
||||||
|
workflowId: model.id,
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// [Life Cycle]:
|
// [Life Cycle]:
|
||||||
// * load all workflows in db
|
// * load all workflows in db
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* 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 { MockServer } from '@nocobase/test';
|
||||||
|
import Database from '@nocobase/database';
|
||||||
|
import { getApp } from '@nocobase/plugin-workflow-test';
|
||||||
|
|
||||||
|
import Plugin from '..';
|
||||||
|
|
||||||
|
describe('workflow > tasks', () => {
|
||||||
|
let app: MockServer;
|
||||||
|
let db: Database;
|
||||||
|
let PostRepo;
|
||||||
|
let WorkflowModel;
|
||||||
|
let plugin: Plugin;
|
||||||
|
let TaskRepo;
|
||||||
|
let UserRepo;
|
||||||
|
let users;
|
||||||
|
let userAgents;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = await getApp({
|
||||||
|
plugins: ['users', 'auth'],
|
||||||
|
});
|
||||||
|
db = app.db;
|
||||||
|
WorkflowModel = db.getCollection('workflows').model;
|
||||||
|
PostRepo = db.getCollection('posts').repository;
|
||||||
|
plugin = app.pm.get(Plugin) as Plugin;
|
||||||
|
TaskRepo = db.getCollection('workflowTasks').repository;
|
||||||
|
UserRepo = db.getCollection('users').repository;
|
||||||
|
|
||||||
|
await UserRepo.create({});
|
||||||
|
users = await UserRepo.find();
|
||||||
|
userAgents = await Promise.all(users.map((user) => app.agent().login(user)));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => app.destroy());
|
||||||
|
|
||||||
|
describe('filter', () => {
|
||||||
|
it('only count current user tasks', async () => {
|
||||||
|
const workflow = await WorkflowModel.create({
|
||||||
|
sync: true,
|
||||||
|
enabled: true,
|
||||||
|
type: 'syncTrigger',
|
||||||
|
});
|
||||||
|
|
||||||
|
await plugin.trigger(workflow, {});
|
||||||
|
|
||||||
|
const e1s = await workflow.getExecutions();
|
||||||
|
expect(e1s.length).toBe(1);
|
||||||
|
|
||||||
|
const tasks = await TaskRepo.createMany({
|
||||||
|
records: [
|
||||||
|
{
|
||||||
|
userId: users[0].id,
|
||||||
|
workflowId: workflow.id,
|
||||||
|
type: 'test',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: users[0].id,
|
||||||
|
workflowId: workflow.id,
|
||||||
|
type: 'test',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: users[1].id,
|
||||||
|
workflowId: workflow.id,
|
||||||
|
type: 'test',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const res1 = await userAgents[0].resource('workflowTasks').countMine();
|
||||||
|
|
||||||
|
expect(res1.status).toBe(200);
|
||||||
|
expect(res1.body.data[0].count).toBe(2);
|
||||||
|
|
||||||
|
const res2 = await userAgents[1].resource('workflowTasks').countMine();
|
||||||
|
expect(res2.status).toBe(200);
|
||||||
|
expect(res2.body.data[0].count).toBe(1);
|
||||||
|
|
||||||
|
await workflow.destroy();
|
||||||
|
|
||||||
|
const res3 = await userAgents[0].resource('workflowTasks').countMine();
|
||||||
|
expect(res3.status).toBe(200);
|
||||||
|
expect(res3.body.data.length).toBe(0);
|
||||||
|
const res4 = await userAgents[1].resource('workflowTasks').countMine();
|
||||||
|
expect(res4.status).toBe(200);
|
||||||
|
expect(res4.body.data.length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -7,6 +7,7 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Op } from 'sequelize';
|
||||||
import { Context, utils } from '@nocobase/actions';
|
import { Context, utils } from '@nocobase/actions';
|
||||||
|
|
||||||
import WorkflowTasksRepository from '../repositories/WorkflowTasksRepository';
|
import WorkflowTasksRepository from '../repositories/WorkflowTasksRepository';
|
||||||
@ -20,5 +21,5 @@ export async function countMine(context: Context, next) {
|
|||||||
},
|
},
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
next();
|
await next();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user