import type { FC, ReactElement, } from 'react' import { cloneElement, memo, useEffect, useMemo, useRef, } from 'react' import { RiCheckboxCircleLine, RiErrorWarningLine, RiLoader2Line, } from '@remixicon/react' import { useTranslation } from 'react-i18next' import type { NodeProps } from '../../types' import { BlockEnum, NodeRunningStatus, } from '../../types' import { useNodesReadOnly, useToolIcon, } from '../../hooks' import { useNodeIterationInteractions } from '../iteration/use-interactions' import type { IterationNodeType } from '../iteration/types' import { NodeSourceHandle, NodeTargetHandle, } from './components/node-handle' import NodeResizer from './components/node-resizer' import NodeControl from './components/node-control' import AddVariablePopupWithPosition from './components/add-variable-popup-with-position' import cn from '@/utils/classnames' import BlockIcon from '@/app/components/workflow/block-icon' import Tooltip from '@/app/components/base/tooltip' type BaseNodeProps = { children: ReactElement } & NodeProps const BaseNode: FC = ({ id, data, children, }) => { const { t } = useTranslation() const nodeRef = useRef(null) const { nodesReadOnly } = useNodesReadOnly() const { handleNodeIterationChildSizeChange } = useNodeIterationInteractions() const toolIcon = useToolIcon(data) useEffect(() => { if (nodeRef.current && data.selected && data.isInIteration) { const resizeObserver = new ResizeObserver(() => { handleNodeIterationChildSizeChange(id) }) resizeObserver.observe(nodeRef.current) return () => { resizeObserver.disconnect() } } }, [data.isInIteration, data.selected, id, handleNodeIterationChildSizeChange]) const showSelectedBorder = data.selected || data._isBundled || data._isEntering const { showRunningBorder, showSuccessBorder, showFailedBorder, } = useMemo(() => { return { showRunningBorder: data._runningStatus === NodeRunningStatus.Running && !showSelectedBorder, showSuccessBorder: data._runningStatus === NodeRunningStatus.Succeeded && !showSelectedBorder, showFailedBorder: data._runningStatus === NodeRunningStatus.Failed && !showSelectedBorder, } }, [data._runningStatus, showSelectedBorder]) return (
{ data._inParallelHovering && (
{t('workflow.common.parallelRun')}
) } { data._showAddVariablePopup && ( ) } { data.type === BlockEnum.Iteration && ( ) } { !data._isCandidate && ( ) } { data.type !== BlockEnum.IfElse && data.type !== BlockEnum.QuestionClassifier && !data._isCandidate && ( ) } { !data._runningStatus && !nodesReadOnly && !data._isCandidate && ( ) }
{data.title}
{ data.type === BlockEnum.Iteration && (data as IterationNodeType).is_parallel && (
{t('workflow.nodes.iteration.parallelModeEnableTitle')}
{t('workflow.nodes.iteration.parallelModeEnableDesc')}
} >
{t('workflow.nodes.iteration.parallelModeUpper')}
) }
{ data._iterationLength && data._iterationIndex && data._runningStatus === NodeRunningStatus.Running && (
{data._iterationIndex > data._iterationLength ? data._iterationLength : data._iterationIndex}/{data._iterationLength}
) } { (data._runningStatus === NodeRunningStatus.Running || data._singleRunningStatus === NodeRunningStatus.Running) && ( ) } { data._runningStatus === NodeRunningStatus.Succeeded && ( ) } { data._runningStatus === NodeRunningStatus.Failed && ( ) }
{ data.type !== BlockEnum.Iteration && ( cloneElement(children, { id, data }) ) } { data.type === BlockEnum.Iteration && (
{cloneElement(children, { id, data })}
) } { data.desc && data.type !== BlockEnum.Iteration && (
{data.desc}
) }
) } export default memo(BaseNode)