hooks.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { useCallback } from 'react'
  2. import {
  3. useNodes,
  4. useStoreApi,
  5. } from 'reactflow'
  6. import { useTranslation } from 'react-i18next'
  7. import { uniqBy } from 'lodash-es'
  8. import produce from 'immer'
  9. import {
  10. useIsChatMode,
  11. useNodeDataUpdate,
  12. useWorkflow,
  13. } from '../../hooks'
  14. import type {
  15. Node,
  16. ValueSelector,
  17. Var,
  18. } from '../../types'
  19. import { useWorkflowStore } from '../../store'
  20. import type {
  21. VarGroupItem,
  22. VariableAssignerNodeType,
  23. } from './types'
  24. import { toNodeAvailableVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
  25. export const useVariableAssigner = () => {
  26. const store = useStoreApi()
  27. const workflowStore = useWorkflowStore()
  28. const { handleNodeDataUpdate } = useNodeDataUpdate()
  29. const handleAssignVariableValueChange = useCallback((nodeId: string, value: ValueSelector, varDetail: Var, groupId?: string) => {
  30. const { getNodes } = store.getState()
  31. const nodes = getNodes()
  32. const node: Node<VariableAssignerNodeType> = nodes.find(node => node.id === nodeId)!
  33. let payload
  34. if (groupId && groupId !== 'target') {
  35. payload = {
  36. advanced_settings: {
  37. ...node.data.advanced_settings,
  38. groups: node.data.advanced_settings?.groups.map((group: VarGroupItem & { groupId: string }) => {
  39. if (group.groupId === groupId && !group.variables.some(item => item.join('.') === (value as ValueSelector).join('.'))) {
  40. return {
  41. ...group,
  42. variables: [...group.variables, value],
  43. output_type: varDetail.type,
  44. }
  45. }
  46. return group
  47. }),
  48. },
  49. }
  50. }
  51. else {
  52. if (node.data.variables.some(item => item.join('.') === (value as ValueSelector).join('.')))
  53. return
  54. payload = {
  55. variables: [...node.data.variables, value],
  56. output_type: varDetail.type,
  57. }
  58. }
  59. handleNodeDataUpdate({
  60. id: nodeId,
  61. data: payload,
  62. })
  63. }, [store, handleNodeDataUpdate])
  64. const handleAddVariableInAddVariablePopupWithPosition = useCallback((
  65. nodeId: string,
  66. variableAssignerNodeId: string,
  67. variableAssignerNodeHandleId: string,
  68. value: ValueSelector,
  69. varDetail: Var,
  70. ) => {
  71. const {
  72. getNodes,
  73. setNodes,
  74. } = store.getState()
  75. const {
  76. setShowAssignVariablePopup,
  77. } = workflowStore.getState()
  78. const newNodes = produce(getNodes(), (draft) => {
  79. draft.forEach((node) => {
  80. if (node.id === nodeId || node.id === variableAssignerNodeId) {
  81. node.data = {
  82. ...node.data,
  83. _showAddVariablePopup: false,
  84. _holdAddVariablePopup: false,
  85. }
  86. }
  87. })
  88. })
  89. setNodes(newNodes)
  90. setShowAssignVariablePopup(undefined)
  91. handleAssignVariableValueChange(variableAssignerNodeId, value, varDetail, variableAssignerNodeHandleId)
  92. }, [store, workflowStore, handleAssignVariableValueChange])
  93. const handleGroupItemMouseEnter = useCallback((groupId: string) => {
  94. const {
  95. setHoveringAssignVariableGroupId,
  96. } = workflowStore.getState()
  97. setHoveringAssignVariableGroupId(groupId)
  98. }, [workflowStore])
  99. const handleGroupItemMouseLeave = useCallback(() => {
  100. const {
  101. connectingNodePayload,
  102. setHoveringAssignVariableGroupId,
  103. } = workflowStore.getState()
  104. if (connectingNodePayload)
  105. setHoveringAssignVariableGroupId(undefined)
  106. }, [workflowStore])
  107. return {
  108. handleAddVariableInAddVariablePopupWithPosition,
  109. handleGroupItemMouseEnter,
  110. handleGroupItemMouseLeave,
  111. handleAssignVariableValueChange,
  112. }
  113. }
  114. export const useGetAvailableVars = () => {
  115. const { t } = useTranslation()
  116. const nodes: Node[] = useNodes()
  117. const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
  118. const isChatMode = useIsChatMode()
  119. const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean) => {
  120. const availableNodes: Node[] = []
  121. const currentNode = nodes.find(node => node.id === nodeId)!
  122. if (!currentNode)
  123. return []
  124. const beforeNodes = getBeforeNodesInSameBranchIncludeParent(nodeId)
  125. availableNodes.push(...beforeNodes)
  126. const parentNode = nodes.find(node => node.id === currentNode.parentId)
  127. return toNodeAvailableVars({
  128. parentNode,
  129. t,
  130. beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId),
  131. isChatMode,
  132. filterVar,
  133. })
  134. }, [nodes, t, isChatMode, getBeforeNodesInSameBranchIncludeParent])
  135. return getAvailableVars
  136. }