dify/web/app/components/base/prompt-editor/plugins/hitl-input-block/variable-block.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

144 lines
4.8 KiB
TypeScript

import type { UpdateWorkflowNodesMapPayload } from '../workflow-variable-block'
import type { WorkflowNodesMap } from '../workflow-variable-block/node'
import type { ValueSelector, Var } from '@/app/components/workflow/types'
import {
PreviewCard,
PreviewCardContent,
PreviewCardTrigger,
} from '@langgenius/dify-ui/preview-card'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { mergeRegister } from '@lexical/utils'
import { COMMAND_PRIORITY_EDITOR } from 'lexical'
import { memo, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
isConversationVar,
isENV,
isGlobalVar,
isRagVariableVar,
isSystemVar,
} from '@/app/components/workflow/nodes/_base/components/variable/utils'
import VarFullPathPanel from '@/app/components/workflow/nodes/_base/components/variable/var-full-path-panel'
import { VariableLabelInEditor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { Type } from '@/app/components/workflow/nodes/llm/types'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import { UPDATE_WORKFLOW_NODES_MAP } from '../workflow-variable-block'
import { HITLInputNode } from './node'
type HITLInputVariableBlockComponentProps = {
variables: string[]
workflowNodesMap: WorkflowNodesMap
environmentVariables?: Var[]
conversationVariables?: Var[]
ragVariables?: Var[]
getVarType?: (payload: { nodeId: string; valueSelector: ValueSelector }) => Type
}
const HITLInputVariableBlockComponent = ({
variables,
workflowNodesMap = {},
getVarType,
environmentVariables,
conversationVariables,
ragVariables,
}: HITLInputVariableBlockComponentProps) => {
const { t } = useTranslation()
const [editor] = useLexicalComposerContext()
const variablesLength = variables.length
const isRagVar = isRagVariableVar(variables)
const isShowAPart = variablesLength > 2 && !isRagVar
const varName = (() => {
const isSystem = isSystemVar(variables)
const varName = variables[variablesLength - 1]
return `${isSystem ? 'sys.' : ''}${varName}`
})()
const [localWorkflowNodesMap, setLocalWorkflowNodesMap] =
useState<WorkflowNodesMap>(workflowNodesMap)
const node = localWorkflowNodesMap![variables[isRagVar ? 1 : 0]!]
const isException = isExceptionVariable(varName, node?.type)
const variableValid = useMemo(() => {
let variableValid = true
const isEnv = isENV(variables)
const isChatVar = isConversationVar(variables)
const isGlobal = isGlobalVar(variables)
if (isGlobal) return true
if (isEnv) {
if (environmentVariables)
variableValid = environmentVariables.some(
(v) => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`,
)
} else if (isChatVar) {
if (conversationVariables)
variableValid = conversationVariables.some(
(v) => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`,
)
} else if (isRagVar) {
if (ragVariables)
variableValid = ragVariables.some(
(v) =>
v.variable ===
`${variables?.[0] ?? ''}.${variables?.[1] ?? ''}.${variables?.[2] ?? ''}`,
)
} else {
variableValid = !!node
}
return variableValid
}, [variables, node, environmentVariables, conversationVariables, isRagVar, ragVariables])
useEffect(() => {
if (!editor.hasNodes([HITLInputNode]))
throw new Error('HITLInputNodePlugin: HITLInputNode not registered on editor')
return mergeRegister(
editor.registerCommand(
UPDATE_WORKFLOW_NODES_MAP,
(payload: UpdateWorkflowNodesMapPayload) => {
setLocalWorkflowNodesMap(payload.workflowNodesMap)
return true
},
COMMAND_PRIORITY_EDITOR,
),
)
}, [editor])
const Item = (
<VariableLabelInEditor
nodeType={node?.type}
nodeTitle={node?.title}
variables={variables}
isExceptionVariable={isException}
errorMsg={
!variableValid ? t(($) => $['errorMsg.invalidVariable'], { ns: 'workflow' }) : undefined
}
notShowFullPath={isShowAPart}
/>
)
if (!node || !isShowAPart) return Item
return (
<PreviewCard>
<PreviewCardTrigger delay={300} closeDelay={200} render={<div>{Item}</div>} />
<PreviewCardContent popupClassName="border-0 bg-transparent p-0 shadow-none">
<VarFullPathPanel
nodeName={node.title}
path={variables.slice(1)}
varType={
getVarType
? getVarType({
nodeId: variables[0]!,
valueSelector: variables,
})
: Type.string
}
nodeType={node?.type}
/>
</PreviewCardContent>
</PreviewCard>
)
}
export default memo(HITLInputVariableBlockComponent)