mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-07-14 07:51:49 +08:00
### What problem does this PR solve? Feat: Create empty document. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
bdebd1b2e3
commit
5043143bc5
@ -8,6 +8,7 @@ import {
|
|||||||
import { LoadingButton } from '@/components/ui/loading-button';
|
import { LoadingButton } from '@/components/ui/loading-button';
|
||||||
import { IModalProps } from '@/interfaces/common';
|
import { IModalProps } from '@/interfaces/common';
|
||||||
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { RenameForm } from './rename-form';
|
import { RenameForm } from './rename-form';
|
||||||
|
|
||||||
@ -16,14 +17,15 @@ export function RenameDialog({
|
|||||||
initialName,
|
initialName,
|
||||||
onOk,
|
onOk,
|
||||||
loading,
|
loading,
|
||||||
}: IModalProps<any> & { initialName?: string }) {
|
title,
|
||||||
|
}: IModalProps<any> & { initialName?: string; title?: ReactNode }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open onOpenChange={hideModal}>
|
<Dialog open onOpenChange={hideModal}>
|
||||||
<DialogContent className="sm:max-w-[425px]">
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{t('common.rename')}</DialogTitle>
|
<DialogTitle>{title || t('common.rename')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<RenameForm
|
<RenameForm
|
||||||
initialName={initialName}
|
initialName={initialName}
|
||||||
|
@ -16,7 +16,10 @@ import {
|
|||||||
useGetPaginationWithRouter,
|
useGetPaginationWithRouter,
|
||||||
useHandleSearchChange,
|
useHandleSearchChange,
|
||||||
} from './logic-hooks';
|
} from './logic-hooks';
|
||||||
import { useGetKnowledgeSearchParams } from './route-hook';
|
import {
|
||||||
|
useGetKnowledgeSearchParams,
|
||||||
|
useSetPaginationParams,
|
||||||
|
} from './route-hook';
|
||||||
|
|
||||||
export const enum DocumentApiAction {
|
export const enum DocumentApiAction {
|
||||||
UploadDocument = 'uploadDocument',
|
UploadDocument = 'uploadDocument',
|
||||||
@ -28,6 +31,7 @@ export const enum DocumentApiAction {
|
|||||||
SetDocumentParser = 'setDocumentParser',
|
SetDocumentParser = 'setDocumentParser',
|
||||||
SetDocumentMeta = 'setDocumentMeta',
|
SetDocumentMeta = 'setDocumentMeta',
|
||||||
FetchAllDocumentList = 'fetchAllDocumentList',
|
FetchAllDocumentList = 'fetchAllDocumentList',
|
||||||
|
CreateDocument = 'createDocument',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useUploadNextDocument = () => {
|
export const useUploadNextDocument = () => {
|
||||||
@ -363,3 +367,37 @@ export const useSetDocumentMeta = () => {
|
|||||||
|
|
||||||
return { setDocumentMeta: mutateAsync, data, loading };
|
return { setDocumentMeta: mutateAsync, data, loading };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useCreateDocument = () => {
|
||||||
|
const { id } = useParams();
|
||||||
|
const { setPaginationParams, page } = useSetPaginationParams();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [DocumentApiAction.CreateDocument],
|
||||||
|
mutationFn: async (name: string) => {
|
||||||
|
const { data } = await kbService.document_create({
|
||||||
|
name,
|
||||||
|
kb_id: id,
|
||||||
|
});
|
||||||
|
if (data.code === 0) {
|
||||||
|
if (page === 1) {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [DocumentApiAction.FetchDocumentList],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setPaginationParams(); // fetch document list
|
||||||
|
}
|
||||||
|
|
||||||
|
message.success(i18n.t('message.created'));
|
||||||
|
}
|
||||||
|
return data.code;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { createDocument: mutateAsync, loading, data };
|
||||||
|
};
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger,
|
HoverCardTrigger,
|
||||||
} from '@/components/ui/hover-card';
|
} from '@/components/ui/hover-card';
|
||||||
|
import { DocumentType } from '@/constants/knowledge';
|
||||||
import { useRemoveDocument } from '@/hooks/use-document-request';
|
import { useRemoveDocument } from '@/hooks/use-document-request';
|
||||||
import { IDocumentInfo } from '@/interfaces/database/document';
|
import { IDocumentInfo } from '@/interfaces/database/document';
|
||||||
import { formatFileSize } from '@/utils/common-util';
|
import { formatFileSize } from '@/utils/common-util';
|
||||||
@ -27,8 +28,9 @@ export function DatasetActionCell({
|
|||||||
record,
|
record,
|
||||||
showRenameModal,
|
showRenameModal,
|
||||||
}: { record: IDocumentInfo } & UseRenameDocumentShowType) {
|
}: { record: IDocumentInfo } & UseRenameDocumentShowType) {
|
||||||
const { id, run } = record;
|
const { id, run, type } = record;
|
||||||
const isRunning = isParserRunning(run);
|
const isRunning = isParserRunning(run);
|
||||||
|
const isVirtualDocument = type === DocumentType.Virtual;
|
||||||
|
|
||||||
const { removeDocument } = useRemoveDocument();
|
const { removeDocument } = useRemoveDocument();
|
||||||
|
|
||||||
@ -83,14 +85,16 @@ export function DatasetActionCell({
|
|||||||
>
|
>
|
||||||
<Pencil />
|
<Pencil />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
{isVirtualDocument || (
|
||||||
variant={'ghost'}
|
<Button
|
||||||
size={'icon'}
|
variant={'ghost'}
|
||||||
onClick={onDownloadDocument}
|
size={'icon'}
|
||||||
disabled={isRunning}
|
onClick={onDownloadDocument}
|
||||||
>
|
disabled={isRunning}
|
||||||
<ArrowDownToLine />
|
>
|
||||||
</Button>
|
<ArrowDownToLine />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<ConfirmDeleteDialog onOk={handleRemove}>
|
<ConfirmDeleteDialog onOk={handleRemove}>
|
||||||
<Button variant={'ghost'} size={'icon'} disabled={isRunning}>
|
<Button variant={'ghost'} size={'icon'} disabled={isRunning}>
|
||||||
<Trash2 className="text-text-delete-red" />
|
<Trash2 className="text-text-delete-red" />
|
||||||
|
@ -24,9 +24,7 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from '@/components/ui/table';
|
} from '@/components/ui/table';
|
||||||
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
|
|
||||||
import { useFetchDocumentList } from '@/hooks/use-document-request';
|
import { useFetchDocumentList } from '@/hooks/use-document-request';
|
||||||
import { IDocumentInfo } from '@/interfaces/database/document';
|
|
||||||
import { getExtension } from '@/utils/document-util';
|
import { getExtension } from '@/utils/document-util';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { SetMetaDialog } from './set-meta-dialog';
|
import { SetMetaDialog } from './set-meta-dialog';
|
||||||
@ -53,8 +51,6 @@ export function DatasetTable({
|
|||||||
React.useState<VisibilityState>({});
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
|
|
||||||
const { currentRecord, setRecord } = useSetSelectedRecord<IDocumentInfo>();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
changeParserLoading,
|
changeParserLoading,
|
||||||
onChangeParserOk,
|
onChangeParserOk,
|
||||||
@ -84,7 +80,6 @@ export function DatasetTable({
|
|||||||
|
|
||||||
const columns = useDatasetTableColumns({
|
const columns = useDatasetTableColumns({
|
||||||
showChangeParserModal,
|
showChangeParserModal,
|
||||||
setCurrentRecord: setRecord,
|
|
||||||
showRenameModal,
|
showRenameModal,
|
||||||
showSetMetaModal,
|
showSetMetaModal,
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { useCreateNextDocument, useNextWebCrawl } from '@/hooks/document-hooks';
|
import { useNextWebCrawl } from '@/hooks/document-hooks';
|
||||||
import { useGetKnowledgeSearchParams } from '@/hooks/route-hook';
|
import { useGetKnowledgeSearchParams } from '@/hooks/route-hook';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { useNavigate } from 'umi';
|
import { useNavigate } from 'umi';
|
||||||
@ -17,34 +17,6 @@ export const useNavigateToOtherPage = () => {
|
|||||||
return { linkToUploadPage, toChunk };
|
return { linkToUploadPage, toChunk };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCreateEmptyDocument = () => {
|
|
||||||
const { createDocument, loading } = useCreateNextDocument();
|
|
||||||
|
|
||||||
const {
|
|
||||||
visible: createVisible,
|
|
||||||
hideModal: hideCreateModal,
|
|
||||||
showModal: showCreateModal,
|
|
||||||
} = useSetModalState();
|
|
||||||
|
|
||||||
const onCreateOk = useCallback(
|
|
||||||
async (name: string) => {
|
|
||||||
const ret = await createDocument(name);
|
|
||||||
if (ret === 0) {
|
|
||||||
hideCreateModal();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[hideCreateModal, createDocument],
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
createLoading: loading,
|
|
||||||
onCreateOk,
|
|
||||||
createVisible,
|
|
||||||
hideCreateModal,
|
|
||||||
showCreateModal,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useGetRowSelection = () => {
|
export const useGetRowSelection = () => {
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
|
|
||||||
|
@ -1,15 +1,26 @@
|
|||||||
import { BulkOperateBar } from '@/components/bulk-operate-bar';
|
import { BulkOperateBar } from '@/components/bulk-operate-bar';
|
||||||
import { FileUploadDialog } from '@/components/file-upload-dialog';
|
import { FileUploadDialog } from '@/components/file-upload-dialog';
|
||||||
import ListFilterBar from '@/components/list-filter-bar';
|
import ListFilterBar from '@/components/list-filter-bar';
|
||||||
|
import { RenameDialog } from '@/components/rename-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { useFetchDocumentList } from '@/hooks/use-document-request';
|
import { useFetchDocumentList } from '@/hooks/use-document-request';
|
||||||
import { Upload } from 'lucide-react';
|
import { Upload } from 'lucide-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { DatasetTable } from './dataset-table';
|
import { DatasetTable } from './dataset-table';
|
||||||
import { useBulkOperateDataset } from './use-bulk-operate-dataset';
|
import { useBulkOperateDataset } from './use-bulk-operate-dataset';
|
||||||
|
import { useCreateEmptyDocument } from './use-create-empty-document';
|
||||||
import { useSelectDatasetFilters } from './use-select-filters';
|
import { useSelectDatasetFilters } from './use-select-filters';
|
||||||
import { useHandleUploadDocument } from './use-upload-document';
|
import { useHandleUploadDocument } from './use-upload-document';
|
||||||
|
|
||||||
export default function Dataset() {
|
export default function Dataset() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
documentUploadVisible,
|
documentUploadVisible,
|
||||||
hideDocumentUploadModal,
|
hideDocumentUploadModal,
|
||||||
@ -29,6 +40,14 @@ export default function Dataset() {
|
|||||||
} = useFetchDocumentList();
|
} = useFetchDocumentList();
|
||||||
const { filters } = useSelectDatasetFilters();
|
const { filters } = useSelectDatasetFilters();
|
||||||
|
|
||||||
|
const {
|
||||||
|
createLoading,
|
||||||
|
onCreateOk,
|
||||||
|
createVisible,
|
||||||
|
hideCreateModal,
|
||||||
|
showCreateModal,
|
||||||
|
} = useCreateEmptyDocument();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="p-8">
|
<section className="p-8">
|
||||||
<ListFilterBar
|
<ListFilterBar
|
||||||
@ -39,14 +58,23 @@ export default function Dataset() {
|
|||||||
onChange={handleFilterSubmit}
|
onChange={handleFilterSubmit}
|
||||||
filters={filters}
|
filters={filters}
|
||||||
>
|
>
|
||||||
<Button
|
<DropdownMenu>
|
||||||
variant={'tertiary'}
|
<DropdownMenuTrigger asChild>
|
||||||
size={'sm'}
|
<Button variant={'tertiary'} size={'sm'}>
|
||||||
onClick={showDocumentUploadModal}
|
<Upload />
|
||||||
>
|
{t('knowledgeDetails.addFile')}
|
||||||
<Upload />
|
</Button>
|
||||||
Upload file
|
</DropdownMenuTrigger>
|
||||||
</Button>
|
<DropdownMenuContent className="w-56">
|
||||||
|
<DropdownMenuItem onClick={showDocumentUploadModal}>
|
||||||
|
{t('fileManager.uploadFile')}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem onClick={showCreateModal}>
|
||||||
|
{t('fileManager.newFolder')}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
</ListFilterBar>
|
</ListFilterBar>
|
||||||
<BulkOperateBar list={list}></BulkOperateBar>
|
<BulkOperateBar list={list}></BulkOperateBar>
|
||||||
<DatasetTable
|
<DatasetTable
|
||||||
@ -61,6 +89,14 @@ export default function Dataset() {
|
|||||||
loading={documentUploadLoading}
|
loading={documentUploadLoading}
|
||||||
></FileUploadDialog>
|
></FileUploadDialog>
|
||||||
)}
|
)}
|
||||||
|
{createVisible && (
|
||||||
|
<RenameDialog
|
||||||
|
hideModal={hideCreateModal}
|
||||||
|
onOk={onCreateOk}
|
||||||
|
loading={createLoading}
|
||||||
|
title={'File Name'}
|
||||||
|
></RenameDialog>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
31
web/src/pages/dataset/dataset/use-create-empty-document.ts
Normal file
31
web/src/pages/dataset/dataset/use-create-empty-document.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
|
import { useCreateDocument } from '@/hooks/use-document-request';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
export const useCreateEmptyDocument = () => {
|
||||||
|
const { createDocument, loading } = useCreateDocument();
|
||||||
|
|
||||||
|
const {
|
||||||
|
visible: createVisible,
|
||||||
|
hideModal: hideCreateModal,
|
||||||
|
showModal: showCreateModal,
|
||||||
|
} = useSetModalState();
|
||||||
|
|
||||||
|
const onCreateOk = useCallback(
|
||||||
|
async (name: string) => {
|
||||||
|
const ret = await createDocument(name);
|
||||||
|
if (ret === 0) {
|
||||||
|
hideCreateModal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[hideCreateModal, createDocument],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
createLoading: loading,
|
||||||
|
onCreateOk,
|
||||||
|
createVisible,
|
||||||
|
hideCreateModal,
|
||||||
|
showCreateModal,
|
||||||
|
};
|
||||||
|
};
|
@ -22,14 +22,12 @@ import { UseChangeDocumentParserShowType } from './use-change-document-parser';
|
|||||||
import { UseRenameDocumentShowType } from './use-rename-document';
|
import { UseRenameDocumentShowType } from './use-rename-document';
|
||||||
import { UseSaveMetaShowType } from './use-save-meta';
|
import { UseSaveMetaShowType } from './use-save-meta';
|
||||||
|
|
||||||
type UseDatasetTableColumnsType = UseChangeDocumentParserShowType & {
|
type UseDatasetTableColumnsType = UseChangeDocumentParserShowType &
|
||||||
setCurrentRecord: (record: IDocumentInfo) => void;
|
UseRenameDocumentShowType &
|
||||||
} & UseRenameDocumentShowType &
|
|
||||||
UseSaveMetaShowType;
|
UseSaveMetaShowType;
|
||||||
|
|
||||||
export function useDatasetTableColumns({
|
export function useDatasetTableColumns({
|
||||||
showChangeParserModal,
|
showChangeParserModal,
|
||||||
setCurrentRecord,
|
|
||||||
showRenameModal,
|
showRenameModal,
|
||||||
showSetMetaModal,
|
showSetMetaModal,
|
||||||
}: UseDatasetTableColumnsType) {
|
}: UseDatasetTableColumnsType) {
|
||||||
|
@ -31,7 +31,7 @@ export function SideBar() {
|
|||||||
const { data } = useFetchKnowledgeBaseConfiguration();
|
const { data } = useFetchKnowledgeBaseConfiguration();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="w-[303px] relative border-r ">
|
<aside className="w-60 relative border-r ">
|
||||||
<div className="p-6 space-y-2 border-b">
|
<div className="p-6 space-y-2 border-b">
|
||||||
<div
|
<div
|
||||||
className="w-[70px] h-[70px] rounded-xl bg-cover"
|
className="w-[70px] h-[70px] rounded-xl bg-cover"
|
||||||
@ -56,9 +56,6 @@ export function SideBar() {
|
|||||||
>
|
>
|
||||||
<item.icon className="w-6 h-6" />
|
<item.icon className="w-6 h-6" />
|
||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
{active && (
|
|
||||||
<div className="absolute right-0 w-[5px] h-[66px] bg-primary rounded-l-xl shadow-[0_0_5.94px_#7561ff,0_0_11.88px_#7561ff,0_0_41.58px_#7561ff,0_0_83.16px_#7561ff,0_0_142.56px_#7561ff,0_0_249.48px_#7561ff]" />
|
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -71,6 +71,8 @@
|
|||||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||||
--sidebar-border: 220 13% 91%;
|
--sidebar-border: 220 13% 91%;
|
||||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
|
|
||||||
|
--background-inverse-strong: rgba(255, 255, 255, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user