diff --git a/web/src/components/rename-modal/index.tsx b/web/src/components/rename-modal/index.tsx new file mode 100644 index 000000000..ba902c578 --- /dev/null +++ b/web/src/components/rename-modal/index.tsx @@ -0,0 +1,78 @@ +import { Form, Input, Modal } from 'antd'; +import { useEffect } from 'react'; +import { IModalManagerChildrenProps } from '../modal-manager'; + +interface IProps extends Omit { + loading: boolean; + initialName: string; + onOk: (name: string) => void; + showModal?(): void; +} + +const RenameModal = ({ + visible, + hideModal, + loading, + initialName, + onOk, +}: IProps) => { + const [form] = Form.useForm(); + + type FieldType = { + name?: string; + }; + + const handleOk = async () => { + const ret = await form.validateFields(); + + return onOk(ret.name); + }; + + const handleCancel = () => { + hideModal(); + }; + + const onFinish = (values: any) => { + console.log('Success:', values); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log('Failed:', errorInfo); + }; + + useEffect(() => { + form.setFieldValue('name', initialName); + }, [initialName, form]); + + return ( + +
+ + label="Name" + name="name" + rules={[{ required: true, message: 'Please input name!' }]} + > + + + +
+ ); +}; + +export default RenameModal; diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index 3f32e9241..9d33d5c09 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -8,7 +8,7 @@ import classNames from 'classnames'; import { ChangeEventHandler, useCallback, useMemo, useState } from 'react'; import reactStringReplace from 'react-string-replace'; import { - useFetchConversation, + useFetchConversationOnMount, useGetFileIcon, useScrollToBottom, useSendMessage, @@ -187,7 +187,7 @@ const MessageItem = ({ const ChatContainer = () => { const [value, setValue] = useState(''); - const conversation: IClientConversation = useFetchConversation(); + const conversation: IClientConversation = useFetchConversationOnMount(); const { sendMessage } = useSendMessage(); const loading = useOneNamespaceEffectsLoading('chatModel', [ 'completeConversation', diff --git a/web/src/pages/chat/hooks.ts b/web/src/pages/chat/hooks.ts index b3d6c128f..69859e8ec 100644 --- a/web/src/pages/chat/hooks.ts +++ b/web/src/pages/chat/hooks.ts @@ -1,6 +1,8 @@ import showDeleteConfirm from '@/components/deleting-confirm'; import { MessageType } from '@/constants/chat'; import { fileIconMap } from '@/constants/common'; +import { useSetModalState } from '@/hooks/commonHooks'; +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { IConversation, IDialog } from '@/interfaces/database/chat'; import { getFileExtension } from '@/utils'; import omit from 'lodash/omit'; @@ -14,7 +16,7 @@ import { VariableTableDataType, } from './interface'; import { ChatModelState } from './model'; -import { isConversationIdNotExist } from './utils'; +import { isConversationIdExist } from './utils'; export const useFetchDialogList = () => { const dispatch = useDispatch(); @@ -392,30 +394,50 @@ export const useSetConversation = () => { return { setConversation }; }; -export const useFetchConversation = () => { - const dispatch = useDispatch(); - const { conversationId } = useGetChatSearchParams(); - const conversation = useSelector( +export const useSelectCurrentConversation = () => { + const conversation: IClientConversation = useSelector( (state: any) => state.chatModel.currentConversation, ); - const setCurrentConversation = useSetCurrentConversation(); - const fetchConversation = useCallback(() => { - if (isConversationIdNotExist(conversationId)) { - dispatch({ + return conversation; +}; + +export const useFetchConversation = () => { + const dispatch = useDispatch(); + + const fetchConversation = useCallback( + (conversationId: string, needToBeSaved = true) => { + return dispatch({ type: 'chatModel/getConversation', payload: { + needToBeSaved, conversation_id: conversationId, }, }); + }, + [dispatch], + ); + + return fetchConversation; +}; + +export const useFetchConversationOnMount = () => { + const { conversationId } = useGetChatSearchParams(); + const conversation = useSelectCurrentConversation(); + const setCurrentConversation = useSetCurrentConversation(); + const fetchConversation = useFetchConversation(); + + const fetchConversationOnMount = useCallback(() => { + if (isConversationIdExist(conversationId)) { + fetchConversation(conversationId); } else { setCurrentConversation({} as IClientConversation); } - }, [dispatch, conversationId, setCurrentConversation]); + }, [fetchConversation, setCurrentConversation, conversationId]); useEffect(() => { - fetchConversation(); - }, [fetchConversation]); + fetchConversationOnMount(); + }, [fetchConversationOnMount]); return conversation; }; @@ -522,4 +544,56 @@ export const useRemoveConversation = () => { return { onRemoveConversation }; }; + +export const useRenameConversation = () => { + const dispatch = useDispatch(); + const [conversation, setConversation] = useState( + {} as IClientConversation, + ); + const fetchConversation = useFetchConversation(); + const { + visible: conversationRenameVisible, + hideModal: hideConversationRenameModal, + showModal: showConversationRenameModal, + } = useSetModalState(); + + const onConversationRenameOk = useCallback( + async (name: string) => { + const ret = await dispatch({ + type: 'chatModel/setConversation', + payload: { ...conversation, conversation_id: conversation.id, name }, + }); + + if (ret.retcode === 0) { + hideConversationRenameModal(); + } + }, + [dispatch, conversation, hideConversationRenameModal], + ); + + const loading = useOneNamespaceEffectsLoading('chatModel', [ + 'setConversation', + ]); + + const handleShowConversationRenameModal = useCallback( + async (conversationId: string) => { + const ret = await fetchConversation(conversationId, false); + if (ret.retcode === 0) { + setConversation(ret.data); + } + showConversationRenameModal(); + }, + [showConversationRenameModal, fetchConversation], + ); + + return { + conversationRenameLoading: loading, + initialConversationName: conversation.name, + onConversationRenameOk, + conversationRenameVisible, + hideConversationRenameModal, + showConversationRenameModal: handleShowConversationRenameModal, + }; +}; + //#endregion diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 580f0c428..e4d7a37f4 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -25,11 +25,13 @@ import { useHandleItemHover, useRemoveConversation, useRemoveDialog, + useRenameConversation, useSelectConversationList, useSelectFirstDialogOnMount, useSetCurrentDialog, } from './hooks'; +import RenameModal from '@/components/rename-modal'; import styles from './index.less'; const Chat = () => { @@ -49,6 +51,14 @@ const Chat = () => { handleItemEnter: handleConversationItemEnter, handleItemLeave: handleConversationItemLeave, } = useHandleItemHover(); + const { + conversationRenameLoading, + initialConversationName, + onConversationRenameOk, + conversationRenameVisible, + hideConversationRenameModal, + showConversationRenameModal, + } = useRenameConversation(); useFetchDialog(dialogId, true); @@ -87,6 +97,14 @@ const Chat = () => { onRemoveConversation([conversationId]); }; + const handleShowConversationRenameModal = + (conversationId: string): MenuItemProps['onClick'] => + ({ domEvent }) => { + domEvent.preventDefault(); + domEvent.stopPropagation(); + showConversationRenameModal(conversationId); + }; + const handleDialogCardClick = (dialogId: string) => () => { handleClickDialog(dialogId); }; @@ -143,7 +161,7 @@ const Chat = () => { const appItems: MenuProps['items'] = [ { key: '1', - onClick: handleShowChatConfigurationModal(conversationId), + onClick: handleShowConversationRenameModal(conversationId), label: ( @@ -262,6 +280,13 @@ const Chat = () => { hideModal={hideModal} id={currentDialog.id} > + ); }; diff --git a/web/src/pages/chat/model.ts b/web/src/pages/chat/model.ts index 912d769a5..659fc3da7 100644 --- a/web/src/pages/chat/model.ts +++ b/web/src/pages/chat/model.ts @@ -110,8 +110,10 @@ const model: DvaModel = { return data.retcode; }, *getConversation({ payload }, { call, put }) { - const { data } = yield call(chatService.getConversation, payload); - if (data.retcode === 0) { + const { data } = yield call(chatService.getConversation, { + conversation_id: payload.conversation_id, + }); + if (data.retcode === 0 && payload.needToBeSaved) { yield put({ type: 'kFModel/fetch_document_thumbnails', payload: { @@ -120,7 +122,7 @@ const model: DvaModel = { }); yield put({ type: 'setCurrentConversation', payload: data.data }); } - return data.retcode; + return data; }, *setConversation({ payload }, { call, put }) { const { data } = yield call(chatService.setConversation, payload); diff --git a/web/src/pages/chat/utils.ts b/web/src/pages/chat/utils.ts index 76744df65..7c3fe80c7 100644 --- a/web/src/pages/chat/utils.ts +++ b/web/src/pages/chat/utils.ts @@ -12,7 +12,7 @@ export const excludeUnEnabledVariables = (values: any) => { ); }; -export const isConversationIdNotExist = (conversationId: string) => { +export const isConversationIdExist = (conversationId: string) => { return conversationId !== EmptyConversationId && conversationId !== ''; };