mirror of
				https://github.com/langgenius/dify.git
				synced 2025-10-31 19:03:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			279 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { useCallback, useMemo } from 'react'
 | |
| import produce from 'immer'
 | |
| import { v4 as uuid4 } from 'uuid'
 | |
| import { useUpdateNodeInternals } from 'reactflow'
 | |
| import type {
 | |
|   Var,
 | |
| } from '../../types'
 | |
| import { VarType } from '../../types'
 | |
| import { LogicalOperator } from './types'
 | |
| import type {
 | |
|   CaseItem,
 | |
|   HandleAddCondition,
 | |
|   HandleAddSubVariableCondition,
 | |
|   HandleRemoveCondition,
 | |
|   HandleToggleConditionLogicalOperator,
 | |
|   HandleToggleSubVariableConditionLogicalOperator,
 | |
|   HandleUpdateCondition,
 | |
|   HandleUpdateSubVariableCondition,
 | |
|   IfElseNodeType,
 | |
| } from './types'
 | |
| import {
 | |
|   branchNameCorrect,
 | |
|   getOperators,
 | |
| } from './utils'
 | |
| import useIsVarFileAttribute from './use-is-var-file-attribute'
 | |
| import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
 | |
| import {
 | |
|   useEdgesInteractions,
 | |
|   useNodesReadOnly,
 | |
| } from '@/app/components/workflow/hooks'
 | |
| import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
 | |
| 
 | |
