### What problem does this PR solve? Feat: Delete the operator node and hide the corresponding sheet #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.20.0
| @@ -1,3 +1,4 @@ | |||
| import message from '@/components/ui/message'; | |||
| import { Authorization } from '@/constants/authorization'; | |||
| import { IReferenceObject } from '@/interfaces/database/chat'; | |||
| import { BeginQuery } from '@/pages/agent/interface'; | |||
| @@ -136,6 +137,9 @@ export const useSendMessageBySSE = (url: string = api.completeConversation) => { | |||
| const val = JSON.parse(value?.data || ''); | |||
| console.info('data:', val); | |||
| if (val.code === 500) { | |||
| message.error(val.message); | |||
| } | |||
| setAnswerList((list) => { | |||
| const nextList = [...list]; | |||
| @@ -32,7 +32,11 @@ import { useAddNode } from '../hooks/use-add-node'; | |||
| import { useBeforeDelete } from '../hooks/use-before-delete'; | |||
| import { useCacheChatLog } from '../hooks/use-cache-chat-log'; | |||
| import { useMoveNote } from '../hooks/use-move-note'; | |||
| import { useShowDrawer, useShowLogSheet } from '../hooks/use-show-drawer'; | |||
| import { | |||
| useHideFormSheetOnNodeDeletion, | |||
| useShowDrawer, | |||
| useShowLogSheet, | |||
| } from '../hooks/use-show-drawer'; | |||
| import { LogSheet } from '../log-sheet'; | |||
| import RunSheet from '../run-sheet'; | |||
| import { ButtonEdge } from './edge'; | |||
| @@ -160,6 +164,9 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { | |||
| setLastSendLoading(false); | |||
| } | |||
| }; | |||
| useHideFormSheetOnNodeDeletion({ hideFormDrawer }); | |||
| return ( | |||
| <div className={styles.canvasWrapper}> | |||
| <svg | |||
| @@ -33,7 +33,7 @@ function InnerBeginNode({ data, id, selected }: NodeProps<IBeginNode>) { | |||
| id={NodeHandleId.Start} | |||
| ></CommonHandle> | |||
| <section className="flex items-center justify-center gap-2"> | |||
| <section className="flex items-center gap-2"> | |||
| <OperatorIcon name={data.label as Operator}></OperatorIcon> | |||
| <div className="truncate text-center font-semibold text-sm"> | |||
| {t(`flow.begin`)} | |||
| @@ -56,7 +56,7 @@ function NoteNode({ data, id, selected }: NodeProps<INoteNode>) { | |||
| <section className="px-1 py-2 flex gap-2 bg-background-highlight items-center note-drag-handle rounded-s-md"> | |||
| <NotebookPen className="size-4" /> | |||
| <Form {...nameForm}> | |||
| <form> | |||
| <form className="flex-1"> | |||
| <FormField | |||
| control={nameForm.control} | |||
| name="name" | |||
| @@ -16,13 +16,13 @@ import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; | |||
| import { Message } from '@/interfaces/database/chat'; | |||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | |||
| import { get } from 'lodash'; | |||
| import { useCallback } from 'react'; | |||
| import { memo, useCallback } from 'react'; | |||
| import { useParams } from 'umi'; | |||
| import DebugContent from '../debug-content'; | |||
| import { BeginQuery } from '../interface'; | |||
| import { buildBeginQueryWithObject } from '../utils'; | |||
| const AgentChatBox = () => { | |||
| function AgentChatBox() { | |||
| const { | |||
| value, | |||
| ref, | |||
| @@ -117,7 +117,7 @@ const AgentChatBox = () => { | |||
| })} | |||
| {/* </Spin> */} | |||
| </div> | |||
| <div ref={ref} /> | |||
| <div ref={ref.scrollRef} /> | |||
| </div> | |||
| <NextMessageInput | |||
| value={value} | |||
| @@ -140,6 +140,6 @@ const AgentChatBox = () => { | |||
| ></PdfDrawer> | |||
| </> | |||
| ); | |||
| }; | |||
| } | |||
| export default AgentChatBox; | |||
| export default memo(AgentChatBox); | |||
| @@ -235,18 +235,23 @@ export const useSendAgentMessage = ( | |||
| params.session_id = sessionId; | |||
| } | |||
| const res = await send(params); | |||
| clearUploadResponseList(); | |||
| try { | |||
| const res = await send(params); | |||
| if (receiveMessageError(res)) { | |||
| sonnerMessage.error(res?.data?.message); | |||
| clearUploadResponseList(); | |||
| // cancel loading | |||
| setValue(message.content); | |||
| removeLatestMessage(); | |||
| } else { | |||
| // refetch(); // pull the message list after sending the message successfully | |||
| if (receiveMessageError(res)) { | |||
| sonnerMessage.error(res?.data?.message); | |||
| // cancel loading | |||
| setValue(message.content); | |||
| removeLatestMessage(); | |||
| } else { | |||
| // refetch(); // pull the message list after sending the message successfully | |||
| } | |||
| } catch (error) { | |||
| console.log('🚀 ~ useSendAgentMessage ~ error:', error); | |||
| } | |||
| }, | |||
| [ | |||
| @@ -167,3 +167,15 @@ export function useShowLogSheet({ | |||
| showLogSheet: handleShow, | |||
| }; | |||
| } | |||
| export function useHideFormSheetOnNodeDeletion({ | |||
| hideFormDrawer, | |||
| }: Pick<ReturnType<typeof useShowFormDrawer>, 'hideFormDrawer'>) { | |||
| const { nodes, clickedNodeId } = useGraphStore((state) => state); | |||
| useEffect(() => { | |||
| if (!nodes.some((x) => x.id === clickedNodeId)) { | |||
| hideFormDrawer(); | |||
| } | |||
| }, [clickedNodeId, hideFormDrawer, nodes]); | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| import { IconFont } from '@/components/icon-font'; | |||
| import SvgIcon from '@/components/svg-icon'; | |||
| import { cn } from '@/lib/utils'; | |||
| import { CirclePlay } from 'lucide-react'; | |||
| import { HousePlus } from 'lucide-react'; | |||
| import { Operator } from './constant'; | |||
| interface IProps { | |||
| @@ -11,7 +11,7 @@ interface IProps { | |||
| export const OperatorIconMap = { | |||
| [Operator.Retrieval]: 'KR', | |||
| [Operator.Begin]: CirclePlay, | |||
| [Operator.Begin]: 'house-plus', | |||
| [Operator.Categorize]: 'a-QuestionClassification', | |||
| [Operator.Message]: 'reply', | |||
| [Operator.Iteration]: 'loop', | |||
| @@ -49,6 +49,14 @@ const Empty = () => { | |||
| const OperatorIcon = ({ name, className }: IProps) => { | |||
| const Icon = OperatorIconMap[name as keyof typeof OperatorIconMap] || Empty; | |||
| if (name === Operator.Begin) { | |||
| return ( | |||
| <div className="inline-block p-1 bg-background-checked rounded-sm"> | |||
| <HousePlus className="rounded size-3" /> | |||
| </div> | |||
| ); | |||
| } | |||
| if (name in SVGIconMap) { | |||
| return ( | |||
| <SvgIcon | |||