refactor(ui): clean code

This commit is contained in:
Fu Diwei
2025-01-03 21:51:40 +08:00
parent b7cd07c996
commit 849e065bb2
14 changed files with 103 additions and 143 deletions

View File

@@ -4,13 +4,13 @@ import Panel from "./Panel";
type PanelContentProps = { name: string; children: React.ReactNode };
type PanelContextType = {
type PanelContextProps = {
open: boolean;
showPanel: ({ name, children }: PanelContentProps) => void;
hidePanel: () => void;
};
const PanelContext = createContext<PanelContextType | undefined>(undefined);
const PanelContext = createContext<PanelContextProps | undefined>(undefined);
export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
const [open, setOpen] = useState(false);
@@ -20,6 +20,7 @@ export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
setOpen(true);
setPanelContent(panelContent);
};
const hidePanel = () => {
setOpen(false);
setPanelContent(null);
@@ -36,7 +37,7 @@ export const PanelProvider = ({ children }: { children: React.ReactNode }) => {
export const usePanel = () => {
const context = useContext(PanelContext);
if (!context) {
throw new Error("useDialog must be used within DialogProvider");
throw new Error("`usePanel` must be used within PanelProvider");
}
return context;
};

View File

@@ -1,8 +1,8 @@
import { useMemo } from "react";
import NodeRender from "@/components/workflow/NodeRender";
import WorkflowProvider from "@/components/workflow/WorkflowProvider";
import EndNode from "@/components/workflow/node/EndNode";
import NodeRender from "@/components/workflow/node/NodeRender";
import { type WorkflowNode } from "@/domain/workflow";
import { useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";

View File

@@ -1,3 +1,5 @@
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import {
CloudUploadOutlined as CloudUploadOutlinedIcon,
PlusOutlined as PlusOutlinedIcon,
@@ -7,60 +9,45 @@ import {
} from "@ant-design/icons";
import { Dropdown } from "antd";
import { WorkflowNodeType, newNode, workflowNodeTypeDefaultNames } from "@/domain/workflow";
import { type WorkflowNode, WorkflowNodeType, newNode } from "@/domain/workflow";
import { useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
import { type BrandNodeProps, type NodeProps } from "../types";
export type AddNodeProps = {
node: WorkflowNode;
};
const dropdownMenus = [
{
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 }: AddNodeProps) => {
const { t } = useTranslation();
const AddNode = ({ node: supnode }: NodeProps | BrandNodeProps) => {
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 node = newNode(type);
addNode(node, supnode.id);
const nextNode = newNode(type);
addNode(nextNode, node.id);
};
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-['']">
<Dropdown
menu={{
items: dropdownMenus.map((item) => {
return {
key: item.type,
label: item.label,
icon: item.icon,
onClick: () => {
handleNodeTypeSelect(item.type);
},
};
}),
}}
trigger={["click"]}
>
<Dropdown menu={{ items: dropdownMenus }} 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">
<PlusOutlinedIcon className="text-white" />
</div>

View File

@@ -6,8 +6,8 @@ import { type WorkflowNode } from "@/domain/workflow";
import { useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
import NodeRender from "../NodeRender";
import AddNode from "./AddNode";
import NodeRender from "./NodeRender";
export type BrandNodeProps = {
node: WorkflowNode;

View File

@@ -3,13 +3,19 @@ import { CloseCircleOutlined as CloseCircleOutlinedIcon, EllipsisOutlined as Ell
import { Button, Card, Dropdown, Popover } from "antd";
import { produce } from "immer";
import { type WorkflowNode } from "@/domain/workflow";
import { useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
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 { updateNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeBranch"]));

View File

@@ -2,13 +2,18 @@ import { memo } from "react";
import { type WorkflowNode, WorkflowNodeType } from "@/domain/workflow";
import WorkflowElement from "./WorkflowElement";
import BranchNode from "./node/BranchNode";
import ConditionNode from "./node/ConditionNode";
import EndNode from "./node/EndNode";
import { type NodeProps } from "./types";
import WorkflowElement from "../WorkflowElement";
import BranchNode from "./BranchNode";
import ConditionNode from "./ConditionNode";
import EndNode from "./EndNode";
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 = () => {
switch (data.type) {
case WorkflowNodeType.Start:

View File

@@ -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;
};