### What problem does this PR solve? feat: save graph data before opening the debug drawer #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.8.0
| import { MessageType } from '@/constants/chat'; | import { MessageType } from '@/constants/chat'; | ||||
| import { useFetchFlow, useResetFlow } from '@/hooks/flow-hooks'; | |||||
| import { useFetchFlow } from '@/hooks/flow-hooks'; | |||||
| import { | import { | ||||
| useHandleMessageInputChange, | useHandleMessageInputChange, | ||||
| useScrollToBottom, | useScrollToBottom, | ||||
| import { useCallback, useEffect, useState } from 'react'; | import { useCallback, useEffect, useState } from 'react'; | ||||
| import { useParams } from 'umi'; | import { useParams } from 'umi'; | ||||
| import { v4 as uuid } from 'uuid'; | import { v4 as uuid } from 'uuid'; | ||||
| import { receiveMessageError } from '../utils'; | |||||
| const antMessage = message; | const antMessage = message; | ||||
| const { id: flowId } = useParams(); | const { id: flowId } = useParams(); | ||||
| const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | ||||
| const { refetch } = useFetchFlow(); | const { refetch } = useFetchFlow(); | ||||
| const { resetFlow } = useResetFlow(); | |||||
| const { send, answer, done } = useSendMessageWithSse(api.runCanvas); | const { send, answer, done } = useSendMessageWithSse(api.runCanvas); | ||||
| } | } | ||||
| const res = await send(params); | const res = await send(params); | ||||
| if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) { | |||||
| if (receiveMessageError(res)) { | |||||
| antMessage.error(res?.data?.retmsg); | antMessage.error(res?.data?.retmsg); | ||||
| // cancel loading | // cancel loading | ||||
| [sendMessage], | [sendMessage], | ||||
| ); | ); | ||||
| /** | |||||
| * Call the reset api before opening the run drawer each time | |||||
| */ | |||||
| const resetFlowBeforeFetchingPrologue = useCallback(async () => { | |||||
| // After resetting, all previous messages will be cleared. | |||||
| const ret = await resetFlow(); | |||||
| if (ret.retcode === 0) { | |||||
| // fetch prologue | |||||
| sendMessage(''); | |||||
| } | |||||
| }, [resetFlow, sendMessage]); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (answer.answer) { | if (answer.answer) { | ||||
| addNewestAnswer(answer); | addNewestAnswer(answer); | ||||
| } | } | ||||
| }, [answer, addNewestAnswer]); | }, [answer, addNewestAnswer]); | ||||
| useEffect(() => { | |||||
| resetFlowBeforeFetchingPrologue(); | |||||
| }, [resetFlowBeforeFetchingPrologue]); | |||||
| const handlePressEnter = useCallback(() => { | const handlePressEnter = useCallback(() => { | ||||
| if (done) { | if (done) { | ||||
| setValue(''); | setValue(''); | 
| import { useFetchFlow } from '@/hooks/flow-hooks'; | import { useFetchFlow } from '@/hooks/flow-hooks'; | ||||
| import { ArrowLeftOutlined } from '@ant-design/icons'; | import { ArrowLeftOutlined } from '@ant-design/icons'; | ||||
| import { Link } from 'umi'; | import { Link } from 'umi'; | ||||
| import { useSaveGraph } from '../hooks'; | |||||
| import { useSaveGraph, useSaveGraphBeforeOpeningDebugDrawer } from '../hooks'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const FlowHeader = ({ showChatDrawer }: IProps) => { | const FlowHeader = ({ showChatDrawer }: IProps) => { | ||||
| const { saveGraph } = useSaveGraph(); | const { saveGraph } = useSaveGraph(); | ||||
| const handleRun = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer); | |||||
| const { data } = useFetchFlow(); | const { data } = useFetchFlow(); | ||||
| return ( | return ( | ||||
| <h3>{data.title}</h3> | <h3>{data.title}</h3> | ||||
| </Space> | </Space> | ||||
| <Space size={'large'}> | <Space size={'large'}> | ||||
| <Button onClick={showChatDrawer}> | |||||
| <Button onClick={handleRun}> | |||||
| <b>Run</b> | <b>Run</b> | ||||
| </Button> | </Button> | ||||
| <Button type="primary" onClick={saveGraph}> | <Button type="primary" onClick={saveGraph}> | 
| import { useSetModalState } from '@/hooks/commonHooks'; | import { useSetModalState } from '@/hooks/commonHooks'; | ||||
| import { useFetchFlow, useSetFlow } from '@/hooks/flow-hooks'; | |||||
| import { useFetchFlow, useResetFlow, useSetFlow } from '@/hooks/flow-hooks'; | |||||
| import { useFetchLlmList } from '@/hooks/llmHooks'; | import { useFetchLlmList } from '@/hooks/llmHooks'; | ||||
| import { IGraph } from '@/interfaces/database/flow'; | import { IGraph } from '@/interfaces/database/flow'; | ||||
| import { useIsFetching } from '@tanstack/react-query'; | import { useIsFetching } from '@tanstack/react-query'; | ||||
| ModelVariableType, | ModelVariableType, | ||||
| settledModelVariableMap, | settledModelVariableMap, | ||||
| } from '@/constants/knowledge'; | } from '@/constants/knowledge'; | ||||
| import { useFetchModelId } from '@/hooks/logicHooks'; | |||||
| import { useFetchModelId, useSendMessageWithSse } from '@/hooks/logicHooks'; | |||||
| import { Variable } from '@/interfaces/database/chat'; | import { Variable } from '@/interfaces/database/chat'; | ||||
| import api from '@/utils/api'; | |||||
| import { useDebounceEffect } from 'ahooks'; | import { useDebounceEffect } from 'ahooks'; | ||||
| import { FormInstance, message } from 'antd'; | import { FormInstance, message } from 'antd'; | ||||
| import { humanId } from 'human-id'; | import { humanId } from 'human-id'; | ||||
| initialRewriteQuestionValues, | initialRewriteQuestionValues, | ||||
| } from './constant'; | } from './constant'; | ||||
| import useGraphStore, { RFState } from './store'; | import useGraphStore, { RFState } from './store'; | ||||
| import { buildDslComponentsByGraph } from './utils'; | |||||
| import { buildDslComponentsByGraph, receiveMessageError } from './utils'; | |||||
| const selector = (state: RFState) => ({ | const selector = (state: RFState) => ({ | ||||
| nodes: state.nodes, | nodes: state.nodes, | ||||
| const { setFlow } = useSetFlow(); | const { setFlow } = useSetFlow(); | ||||
| const { id } = useParams(); | const { id } = useParams(); | ||||
| const { nodes, edges } = useGraphStore((state) => state); | const { nodes, edges } = useGraphStore((state) => state); | ||||
| const saveGraph = useCallback(() => { | |||||
| const saveGraph = useCallback(async () => { | |||||
| const dslComponents = buildDslComponentsByGraph(nodes, edges); | const dslComponents = buildDslComponentsByGraph(nodes, edges); | ||||
| setFlow({ | |||||
| return setFlow({ | |||||
| id, | id, | ||||
| title: data.title, | title: data.title, | ||||
| dsl: { ...data.dsl, graph: { nodes, edges }, components: dslComponents }, | dsl: { ...data.dsl, graph: { nodes, edges }, components: dslComponents }, | ||||
| return { name, handleNameBlur, handleNameChange }; | return { name, handleNameBlur, handleNameChange }; | ||||
| }; | }; | ||||
| export const useSaveGraphBeforeOpeningDebugDrawer = (show: () => void) => { | |||||
| const { id } = useParams(); | |||||
| const { saveGraph } = useSaveGraph(); | |||||
| const { resetFlow } = useResetFlow(); | |||||
| const { send } = useSendMessageWithSse(api.runCanvas); | |||||
| const handleRun = useCallback(async () => { | |||||
| const saveRet = await saveGraph(); | |||||
| if (saveRet?.retcode === 0) { | |||||
| // Call the reset api before opening the run drawer each time | |||||
| const resetRet = await resetFlow(); | |||||
| // After resetting, all previous messages will be cleared. | |||||
| if (resetRet?.retcode === 0) { | |||||
| // fetch prologue | |||||
| const sendRet = await send({ id }); | |||||
| if (receiveMessageError(sendRet)) { | |||||
| message.error(sendRet?.data?.retmsg); | |||||
| } else { | |||||
| show(); | |||||
| } | |||||
| } | |||||
| } | |||||
| }, [saveGraph, resetFlow, id, send, show]); | |||||
| return handleRun; | |||||
| }; | 
| return components; | return components; | ||||
| }; | }; | ||||
| export const receiveMessageError = (res: any) => | |||||
| res && (res?.response.status !== 200 || res?.data?.retcode !== 0); |