From 30ae78755b4583e98e00857e78e556afc5c9f7a1 Mon Sep 17 00:00:00 2001 From: balibabu Date: Fri, 15 Aug 2025 12:05:27 +0800 Subject: [PATCH] Feat: Delete or filter conversations #3221 (#9491) ### What problem does this PR solve? Feat: Delete or filter conversations #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- .../hooks/logic-hooks/use-change-search.ts | 14 ++++++ web/src/hooks/use-chat-request.ts | 11 ++++- .../chat/app-settings/chat-settings.tsx | 2 +- .../next-chats/chat/conversation-dropdown.tsx | 48 +++++++++++++++++++ web/src/pages/next-chats/chat/index.tsx | 12 ++--- .../pages/next-chats/chat/llm-select-form.tsx | 13 +++++ web/src/pages/next-chats/chat/sessions.tsx | 20 +++++--- .../hooks/use-select-conversation-list.ts | 15 +++++- 8 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 web/src/hooks/logic-hooks/use-change-search.ts create mode 100644 web/src/pages/next-chats/chat/conversation-dropdown.tsx diff --git a/web/src/hooks/logic-hooks/use-change-search.ts b/web/src/hooks/logic-hooks/use-change-search.ts new file mode 100644 index 000000000..c404456cc --- /dev/null +++ b/web/src/hooks/logic-hooks/use-change-search.ts @@ -0,0 +1,14 @@ +import { useCallback, useState } from 'react'; + +export const useHandleSearchStrChange = () => { + const [searchString, setSearchString] = useState(''); + const handleInputChange = useCallback( + (e: React.ChangeEvent) => { + const value = e.target.value; + setSearchString(value); + }, + [], + ); + + return { handleInputChange, searchString }; +}; diff --git a/web/src/hooks/use-chat-request.ts b/web/src/hooks/use-chat-request.ts index 8fb01ba78..c16b97cc7 100644 --- a/web/src/hooks/use-chat-request.ts +++ b/web/src/hooks/use-chat-request.ts @@ -17,6 +17,7 @@ import { useGetPaginationWithRouter, useHandleSearchChange, } from './logic-hooks'; +import { useHandleSearchStrChange } from './logic-hooks/use-change-search'; export const enum ChatApiAction { FetchDialogList = 'fetchDialogList', @@ -229,6 +230,9 @@ export const useClickConversationCard = () => { export const useFetchConversationList = () => { const { id } = useParams(); const { handleClickConversation } = useClickConversationCard(); + + const { searchString, handleInputChange } = useHandleSearchStrChange(); + const { data, isFetching: loading, @@ -239,6 +243,11 @@ export const useFetchConversationList = () => { gcTime: 0, refetchOnWindowFocus: false, enabled: !!id, + select(data) { + return searchString + ? data.filter((x) => x.name.includes(searchString)) + : data; + }, queryFn: async () => { const { data } = await chatService.listConversation( { params: { dialog_id: id } }, @@ -255,7 +264,7 @@ export const useFetchConversationList = () => { }, }); - return { data, loading, refetch }; + return { data, loading, refetch, searchString, handleInputChange }; }; export const useFetchConversation = () => { diff --git a/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx b/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx index c1c81969a..8196637f3 100644 --- a/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx +++ b/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx @@ -75,7 +75,7 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) {
-
+
diff --git a/web/src/pages/next-chats/chat/conversation-dropdown.tsx b/web/src/pages/next-chats/chat/conversation-dropdown.tsx new file mode 100644 index 000000000..83193f57c --- /dev/null +++ b/web/src/pages/next-chats/chat/conversation-dropdown.tsx @@ -0,0 +1,48 @@ +import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { useRemoveConversation } from '@/hooks/use-chat-request'; +import { IConversation } from '@/interfaces/database/chat'; +import { Trash2 } from 'lucide-react'; +import { MouseEventHandler, PropsWithChildren, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +export function ConversationDropdown({ + children, + conversation, +}: PropsWithChildren & { + conversation: IConversation; +}) { + const { t } = useTranslation(); + + const { removeConversation } = useRemoveConversation(); + + const handleDelete: MouseEventHandler = useCallback(() => { + removeConversation([conversation.id]); + }, [conversation.id, removeConversation]); + + return ( + + {children} + + + { + e.preventDefault(); + }} + onClick={(e) => { + e.stopPropagation(); + }} + > + {t('common.delete')} + + + + + ); +} diff --git a/web/src/pages/next-chats/chat/index.tsx b/web/src/pages/next-chats/chat/index.tsx index 19947f65c..9188c1beb 100644 --- a/web/src/pages/next-chats/chat/index.tsx +++ b/web/src/pages/next-chats/chat/index.tsx @@ -18,13 +18,12 @@ import { } from '@/hooks/use-chat-request'; import { cn } from '@/lib/utils'; import { isEmpty } from 'lodash'; -import { ArrowUpRight, LogOut } from 'lucide-react'; +import { ArrowUpRight, LogOut, Send } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useHandleClickConversationCard } from '../hooks/use-click-card'; import { ChatSettings } from './app-settings/chat-settings'; import { MultipleChatBox } from './chat-box/multiple-chat-box'; import { SingleChatBox } from './chat-box/single-chat-box'; -import { LLMSelectForm } from './llm-select-form'; import { Sessions } from './sessions'; import { useAddChatBox } from './use-add-box'; import { useSwitchDebugMode } from './use-switch-debug-mode'; @@ -88,6 +87,10 @@ export default function Chat() { +
-
- {conversation.name} - -
+
{conversation.name}
setSearchStr(e.target.value)} - value={searchStr} + onChange={handleInputChange} + value={searchString} >
@@ -86,7 +90,9 @@ export function Sessions({ > {x.name} - + + + ))} diff --git a/web/src/pages/next-chats/hooks/use-select-conversation-list.ts b/web/src/pages/next-chats/hooks/use-select-conversation-list.ts index 26b165d52..a40c57a0c 100644 --- a/web/src/pages/next-chats/hooks/use-select-conversation-list.ts +++ b/web/src/pages/next-chats/hooks/use-select-conversation-list.ts @@ -43,7 +43,12 @@ export const useSelectDerivedConversationList = () => { const { t } = useTranslate('chat'); const [list, setList] = useState>([]); - const { data: conversationList, loading } = useFetchConversationList(); + const { + data: conversationList, + loading, + handleInputChange, + searchString, + } = useFetchConversationList(); const { id: dialogId } = useParams(); const { setNewConversationRouteParams } = useSetNewConversationRouteParams(); const prologue = useFindPrologueFromDialogList(); @@ -81,5 +86,11 @@ export const useSelectDerivedConversationList = () => { setList([...conversationList]); }, [conversationList]); - return { list, addTemporaryConversation, loading }; + return { + list, + addTemporaryConversation, + loading, + handleInputChange, + searchString, + }; };