Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

panel.tsx 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import type { FC } from 'react'
  2. import { useCallback, useEffect, useMemo, useState } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import {
  5. RiCloseLine,
  6. } from '@remixicon/react'
  7. import { useStore } from '../store'
  8. import useCurrentVars from '../hooks/use-inspect-vars-crud'
  9. import Empty from './empty'
  10. import Left from './left'
  11. import Right from './right'
  12. import ActionButton from '@/app/components/base/action-button'
  13. import type { VarInInspect } from '@/types/workflow'
  14. import { VarInInspectType } from '@/types/workflow'
  15. import cn from '@/utils/classnames'
  16. import type { NodeProps } from '../types'
  17. export type currentVarType = {
  18. nodeId: string
  19. nodeType: string
  20. title: string
  21. isValueFetched?: boolean
  22. var: VarInInspect
  23. nodeData: NodeProps['data']
  24. }
  25. const Panel: FC = () => {
  26. const { t } = useTranslation()
  27. const bottomPanelWidth = useStore(s => s.bottomPanelWidth)
  28. const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel)
  29. const [showLeftPanel, setShowLeftPanel] = useState(true)
  30. const environmentVariables = useStore(s => s.environmentVariables)
  31. const currentFocusNodeId = useStore(s => s.currentFocusNodeId)
  32. const setCurrentFocusNodeId = useStore(s => s.setCurrentFocusNodeId)
  33. const [currentVarId, setCurrentVarId] = useState('')
  34. const {
  35. conversationVars,
  36. systemVars,
  37. nodesWithInspectVars,
  38. fetchInspectVarValue,
  39. } = useCurrentVars()
  40. const isEmpty = useMemo(() => {
  41. const allVars = [...environmentVariables, ...conversationVars, ...systemVars, ...nodesWithInspectVars]
  42. return allVars.length === 0
  43. }, [environmentVariables, conversationVars, systemVars, nodesWithInspectVars])
  44. const currentNodeInfo = useMemo(() => {
  45. if (!currentFocusNodeId) return
  46. if (currentFocusNodeId === VarInInspectType.environment) {
  47. const currentVar = environmentVariables.find(v => v.id === currentVarId)
  48. const res = {
  49. nodeId: VarInInspectType.environment,
  50. title: VarInInspectType.environment,
  51. nodeType: VarInInspectType.environment,
  52. }
  53. if (currentVar) {
  54. return {
  55. ...res,
  56. var: {
  57. ...currentVar,
  58. type: VarInInspectType.environment,
  59. visible: true,
  60. ...(currentVar.value_type === 'secret' ? { value: '******************' } : {}),
  61. },
  62. }
  63. }
  64. return res
  65. }
  66. if (currentFocusNodeId === VarInInspectType.conversation) {
  67. const currentVar = conversationVars.find(v => v.id === currentVarId)
  68. const res = {
  69. nodeId: VarInInspectType.conversation,
  70. title: VarInInspectType.conversation,
  71. nodeType: VarInInspectType.conversation,
  72. }
  73. if (currentVar) {
  74. return {
  75. ...res,
  76. var: {
  77. ...currentVar,
  78. type: VarInInspectType.conversation,
  79. },
  80. }
  81. }
  82. return res
  83. }
  84. if (currentFocusNodeId === VarInInspectType.system) {
  85. const currentVar = systemVars.find(v => v.id === currentVarId)
  86. const res = {
  87. nodeId: VarInInspectType.system,
  88. title: VarInInspectType.system,
  89. nodeType: VarInInspectType.system,
  90. }
  91. if (currentVar) {
  92. return {
  93. ...res,
  94. var: {
  95. ...currentVar,
  96. type: VarInInspectType.system,
  97. },
  98. }
  99. }
  100. return res
  101. }
  102. const targetNode = nodesWithInspectVars.find(node => node.nodeId === currentFocusNodeId)
  103. if (!targetNode) return
  104. const currentVar = targetNode.vars.find(v => v.id === currentVarId)
  105. return {
  106. nodeId: targetNode.nodeId,
  107. nodeType: targetNode.nodeType,
  108. title: targetNode.title,
  109. isSingRunRunning: targetNode.isSingRunRunning,
  110. isValueFetched: targetNode.isValueFetched,
  111. nodeData: targetNode.nodePayload,
  112. ...(currentVar ? { var: currentVar } : {}),
  113. }
  114. }, [currentFocusNodeId, currentVarId, environmentVariables, conversationVars, systemVars, nodesWithInspectVars])
  115. const isCurrentNodeVarValueFetching = useMemo(() => {
  116. if (!currentNodeInfo) return false
  117. const targetNode = nodesWithInspectVars.find(node => node.nodeId === currentNodeInfo.nodeId)
  118. if (!targetNode) return false
  119. return !targetNode.isValueFetched
  120. }, [currentNodeInfo, nodesWithInspectVars])
  121. const handleNodeVarSelect = useCallback((node: currentVarType) => {
  122. setCurrentFocusNodeId(node.nodeId)
  123. setCurrentVarId(node.var.id)
  124. }, [setCurrentFocusNodeId, setCurrentVarId])
  125. useEffect(() => {
  126. if (currentFocusNodeId && currentVarId) {
  127. const targetNode = nodesWithInspectVars.find(node => node.nodeId === currentFocusNodeId)
  128. if (targetNode && !targetNode.isValueFetched)
  129. fetchInspectVarValue([currentFocusNodeId])
  130. }
  131. }, [currentFocusNodeId, currentVarId, nodesWithInspectVars, fetchInspectVarValue])
  132. if (isEmpty) {
  133. return (
  134. <div className={cn('flex h-full flex-col')}>
  135. <div className='flex shrink-0 items-center justify-between pl-4 pr-2 pt-2'>
  136. <div className='system-sm-semibold-uppercase text-text-primary'>{t('workflow.debug.variableInspect.title')}</div>
  137. <ActionButton onClick={() => setShowVariableInspectPanel(false)}>
  138. <RiCloseLine className='h-4 w-4' />
  139. </ActionButton>
  140. </div>
  141. <div className='grow p-2'>
  142. <Empty />
  143. </div>
  144. </div>
  145. )
  146. }
  147. return (
  148. <div className={cn('relative flex h-full')}>
  149. {/* left */}
  150. {bottomPanelWidth < 488 && showLeftPanel && <div className='absolute left-0 top-0 h-full w-full' onClick={() => setShowLeftPanel(false)}></div>}
  151. <div
  152. className={cn(
  153. 'w-60 shrink-0 border-r border-divider-burn',
  154. bottomPanelWidth < 488
  155. ? showLeftPanel
  156. ? 'absolute left-0 top-0 z-10 h-full w-[217px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg backdrop-blur-sm'
  157. : 'hidden'
  158. : 'block',
  159. )}
  160. >
  161. <Left
  162. currentNodeVar={currentNodeInfo as currentVarType}
  163. handleVarSelect={handleNodeVarSelect}
  164. />
  165. </div>
  166. {/* right */}
  167. <div className='w-0 grow'>
  168. <Right
  169. nodeId={currentFocusNodeId!}
  170. isValueFetching={isCurrentNodeVarValueFetching}
  171. currentNodeVar={currentNodeInfo as currentVarType}
  172. handleOpenMenu={() => setShowLeftPanel(true)}
  173. />
  174. </div>
  175. </div>
  176. )
  177. }
  178. export default Panel