mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-05 20:16:04 +08:00
### What problem does this PR solve? Feat: Preview the file #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
1aa97600df
commit
8ce5e69b2f
@ -1,4 +1,5 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
||||||
|
import NewDocumentLink from '@/components/new-document-link';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -9,8 +10,12 @@ import {
|
|||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { useDownloadFile } from '@/hooks/file-manager-hooks';
|
import { useDownloadFile } from '@/hooks/file-manager-hooks';
|
||||||
import { IFile } from '@/interfaces/database/file-manager';
|
import { IFile } from '@/interfaces/database/file-manager';
|
||||||
|
import {
|
||||||
|
getExtension,
|
||||||
|
isSupportedPreviewDocumentType,
|
||||||
|
} from '@/utils/document-util';
|
||||||
import { CellContext } from '@tanstack/react-table';
|
import { CellContext } from '@tanstack/react-table';
|
||||||
import { EllipsisVertical, Link2, Trash2 } from 'lucide-react';
|
import { EllipsisVertical, Eye, Link2, Trash2 } from 'lucide-react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
@ -18,6 +23,7 @@ import {
|
|||||||
UseRenameCurrentFileReturnType,
|
UseRenameCurrentFileReturnType,
|
||||||
} from './hooks';
|
} from './hooks';
|
||||||
import { UseMoveDocumentShowType } from './use-move-file';
|
import { UseMoveDocumentShowType } from './use-move-file';
|
||||||
|
import { isFolderType } from './util';
|
||||||
|
|
||||||
type IProps = Pick<CellContext<IFile, unknown>, 'row'> &
|
type IProps = Pick<CellContext<IFile, unknown>, 'row'> &
|
||||||
Pick<UseHandleConnectToKnowledgeReturnType, 'showConnectToKnowledgeModal'> &
|
Pick<UseHandleConnectToKnowledgeReturnType, 'showConnectToKnowledgeModal'> &
|
||||||
@ -34,6 +40,8 @@ export function ActionCell({
|
|||||||
const record = row.original;
|
const record = row.original;
|
||||||
const documentId = record.id;
|
const documentId = record.id;
|
||||||
const { downloadFile } = useDownloadFile();
|
const { downloadFile } = useDownloadFile();
|
||||||
|
const isFolder = isFolderType(record.type);
|
||||||
|
const extension = getExtension(record.name);
|
||||||
|
|
||||||
const handleShowConnectToKnowledgeModal = useCallback(() => {
|
const handleShowConnectToKnowledgeModal = useCallback(() => {
|
||||||
showConnectToKnowledgeModal(record);
|
showConnectToKnowledgeModal(record);
|
||||||
@ -57,20 +65,31 @@ export function ActionCell({
|
|||||||
return (
|
return (
|
||||||
<section className="flex gap-4 items-center">
|
<section className="flex gap-4 items-center">
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="ghost"
|
||||||
size={'icon'}
|
size={'icon'}
|
||||||
onClick={handleShowConnectToKnowledgeModal}
|
onClick={handleShowConnectToKnowledgeModal}
|
||||||
>
|
>
|
||||||
<Link2 />
|
<Link2 />
|
||||||
</Button>
|
</Button>
|
||||||
<ConfirmDeleteDialog>
|
<ConfirmDeleteDialog>
|
||||||
<Button variant="secondary" size={'icon'}>
|
<Button variant="ghost" size={'icon'}>
|
||||||
<Trash2 />
|
<Trash2 />
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmDeleteDialog>
|
</ConfirmDeleteDialog>
|
||||||
|
{isSupportedPreviewDocumentType(extension) && (
|
||||||
|
<NewDocumentLink
|
||||||
|
documentId={documentId}
|
||||||
|
documentName={record.name}
|
||||||
|
color="black"
|
||||||
|
>
|
||||||
|
<Button variant={'ghost'} size={'icon'}>
|
||||||
|
<Eye />
|
||||||
|
</Button>
|
||||||
|
</NewDocumentLink>
|
||||||
|
)}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="secondary" size={'icon'}>
|
<Button variant="ghost" size={'icon'}>
|
||||||
<EllipsisVertical />
|
<EllipsisVertical />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
@ -83,9 +102,11 @@ export function ActionCell({
|
|||||||
{t('common.rename')}
|
{t('common.rename')}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem onClick={onDownloadDocument}>
|
{isFolder || (
|
||||||
{t('common.download')}
|
<DropdownMenuItem onClick={onDownloadDocument}>
|
||||||
</DropdownMenuItem>
|
{t('common.download')}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</section>
|
</section>
|
||||||
|
@ -17,7 +17,6 @@ import * as React from 'react';
|
|||||||
import { RenameDialog } from '@/components/rename-dialog';
|
import { RenameDialog } from '@/components/rename-dialog';
|
||||||
import SvgIcon from '@/components/svg-icon';
|
import SvgIcon from '@/components/svg-icon';
|
||||||
import { TableEmpty, TableSkeleton } from '@/components/table-skeleton';
|
import { TableEmpty, TableSkeleton } from '@/components/table-skeleton';
|
||||||
import { Badge } from '@/components/ui/badge';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import {
|
import {
|
||||||
@ -44,9 +43,11 @@ import { useMemo } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ActionCell } from './action-cell';
|
import { ActionCell } from './action-cell';
|
||||||
import { useHandleConnectToKnowledge, useRenameCurrentFile } from './hooks';
|
import { useHandleConnectToKnowledge, useRenameCurrentFile } from './hooks';
|
||||||
|
import { KnowledgeCell } from './knowledge-cell';
|
||||||
import { LinkToDatasetDialog } from './link-to-dataset-dialog';
|
import { LinkToDatasetDialog } from './link-to-dataset-dialog';
|
||||||
import { UseMoveDocumentShowType } from './use-move-file';
|
import { UseMoveDocumentShowType } from './use-move-file';
|
||||||
import { useNavigateToOtherFolder } from './use-navigate-to-folder';
|
import { useNavigateToOtherFolder } from './use-navigate-to-folder';
|
||||||
|
import { isFolderType } from './util';
|
||||||
|
|
||||||
type FilesTableProps = Pick<
|
type FilesTableProps = Pick<
|
||||||
ReturnType<typeof useFetchFileList>,
|
ReturnType<typeof useFetchFileList>,
|
||||||
@ -133,7 +134,7 @@ export function FilesTable({
|
|||||||
const name: string = row.getValue('name');
|
const name: string = row.getValue('name');
|
||||||
const type = row.original.type;
|
const type = row.original.type;
|
||||||
const id = row.original.id;
|
const id = row.original.id;
|
||||||
const isFolder = type === 'folder';
|
const isFolder = isFolderType(type);
|
||||||
|
|
||||||
const handleNameClick = () => {
|
const handleNameClick = () => {
|
||||||
if (isFolder) {
|
if (isFolder) {
|
||||||
@ -204,24 +205,8 @@ export function FilesTable({
|
|||||||
accessorKey: 'kbs_info',
|
accessorKey: 'kbs_info',
|
||||||
header: t('knowledgeBase'),
|
header: t('knowledgeBase'),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const value = row.getValue('kbs_info');
|
const value: IFile['kbs_info'] = row.getValue('kbs_info');
|
||||||
return Array.isArray(value) ? (
|
return <KnowledgeCell value={value}></KnowledgeCell>;
|
||||||
<section className="flex gap-2 items-center">
|
|
||||||
{value?.slice(0, 2).map((x) => (
|
|
||||||
<Badge key={x.kb_id} className="" variant={'tertiary'}>
|
|
||||||
{x.kb_name}
|
|
||||||
</Badge>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{value.length > 2 && (
|
|
||||||
<Button variant={'icon'} size={'auto'}>
|
|
||||||
+{value.length - 2}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
41
web/src/pages/files/knowledge-cell.tsx
Normal file
41
web/src/pages/files/knowledge-cell.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
import {
|
||||||
|
HoverCard,
|
||||||
|
HoverCardContent,
|
||||||
|
HoverCardTrigger,
|
||||||
|
} from '@/components/ui/hover-card';
|
||||||
|
import { IFile } from '@/interfaces/database/file-manager';
|
||||||
|
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'}>
|
||||||
|
{x.kb_name}
|
||||||
|
</Badge>
|
||||||
|
));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return Array.isArray(value) ? (
|
||||||
|
<section className="flex gap-2 items-center">
|
||||||
|
{renderBadges(value?.slice(0, 2))}
|
||||||
|
|
||||||
|
{value.length > 2 && (
|
||||||
|
<HoverCard>
|
||||||
|
<HoverCardTrigger>
|
||||||
|
<Button variant={'icon'} size={'auto'}>
|
||||||
|
+{value.length - 2}
|
||||||
|
</Button>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<HoverCardContent className="flex gap-2 flex-wrap">
|
||||||
|
{renderBadges(value)}
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCard>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
3
web/src/pages/files/util.ts
Normal file
3
web/src/pages/files/util.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export function isFolderType(type: string) {
|
||||||
|
return type === 'folder';
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user