mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-26 00:46:52 +08:00
### What problem does this PR solve? Feat: Upload agent file #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,9 +1,10 @@
|
||||
import { FileMimeType } from '@/constants/common';
|
||||
import { useToast } from '@/components/hooks/use-toast';
|
||||
import { FileMimeType, Platform } from '@/constants/common';
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useFetchFlow } from '@/hooks/flow-hooks';
|
||||
import { IGraph } from '@/interfaces/database/flow';
|
||||
import { downloadJsonFile } from '@/utils/file-util';
|
||||
import { message, UploadFile } from 'antd';
|
||||
import { message } from 'antd';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -20,13 +21,21 @@ export const useHandleExportOrImportJsonFile = () => {
|
||||
const setGraphInfo = useSetGraphInfo();
|
||||
const { data } = useFetchFlow();
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
|
||||
const onFileUploadOk = useCallback(
|
||||
async (fileList: UploadFile[]) => {
|
||||
async ({
|
||||
fileList,
|
||||
platform,
|
||||
}: {
|
||||
fileList: File[];
|
||||
platform: Platform;
|
||||
}) => {
|
||||
console.log('🚀 ~ useHandleExportOrImportJsonFile ~ platform:', platform);
|
||||
if (fileList.length > 0) {
|
||||
const file: File = fileList[0] as unknown as File;
|
||||
const file = fileList[0];
|
||||
if (file.type !== FileMimeType.Json) {
|
||||
message.error(t('flow.jsonUploadTypeErrorMessage'));
|
||||
toast({ title: t('flow.jsonUploadTypeErrorMessage') });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -45,7 +54,7 @@ export const useHandleExportOrImportJsonFile = () => {
|
||||
}
|
||||
}
|
||||
},
|
||||
[hideFileUploadModal, setGraphInfo, t],
|
||||
[hideFileUploadModal, setGraphInfo, t, toast],
|
||||
);
|
||||
|
||||
const handleExportJson = useCallback(() => {
|
||||
|
||||
@ -1,12 +1,35 @@
|
||||
import { PageHeader } from '@/components/page-header';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { Trash2 } from 'lucide-react';
|
||||
import { CodeXml, EllipsisVertical, Forward, Import, Key } from 'lucide-react';
|
||||
import { ComponentPropsWithoutRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AgentSidebar } from './agent-sidebar';
|
||||
import FlowCanvas from './canvas';
|
||||
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
|
||||
import { useFetchDataOnMount } from './hooks/use-fetch-data';
|
||||
import { useOpenDocument } from './hooks/use-open-document';
|
||||
import { UploadAgentDialog } from './upload-agent-dialog';
|
||||
|
||||
function AgentDropdownMenuItem({
|
||||
children,
|
||||
...props
|
||||
}: ComponentPropsWithoutRef<typeof DropdownMenuItem>) {
|
||||
return (
|
||||
<DropdownMenuItem className="flex justify-between items-center" {...props}>
|
||||
{children}
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Agent() {
|
||||
const { navigateToAgentList } = useNavigatePage();
|
||||
@ -15,6 +38,15 @@ export default function Agent() {
|
||||
hideModal: hideChatDrawer,
|
||||
showModal: showChatDrawer,
|
||||
} = useSetModalState();
|
||||
const { t } = useTranslation();
|
||||
const openDocument = useOpenDocument();
|
||||
const {
|
||||
handleExportJson,
|
||||
handleImportJson,
|
||||
fileUploadVisible,
|
||||
onFileUploadOk,
|
||||
hideFileUploadModal,
|
||||
} = useHandleExportOrImportJsonFile();
|
||||
|
||||
useFetchDataOnMount();
|
||||
|
||||
@ -22,15 +54,38 @@ export default function Agent() {
|
||||
<section>
|
||||
<PageHeader back={navigateToAgentList} title="Agent 01">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant={'icon'} size={'icon'}>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<Button variant={'icon'} size={'icon'}>
|
||||
<EllipsisVertical />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<AgentDropdownMenuItem onClick={openDocument}>
|
||||
API
|
||||
<Key />
|
||||
</AgentDropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<AgentDropdownMenuItem onClick={handleImportJson}>
|
||||
Import
|
||||
<Import />
|
||||
</AgentDropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<AgentDropdownMenuItem onClick={handleExportJson}>
|
||||
Export
|
||||
<Forward />
|
||||
</AgentDropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<AgentDropdownMenuItem>
|
||||
{t('common.embedIntoSite')}
|
||||
<CodeXml />
|
||||
</AgentDropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<Button variant={'outline'} size={'sm'}>
|
||||
Save
|
||||
</Button>
|
||||
<Button variant={'outline'} size={'sm'}>
|
||||
API
|
||||
</Button>
|
||||
<Button variant={'outline'} size={'sm'}>
|
||||
Run app
|
||||
</Button>
|
||||
@ -54,6 +109,12 @@ export default function Agent() {
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
</div>
|
||||
{fileUploadVisible && (
|
||||
<UploadAgentDialog
|
||||
hideModal={hideFileUploadModal}
|
||||
onOk={onFileUploadOk}
|
||||
></UploadAgentDialog>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
36
web/src/pages/agent/upload-agent-dialog/index.tsx
Normal file
36
web/src/pages/agent/upload-agent-dialog/index.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { LoadingButton } from '@/components/ui/loading-button';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { UploadAgentForm } from './upload-agent-form';
|
||||
|
||||
export function UploadAgentDialog({
|
||||
hideModal,
|
||||
onOk,
|
||||
loading,
|
||||
}: IModalProps<any>) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dialog open onOpenChange={hideModal}>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('fileManager.uploadFile')}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<UploadAgentForm hideModal={hideModal} onOk={onOk}></UploadAgentForm>
|
||||
<DialogFooter>
|
||||
<LoadingButton type="submit" form={TagRenameId} loading={loading}>
|
||||
{t('common.save')}
|
||||
</LoadingButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FileUploader } from '@/components/file-uploader';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { RAGFlowSelect } from '@/components/ui/select';
|
||||
import { FileMimeType, Platform } from '@/constants/common';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const options = Object.values(Platform).map((x) => ({ label: x, value: x }));
|
||||
|
||||
export function UploadAgentForm({ hideModal, onOk }: IModalProps<any>) {
|
||||
const { t } = useTranslation();
|
||||
const FormSchema = z.object({
|
||||
platform: z
|
||||
.string()
|
||||
.min(1, {
|
||||
message: t('common.namePlaceholder'),
|
||||
})
|
||||
.trim(),
|
||||
fileList: z.array(z.instanceof(File)),
|
||||
});
|
||||
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: { platform: Platform.RAGFlow },
|
||||
});
|
||||
|
||||
async function onSubmit(data: z.infer<typeof FormSchema>) {
|
||||
console.log('🚀 ~ onSubmit ~ data:', data);
|
||||
const ret = await onOk?.(data);
|
||||
if (ret) {
|
||||
hideModal?.();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-6"
|
||||
id={TagRenameId}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="fileList"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('common.name')}</FormLabel>
|
||||
<FormControl>
|
||||
<FileUploader
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
maxFileCount={1}
|
||||
maxSize={4 * 1024 * 1024}
|
||||
accept={{ '*.json': [FileMimeType.Json] }}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="platform"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('common.name')}</FormLabel>
|
||||
<FormControl>
|
||||
<RAGFlowSelect {...field} options={options} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user