tachybase_todo/packages/plugins/@nocobase/plugin-workflow/src/client/AddButton.tsx
Junyi 0e7cb9e5cf
refactor(plugin-workflow): split workflow features into plugins (#3115)
* refactor(plugin-workflow): split manual and dynamic calculation into plugins

* refactor(plugin-workflow): move loop to plugin

* refactor(plugin-workflow): move parallel to plugin

* fix(plugin-dynamic-calculation): fix package title

* fix(plugin-workflow): fix plugin name

* refactor(plugin-workflow): move delay to plugin

* refactor(plugin-workflow): simplify exporting names

* refactor(plugin-workflow): move aggregate to plugin

* refactor(plugin-workflow): move sql to plugin

* refactor(plugin-workflow): move reqeust to plugin

* refactor(plugin-workflow): move form trigger to plugin

* refactor(plugin-workflow): move locale to plugins

* fix(plugin-workflow): fix test cases

* fix(plugin-workflow-request): package name typo

* fix(plugin-workflow): remove clean db from testkit

* fix(plugin-workflow-sql): skip independent case

* fix(plugin-workflow-sql): skip independent case

* fix(plugin-workflow-delay): fix test cases

* test(plugin-workflow-delay): fix test cases

* test(plugin-workflow-delay): fix test cases

* test(plugin-workflow-delay): fix test cases

* test(plugin-workflow-delay): fix test cases

* fix(plugin-workflow): fix migration version matching

* test(plugin-workflow): fix test case

* refactor(plugin-workflow): correct exporting of testkit

* fix(plugin-workflow): fix testkit and require module

* refactor(plugin-workflow): add workflow-test package for testing

* test(plugin-workflow): test weird case

* fix(plugin-workflow-test): remove workflow dependency to avoid cycling

* fix(plugin-workflow): fix migration version

* fix(plugin-workflow): fix migration and packages

* fix(plugin-workflow): fix package dependencies

* fix(preset): fix builtin list in preset

* fix(plugin-workflow): add package entry file

* fix(plugin-workflow): fix migrations

* refactor(plugin-workflow): remove require

* fix(plugin-workflow): fix locale namespace

* fix(plugin-workflow): fix merged errors

* fix(plugin-workflow): fix import cycling references

* refactor(plugin-workflow): change instruction and triggers to classes in client

* fix(plugin-workflow): fix migration version
2023-12-07 05:46:58 -08:00

126 lines
3.8 KiB
TypeScript

import React, { useCallback, useMemo } from 'react';
import { Button, Dropdown, MenuProps } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { css, useAPIClient, useCompile, usePlugin } from '@nocobase/client';
import WorkflowPlugin from '.';
import { useFlowContext } from './FlowContext';
import { NAMESPACE } from './locale';
import { Instruction } from './nodes';
import useStyles from './style';
interface AddButtonProps {
upstream;
branchIndex?: number | null;
[key: string]: any;
}
export function AddButton(props: AddButtonProps) {
const { upstream, branchIndex = null } = props;
const { instructions } = usePlugin(WorkflowPlugin);
const compile = useCompile();
const api = useAPIClient();
const { workflow, refresh } = useFlowContext() ?? {};
const instructionList = Array.from(instructions.getValues()) as Instruction[];
const { styles } = useStyles();
const groups = useMemo(() => {
return [
{ key: 'control', label: `{{t("Control", { ns: "${NAMESPACE}" })}}` },
{ key: 'collection', label: `{{t("Collection operations", { ns: "${NAMESPACE}" })}}` },
{ key: 'manual', label: `{{t("Manual", { ns: "${NAMESPACE}" })}}` },
{ key: 'extended', label: `{{t("Extended types", { ns: "${NAMESPACE}" })}}` },
]
.filter((group) => instructionList.filter((item) => item.group === group.key).length)
.map((group) => {
const groupInstructions = instructionList.filter(
(item) =>
item.group === group.key &&
(item.isAvailable ? item.isAvailable({ workflow, upstream, branchIndex }) : true),
);
return {
...group,
type: 'group',
children: groupInstructions.map((item) => ({
role: 'button',
'aria-label': item.type,
key: item.type,
label: item.title,
type: item.options ? 'subMenu' : null,
children: item.options
? item.options.map((option) => ({
role: 'button',
'aria-label': option.key,
key: option.key,
label: option.label,
}))
: null,
})),
};
});
}, [branchIndex, instructionList, upstream, workflow]);
const resource = useMemo(() => {
if (!workflow) {
return null;
}
return api.resource('workflows.nodes', workflow.id);
}, [workflow?.id]);
const onCreate = useCallback(
async ({ keyPath }) => {
const type = keyPath.pop();
const config = {};
const [optionKey] = keyPath;
const instruction = instructions.get(type);
if (optionKey) {
const { value } = instruction.options?.find((item) => item.key === optionKey) ?? {};
Object.assign(config, typeof value === 'function' ? value() : value);
}
if (resource) {
await resource.create({
values: {
type,
upstreamId: upstream?.id ?? null,
branchIndex,
title: compile(instruction.title),
config,
},
});
refresh();
}
},
[branchIndex, resource?.create, upstream?.id],
);
const menu = useMemo<MenuProps>(() => {
return {
onClick: onCreate,
items: compile(groups),
};
}, [groups, onCreate]);
if (!workflow) {
return null;
}
return (
<div className={styles.addButtonClass}>
<Dropdown
trigger={['click']}
menu={menu}
disabled={workflow.executed}
overlayClassName={css`
.ant-dropdown-menu-root {
max-height: 30em;
overflow-y: auto;
}
`}
>
<Button aria-label={props['aria-label'] || 'add-button'} shape="circle" icon={<PlusOutlined />} />
</Dropdown>
</div>
);
}