123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- import type {
- FC,
- ReactElement,
- } from 'react'
- import {
- cloneElement,
- memo,
- useMemo,
- useRef,
- } from 'react'
- import type { NodeProps } from '../../types'
- import {
- BlockEnum,
- NodeRunningStatus,
- } from '../../types'
- import {
- useNodesReadOnly,
- useToolIcon,
- } from '../../hooks'
- import {
- NodeSourceHandle,
- NodeTargetHandle,
- } from './components/node-handle'
- import NodeControl from './components/node-control'
- import BlockIcon from '@/app/components/workflow/block-icon'
- import {
- CheckCircle,
- Loading02,
- } from '@/app/components/base/icons/src/vender/line/general'
- import { AlertCircle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
- type BaseNodeProps = {
- children: ReactElement
- } & NodeProps
- const BaseNode: FC<BaseNodeProps> = ({
- id,
- data,
- children,
- }) => {
- const nodeRef = useRef<HTMLDivElement>(null)
- const { nodesReadOnly } = useNodesReadOnly()
- const toolIcon = useToolIcon(data)
- const showSelectedBorder = data.selected || data._isBundled
- 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 (
- <div
- className={`
- flex border-[2px] rounded-2xl
- ${(showSelectedBorder && !data._isInvalidConnection) ? 'border-primary-600' : 'border-transparent'}
- `}
- ref={nodeRef}
- >
- <div
- className={`
- group relative pb-1 w-[240px] bg-[#fcfdff] shadow-xs
- border border-transparent rounded-[15px]
- ${!data._runningStatus && 'hover:shadow-lg'}
- ${showRunningBorder && '!border-primary-500'}
- ${showSuccessBorder && '!border-[#12B76A]'}
- ${showFailedBorder && '!border-[#F04438]'}
- ${data._isInvalidConnection && '!border-[#F04438]'}
- ${data._isBundled && '!shadow-lg'}
- `}
- >
- {
- data.type !== BlockEnum.VariableAssigner && !data._isCandidate && (
- <NodeTargetHandle
- id={id}
- data={data}
- handleClassName='!top-4 !-left-[9px] !translate-y-0'
- handleId='target'
- />
- )
- }
- {
- data.type !== BlockEnum.IfElse && data.type !== BlockEnum.QuestionClassifier && !data._isCandidate && (
- <NodeSourceHandle
- id={id}
- data={data}
- handleClassName='!top-4 !-right-[9px] !translate-y-0'
- handleId='source'
- />
- )
- }
- {
- !data._runningStatus && !nodesReadOnly && !data._isCandidate && (
- <NodeControl
- id={id}
- data={data}
- />
- )
- }
- <div className='flex items-center px-3 pt-3 pb-2'>
- <BlockIcon
- className='shrink-0 mr-2'
- type={data.type}
- size='md'
- toolIcon={toolIcon}
- />
- <div
- title={data.title}
- className='grow mr-1 text-[13px] font-semibold text-gray-700 truncate'
- >
- {data.title}
- </div>
- {
- (data._runningStatus === NodeRunningStatus.Running || data._singleRunningStatus === NodeRunningStatus.Running) && (
- <Loading02 className='w-3.5 h-3.5 text-primary-600 animate-spin' />
- )
- }
- {
- data._runningStatus === NodeRunningStatus.Succeeded && (
- <CheckCircle className='w-3.5 h-3.5 text-[#12B76A]' />
- )
- }
- {
- data._runningStatus === NodeRunningStatus.Failed && (
- <AlertCircle className='w-3.5 h-3.5 text-[#F04438]' />
- )
- }
- </div>
- {cloneElement(children, { id, data })}
- {
- data.desc && (
- <div className='px-3 pt-1 pb-2 text-xs leading-[18px] text-gray-500 whitespace-pre-line break-words'>
- {data.desc}
- </div>
- )
- }
- </div>
- </div>
- )
- }
- export default memo(BaseNode)
|