import { memo, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { CloseCircleOutlined as CloseCircleOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon } from "@ant-design/icons"; import { useControllableValue } from "ahooks"; import { Avatar, Button, Card, Drawer, Dropdown, Modal, Popover, Space, Typography } from "antd"; import { produce } from "immer"; import { isEqual } from "radash"; import Show from "@/components/Show"; import { deployProvidersMap } from "@/domain/provider"; import { notifyChannelsMap } from "@/domain/settings"; import { WORKFLOW_TRIGGERS, type WorkflowNode, type WorkflowNodeConfigForApply, type WorkflowNodeConfigForDeploy, type WorkflowNodeConfigForNotify, type WorkflowNodeConfigForStart, WorkflowNodeType, } from "@/domain/workflow"; import { useAntdForm, useZustandShallowSelector } from "@/hooks"; import { useAccessesStore } from "@/stores/access"; import { useContactEmailsStore } from "@/stores/contact"; import { useWorkflowStore } from "@/stores/workflow"; import AddNode from "./AddNode"; import ApplyNodeForm from "./ApplyNodeForm"; import DeployNodeForm from "./DeployNodeForm"; import NotifyNodeForm from "./NotifyNodeForm"; import StartNodeForm from "./StartNodeForm"; export type CommonNodeProps = { node: WorkflowNode; disabled?: boolean; }; const CommonNode = ({ node, disabled }: CommonNodeProps) => { const { t } = useTranslation(); const { updateNode, removeNode } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeNode"])); const [drawerOpen, setDrawerOpen] = useState(false); const workflowNodeEl = useMemo(() => { if (!node.validated) { return {t("workflow_node.action.configure_node")}; } switch (node.type) { case WorkflowNodeType.Start: { const config = (node.config as WorkflowNodeConfigForStart) ?? {}; return (
{config.trigger === WORKFLOW_TRIGGERS.AUTO ? t("workflow.props.trigger.auto") : config.trigger === WORKFLOW_TRIGGERS.MANUAL ? t("workflow.props.trigger.manual") : " "} {config.trigger === WORKFLOW_TRIGGERS.AUTO ? config.triggerCron : ""}
); } case WorkflowNodeType.Apply: { const config = (node.config as WorkflowNodeConfigForApply) ?? {}; return {config.domains || " "}; } case WorkflowNodeType.Deploy: { const config = (node.config as WorkflowNodeConfigForDeploy) ?? {}; const provider = deployProvidersMap.get(config.provider); return ( {t(provider?.name ?? "")} ); } case WorkflowNodeType.Notify: { const config = (node.config as WorkflowNodeConfigForNotify) ?? {}; const channel = notifyChannelsMap.get(config.channel as string); return (
{t(channel?.name ?? " ")} {config.subject ?? ""}
); } default: { console.warn(`[certimate] unsupported workflow node type: ${node.type}`); return <>; } } }, [node]); const handleNodeClick = () => { setDrawerOpen(true); }; const handleNodeNameBlur = (e: React.FocusEvent) => { const oldName = node.name; const newName = e.target.innerText.trim(); if (oldName === newName) { return; } updateNode( produce(node, (draft) => { draft.name = newName; }) ); }; return ( <> , danger: true, onClick: () => { if (disabled) return; removeNode(node.id); }, }, ], }} trigger={["click"]} > } open={open} title={node.name} width={640} onClose={handleClose} > {formEl} ); }; export default memo(CommonNode);