'use client' import type { FC } from 'react' import type { WorkflowNodesMap } from '../workflow-variable-block/node' import type { FormInputItem } from '@/app/components/workflow/nodes/human-input/types' import type { Type } from '@/app/components/workflow/nodes/llm/types' import type { ValueSelector, Var } from '@/app/components/workflow/types' import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog' import { useBoolean } from 'ahooks' import * as React from 'react' import { useCallback, useEffect, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' import { createDefaultParagraphFormInput, isFileFormInput, isParagraphFormInput, isSelectFormInput, } from '@/app/components/workflow/nodes/human-input/types' import ActionButton from '../../../action-button' import { VariableX } from '../../../icons/src/vender/workflow' import InputField from './input-field' import VariableBlock from './variable-block' const i18nPrefix = 'nodes.humanInput.insertInputField' type HITLInputComponentUIProps = { nodeId: string varName: string formInput?: FormInputItem unavailableVariableNames?: string[] onChange: (input: FormInputItem) => void onRename: (payload: FormInputItem, oldName: string) => void onRemove: (varName: string) => void workflowNodesMap: WorkflowNodesMap environmentVariables?: Var[] conversationVariables?: Var[] ragVariables?: Var[] getVarType?: (payload: { nodeId: string; valueSelector: ValueSelector }) => Type readonly?: boolean } const HITLInputComponentUI: FC = ({ nodeId, varName, formInput, unavailableVariableNames = [], onChange, onRename, onRemove, workflowNodesMap = {}, getVarType, environmentVariables, conversationVariables, ragVariables, readonly, }) => { const { t } = useTranslation() const resolvedFormInput = formInput || createDefaultParagraphFormInput(varName) const paragraphDefault = isParagraphFormInput(resolvedFormInput) ? resolvedFormInput.default : null const [isShowEditModal, { setTrue: showEditModal, setFalse: hideEditModal }] = useBoolean(false) useEffect(() => { if (readonly) hideEditModal() }, [hideEditModal, readonly]) // Lexical delegate the click make it unable to add click by the method of react const editBtnRef = useRef(null) useEffect(() => { const editBtn = editBtnRef.current if (editBtn) editBtn.addEventListener('click', showEditModal) return () => { if (editBtn) editBtn.removeEventListener('click', showEditModal) } }, [showEditModal]) const removeBtnRef = useRef(null) useEffect(() => { const removeBtn = removeBtnRef.current const removeHandler = () => onRemove(varName) if (removeBtn) removeBtn.addEventListener('click', removeHandler) return () => { if (removeBtn) removeBtn.removeEventListener('click', removeHandler) } }, [onRemove, varName]) const handleChange = useCallback( (newPayload: FormInputItem) => { if ( newPayload.output_variable_name !== varName && unavailableVariableNames.includes(newPayload.output_variable_name) ) return if (varName === newPayload.output_variable_name) onChange(newPayload) else onRename(newPayload, varName) hideEditModal() }, [hideEditModal, onChange, onRename, unavailableVariableNames, varName], ) const isDefaultValueVariable = useMemo(() => { return paragraphDefault?.type === 'variable' }, [paragraphDefault]) const inputTypeLabel = useMemo(() => { if (isParagraphFormInput(resolvedFormInput)) return t(($) => $['variableConfig.paragraph'], { ns: 'appDebug' }) if (isSelectFormInput(resolvedFormInput)) return t(($) => $['variableConfig.select'], { ns: 'appDebug' }) if (isFileFormInput(resolvedFormInput)) return t(($) => $['variableConfig.single-file'], { ns: 'appDebug' }) return t(($) => $['variableConfig.multi-files'], { ns: 'appDebug' }) }, [resolvedFormInput, t]) const variableSelector = useMemo(() => { if (isDefaultValueVariable) return paragraphDefault?.selector || [] if (isSelectFormInput(resolvedFormInput) && resolvedFormInput.option_source.type === 'variable') return resolvedFormInput.option_source.selector return null }, [isDefaultValueVariable, paragraphDefault?.selector, resolvedFormInput]) const summaryText = useMemo(() => { if (isParagraphFormInput(resolvedFormInput)) return paragraphDefault?.value || inputTypeLabel if (isSelectFormInput(resolvedFormInput)) { if (resolvedFormInput.option_source.type === 'variable') return t(($) => $[`${i18nPrefix}.variable`], { ns: 'workflow' }) return resolvedFormInput.option_source.value.join(', ') || inputTypeLabel } return inputTypeLabel }, [inputTypeLabel, paragraphDefault?.value, resolvedFormInput, t]) return (
{varName}
{variableSelector ? ( ) : (
{summaryText}
)}
{inputTypeLabel}
{/* Actions */} {!readonly && (
$['operation.edit'], { ns: 'common' })}>
$['operation.remove'], { ns: 'common' })}>
)}
{isShowEditModal && ( { if (!open) hideEditModal() }} > )}
) } export default React.memo(HITLInputComponentUI)