import { memo, useCallback, useMemo, useRef, useState, } from 'react' import { RiCloseLine, RiEqualizer2Line } from '@remixicon/react' import { useTranslation } from 'react-i18next' import { useNodes } from 'reactflow' import { useWorkflowInteractions, } from '../../hooks' import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync' import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync' import { BlockEnum } from '../../types' import type { StartNodeType } from '../../nodes/start/types' import { useResizePanel } from '../../nodes/_base/hooks/use-resize-panel' import ChatWrapper from './chat-wrapper' import cn from '@/utils/classnames' import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows' import Tooltip from '@/app/components/base/tooltip' import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' import { useStore } from '@/app/components/workflow/store' import { debounce, noop } from 'lodash-es' export type ChatWrapperRefType = { handleRestart: () => void } const DebugAndPreview = () => { const { t } = useTranslation() const chatRef = useRef({ handleRestart: noop }) const { handleCancelDebugAndPreviewPanel } = useWorkflowInteractions() const { handleNodeCancelRunningStatus } = useNodesInteractionsWithoutSync() const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync() const [expanded, setExpanded] = useState(true) const nodes = useNodes() const selectedNode = nodes.find(node => node.data.selected) const startNode = nodes.find(node => node.data.type === BlockEnum.Start) const variables = startNode?.data.variables || [] const visibleVariables = variables.filter(v => v.hide !== true) const [showConversationVariableModal, setShowConversationVariableModal] = useState(false) const handleRestartChat = () => { handleNodeCancelRunningStatus() handleEdgeCancelRunningStatus() chatRef.current.handleRestart() } const workflowCanvasWidth = useStore(s => s.workflowCanvasWidth) const nodePanelWidth = useStore(s => s.nodePanelWidth) const panelWidth = useStore(s => s.previewPanelWidth) const setPanelWidth = useStore(s => s.setPreviewPanelWidth) const handleResize = useCallback((width: number) => { localStorage.setItem('debug-and-preview-panel-width', `${width}`) setPanelWidth(width) }, [setPanelWidth]) const maxPanelWidth = useMemo(() => { if (!workflowCanvasWidth) return 720 if (!selectedNode) return workflowCanvasWidth - 400 return workflowCanvasWidth - 400 - 400 }, [workflowCanvasWidth, selectedNode, nodePanelWidth]) const { triggerRef, containerRef, } = useResizePanel({ direction: 'horizontal', triggerDirection: 'left', minWidth: 400, maxWidth: maxPanelWidth, onResize: debounce(handleResize), }) return (
{t('workflow.common.debugAndPreview').toLocaleUpperCase()}
handleRestartChat()}> {visibleVariables.length > 0 && (
setExpanded(!expanded)}> {expanded &&
}
)}
setShowConversationVariableModal(false)} showInputsFieldsPanel={expanded} onHide={() => setExpanded(false)} />
) } export default memo(DebugAndPreview)