dify/web/app/components/workflow/nodes/variable-assigner/components/node-group-item.tsx
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

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)