mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-09 14:09:52 +00:00
refactor(ui): clean code
This commit is contained in:
parent
b7cd07c996
commit
849e065bb2
@ -93,6 +93,7 @@ module.exports = {
|
|||||||
ignoreDeclarationSort: true,
|
ignoreDeclarationSort: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"tailwindcss/no-custom-classname": "off",
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
|
@ -4,7 +4,7 @@ import { Button, Drawer, type DrawerProps, Form, type FormProps, type ModalProps
|
|||||||
|
|
||||||
import { useAntdForm, useTriggerElement } from "@/hooks";
|
import { useAntdForm, useTriggerElement } from "@/hooks";
|
||||||
|
|
||||||
export interface DrawerFormProps<T extends NonNullable<unknown> = NonNullable<unknown>> extends Omit<FormProps<T>, "title" | "onFinish"> {
|
export interface DrawerFormProps<T extends NonNullable<unknown> = any> extends Omit<FormProps<T>, "title" | "onFinish"> {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@ -22,7 +22,7 @@ export interface DrawerFormProps<T extends NonNullable<unknown> = NonNullable<un
|
|||||||
onFinish?: (values: T) => void | Promise<unknown>;
|
onFinish?: (values: T) => void | Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DrawerForm = <T extends NonNullable<unknown> = NonNullable<unknown>>({
|
const DrawerForm = <T extends NonNullable<unknown> = any>({
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
children,
|
children,
|
||||||
|
@ -3,7 +3,7 @@ import { Form, type FormProps, Modal, type ModalProps } from "antd";
|
|||||||
|
|
||||||
import { useAntdForm, useTriggerElement } from "@/hooks";
|
import { useAntdForm, useTriggerElement } from "@/hooks";
|
||||||
|
|
||||||
export interface ModalFormProps<T extends NonNullable<unknown> = NonNullable<unknown>> extends Omit<FormProps<T>, "title" | "onFinish"> {
|
export interface ModalFormProps<T extends NonNullable<unknown> = any> extends Omit<FormProps<T>, "title" | "onFinish"> {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@ -35,7 +35,7 @@ export interface ModalFormProps<T extends NonNullable<unknown> = NonNullable<unk
|
|||||||
onFinish?: (values: T) => void | Promise<unknown>;
|
onFinish?: (values: T) => void | Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalForm = <T extends NonNullable<unknown> = NonNullable<unknown>>({
|
const ModalForm = <T extends NonNullable<unknown> = any>({
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
children,
|
children,
|
||||||
|
@ -4,13 +4,13 @@ import Panel from "./Panel";
|
|||||||
|
|
||||||
type PanelContentProps = { name: string; children: React.ReactNode };
|
type PanelContentProps = { name: string; children: React.ReactNode };
|
||||||
|
|
||||||
type PanelContextType = {
|
type PanelContextProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
showPanel: ({ name, children }: PanelContentProps) => void;
|
showPanel: ({ name, children }: PanelContentProps) => void;
|
||||||
hidePanel: () => void;
|
hidePanel: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const PanelContext = createContext<PanelContextType | undefined>(undefined);
|
const PanelContext = createContext<PanelContextProps | undefined>(undefined);
|
||||||
|
|
||||||
export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
|
export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
@ -20,6 +20,7 @@ export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
setOpen(true);
|
setOpen(true);
|
||||||
setPanelContent(panelContent);
|
setPanelContent(panelContent);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hidePanel = () => {
|
const hidePanel = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setPanelContent(null);
|
setPanelContent(null);
|
||||||
@ -36,7 +37,7 @@ export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
export const usePanel = () => {
|
export const usePanel = () => {
|
||||||
const context = useContext(PanelContext);
|
const context = useContext(PanelContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error("useDialog must be used within DialogProvider");
|
throw new Error("`usePanel` must be used within PanelProvider");
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
import NodeRender from "@/components/workflow/NodeRender";
|
|
||||||
import WorkflowProvider from "@/components/workflow/WorkflowProvider";
|
import WorkflowProvider from "@/components/workflow/WorkflowProvider";
|
||||||
import EndNode from "@/components/workflow/node/EndNode";
|
import EndNode from "@/components/workflow/node/EndNode";
|
||||||
|
import NodeRender from "@/components/workflow/node/NodeRender";
|
||||||
import { type WorkflowNode } from "@/domain/workflow";
|
import { type WorkflowNode } from "@/domain/workflow";
|
||||||
import { useZustandShallowSelector } from "@/hooks";
|
import { useZustandShallowSelector } from "@/hooks";
|
||||||
import { useWorkflowStore } from "@/stores/workflow";
|
import { useWorkflowStore } from "@/stores/workflow";
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
CloudUploadOutlined as CloudUploadOutlinedIcon,
|
CloudUploadOutlined as CloudUploadOutlinedIcon,
|
||||||
PlusOutlined as PlusOutlinedIcon,
|
PlusOutlined as PlusOutlinedIcon,
|
||||||
@ -7,60 +9,45 @@ import {
|
|||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { Dropdown } from "antd";
|
import { Dropdown } from "antd";
|
||||||
|
|
||||||
import { WorkflowNodeType, newNode, workflowNodeTypeDefaultNames } from "@/domain/workflow";
|
import { type WorkflowNode, WorkflowNodeType, newNode } from "@/domain/workflow";
|
||||||
import { useZustandShallowSelector } from "@/hooks";
|
import { useZustandShallowSelector } from "@/hooks";
|
||||||
import { useWorkflowStore } from "@/stores/workflow";
|
import { useWorkflowStore } from "@/stores/workflow";
|
||||||
|
|
||||||
import { type BrandNodeProps, type NodeProps } from "../types";
|
export type AddNodeProps = {
|
||||||
|
node: WorkflowNode;
|
||||||
|
};
|
||||||
|
|
||||||
const dropdownMenus = [
|
const AddNode = ({ node }: AddNodeProps) => {
|
||||||
{
|
const { t } = useTranslation();
|
||||||
type: WorkflowNodeType.Apply,
|
|
||||||
label: workflowNodeTypeDefaultNames.get(WorkflowNodeType.Apply),
|
|
||||||
icon: <SolutionOutlinedIcon />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: WorkflowNodeType.Deploy,
|
|
||||||
label: workflowNodeTypeDefaultNames.get(WorkflowNodeType.Deploy),
|
|
||||||
icon: <CloudUploadOutlinedIcon />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: WorkflowNodeType.Branch,
|
|
||||||
label: workflowNodeTypeDefaultNames.get(WorkflowNodeType.Branch),
|
|
||||||
icon: <SisternodeOutlinedIcon />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: WorkflowNodeType.Notify,
|
|
||||||
label: workflowNodeTypeDefaultNames.get(WorkflowNodeType.Notify),
|
|
||||||
icon: <SendOutlinedIcon />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const AddNode = ({ node: supnode }: NodeProps | BrandNodeProps) => {
|
|
||||||
const { addNode } = useWorkflowStore(useZustandShallowSelector(["addNode"]));
|
const { addNode } = useWorkflowStore(useZustandShallowSelector(["addNode"]));
|
||||||
|
|
||||||
|
const dropdownMenus = useMemo(() => {
|
||||||
|
return [
|
||||||
|
[WorkflowNodeType.Apply, "workflow_node.apply.label", <SolutionOutlinedIcon />],
|
||||||
|
[WorkflowNodeType.Deploy, "workflow_node.deploy.label", <CloudUploadOutlinedIcon />],
|
||||||
|
[WorkflowNodeType.Branch, "workflow_node.branch.label", <SisternodeOutlinedIcon />],
|
||||||
|
[WorkflowNodeType.Notify, "workflow_node.notify.label", <SendOutlinedIcon />],
|
||||||
|
].map(([type, label, icon]) => {
|
||||||
|
return {
|
||||||
|
key: type as string,
|
||||||
|
label: t(label as string),
|
||||||
|
icon: icon,
|
||||||
|
onClick: () => {
|
||||||
|
handleNodeTypeSelect(type as WorkflowNodeType);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleNodeTypeSelect = (type: WorkflowNodeType) => {
|
const handleNodeTypeSelect = (type: WorkflowNodeType) => {
|
||||||
const node = newNode(type);
|
const nextNode = newNode(type);
|
||||||
addNode(node, supnode.id);
|
addNode(nextNode, node.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative py-6 before:absolute before:left-1/2 before:top-0 before:h-full before:w-[2px] before:-translate-x-1/2 before:bg-stone-200 before:content-['']">
|
<div className="relative py-6 before:absolute before:left-1/2 before:top-0 before:h-full before:w-[2px] before:-translate-x-1/2 before:bg-stone-200 before:content-['']">
|
||||||
<Dropdown
|
<Dropdown menu={{ items: dropdownMenus }} trigger={["click"]}>
|
||||||
menu={{
|
|
||||||
items: dropdownMenus.map((item) => {
|
|
||||||
return {
|
|
||||||
key: item.type,
|
|
||||||
label: item.label,
|
|
||||||
icon: item.icon,
|
|
||||||
onClick: () => {
|
|
||||||
handleNodeTypeSelect(item.type);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
trigger={["click"]}
|
|
||||||
>
|
|
||||||
<div className="relative z-[1] flex size-5 cursor-pointer items-center justify-center rounded-full bg-stone-400 hover:bg-stone-500">
|
<div className="relative z-[1] flex size-5 cursor-pointer items-center justify-center rounded-full bg-stone-400 hover:bg-stone-500">
|
||||||
<PlusOutlinedIcon className="text-white" />
|
<PlusOutlinedIcon className="text-white" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,8 +6,8 @@ import { type WorkflowNode } from "@/domain/workflow";
|
|||||||
import { useZustandShallowSelector } from "@/hooks";
|
import { useZustandShallowSelector } from "@/hooks";
|
||||||
import { useWorkflowStore } from "@/stores/workflow";
|
import { useWorkflowStore } from "@/stores/workflow";
|
||||||
|
|
||||||
import NodeRender from "../NodeRender";
|
|
||||||
import AddNode from "./AddNode";
|
import AddNode from "./AddNode";
|
||||||
|
import NodeRender from "./NodeRender";
|
||||||
|
|
||||||
export type BrandNodeProps = {
|
export type BrandNodeProps = {
|
||||||
node: WorkflowNode;
|
node: WorkflowNode;
|
||||||
|
@ -3,13 +3,19 @@ import { CloseCircleOutlined as CloseCircleOutlinedIcon, EllipsisOutlined as Ell
|
|||||||
import { Button, Card, Dropdown, Popover } from "antd";
|
import { Button, Card, Dropdown, Popover } from "antd";
|
||||||
import { produce } from "immer";
|
import { produce } from "immer";
|
||||||
|
|
||||||
|
import { type WorkflowNode } from "@/domain/workflow";
|
||||||
import { useZustandShallowSelector } from "@/hooks";
|
import { useZustandShallowSelector } from "@/hooks";
|
||||||
import { useWorkflowStore } from "@/stores/workflow";
|
import { useWorkflowStore } from "@/stores/workflow";
|
||||||
|
|
||||||
import AddNode from "./AddNode";
|
import AddNode from "./AddNode";
|
||||||
import { type NodeProps } from "../types";
|
|
||||||
|
|
||||||
const ConditionNode = ({ node, branchId, branchIndex }: NodeProps) => {
|
export type ConditionNodeProps = {
|
||||||
|
node: WorkflowNode;
|
||||||
|
branchId?: string;
|
||||||
|
branchIndex?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConditionNode = ({ node, branchId, branchIndex }: ConditionNodeProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { updateNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeBranch"]));
|
const { updateNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeBranch"]));
|
||||||
|
@ -2,13 +2,18 @@ import { memo } from "react";
|
|||||||
|
|
||||||
import { type WorkflowNode, WorkflowNodeType } from "@/domain/workflow";
|
import { type WorkflowNode, WorkflowNodeType } from "@/domain/workflow";
|
||||||
|
|
||||||
import WorkflowElement from "./WorkflowElement";
|
import WorkflowElement from "../WorkflowElement";
|
||||||
import BranchNode from "./node/BranchNode";
|
import BranchNode from "./BranchNode";
|
||||||
import ConditionNode from "./node/ConditionNode";
|
import ConditionNode from "./ConditionNode";
|
||||||
import EndNode from "./node/EndNode";
|
import EndNode from "./EndNode";
|
||||||
import { type NodeProps } from "./types";
|
|
||||||
|
|
||||||
const NodeRender = ({ node: data, branchId, branchIndex }: NodeProps) => {
|
export type NodeRenderProps = {
|
||||||
|
node: WorkflowNode;
|
||||||
|
branchId?: string;
|
||||||
|
branchIndex?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NodeRender = ({ node: data, branchId, branchIndex }: NodeRenderProps) => {
|
||||||
const render = () => {
|
const render = () => {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case WorkflowNodeType.Start:
|
case WorkflowNodeType.Start:
|
@ -1,17 +0,0 @@
|
|||||||
import { type WorkflowBranchNode, type WorkflowNode } from "@/domain/workflow";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export type NodeProps = {
|
|
||||||
node: WorkflowNode | WorkflowBranchNode;
|
|
||||||
branchId?: string;
|
|
||||||
branchIndex?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export type BrandNodeProps = {
|
|
||||||
node: WorkflowBranchNode;
|
|
||||||
};
|
|
@ -7,7 +7,7 @@ export const SETTINGS_NAMES = Object.freeze({
|
|||||||
|
|
||||||
export type SettingsNames = (typeof SETTINGS_NAMES)[keyof typeof SETTINGS_NAMES];
|
export type SettingsNames = (typeof SETTINGS_NAMES)[keyof typeof SETTINGS_NAMES];
|
||||||
|
|
||||||
export interface SettingsModel<T extends NonNullable<unknown> = NonNullable<unknown>> extends BaseModel {
|
export interface SettingsModel<T extends NonNullable<unknown> = any> extends BaseModel {
|
||||||
name: string;
|
name: string;
|
||||||
content: T;
|
content: T;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import { produce } from "immer";
|
|||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
import i18n from "@/i18n";
|
import i18n from "@/i18n";
|
||||||
import { deployProvidersMap } from "./provider";
|
|
||||||
|
|
||||||
export interface WorkflowModel extends BaseModel {
|
export interface WorkflowModel extends BaseModel {
|
||||||
name: string;
|
name: string;
|
||||||
@ -28,7 +27,7 @@ export enum WorkflowNodeType {
|
|||||||
Custom = "custom",
|
Custom = "custom",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const workflowNodeTypeDefaultNames: Map<WorkflowNodeType, string> = new Map([
|
const workflowNodeTypeDefaultNames: Map<WorkflowNodeType, string> = new Map([
|
||||||
[WorkflowNodeType.Start, i18n.t("workflow_node.start.label")],
|
[WorkflowNodeType.Start, i18n.t("workflow_node.start.label")],
|
||||||
[WorkflowNodeType.End, i18n.t("workflow_node.end.label")],
|
[WorkflowNodeType.End, i18n.t("workflow_node.end.label")],
|
||||||
[WorkflowNodeType.Branch, i18n.t("workflow_node.branch.label")],
|
[WorkflowNodeType.Branch, i18n.t("workflow_node.branch.label")],
|
||||||
@ -39,7 +38,7 @@ export const workflowNodeTypeDefaultNames: Map<WorkflowNodeType, string> = new M
|
|||||||
[WorkflowNodeType.Custom, i18n.t("workflow_node.custom.title")],
|
[WorkflowNodeType.Custom, i18n.t("workflow_node.custom.title")],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const workflowNodeTypeDefaultInputs: Map<WorkflowNodeType, WorkflowNodeIO[]> = new Map([
|
const workflowNodeTypeDefaultInputs: Map<WorkflowNodeType, WorkflowNodeIO[]> = new Map([
|
||||||
[WorkflowNodeType.Apply, []],
|
[WorkflowNodeType.Apply, []],
|
||||||
[
|
[
|
||||||
WorkflowNodeType.Deploy,
|
WorkflowNodeType.Deploy,
|
||||||
@ -55,7 +54,7 @@ export const workflowNodeTypeDefaultInputs: Map<WorkflowNodeType, WorkflowNodeIO
|
|||||||
[WorkflowNodeType.Notify, []],
|
[WorkflowNodeType.Notify, []],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const workflowNodeTypeDefaultOutputs: Map<WorkflowNodeType, WorkflowNodeIO[]> = new Map([
|
const workflowNodeTypeDefaultOutputs: Map<WorkflowNodeType, WorkflowNodeIO[]> = new Map([
|
||||||
[
|
[
|
||||||
WorkflowNodeType.Apply,
|
WorkflowNodeType.Apply,
|
||||||
[
|
[
|
||||||
@ -80,25 +79,12 @@ export type WorkflowNode = {
|
|||||||
input?: WorkflowNodeIO[];
|
input?: WorkflowNodeIO[];
|
||||||
output?: WorkflowNodeIO[];
|
output?: WorkflowNodeIO[];
|
||||||
|
|
||||||
next?: WorkflowNode | WorkflowBranchNode;
|
next?: WorkflowNode;
|
||||||
branches?: WorkflowNode[];
|
branches?: WorkflowNode[];
|
||||||
|
|
||||||
validated?: boolean;
|
validated?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export type WorkflowBranchNode = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
type: WorkflowNodeType.Branch;
|
|
||||||
|
|
||||||
branches: WorkflowNode[];
|
|
||||||
|
|
||||||
next?: WorkflowNode | WorkflowBranchNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type WorkflowNodeIO = {
|
export type WorkflowNodeIO = {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
@ -150,11 +136,11 @@ type NewNodeOptions = {
|
|||||||
branchIndex?: number;
|
branchIndex?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const newNode = (nodeType: WorkflowNodeType, options: NewNodeOptions = {}): WorkflowNode | WorkflowBranchNode => {
|
export const newNode = (nodeType: WorkflowNodeType, options: NewNodeOptions = {}): WorkflowNode => {
|
||||||
const nodeTypeName = workflowNodeTypeDefaultNames.get(nodeType) || "";
|
const nodeTypeName = workflowNodeTypeDefaultNames.get(nodeType) || "";
|
||||||
const nodeName = options.branchIndex != null ? `${nodeTypeName} ${options.branchIndex + 1}` : nodeTypeName;
|
const nodeName = options.branchIndex != null ? `${nodeTypeName} ${options.branchIndex + 1}` : nodeTypeName;
|
||||||
|
|
||||||
const node: WorkflowNode | WorkflowBranchNode = {
|
const node: WorkflowNode = {
|
||||||
id: nanoid(),
|
id: nanoid(),
|
||||||
name: nodeName,
|
name: nodeName,
|
||||||
type: nodeType,
|
type: nodeType,
|
||||||
@ -186,11 +172,7 @@ export const newNode = (nodeType: WorkflowNodeType, options: NewNodeOptions = {}
|
|||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isWorkflowBranchNode = (node: WorkflowNode | WorkflowBranchNode): node is WorkflowBranchNode => {
|
export const updateNode = (node: WorkflowNode, targetNode: WorkflowNode) => {
|
||||||
return node.type === WorkflowNodeType.Branch;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateNode = (node: WorkflowNode | WorkflowBranchNode, targetNode: WorkflowNode | WorkflowBranchNode) => {
|
|
||||||
return produce(node, (draft) => {
|
return produce(node, (draft) => {
|
||||||
let current = draft;
|
let current = draft;
|
||||||
while (current) {
|
while (current) {
|
||||||
@ -198,8 +180,8 @@ export const updateNode = (node: WorkflowNode | WorkflowBranchNode, targetNode:
|
|||||||
Object.assign(current, targetNode);
|
Object.assign(current, targetNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isWorkflowBranchNode(current)) {
|
if (current.type === WorkflowNodeType.Branch) {
|
||||||
current.branches = current.branches.map((branch) => updateNode(branch, targetNode));
|
current.branches = current.branches!.map((branch) => updateNode(branch, targetNode));
|
||||||
}
|
}
|
||||||
current = current.next as WorkflowNode;
|
current = current.next as WorkflowNode;
|
||||||
}
|
}
|
||||||
@ -207,21 +189,21 @@ export const updateNode = (node: WorkflowNode | WorkflowBranchNode, targetNode:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addNode = (node: WorkflowNode | WorkflowBranchNode, preId: string, targetNode: WorkflowNode | WorkflowBranchNode) => {
|
export const addNode = (node: WorkflowNode, preId: string, targetNode: WorkflowNode) => {
|
||||||
return produce(node, (draft) => {
|
return produce(node, (draft) => {
|
||||||
let current = draft;
|
let current = draft;
|
||||||
while (current) {
|
while (current) {
|
||||||
if (current.id === preId && !isWorkflowBranchNode(targetNode)) {
|
if (current.id === preId && targetNode.type !== WorkflowNodeType.Branch) {
|
||||||
targetNode.next = current.next;
|
targetNode.next = current.next;
|
||||||
current.next = targetNode;
|
current.next = targetNode;
|
||||||
break;
|
break;
|
||||||
} else if (current.id === preId && isWorkflowBranchNode(targetNode)) {
|
} else if (current.id === preId && targetNode.type === WorkflowNodeType.Branch) {
|
||||||
targetNode.branches[0].next = current.next;
|
targetNode.branches![0].next = current.next;
|
||||||
current.next = targetNode;
|
current.next = targetNode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isWorkflowBranchNode(current)) {
|
if (current.type === WorkflowNodeType.Branch) {
|
||||||
current.branches = current.branches.map((branch) => addNode(branch, preId, targetNode));
|
current.branches = current.branches!.map((branch) => addNode(branch, preId, targetNode));
|
||||||
}
|
}
|
||||||
current = current.next as WorkflowNode;
|
current = current.next as WorkflowNode;
|
||||||
}
|
}
|
||||||
@ -229,23 +211,23 @@ export const addNode = (node: WorkflowNode | WorkflowBranchNode, preId: string,
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addBranch = (node: WorkflowNode | WorkflowBranchNode, branchNodeId: string) => {
|
export const addBranch = (node: WorkflowNode, branchNodeId: string) => {
|
||||||
return produce(node, (draft) => {
|
return produce(node, (draft) => {
|
||||||
let current = draft;
|
let current = draft;
|
||||||
while (current) {
|
while (current) {
|
||||||
if (current.id === branchNodeId) {
|
if (current.id === branchNodeId) {
|
||||||
if (!isWorkflowBranchNode(current)) {
|
if (current.type !== WorkflowNodeType.Branch) {
|
||||||
return draft;
|
return draft;
|
||||||
}
|
}
|
||||||
current.branches.push(
|
current.branches!.push(
|
||||||
newNode(WorkflowNodeType.Condition, {
|
newNode(WorkflowNodeType.Condition, {
|
||||||
branchIndex: current.branches.length,
|
branchIndex: current.branches!.length,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isWorkflowBranchNode(current)) {
|
if (current.type === WorkflowNodeType.Branch) {
|
||||||
current.branches = current.branches.map((branch) => addBranch(branch, branchNodeId));
|
current.branches = current.branches!.map((branch) => addBranch(branch, branchNodeId));
|
||||||
}
|
}
|
||||||
current = current.next as WorkflowNode;
|
current = current.next as WorkflowNode;
|
||||||
}
|
}
|
||||||
@ -253,7 +235,7 @@ export const addBranch = (node: WorkflowNode | WorkflowBranchNode, branchNodeId:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeNode = (node: WorkflowNode | WorkflowBranchNode, targetNodeId: string) => {
|
export const removeNode = (node: WorkflowNode, targetNodeId: string) => {
|
||||||
return produce(node, (draft) => {
|
return produce(node, (draft) => {
|
||||||
let current = draft;
|
let current = draft;
|
||||||
while (current) {
|
while (current) {
|
||||||
@ -261,8 +243,8 @@ export const removeNode = (node: WorkflowNode | WorkflowBranchNode, targetNodeId
|
|||||||
current.next = current.next.next;
|
current.next = current.next.next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isWorkflowBranchNode(current)) {
|
if (current.type === WorkflowNodeType.Branch) {
|
||||||
current.branches = current.branches.map((branch) => removeNode(branch, targetNodeId));
|
current.branches = current.branches!.map((branch) => removeNode(branch, targetNodeId));
|
||||||
}
|
}
|
||||||
current = current.next as WorkflowNode;
|
current = current.next as WorkflowNode;
|
||||||
}
|
}
|
||||||
@ -270,10 +252,10 @@ export const removeNode = (node: WorkflowNode | WorkflowBranchNode, targetNodeId
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeBranch = (node: WorkflowNode | WorkflowBranchNode, branchNodeId: string, branchIndex: number) => {
|
export const removeBranch = (node: WorkflowNode, branchNodeId: string, branchIndex: number) => {
|
||||||
return produce(node, (draft) => {
|
return produce(node, (draft) => {
|
||||||
let current = draft;
|
let current = draft;
|
||||||
let last: WorkflowNode | WorkflowBranchNode | undefined = {
|
let last: WorkflowNode | undefined = {
|
||||||
id: "",
|
id: "",
|
||||||
name: "",
|
name: "",
|
||||||
type: WorkflowNodeType.Start,
|
type: WorkflowNodeType.Start,
|
||||||
@ -281,17 +263,17 @@ export const removeBranch = (node: WorkflowNode | WorkflowBranchNode, branchNode
|
|||||||
};
|
};
|
||||||
while (current && last) {
|
while (current && last) {
|
||||||
if (current.id === branchNodeId) {
|
if (current.id === branchNodeId) {
|
||||||
if (!isWorkflowBranchNode(current)) {
|
if (current.type !== WorkflowNodeType.Branch) {
|
||||||
return draft;
|
return draft;
|
||||||
}
|
}
|
||||||
current.branches.splice(branchIndex, 1);
|
current.branches!.splice(branchIndex, 1);
|
||||||
|
|
||||||
// 如果仅剩一个分支,删除分支节点,将分支节点的下一个节点挂载到当前节点
|
// 如果仅剩一个分支,删除分支节点,将分支节点的下一个节点挂载到当前节点
|
||||||
if (current.branches.length === 1) {
|
if (current.branches!.length === 1) {
|
||||||
const branch = current.branches[0];
|
const branch = current.branches![0];
|
||||||
if (branch.next) {
|
if (branch.next) {
|
||||||
last.next = branch.next;
|
last.next = branch.next;
|
||||||
let lastNode: WorkflowNode | WorkflowBranchNode | undefined = branch.next;
|
let lastNode: WorkflowNode | undefined = branch.next;
|
||||||
while (lastNode?.next) {
|
while (lastNode?.next) {
|
||||||
lastNode = lastNode.next;
|
lastNode = lastNode.next;
|
||||||
}
|
}
|
||||||
@ -303,8 +285,8 @@ export const removeBranch = (node: WorkflowNode | WorkflowBranchNode, branchNode
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isWorkflowBranchNode(current)) {
|
if (current.type === WorkflowNodeType.Branch) {
|
||||||
current.branches = current.branches.map((branch) => removeBranch(branch, branchNodeId, branchIndex));
|
current.branches = current.branches!.map((branch) => removeBranch(branch, branchNodeId, branchIndex));
|
||||||
}
|
}
|
||||||
current = current.next as WorkflowNode;
|
current = current.next as WorkflowNode;
|
||||||
last = last.next;
|
last = last.next;
|
||||||
@ -314,10 +296,10 @@ export const removeBranch = (node: WorkflowNode | WorkflowBranchNode, branchNode
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 1 个分支的节点,不应该能获取到相邻分支上节点的输出
|
// 1 个分支的节点,不应该能获取到相邻分支上节点的输出
|
||||||
export const getWorkflowOutputBeforeId = (node: WorkflowNode | WorkflowBranchNode, id: string, type: string): WorkflowNode[] => {
|
export const getWorkflowOutputBeforeId = (node: WorkflowNode, id: string, type: string): WorkflowNode[] => {
|
||||||
const output: WorkflowNode[] = [];
|
const output: WorkflowNode[] = [];
|
||||||
|
|
||||||
const traverse = (current: WorkflowNode | WorkflowBranchNode, output: WorkflowNode[]) => {
|
const traverse = (current: WorkflowNode, output: WorkflowNode[]) => {
|
||||||
if (!current) {
|
if (!current) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -325,16 +307,16 @@ export const getWorkflowOutputBeforeId = (node: WorkflowNode | WorkflowBranchNod
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isWorkflowBranchNode(current) && current.output && current.output.some((io) => io.type === type)) {
|
if (current.type !== WorkflowNodeType.Branch && current.output && current.output.some((io) => io.type === type)) {
|
||||||
output.push({
|
output.push({
|
||||||
...current,
|
...current,
|
||||||
output: current.output.filter((io) => io.type === type),
|
output: current.output.filter((io) => io.type === type),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWorkflowBranchNode(current)) {
|
if (current.type === WorkflowNodeType.Branch) {
|
||||||
const currentLength = output.length;
|
const currentLength = output.length;
|
||||||
for (const branch of current.branches) {
|
for (const branch of current.branches!) {
|
||||||
if (traverse(branch, output)) {
|
if (traverse(branch, output)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
import { useDeepCompareEffect } from "ahooks";
|
import { useDeepCompareEffect } from "ahooks";
|
||||||
import { Form, type FormInstance, type FormProps } from "antd";
|
import { Form, type FormInstance, type FormProps } from "antd";
|
||||||
|
|
||||||
export interface UseAntdFormOptions<T extends NonNullable<unknown> = NonNullable<unknown>> {
|
export interface UseAntdFormOptions<T extends NonNullable<unknown> = any> {
|
||||||
form?: FormInstance<T>;
|
form?: FormInstance<T>;
|
||||||
initialValues?: Partial<T> | (() => Partial<T> | Promise<Partial<T>>);
|
initialValues?: Partial<T> | (() => Partial<T> | Promise<Partial<T>>);
|
||||||
onSubmit?: (values: T) => unknown;
|
onSubmit?: (values: T) => unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseAntdFormReturns<T extends NonNullable<unknown> = NonNullable<unknown>> {
|
export interface UseAntdFormReturns<T extends NonNullable<unknown> = any> {
|
||||||
form: FormInstance<T>;
|
form: FormInstance<T>;
|
||||||
formProps: Omit<FormProps<T>, "children">;
|
formProps: Omit<FormProps<T>, "children">;
|
||||||
formPending: boolean;
|
formPending: boolean;
|
||||||
@ -20,11 +20,7 @@ export interface UseAntdFormReturns<T extends NonNullable<unknown> = NonNullable
|
|||||||
* @param {UseAntdFormOptions} options
|
* @param {UseAntdFormOptions} options
|
||||||
* @returns {UseAntdFormReturns}
|
* @returns {UseAntdFormReturns}
|
||||||
*/
|
*/
|
||||||
const useAntdForm = <T extends NonNullable<unknown> = NonNullable<unknown>>({
|
const useAntdForm = <T extends NonNullable<unknown> = any>({ initialValues, form, onSubmit }: UseAntdFormOptions<T>): UseAntdFormReturns<T> => {
|
||||||
initialValues,
|
|
||||||
form,
|
|
||||||
onSubmit,
|
|
||||||
}: UseAntdFormOptions<T>): UseAntdFormReturns<T> => {
|
|
||||||
const formInst = form ?? Form["useForm"]()[0];
|
const formInst = form ?? Form["useForm"]()[0];
|
||||||
const [formInitialValues, setFormInitialValues] = useState<Partial<T>>();
|
const [formInitialValues, setFormInitialValues] = useState<Partial<T>>();
|
||||||
const [formPending, setFormPending] = useState(false);
|
const [formPending, setFormPending] = useState(false);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type WorkflowBranchNode,
|
|
||||||
type WorkflowModel,
|
type WorkflowModel,
|
||||||
type WorkflowNode,
|
type WorkflowNode,
|
||||||
addBranch,
|
addBranch,
|
||||||
@ -112,7 +111,7 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateNode: async (node: WorkflowNode | WorkflowBranchNode) => {
|
updateNode: async (node: WorkflowNode) => {
|
||||||
const newRoot = updateNode(get().workflow.draft as WorkflowNode, node);
|
const newRoot = updateNode(get().workflow.draft as WorkflowNode, node);
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: (get().workflow.id as string) ?? "",
|
||||||
@ -132,7 +131,7 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addNode: async (node: WorkflowNode | WorkflowBranchNode, preId: string) => {
|
addNode: async (node: WorkflowNode, preId: string) => {
|
||||||
const newRoot = addNode(get().workflow.draft as WorkflowNode, preId, node);
|
const newRoot = addNode(get().workflow.draft as WorkflowNode, preId, node);
|
||||||
const resp = await saveWorkflow({
|
const resp = await saveWorkflow({
|
||||||
id: (get().workflow.id as string) ?? "",
|
id: (get().workflow.id as string) ?? "",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user