mirror of
https://github.com/langgenius/dify.git
synced 2026-07-25 13:38:31 +08:00
158 lines
5.7 KiB
TypeScript
158 lines
5.7 KiB
TypeScript
import type { Node, ValueSelector, VarType } from '../../../types'
|
|
import type { VariableAssignerNodeType } from '../types'
|
|
import { cn } from '@langgenius/dify-ui/cn'
|
|
import { memo, useMemo } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { useNodes } from 'reactflow'
|
|
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
|
import { VariableLabelInNode } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
|
import { isExceptionVariable } from '@/app/components/workflow/utils'
|
|
import { useStore } from '../../../store'
|
|
import { BlockEnum } from '../../../types'
|
|
import { useGetAvailableVars, useVariableAssigner } from '../hooks'
|
|
import { filterVar } from '../utils'
|
|
import AddVariable from './add-variable'
|
|
|
|
const i18nPrefix = 'nodes.variableAssigner'
|
|
type GroupItem = {
|
|
groupEnabled: boolean
|
|
targetHandleId: string
|
|
title: string
|
|
type: string
|
|
variables: ValueSelector[]
|
|
variableAssignerNodeId: string
|
|
variableAssignerNodeData: VariableAssignerNodeType
|
|
}
|
|
type NodeGroupItemProps = {
|
|
item: GroupItem
|
|
}
|
|
const NodeGroupItem = ({ item }: NodeGroupItemProps) => {
|
|
const { t } = useTranslation()
|
|
const enteringNodePayload = useStore((s) => s.enteringNodePayload)
|
|
const hoveringAssignVariableGroupId = useStore((s) => s.hoveringAssignVariableGroupId)
|
|
const nodes: Node[] = useNodes()
|
|
const { handleGroupItemMouseEnter, handleGroupItemMouseLeave } = useVariableAssigner()
|
|
const getAvailableVars = useGetAvailableVars()
|
|
const groupEnabled = item.groupEnabled
|
|
const outputType = useMemo(() => {
|
|
if (!groupEnabled) return item.variableAssignerNodeData.output_type
|
|
|
|
const group = item.variableAssignerNodeData.advanced_settings?.groups.find(
|
|
(group) => group.groupId === item.targetHandleId,
|
|
)
|
|
return group?.output_type || ''
|
|
}, [item.variableAssignerNodeData, item.targetHandleId, groupEnabled])
|
|
const availableVars = getAvailableVars(
|
|
item.variableAssignerNodeId,
|
|
item.targetHandleId,
|
|
filterVar(outputType as VarType),
|
|
true,
|
|
)
|
|
const showSelectionBorder = useMemo(() => {
|
|
if (groupEnabled && enteringNodePayload?.nodeId === item.variableAssignerNodeId) {
|
|
if (hoveringAssignVariableGroupId)
|
|
return hoveringAssignVariableGroupId !== item.targetHandleId
|
|
else
|
|
return (
|
|
enteringNodePayload?.nodeData.advanced_settings?.groups[0]!.groupId !==
|
|
item.targetHandleId
|
|
)
|
|
}
|
|
|
|
return false
|
|
}, [
|
|
enteringNodePayload,
|
|
groupEnabled,
|
|
hoveringAssignVariableGroupId,
|
|
item.targetHandleId,
|
|
item.variableAssignerNodeId,
|
|
])
|
|
const showSelectedBorder = useMemo(() => {
|
|
if (groupEnabled && enteringNodePayload?.nodeId === item.variableAssignerNodeId) {
|
|
if (hoveringAssignVariableGroupId)
|
|
return hoveringAssignVariableGroupId === item.targetHandleId
|
|
else
|
|
return (
|
|
enteringNodePayload?.nodeData.advanced_settings?.groups[0]!.groupId ===
|
|
item.targetHandleId
|
|
)
|
|
}
|
|
|
|
return false
|
|
}, [
|
|
enteringNodePayload,
|
|
groupEnabled,
|
|
hoveringAssignVariableGroupId,
|
|
item.targetHandleId,
|
|
item.variableAssignerNodeId,
|
|
])
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'relative rounded-lg border-[1.5px] border-transparent px-1.5 pt-1 pb-1.5',
|
|
showSelectionBorder && 'border-dashed! border-divider-subtle! bg-state-base-hover',
|
|
showSelectedBorder && 'border-text-accent! bg-util-colors-blue-blue-50!',
|
|
)}
|
|
onMouseEnter={() => groupEnabled && handleGroupItemMouseEnter(item.targetHandleId)}
|
|
onMouseLeave={handleGroupItemMouseLeave}
|
|
>
|
|
<div className="flex h-4 items-center justify-between text-[10px] font-medium text-text-tertiary">
|
|
<span
|
|
className={cn('grow truncate uppercase', showSelectedBorder && 'text-text-accent')}
|
|
title={item.title}
|
|
>
|
|
{item.title}
|
|
</span>
|
|
<div className="flex items-center">
|
|
<span className="ml-2 shrink-0">{item.type}</span>
|
|
<div className="mr-1 ml-2 h-2.5 w-px bg-divider-regular"></div>
|
|
<AddVariable
|
|
availableVars={availableVars}
|
|
variableAssignerNodeId={item.variableAssignerNodeId}
|
|
variableAssignerNodeData={item.variableAssignerNodeData}
|
|
handleId={item.targetHandleId}
|
|
/>
|
|
</div>
|
|
</div>
|
|
{!item.variables.length && (
|
|
<div
|
|
className={cn(
|
|
'relative flex h-[22px] items-center justify-between space-x-1 rounded-md bg-workflow-block-parma-bg px-1 text-[10px] font-normal text-text-tertiary uppercase',
|
|
(showSelectedBorder || showSelectionBorder) && 'bg-black/2!',
|
|
)}
|
|
>
|
|
{t(($) => $[`${i18nPrefix}.varNotSet`], { ns: 'workflow' })}
|
|
</div>
|
|
)}
|
|
{!!item.variables.length && (
|
|
<div className="space-y-0.5">
|
|
{item.variables.map((variable = [], index) => {
|
|
const isSystem = isSystemVar(variable)
|
|
|
|
const node = isSystem
|
|
? nodes.find((node) => node.data.type === BlockEnum.Start)
|
|
: nodes.find((node) => node.id === variable[0])
|
|
const varName = isSystem
|
|
? `sys.${variable[variable.length - 1]}`
|
|
: variable.slice(1).join('.')
|
|
const isException = isExceptionVariable(varName, node?.data.type)
|
|
|
|
return (
|
|
<VariableLabelInNode
|
|
key={index}
|
|
variables={variable}
|
|
nodeType={node?.data.type}
|
|
nodeTitle={node?.data.title}
|
|
isExceptionVariable={isException}
|
|
/>
|
|
)
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default memo(NodeGroupItem)
|