diff --git a/ui/src/components/workflow/designer/Designer.tsx b/ui/src/components/workflow/designer/Designer.tsx index 0a8493a8a..d1ee616b1 100644 --- a/ui/src/components/workflow/designer/Designer.tsx +++ b/ui/src/components/workflow/designer/Designer.tsx @@ -20,8 +20,8 @@ import { isTouchSupported } from "@/utils/browser"; import { DegisnerContextProvider } from "./_context"; import { getAllElements } from "./elements"; import NodeRender from "./NodeRender"; -import { getAllNodeRegistries } from "./nodes"; -import { BranchNode } from "./nodes/_shared"; +import { getAllNodeRegistries, isNodeTypeRegistered } from "./nodes"; +import { BaseNode } from "./nodes/_shared"; import "./flowgram.css"; export interface DesignerProps { @@ -110,7 +110,7 @@ const Designer = forwardRef( defaultExpanded: true, }, formMeta: { - render: () => , + render: () => , }, }; }, @@ -195,6 +195,12 @@ const Designer = forwardRef( if (typeof node === "string") { node = flowgramEditorRef.current!.document.getNode(node)!; } + if (!node) { + return Promise.reject(`Node '${node}' not found`); + } + if (!isNodeTypeRegistered(node.type)) { + return Promise.reject(`Node type '${node.type}' is not registered`); + } const form = node.form; return form ? form.validate().then((res) => res && !form.state.invalid) : Promise.resolve(true); diff --git a/ui/src/components/workflow/designer/nodes/NodeRegistries.ts b/ui/src/components/workflow/designer/nodes/NodeRegistries.ts new file mode 100644 index 000000000..c515716cc --- /dev/null +++ b/ui/src/components/workflow/designer/nodes/NodeRegistries.ts @@ -0,0 +1,35 @@ +import { type FlowNodeType } from "@flowgram.ai/fixed-layout-editor"; + +import { BizApplyNodeRegistry } from "./BizApplyNodeRegistry"; +import { BizDeployNodeRegistry } from "./BizDeployNodeRegistry"; +import { BizMonitorNodeRegistry } from "./BizMonitorNodeRegistry"; +import { BizNotifyNodeRegistry } from "./BizNotifyNodeRegistry"; +import { BizUploadNodeRegistry } from "./BizUploadNodeRegistry"; +import { BranchBlockNodeRegistry, ConditionNodeRegistry } from "./ConditionNode"; +import { DelayNodeRegistry } from "./DelayNode"; +import { EndNodeRegistry } from "./EndNode"; +import { StartNodeRegistry } from "./StartNode"; +import { CatchBlockNodeRegistry, TryCatchNodeRegistry } from "./TryCatchNode"; + +const nodeRegistries = [ + StartNodeRegistry, + EndNodeRegistry, + DelayNodeRegistry, + BizApplyNodeRegistry, + BizUploadNodeRegistry, + BizMonitorNodeRegistry, + BizDeployNodeRegistry, + BizNotifyNodeRegistry, + ConditionNodeRegistry, + BranchBlockNodeRegistry, + TryCatchNodeRegistry, + CatchBlockNodeRegistry, +]; + +export const getAllNodeRegistries = () => { + return [...nodeRegistries]; +}; + +export const isNodeTypeRegistered = (type: FlowNodeType) => { + return nodeRegistries.some((registry) => registry.type === type); +}; diff --git a/ui/src/components/workflow/designer/nodes/_shared.tsx b/ui/src/components/workflow/designer/nodes/_shared.tsx index 8fca70dcc..582c25605 100644 --- a/ui/src/components/workflow/designer/nodes/_shared.tsx +++ b/ui/src/components/workflow/designer/nodes/_shared.tsx @@ -17,6 +17,7 @@ import { mergeCls } from "@/utils/css"; import { type NodeJSON, type NodeRegistry } from "./typings"; import { duplicateNodeJSON } from "../_util"; import { useNodeRenderContext } from "../NodeRenderContext"; +import { isNodeTypeRegistered } from "./NodeRegistries"; const useInternalRenamingInput = ({ nodeRender }: { nodeRender: NodeRenderReturnType }) => { const inputRef = useRef(null); @@ -98,11 +99,11 @@ const InternalNodeCard = ({ const isActivated = useMemo(() => nodeRenderData.activated || nodeRenderData.lineActivated, [nodeRenderData.activated, nodeRenderData.lineActivated]); const [isHovering, setIsHovering] = useState(false); - const [isNodeInvalid, setIsNodeInvalid] = useState(false); + const [isNodeInvalid, setIsNodeInvalid] = useState(!isNodeTypeRegistered(nodeRegistry.type)); const isNodeDisabled = useWatchFormValueIn(nodeRender.node, "disabled"); const formState = useWatchFormState(nodeRender.node); - useEffect(() => setIsNodeInvalid(!!formState?.invalid), [formState?.invalid]); + useEffect(() => setIsNodeInvalid(!isNodeTypeRegistered(nodeRegistry.type) || !!formState?.invalid), [formState?.invalid]); return ( { - return [ - StartNodeRegistry, - EndNodeRegistry, - DelayNodeRegistry, - BizApplyNodeRegistry, - BizUploadNodeRegistry, - BizMonitorNodeRegistry, - BizDeployNodeRegistry, - BizNotifyNodeRegistry, - ConditionNodeRegistry, - BranchBlockNodeRegistry, - TryCatchNodeRegistry, - CatchBlockNodeRegistry, - ]; -}; +export { getAllNodeRegistries, isNodeTypeRegistered } from "./NodeRegistries"; export type * from "./typings";