mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Delete or filter conversations #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
14
web/src/hooks/logic-hooks/use-change-search.ts
Normal file
14
web/src/hooks/logic-hooks/use-change-search.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export const useHandleSearchStrChange = () => {
|
||||
const [searchString, setSearchString] = useState('');
|
||||
const handleInputChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const value = e.target.value;
|
||||
setSearchString(value);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return { handleInputChange, searchString };
|
||||
};
|
||||
@ -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 = () => {
|
||||
|
||||
@ -75,7 +75,7 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) {
|
||||
</div>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit, onInvalid)}>
|
||||
<section className="space-y-6 overflow-auto max-h-[87vh] pr-4">
|
||||
<section className="space-y-6 overflow-auto max-h-[85vh] pr-4">
|
||||
<ChatBasicSetting></ChatBasicSetting>
|
||||
<Separator />
|
||||
<ChatPromptEngine></ChatPromptEngine>
|
||||
|
||||
48
web/src/pages/next-chats/chat/conversation-dropdown.tsx
Normal file
48
web/src/pages/next-chats/chat/conversation-dropdown.tsx
Normal file
@ -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<HTMLDivElement> = useCallback(() => {
|
||||
removeConversation([conversation.id]);
|
||||
}, [conversation.id, removeConversation]);
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
||||
<DropdownMenuItem
|
||||
className="text-state-error"
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{t('common.delete')} <Trash2 />
|
||||
</DropdownMenuItem>
|
||||
</ConfirmDeleteDialog>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
@ -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() {
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<Button>
|
||||
<Send />
|
||||
{t('common.embedIntoSite')}
|
||||
</Button>
|
||||
</PageHeader>
|
||||
<div className="flex flex-1 min-h-0">
|
||||
<Sessions
|
||||
@ -103,10 +106,7 @@ export default function Chat() {
|
||||
className={cn('p-5', { 'border-b': hasSingleChatBox })}
|
||||
>
|
||||
<CardTitle className="flex justify-between items-center text-base">
|
||||
<div className="flex gap-3 items-center">
|
||||
{conversation.name}
|
||||
<LLMSelectForm></LLMSelectForm>
|
||||
</div>
|
||||
<div>{conversation.name}</div>
|
||||
|
||||
<Button
|
||||
variant={'ghost'}
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import { LargeModelFormFieldWithoutFilter } from '@/components/large-model-form-field';
|
||||
import { LlmSettingSchema } from '@/components/llm-setting-items/next';
|
||||
import { Form } from '@/components/ui/form';
|
||||
import { useFetchDialog } from '@/hooks/use-chat-request';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
export function LLMSelectForm() {
|
||||
const FormSchema = z.object(LlmSettingSchema);
|
||||
const { data } = useFetchDialog();
|
||||
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
@ -15,6 +19,15 @@ export function LLMSelectForm() {
|
||||
},
|
||||
});
|
||||
|
||||
// const values = useWatch({ control: form.control, name: ['llm_id'] });
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(data)) {
|
||||
form.reset({ llm_id: data.llm_id, ...data.llm_setting });
|
||||
}
|
||||
form.reset(data);
|
||||
}, [data, form]);
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<LargeModelFormFieldWithoutFilter></LargeModelFormFieldWithoutFilter>
|
||||
|
||||
@ -10,9 +10,10 @@ import {
|
||||
} from '@/hooks/use-chat-request';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { PanelLeftClose, PanelRightClose, Plus } from 'lucide-react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useHandleClickConversationCard } from '../hooks/use-click-card';
|
||||
import { useSelectDerivedConversationList } from '../hooks/use-select-conversation-list';
|
||||
import { ConversationDropdown } from './conversation-dropdown';
|
||||
|
||||
type SessionProps = Pick<
|
||||
ReturnType<typeof useHandleClickConversationCard>,
|
||||
@ -23,11 +24,14 @@ export function Sessions({
|
||||
handleConversationCardClick,
|
||||
switchSettingVisible,
|
||||
}: SessionProps) {
|
||||
const { list: conversationList, addTemporaryConversation } =
|
||||
useSelectDerivedConversationList();
|
||||
const {
|
||||
list: conversationList,
|
||||
addTemporaryConversation,
|
||||
handleInputChange,
|
||||
searchString,
|
||||
} = useSelectDerivedConversationList();
|
||||
const { data } = useFetchDialog();
|
||||
const { visible, switchVisible } = useSetModalState(true);
|
||||
const [searchStr, setSearchStr] = useState('');
|
||||
|
||||
const handleCardClick = useCallback(
|
||||
(conversationId: string, isNew: boolean) => () => {
|
||||
@ -71,8 +75,8 @@ export function Sessions({
|
||||
</div>
|
||||
<div className="pb-4">
|
||||
<SearchInput
|
||||
onChange={(e) => setSearchStr(e.target.value)}
|
||||
value={searchStr}
|
||||
onChange={handleInputChange}
|
||||
value={searchString}
|
||||
></SearchInput>
|
||||
</div>
|
||||
<div className="space-y-4 flex-1 overflow-auto">
|
||||
@ -86,7 +90,9 @@ export function Sessions({
|
||||
>
|
||||
<CardContent className="px-3 py-2 flex justify-between items-center group">
|
||||
{x.name}
|
||||
<MoreButton></MoreButton>
|
||||
<ConversationDropdown conversation={x}>
|
||||
<MoreButton></MoreButton>
|
||||
</ConversationDropdown>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@ -43,7 +43,12 @@ export const useSelectDerivedConversationList = () => {
|
||||
const { t } = useTranslate('chat');
|
||||
|
||||
const [list, setList] = useState<Array<IConversation>>([]);
|
||||
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,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user