mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-26 00:46:52 +08:00
Feat: Adjust the operation cell of the table on the file management page and dataset page #3221. (#7526)
### What problem does this PR solve? Feat: Adjust the operation cell of the table on the file management page and dataset page #3221. ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -11,7 +11,7 @@ import { IDocumentInfo } from '@/interfaces/database/document';
|
||||
import { formatFileSize } from '@/utils/common-util';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import { downloadDocument } from '@/utils/file-util';
|
||||
import { ArrowDownToLine, Pencil, ScrollText, Trash2 } from 'lucide-react';
|
||||
import { ArrowDownToLine, FolderPen, ScrollText, Trash2 } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { UseRenameDocumentShowType } from './use-rename-document';
|
||||
import { isParserRunning } from './utils';
|
||||
@ -50,10 +50,18 @@ export function DatasetActionCell({
|
||||
}, [record, showRenameModal]);
|
||||
|
||||
return (
|
||||
<section className="flex gap-4 items-center">
|
||||
<section className="flex gap-4 items-center text-text-sub-title-invert">
|
||||
<Button
|
||||
variant={'ghost'}
|
||||
size={'sm'}
|
||||
disabled={isRunning}
|
||||
onClick={handleRename}
|
||||
>
|
||||
<FolderPen />
|
||||
</Button>
|
||||
<HoverCard>
|
||||
<HoverCardTrigger>
|
||||
<Button variant="ghost" size={'icon'} disabled={isRunning}>
|
||||
<Button variant="ghost" disabled={isRunning} size={'sm'}>
|
||||
<ScrollText />
|
||||
</Button>
|
||||
</HoverCardTrigger>
|
||||
@ -77,27 +85,20 @@ export function DatasetActionCell({
|
||||
</ul>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
<Button
|
||||
variant={'ghost'}
|
||||
size={'icon'}
|
||||
disabled={isRunning}
|
||||
onClick={handleRename}
|
||||
>
|
||||
<Pencil />
|
||||
</Button>
|
||||
|
||||
{isVirtualDocument || (
|
||||
<Button
|
||||
variant={'ghost'}
|
||||
size={'icon'}
|
||||
onClick={onDownloadDocument}
|
||||
disabled={isRunning}
|
||||
size={'sm'}
|
||||
>
|
||||
<ArrowDownToLine />
|
||||
</Button>
|
||||
)}
|
||||
<ConfirmDeleteDialog onOk={handleRemove}>
|
||||
<Button variant={'ghost'} size={'icon'} disabled={isRunning}>
|
||||
<Trash2 className="text-text-delete-red" />
|
||||
<Button variant={'ghost'} size={'sm'} disabled={isRunning}>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</ConfirmDeleteDialog>
|
||||
</section>
|
||||
|
||||
@ -119,7 +119,7 @@ export function DatasetTable({
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<Table>
|
||||
<Table rootClassName="max-h-[82vh]">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
@ -164,11 +164,7 @@ export function DatasetTable({
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end space-x-2 py-4">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{' '}
|
||||
{pagination?.total} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-end py-4">
|
||||
<div className="space-x-2">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
|
||||
@ -50,7 +50,7 @@ export default function Dataset() {
|
||||
showCreateModal,
|
||||
} = useCreateEmptyDocument();
|
||||
|
||||
const { rowSelection, rowSelectionIsEmpty, setRowSelection } =
|
||||
const { rowSelection, rowSelectionIsEmpty, setRowSelection, selectedCount } =
|
||||
useRowSelection();
|
||||
|
||||
const { list } = useBulkOperateDataset({
|
||||
@ -68,6 +68,15 @@ export default function Dataset() {
|
||||
value={filterValue}
|
||||
onChange={handleFilterSubmit}
|
||||
filters={filters}
|
||||
leftPanel={
|
||||
<div className="items-start">
|
||||
<div className="pb-1">Dataset</div>
|
||||
<div className="text-text-sub-title-invert text-sm">
|
||||
Please wait for your files to finish parsing before starting an
|
||||
AI-powered chat.
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@ -87,7 +96,9 @@ export default function Dataset() {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</ListFilterBar>
|
||||
{rowSelectionIsEmpty || <BulkOperateBar list={list}></BulkOperateBar>}
|
||||
{rowSelectionIsEmpty || (
|
||||
<BulkOperateBar list={list} count={selectedCount}></BulkOperateBar>
|
||||
)}
|
||||
<DatasetTable
|
||||
documents={documents}
|
||||
pagination={pagination}
|
||||
|
||||
@ -56,10 +56,10 @@ export function ParsingStatusCell({
|
||||
}, [record, showSetMetaModal]);
|
||||
|
||||
return (
|
||||
<section className="flex gap-2 items-center ">
|
||||
<div>
|
||||
<section className="flex gap-2 items-center">
|
||||
<div className="w-28 flex items-center justify-between">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant={'ghost'} size={'sm'}>
|
||||
{parser_id}
|
||||
</Button>
|
||||
@ -73,8 +73,7 @@ export function ParsingStatusCell({
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<Separator orientation="vertical" />
|
||||
<Separator orientation="vertical" className="h-2.5" />
|
||||
</div>
|
||||
<ConfirmDeleteDialog
|
||||
title={t(`knowledgeDetails.redo`, { chunkNum: chunk_num })}
|
||||
|
||||
@ -1,13 +1,6 @@
|
||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
||||
import NewDocumentLink from '@/components/new-document-link';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { useDownloadFile } from '@/hooks/file-manager-hooks';
|
||||
import { IFile } from '@/interfaces/database/file-manager';
|
||||
import {
|
||||
@ -15,9 +8,15 @@ import {
|
||||
isSupportedPreviewDocumentType,
|
||||
} from '@/utils/document-util';
|
||||
import { CellContext } from '@tanstack/react-table';
|
||||
import { EllipsisVertical, Eye, Link2, Trash2 } from 'lucide-react';
|
||||
import {
|
||||
ArrowDownToLine,
|
||||
Eye,
|
||||
FolderInput,
|
||||
FolderPen,
|
||||
Link2,
|
||||
Trash2,
|
||||
} from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
UseHandleConnectToKnowledgeReturnType,
|
||||
UseRenameCurrentFileReturnType,
|
||||
@ -36,7 +35,6 @@ export function ActionCell({
|
||||
showFileRenameModal,
|
||||
showMoveFileModal,
|
||||
}: IProps) {
|
||||
const { t } = useTranslation();
|
||||
const record = row.original;
|
||||
const documentId = record.id;
|
||||
const { downloadFile } = useDownloadFile();
|
||||
@ -63,33 +61,43 @@ export function ActionCell({
|
||||
}, [record, showMoveFileModal]);
|
||||
|
||||
return (
|
||||
<section className="flex gap-4 items-center">
|
||||
<section className="flex gap-4 items-center text-text-sub-title-invert">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size={'icon'}
|
||||
size={'sm'}
|
||||
onClick={handleShowConnectToKnowledgeModal}
|
||||
>
|
||||
<Link2 />
|
||||
</Button>
|
||||
<ConfirmDeleteDialog>
|
||||
<Button variant="ghost" size={'icon'}>
|
||||
<Trash2 className="text-text-delete-red" />
|
||||
<Button variant="ghost" size={'sm'} onClick={handleShowMoveFileModal}>
|
||||
<FolderInput />
|
||||
</Button>
|
||||
|
||||
<Button variant="ghost" size={'sm'} onClick={handleShowFileRenameModal}>
|
||||
<FolderPen />
|
||||
</Button>
|
||||
|
||||
{isFolder || (
|
||||
<Button variant={'ghost'} size={'sm'} onClick={onDownloadDocument}>
|
||||
<ArrowDownToLine />
|
||||
</Button>
|
||||
</ConfirmDeleteDialog>
|
||||
)}
|
||||
|
||||
{isSupportedPreviewDocumentType(extension) && (
|
||||
<NewDocumentLink
|
||||
documentId={documentId}
|
||||
documentName={record.name}
|
||||
color="black"
|
||||
className="text-text-sub-title-invert"
|
||||
>
|
||||
<Button variant={'ghost'} size={'icon'}>
|
||||
<Button variant={'ghost'} size={'sm'}>
|
||||
<Eye />
|
||||
</Button>
|
||||
</NewDocumentLink>
|
||||
)}
|
||||
<DropdownMenu>
|
||||
|
||||
{/* <DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size={'icon'}>
|
||||
<Button variant="ghost" size={'sm'}>
|
||||
<EllipsisVertical />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
@ -108,7 +116,12 @@ export function ActionCell({
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</DropdownMenu> */}
|
||||
<ConfirmDeleteDialog>
|
||||
<Button variant="ghost" size={'sm'}>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</ConfirmDeleteDialog>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@ -304,12 +304,7 @@ export function FilesTable({
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
<div className="flex items-center justify-end space-x-2 py-4">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of {total} row(s)
|
||||
selected.
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end py-4">
|
||||
<div className="space-x-2">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
|
||||
@ -20,6 +20,7 @@ import { MoveDialog } from './move-dialog';
|
||||
import { useBulkOperateFile } from './use-bulk-operate-file';
|
||||
import { useHandleCreateFolder } from './use-create-folder';
|
||||
import { useHandleMoveFile } from './use-move-file';
|
||||
import { useSelectBreadcrumbItems } from './use-navigate-to-folder';
|
||||
import { useHandleUploadFile } from './use-upload-file';
|
||||
|
||||
export default function Files() {
|
||||
@ -55,6 +56,7 @@ export default function Files() {
|
||||
setRowSelection,
|
||||
rowSelectionIsEmpty,
|
||||
clearRowSelection,
|
||||
selectedCount,
|
||||
} = useRowSelection();
|
||||
|
||||
const {
|
||||
@ -72,9 +74,11 @@ export default function Files() {
|
||||
setRowSelection,
|
||||
});
|
||||
|
||||
const breadcrumbItems = useSelectBreadcrumbItems();
|
||||
|
||||
const leftPanel = (
|
||||
<div>
|
||||
<FileBreadcrumb></FileBreadcrumb>
|
||||
{breadcrumbItems.length > 0 ? <FileBreadcrumb></FileBreadcrumb> : 'File'}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -85,6 +89,7 @@ export default function Files() {
|
||||
searchString={searchString}
|
||||
onSearchChange={handleInputChange}
|
||||
showFilter={false}
|
||||
icon={'file'}
|
||||
>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@ -104,7 +109,9 @@ export default function Files() {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</ListFilterBar>
|
||||
{!rowSelectionIsEmpty && <BulkOperateBar list={list}></BulkOperateBar>}
|
||||
{!rowSelectionIsEmpty && (
|
||||
<BulkOperateBar list={list} count={selectedCount}></BulkOperateBar>
|
||||
)}
|
||||
<FilesTable
|
||||
files={files}
|
||||
total={total}
|
||||
|
||||
@ -7,12 +7,13 @@ import {
|
||||
HoverCardTrigger,
|
||||
} from '@/components/ui/hover-card';
|
||||
import { IFile } from '@/interfaces/database/file-manager';
|
||||
import { Ellipsis } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export function KnowledgeCell({ value }: { value: IFile['kbs_info'] }) {
|
||||
const renderBadges = useCallback((list: IFile['kbs_info'] = []) => {
|
||||
return list.map((x) => (
|
||||
<Badge key={x.kb_id} className="" variant={'tertiary'}>
|
||||
<Badge key={x.kb_id} variant={'secondary'}>
|
||||
{x.kb_name}
|
||||
</Badge>
|
||||
));
|
||||
@ -25,8 +26,8 @@ export function KnowledgeCell({ value }: { value: IFile['kbs_info'] }) {
|
||||
{value.length > 2 && (
|
||||
<HoverCard>
|
||||
<HoverCardTrigger>
|
||||
<Button variant={'icon'} size={'auto'}>
|
||||
+{value.length - 2}
|
||||
<Button variant={'ghost'} size={'sm'}>
|
||||
<Ellipsis />
|
||||
</Button>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent className="flex gap-2 flex-wrap">
|
||||
|
||||
Reference in New Issue
Block a user