mirror of
https://github.com/langgenius/dify.git
synced 2026-02-27 04:57:08 +08:00
Signed-off-by: yihong0618 <zouzou0208@gmail.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: xhe <xw897002528@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: kurokobo <kuro664@gmail.com> Co-authored-by: Hiroshi Fujita <fujita-h@users.noreply.github.com> Co-authored-by: NFish <douxc512@gmail.com> Co-authored-by: Gen Sato <52241300+halogen22@users.noreply.github.com> Co-authored-by: eux <euxuuu@gmail.com> Co-authored-by: huangzhuo1949 <167434202+huangzhuo1949@users.noreply.github.com> Co-authored-by: huangzhuo <huangzhuo1@xiaomi.com> Co-authored-by: lotsik <lotsik@mail.ru> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: nite-knite <nkCoding@gmail.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: gakkiyomi <gakkiyomi@aliyun.com> Co-authored-by: CN-P5 <heibai2006@gmail.com> Co-authored-by: CN-P5 <heibai2006@qq.com> Co-authored-by: Chuehnone <1897025+chuehnone@users.noreply.github.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: Kevin9703 <51311316+Kevin9703@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Boris Feld <lothiraldan@gmail.com> Co-authored-by: mbo <himabo@gmail.com> Co-authored-by: mabo <mabo@aeyes.ai> Co-authored-by: Warren Chen <warren.chen830@gmail.com> Co-authored-by: KVOJJJin <jzongcode@gmail.com> Co-authored-by: JzoNgKVO <27049666+JzoNgKVO@users.noreply.github.com> Co-authored-by: jiandanfeng <chenjh3@wangsu.com> Co-authored-by: zhu-an <70234959+xhdd123321@users.noreply.github.com> Co-authored-by: zhaoqingyu.1075 <zhaoqingyu.1075@bytedance.com> Co-authored-by: 海狸大師 <86974027+yenslife@users.noreply.github.com> Co-authored-by: Xu Song <xusong.vip@gmail.com> Co-authored-by: rayshaw001 <396301947@163.com> Co-authored-by: Ding Jiatong <dingjiatong@gmail.com> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: JasonVV <jasonwangiii@outlook.com> Co-authored-by: le0zh <newlight@qq.com> Co-authored-by: zhuxinliang <zhuxinliang@didiglobal.com> Co-authored-by: k-zaku <zaku99@outlook.jp> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: luckylhb90 <luckylhb90@gmail.com> Co-authored-by: hobo.l <hobo.l@binance.com> Co-authored-by: jiangbo721 <365065261@qq.com> Co-authored-by: 刘江波 <jiangbo721@163.com> Co-authored-by: Shun Miyazawa <34241526+miya@users.noreply.github.com> Co-authored-by: EricPan <30651140+Egfly@users.noreply.github.com> Co-authored-by: crazywoola <427733928@qq.com> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: sino <sino2322@gmail.com> Co-authored-by: Jhvcc <37662342+Jhvcc@users.noreply.github.com> Co-authored-by: lowell <lowell.hu@zkteco.in> Co-authored-by: Ademílson Tonato <ademilsonft@outlook.com> Co-authored-by: Ademílson Tonato <ademilson.tonato@refurbed.com> Co-authored-by: IWAI, Masaharu <iwaim.sub@gmail.com> Co-authored-by: Yueh-Po Peng (Yabi) <94939112+y10ab1@users.noreply.github.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Jason <ggbbddjm@gmail.com> Co-authored-by: Xin Zhang <sjhpzx@gmail.com> Co-authored-by: yjc980121 <3898524+yjc980121@users.noreply.github.com> Co-authored-by: heyszt <36215648+hieheihei@users.noreply.github.com> Co-authored-by: Abdullah AlOsaimi <osaimiacc@gmail.com> Co-authored-by: Abdullah AlOsaimi <189027247+osaimi@users.noreply.github.com> Co-authored-by: Yingchun Lai <laiyingchun@apache.org> Co-authored-by: Hash Brown <hi@xzd.me> Co-authored-by: zuodongxu <192560071+zuodongxu@users.noreply.github.com> Co-authored-by: Masashi Tomooka <tmokmss@users.noreply.github.com> Co-authored-by: aplio <ryo.091219@gmail.com> Co-authored-by: Obada Khalili <54270856+obadakhalili@users.noreply.github.com> Co-authored-by: Nam Vu <zuzoovn@gmail.com> Co-authored-by: Kei YAMAZAKI <1715090+kei-yamazaki@users.noreply.github.com> Co-authored-by: TechnoHouse <13776377+deephbz@users.noreply.github.com> Co-authored-by: Riddhimaan-Senapati <114703025+Riddhimaan-Senapati@users.noreply.github.com> Co-authored-by: MaFee921 <31881301+2284730142@users.noreply.github.com> Co-authored-by: te-chan <t-nakanome@sakura-is.co.jp> Co-authored-by: HQidea <HQidea@users.noreply.github.com> Co-authored-by: Joshbly <36315710+Joshbly@users.noreply.github.com> Co-authored-by: xhe <xw897002528@gmail.com> Co-authored-by: weiwenyan-dev <154779315+weiwenyan-dev@users.noreply.github.com> Co-authored-by: ex_wenyan.wei <ex_wenyan.wei@tcl.com> Co-authored-by: engchina <12236799+engchina@users.noreply.github.com> Co-authored-by: engchina <atjapan2015@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 呆萌闷油瓶 <253605712@qq.com> Co-authored-by: Kemal <kemalmeler@outlook.com> Co-authored-by: Lazy_Frog <4590648+lazyFrogLOL@users.noreply.github.com> Co-authored-by: Novice Lee <novicelee@NoviPro.local> Co-authored-by: Yi Xiao <54782454+YIXIAO0@users.noreply.github.com> Co-authored-by: Steven sun <98230804+Tuyohai@users.noreply.github.com> Co-authored-by: steven <sunzwj@digitalchina.com> Co-authored-by: Kalo Chin <91766386+fdb02983rhy@users.noreply.github.com> Co-authored-by: Katy Tao <34019945+KatyTao@users.noreply.github.com> Co-authored-by: depy <42985524+h4ckdepy@users.noreply.github.com> Co-authored-by: 胡春东 <gycm520@gmail.com> Co-authored-by: Junjie.M <118170653@qq.com>
273 lines
8.7 KiB
TypeScript
273 lines
8.7 KiB
TypeScript
import type {
|
|
FC,
|
|
ReactElement,
|
|
} from 'react'
|
|
import {
|
|
cloneElement,
|
|
memo,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
} from 'react'
|
|
import {
|
|
RiAlertFill,
|
|
RiCheckboxCircleFill,
|
|
RiErrorWarningFill,
|
|
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 {
|
|
hasErrorHandleNode,
|
|
hasRetryNode,
|
|
} from '../../utils'
|
|
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 ErrorHandleOnNode from './components/error-handle/error-handle-on-node'
|
|
import RetryOnNode from './components/retry/retry-on-node'
|
|
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<BaseNodeProps> = ({
|
|
id,
|
|
data,
|
|
children,
|
|
}) => {
|
|
const { t } = useTranslation()
|
|
const nodeRef = useRef<HTMLDivElement>(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,
|
|
showExceptionBorder,
|
|
} = useMemo(() => {
|
|
return {
|
|
showRunningBorder: data._runningStatus === NodeRunningStatus.Running && !showSelectedBorder,
|
|
showSuccessBorder: data._runningStatus === NodeRunningStatus.Succeeded && !showSelectedBorder,
|
|
showFailedBorder: data._runningStatus === NodeRunningStatus.Failed && !showSelectedBorder,
|
|
showExceptionBorder: data._runningStatus === NodeRunningStatus.Exception && !showSelectedBorder,
|
|
}
|
|
}, [data._runningStatus, showSelectedBorder])
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex border-[2px] rounded-2xl',
|
|
showSelectedBorder ? 'border-components-option-card-option-selected-border' : 'border-transparent',
|
|
!showSelectedBorder && data._inParallelHovering && 'border-workflow-block-border-highlight',
|
|
data._waitingRun && 'opacity-70',
|
|
)}
|
|
ref={nodeRef}
|
|
style={{
|
|
width: data.type === BlockEnum.Iteration ? data.width : 'auto',
|
|
height: data.type === BlockEnum.Iteration ? data.height : 'auto',
|
|
}}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'group relative pb-1 shadow-xs',
|
|
'border border-transparent rounded-[15px]',
|
|
data.type !== BlockEnum.Iteration && 'w-[240px] bg-workflow-block-bg',
|
|
data.type === BlockEnum.Iteration && 'flex flex-col w-full h-full bg-workflow-block-bg-transparent border-workflow-block-border',
|
|
!data._runningStatus && 'hover:shadow-lg',
|
|
showRunningBorder && '!border-state-accent-solid',
|
|
showSuccessBorder && '!border-state-success-solid',
|
|
showFailedBorder && '!border-state-destructive-solid',
|
|
showExceptionBorder && '!border-state-warning-solid',
|
|
data._isBundled && '!shadow-lg',
|
|
)}
|
|
>
|
|
{
|
|
data._inParallelHovering && (
|
|
<div className='absolute left-2 -top-2.5 top system-2xs-medium-uppercase text-text-tertiary z-10'>
|
|
{t('workflow.common.parallelRun')}
|
|
</div>
|
|
)
|
|
}
|
|
{
|
|
data._showAddVariablePopup && (
|
|
<AddVariablePopupWithPosition
|
|
nodeId={id}
|
|
nodeData={data}
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
data.type === BlockEnum.Iteration && (
|
|
<NodeResizer
|
|
nodeId={id}
|
|
nodeData={data}
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
!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={cn(
|
|
'flex items-center px-3 pt-3 pb-2 rounded-t-2xl',
|
|
data.type === BlockEnum.Iteration && 'bg-transparent',
|
|
)}>
|
|
<BlockIcon
|
|
className='shrink-0 mr-2'
|
|
type={data.type}
|
|
size='md'
|
|
toolIcon={toolIcon}
|
|
/>
|
|
<div
|
|
title={data.title}
|
|
className='grow mr-1 system-sm-semibold-uppercase text-text-primary truncate flex items-center'
|
|
>
|
|
<div>
|
|
{data.title}
|
|
</div>
|
|
{
|
|
data.type === BlockEnum.Iteration && (data as IterationNodeType).is_parallel && (
|
|
<Tooltip popupContent={
|
|
<div className='w-[180px]'>
|
|
<div className='font-extrabold'>
|
|
{t('workflow.nodes.iteration.parallelModeEnableTitle')}
|
|
</div>
|
|
{t('workflow.nodes.iteration.parallelModeEnableDesc')}
|
|
</div>}
|
|
>
|
|
<div className='flex justify-center items-center px-[5px] py-[3px] ml-1 border-[1px] border-text-warning rounded-[5px] text-text-warning system-2xs-medium-uppercase '>
|
|
{t('workflow.nodes.iteration.parallelModeUpper')}
|
|
</div>
|
|
</Tooltip>
|
|
)
|
|
}
|
|
</div>
|
|
{
|
|
data._iterationLength && data._iterationIndex && data._runningStatus === NodeRunningStatus.Running && (
|
|
<div className='mr-1.5 text-xs font-medium text-text-accent'>
|
|
{data._iterationIndex > data._iterationLength ? data._iterationLength : data._iterationIndex}/{data._iterationLength}
|
|
</div>
|
|
)
|
|
}
|
|
{
|
|
(data._runningStatus === NodeRunningStatus.Running || data._singleRunningStatus === NodeRunningStatus.Running) && (
|
|
<RiLoader2Line className='w-3.5 h-3.5 text-text-accent animate-spin' />
|
|
)
|
|
}
|
|
{
|
|
data._runningStatus === NodeRunningStatus.Succeeded && (
|
|
<RiCheckboxCircleFill className='w-3.5 h-3.5 text-text-success' />
|
|
)
|
|
}
|
|
{
|
|
data._runningStatus === NodeRunningStatus.Failed && (
|
|
<RiErrorWarningFill className='w-3.5 h-3.5 text-text-destructive' />
|
|
)
|
|
}
|
|
{
|
|
data._runningStatus === NodeRunningStatus.Exception && (
|
|
<RiAlertFill className='w-3.5 h-3.5 text-text-warning-secondary' />
|
|
)
|
|
}
|
|
</div>
|
|
{
|
|
data.type !== BlockEnum.Iteration && (
|
|
cloneElement(children, { id, data })
|
|
)
|
|
}
|
|
{
|
|
data.type === BlockEnum.Iteration && (
|
|
<div className='grow pl-1 pr-1 pb-1'>
|
|
{cloneElement(children, { id, data })}
|
|
</div>
|
|
)
|
|
}
|
|
{
|
|
hasRetryNode(data.type) && (
|
|
<RetryOnNode
|
|
id={id}
|
|
data={data}
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
hasErrorHandleNode(data.type) && (
|
|
<ErrorHandleOnNode
|
|
id={id}
|
|
data={data}
|
|
/>
|
|
)
|
|
}
|
|
{
|
|
data.desc && data.type !== BlockEnum.Iteration && (
|
|
<div className='px-3 pt-1 pb-2 system-xs-regular text-text-tertiary whitespace-pre-line break-words'>
|
|
{data.desc}
|
|
</div>
|
|
)
|
|
}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default memo(BaseNode)
|