| const useConfig = (id: string, payload: IfElseNodeType) => {
 | |
|   const updateNodeInternals = useUpdateNodeInternals()
 | |
|   const { nodesReadOnly: readOnly } = useNodesReadOnly()
 | |
|   const { handleEdgeDeleteByDeleteBranch } = useEdgesInteractions()
 | |
|   const { inputs, setInputs } = useNodeCrud<IfElseNodeType>(id, payload)
 | |
| 
 | |
|   const filterVar = useCallback(() => {
 | |
|     return true
 | |
|   }, [])
 | |
| 
 | |
|   const {
 | |
|     availableVars,
 | |
|     availableNodesWithParent,
 | |
|   } = useAvailableVarList(id, {
 | |
|     onlyLeafNodeVar: false,
 | |
|     filterVar,
 | |
|   })
 | |
| 
 | |
|   const filterNumberVar = useCallback((varPayload: Var) => {
 | |
|     return varPayload.type === VarType.number
 | |
|   }, [])
 | |
| 
 | |
|   const {
 | |
|     getIsVarFileAttribute,
 | |
|   } = useIsVarFileAttribute({
 | |
|     nodeId: id,
 | |
|     isInIteration: payload.isInIteration,
 | |
|     isInLoop: payload.isInLoop,
 | |
|   })
 | |
| 
 | |
|   const varsIsVarFileAttribute = useMemo(() => {
 | |
|     const conditions: Record<string, boolean> = {}
 | |
|     inputs.cases?.forEach((c) => {
 | |
|       c.conditions.forEach((condition) => {
 | |
|         conditions[condition.id] = getIsVarFileAttribute(condition.variable_selector!)
 | |
|       })
 | |
|     })
 | |
|     return conditions
 | |
|   }, [inputs.cases, getIsVarFileAttribute])
 | |
| 
 | |
|   const {
 | |
|     availableVars: availableNumberVars,
 | |
|     availableNodesWithParent: availableNumberNodesWithParent,
 | |
|   } = useAvailableVarList(id, {
 | |
|     onlyLeafNodeVar: false,
 | |
|     filterVar: filterNumberVar,
 | |
|   })
 | |
| 
 | |
|   const handleAddCase = useCallback(() => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       if (draft.cases) {
 | |
|         const case_id = uuid4()
 | |
|         draft.cases.push({
 | |
|           case_id,
 | |
|           logical_operator: LogicalOperator.and,
 | |
|           conditions: [],
 | |
|         })
 | |
|         if (draft._targetBranches) {
 | |
|           const elseCaseIndex = draft._targetBranches.findIndex(branch => branch.id === 'false')
 | |
|           if (elseCaseIndex > -1) {
 | |
|             draft._targetBranches = branchNameCorrect([
 | |
|               ...draft._targetBranches.slice(0, elseCaseIndex),
 | |
|               {
 | |
|                 id: case_id,
 | |
|                 name: '',
 | |
|               },
 | |
|               ...draft._targetBranches.slice(elseCaseIndex),
 | |
|             ])
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleRemoveCase = useCallback((caseId: string) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       draft.cases = draft.cases?.filter(item => item.case_id !== caseId)
 | |
| 
 | |
|       if (draft._targetBranches)
 | |
|         draft._targetBranches = branchNameCorrect(draft._targetBranches.filter(branch => branch.id !== caseId))
 | |
| 
 | |
|       handleEdgeDeleteByDeleteBranch(id, caseId)
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs, id, handleEdgeDeleteByDeleteBranch])
 | |
| 
 | |
|   const handleSortCase = useCallback((newCases: (CaseItem & { id: string })[]) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       draft.cases = newCases.filter(Boolean).map(item => ({
 | |
|         id: item.id,
 | |
|         case_id: item.case_id,
 | |
|         logical_operator: item.logical_operator,
 | |
|         conditions: item.conditions,
 | |
|       }))
 | |
| 
 | |
|       draft._targetBranches = branchNameCorrect([
 | |
|         ...newCases.filter(Boolean).map(item => ({ id: item.case_id, name: '' })),
 | |
|         { id: 'false', name: '' },
 | |
|       ])
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|     updateNodeInternals(id)
 | |
|   }, [id, inputs, setInputs, updateNodeInternals])
 | |
| 
 | |
|   const handleAddCondition = useCallback<HandleAddCondition>((caseId, valueSelector, varItem) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const targetCase = draft.cases?.find(item => item.case_id === caseId)
 | |
|       if (targetCase) {
 | |
|         targetCase.conditions.push({
 | |
|           id: uuid4(),
 | |
|           varType: varItem.type,
 | |
|           variable_selector: valueSelector,
 | |
|           comparison_operator: getOperators(varItem.type, getIsVarFileAttribute(valueSelector) ? { key: valueSelector.slice(-1)[0] } : undefined)[0],
 | |
|           value: '',
 | |
|         })
 | |
|       }
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [getIsVarFileAttribute, inputs, setInputs])
 | |
| 
 | |
|   const handleRemoveCondition = useCallback<HandleRemoveCondition>((caseId, conditionId) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const targetCase = draft.cases?.find(item => item.case_id === caseId)
 | |
|       if (targetCase)
 | |
|         targetCase.conditions = targetCase.conditions.filter(item => item.id !== conditionId)
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleUpdateCondition = useCallback<HandleUpdateCondition>((caseId, conditionId, newCondition) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const targetCase = draft.cases?.find(item => item.case_id === caseId)
 | |
|       if (targetCase) {
 | |
|         const targetCondition = targetCase.conditions.find(item => item.id === conditionId)
 | |
|         if (targetCondition)
 | |
|           Object.assign(targetCondition, newCondition)
 | |
|       }
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleToggleConditionLogicalOperator = useCallback<HandleToggleConditionLogicalOperator>((caseId) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const targetCase = draft.cases?.find(item => item.case_id === caseId)
 | |
|       if (targetCase)
 | |
|         targetCase.logical_operator = targetCase.logical_operator === LogicalOperator.and ? LogicalOperator.or : LogicalOperator.and
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleAddSubVariableCondition = useCallback<HandleAddSubVariableCondition>((caseId: string, conditionId: string, key?: string) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const condition = draft.cases?.find(item => item.case_id === caseId)?.conditions.find(item => item.id === conditionId)
 | |
|       if (!condition)
 | |
|         return
 | |
|       if (!condition?.sub_variable_condition) {
 | |
|         condition.sub_variable_condition = {
 | |
|           case_id: uuid4(),
 | |
|           logical_operator: LogicalOperator.and,
 | |
|           conditions: [],
 | |
|         }
 | |
|       }
 | |
|       const subVarCondition = condition.sub_variable_condition
 | |
|       if (subVarCondition) {
 | |
|         if (!subVarCondition.conditions)
 | |
|           subVarCondition.conditions = []
 | |
| 
 | |
|         subVarCondition.conditions.push({
 | |
|           id: uuid4(),
 | |
|           key: key || '',
 | |
|           varType: VarType.string,
 | |
|           comparison_operator: undefined,
 | |
|           value: '',
 | |
|         })
 | |
|       }
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleRemoveSubVariableCondition = useCallback((caseId: string, conditionId: string, subConditionId: string) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const condition = draft.cases?.find(item => item.case_id === caseId)?.conditions.find(item => item.id === conditionId)
 | |
|       if (!condition)
 | |
|         return
 | |
|       if (!condition?.sub_variable_condition)
 | |
|         return
 | |
|       const subVarCondition = condition.sub_variable_condition
 | |
|       if (subVarCondition)
 | |
|         subVarCondition.conditions = subVarCondition.conditions.filter(item => item.id !== subConditionId)
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleUpdateSubVariableCondition = useCallback<HandleUpdateSubVariableCondition>((caseId, conditionId, subConditionId, newSubCondition) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const targetCase = draft.cases?.find(item => item.case_id === caseId)
 | |
|       if (targetCase) {
 | |
|         const targetCondition = targetCase.conditions.find(item => item.id === conditionId)
 | |
|         if (targetCondition && targetCondition.sub_variable_condition) {
 | |
|           const targetSubCondition = targetCondition.sub_variable_condition.conditions.find(item => item.id === subConditionId)
 | |
|           if (targetSubCondition)
 | |
|             Object.assign(targetSubCondition, newSubCondition)
 | |
|         }
 | |
|       }
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   const handleToggleSubVariableConditionLogicalOperator = useCallback<HandleToggleSubVariableConditionLogicalOperator>((caseId, conditionId) => {
 | |
|     const newInputs = produce(inputs, (draft) => {
 | |
|       const targetCase = draft.cases?.find(item => item.case_id === caseId)
 | |
|       if (targetCase) {
 | |
|         const targetCondition = targetCase.conditions.find(item => item.id === conditionId)
 | |
|         if (targetCondition && targetCondition.sub_variable_condition)
 | |
|           targetCondition.sub_variable_condition.logical_operator = targetCondition.sub_variable_condition.logical_operator === LogicalOperator.and ? LogicalOperator.or : LogicalOperator.and
 | |
|       }
 | |
|     })
 | |
|     setInputs(newInputs)
 | |
|   }, [inputs, setInputs])
 | |
| 
 | |
|   return {
 | |
|     readOnly,
 | |
|     inputs,
 | |
|     filterVar,
 | |
|     filterNumberVar,
 | |
|     handleAddCase,
 | |
|     handleRemoveCase,
 | |
|     handleSortCase,
 | |
|     handleAddCondition,
 | |
|     handleRemoveCondition,
 | |
|     handleUpdateCondition,
 | |
|     handleToggleConditionLogicalOperator,
 | |
|     handleAddSubVariableCondition,
 | |
|     handleUpdateSubVariableCondition,
 | |
|     handleRemoveSubVariableCondition,
 | |
|     handleToggleSubVariableConditionLogicalOperator,
 | |
|     nodesOutputVars: availableVars,
 | |
|     availableNodes: availableNodesWithParent,
 | |
|     nodesOutputNumberVars: availableNumberVars,
 | |
|     availableNumberNodes: availableNumberNodesWithParent,
 | |
|     varsIsVarFileAttribute,
 | |
|   }
 | |
| }
 | |
| 
 | |
| export default useConfig
 | 
