| import { useCallback } from 'react' | |
| import { | |
| useNodes, | |
| useStoreApi, | |
| } from 'reactflow' | |
| import { uniqBy } from 'lodash-es' | |
| import produce from 'immer' | |
| import { | |
| useIsChatMode, | |
| useNodeDataUpdate, | |
| useWorkflow, | |
| useWorkflowVariables, | |
| } from '../../hooks' | |
| import type { | |
| Node, | |
| ValueSelector, | |
| Var, | |
| } from '../../types' | |
| import { useWorkflowStore } from '../../store' | |
| import type { | |
| VarGroupItem, | |
| VariableAssignerNodeType, | |
| } from './types' | |
| export const useVariableAssigner = () => { | |
| const store = useStoreApi() | |
| const workflowStore = useWorkflowStore() | |
| const { handleNodeDataUpdate } = useNodeDataUpdate() | |
| const handleAssignVariableValueChange = useCallback((nodeId: string, value: ValueSelector, varDetail: Var, groupId?: string) => { | |
| const { getNodes } = store.getState() | |
| const nodes = getNodes() | |
| const node: Node<VariableAssignerNodeType> = nodes.find(node => node.id === nodeId)! | |
| let payload | |
| if (groupId && groupId !== 'target') { | |
| payload = { | |
| advanced_settings: { | |
| ...node.data.advanced_settings, | |
| groups: node.data.advanced_settings?.groups.map((group: VarGroupItem & { groupId: string }) => { | |
| if (group.groupId === groupId && !group.variables.some(item => item.join('.') === (value as ValueSelector).join('.'))) { | |
| return { | |
| ...group, | |
| variables: [...group.variables, value], | |
| output_type: varDetail.type, | |
| } | |
| } | |
| return group | |
| }), | |
| }, | |
| } | |
| } | |
| else { | |
| if (node.data.variables.some(item => item.join('.') === (value as ValueSelector).join('.'))) | |
| return | |
| payload = { | |
| variables: [...node.data.variables, value], | |
| output_type: varDetail.type, | |
| } | |
| } | |
| handleNodeDataUpdate({ | |
| id: nodeId, | |
| data: payload, | |
| }) | |
| }, [store, handleNodeDataUpdate]) | |
| const handleAddVariableInAddVariablePopupWithPosition = useCallback(( | |
| nodeId: string, | |
| variableAssignerNodeId: string, | |
| variableAssignerNodeHandleId: string, | |
| value: ValueSelector, | |
| varDetail: Var, | |
| ) => { | |
| const { | |
| getNodes, | |
| setNodes, | |
| } = store.getState() | |
| const { | |
| setShowAssignVariablePopup, | |
| } = workflowStore.getState() | |
| const newNodes = produce(getNodes(), (draft) => { | |
| draft.forEach((node) => { | |
| if (node.id === nodeId || node.id === variableAssignerNodeId) { | |
| node.data = { | |
| ...node.data, | |
| _showAddVariablePopup: false, | |
| _holdAddVariablePopup: false, | |
| } | |
| } | |
| }) | |
| }) | |
| setNodes(newNodes) | |
| setShowAssignVariablePopup(undefined) | |
| handleAssignVariableValueChange(variableAssignerNodeId, value, varDetail, variableAssignerNodeHandleId) | |
| }, [store, workflowStore, handleAssignVariableValueChange]) | |
| const handleGroupItemMouseEnter = useCallback((groupId: string) => { | |
| const { | |
| setHoveringAssignVariableGroupId, | |
| } = workflowStore.getState() | |
| setHoveringAssignVariableGroupId(groupId) | |
| }, [workflowStore]) | |
| const handleGroupItemMouseLeave = useCallback(() => { | |
| const { | |
| connectingNodePayload, | |
| setHoveringAssignVariableGroupId, | |
| } = workflowStore.getState() | |
| if (connectingNodePayload) | |
| setHoveringAssignVariableGroupId(undefined) | |
| }, [workflowStore]) | |
| return { | |
| handleAddVariableInAddVariablePopupWithPosition, | |
| handleGroupItemMouseEnter, | |
| handleGroupItemMouseLeave, | |
| handleAssignVariableValueChange, | |
| } | |
| } | |
| export const useGetAvailableVars = () => { | |
| const nodes: Node[] = useNodes() | |
| const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow() | |
| const { getNodeAvailableVars } = useWorkflowVariables() | |
| const isChatMode = useIsChatMode() | |
| const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => { | |
| const availableNodes: Node[] = [] | |
| const currentNode = nodes.find(node => node.id === nodeId)! | |
| if (!currentNode) | |
| return [] | |
| const beforeNodes = getBeforeNodesInSameBranchIncludeParent(nodeId) | |
| availableNodes.push(...beforeNodes) | |
| const parentNode = nodes.find(node => node.id === currentNode.parentId) | |
| if (hideEnv) { | |
| return getNodeAvailableVars({ | |
| parentNode, | |
| beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId), | |
| isChatMode, | |
| hideEnv, | |
| hideChatVar: hideEnv, | |
| filterVar, | |
| }) | |
| .map(node => ({ | |
| ...node, | |
| vars: node.isStartNode ? node.vars.filter(v => !v.variable.startsWith('sys.')) : node.vars, | |
| })) | |
| .filter(item => item.vars.length > 0) | |
| } | |
| return getNodeAvailableVars({ | |
| parentNode, | |
| beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId), | |
| isChatMode, | |
| filterVar, | |
| }) | |
| }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode]) | |
| return getAvailableVars | |
| } | |