mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-12 00:39:01 +08:00
### What problem does this PR solve? Feat: Add DatasetTable #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
1e0fc76efa
commit
c93e0355c3
@ -11,7 +11,7 @@ const Switch = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<SwitchPrimitives.Root
|
<SwitchPrimitives.Root
|
||||||
className={cn(
|
className={cn(
|
||||||
'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-colors-background-core-standard data-[state=unchecked]:bg-colors-background-inverse-standard',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -19,7 +19,7 @@ const Switch = React.forwardRef<
|
|||||||
>
|
>
|
||||||
<SwitchPrimitives.Thumb
|
<SwitchPrimitives.Thumb
|
||||||
className={cn(
|
className={cn(
|
||||||
'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
|
'pointer-events-none block h-5 w-5 rounded-full bg-colors-text-neutral-strong shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SwitchPrimitives.Root>
|
</SwitchPrimitives.Root>
|
||||||
|
@ -3,7 +3,7 @@ import { Header } from './next-header';
|
|||||||
|
|
||||||
export default function NextLayout() {
|
export default function NextLayout() {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section className="h-full flex flex-col">
|
||||||
<Header></Header>
|
<Header></Header>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</section>
|
</section>
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
getSortedRowModel,
|
getSortedRowModel,
|
||||||
useReactTable,
|
useReactTable,
|
||||||
} from '@tanstack/react-table';
|
} from '@tanstack/react-table';
|
||||||
import { ArrowUpDown, MoreHorizontal } from 'lucide-react';
|
import { ArrowUpDown, MoreHorizontal, Pencil } from 'lucide-react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@ -25,6 +25,7 @@ import {
|
|||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -35,6 +36,7 @@ import {
|
|||||||
} from '@/components/ui/table';
|
} from '@/components/ui/table';
|
||||||
import { RunningStatus } from '@/constants/knowledge';
|
import { RunningStatus } from '@/constants/knowledge';
|
||||||
import { IDocumentInfo } from '@/interfaces/database/document';
|
import { IDocumentInfo } from '@/interfaces/database/document';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const data: IDocumentInfo[] = [
|
const data: IDocumentInfo[] = [
|
||||||
{
|
{
|
||||||
@ -68,97 +70,6 @@ const data: IDocumentInfo[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const columns: ColumnDef<IDocumentInfo>[] = [
|
|
||||||
{
|
|
||||||
id: 'select',
|
|
||||||
header: ({ table }) => (
|
|
||||||
<Checkbox
|
|
||||||
checked={
|
|
||||||
table.getIsAllPageRowsSelected() ||
|
|
||||||
(table.getIsSomePageRowsSelected() && 'indeterminate')
|
|
||||||
}
|
|
||||||
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
|
|
||||||
aria-label="Select all"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<Checkbox
|
|
||||||
checked={row.getIsSelected()}
|
|
||||||
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
|
||||||
aria-label="Select row"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
enableSorting: false,
|
|
||||||
enableHiding: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'status',
|
|
||||||
header: 'Status',
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<div className="capitalize">{row.getValue('status')}</div>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'email',
|
|
||||||
header: ({ column }) => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
|
||||||
>
|
|
||||||
Email
|
|
||||||
<ArrowUpDown />
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
cell: ({ row }) => <div className="lowercase">{row.getValue('email')}</div>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'amount',
|
|
||||||
header: () => <div className="text-right">Amount</div>,
|
|
||||||
cell: ({ row }) => {
|
|
||||||
const amount = parseFloat(row.getValue('amount'));
|
|
||||||
|
|
||||||
// Format the amount as a dollar amount
|
|
||||||
const formatted = new Intl.NumberFormat('en-US', {
|
|
||||||
style: 'currency',
|
|
||||||
currency: 'USD',
|
|
||||||
}).format(amount);
|
|
||||||
|
|
||||||
return <div className="text-right font-medium">{formatted}</div>;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'actions',
|
|
||||||
enableHiding: false,
|
|
||||||
cell: ({ row }) => {
|
|
||||||
const payment = row.original;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
|
||||||
<span className="sr-only">Open menu</span>
|
|
||||||
<MoreHorizontal />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="end">
|
|
||||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
|
||||||
<DropdownMenuItem
|
|
||||||
onClick={() => navigator.clipboard.writeText(payment.id)}
|
|
||||||
>
|
|
||||||
Copy payment ID
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuItem>View customer</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem>View payment details</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function DatasetTable() {
|
export function DatasetTable() {
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
@ -167,6 +78,119 @@ export function DatasetTable() {
|
|||||||
const [columnVisibility, setColumnVisibility] =
|
const [columnVisibility, setColumnVisibility] =
|
||||||
React.useState<VisibilityState>({});
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
|
const { t } = useTranslation('translation', {
|
||||||
|
keyPrefix: 'knowledgeDetails',
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns: ColumnDef<IDocumentInfo>[] = [
|
||||||
|
{
|
||||||
|
id: 'select',
|
||||||
|
header: ({ table }) => (
|
||||||
|
<Checkbox
|
||||||
|
checked={
|
||||||
|
table.getIsAllPageRowsSelected() ||
|
||||||
|
(table.getIsSomePageRowsSelected() && 'indeterminate')
|
||||||
|
}
|
||||||
|
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
|
||||||
|
aria-label="Select all"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<Checkbox
|
||||||
|
checked={row.getIsSelected()}
|
||||||
|
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||||
|
aria-label="Select row"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'name',
|
||||||
|
header: ({ column }) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||||
|
>
|
||||||
|
{t('name')}
|
||||||
|
<ArrowUpDown />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="capitalize">{row.getValue('name')}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'create_time',
|
||||||
|
header: ({ column }) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||||
|
>
|
||||||
|
{t('uploadDate')}
|
||||||
|
<ArrowUpDown />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="lowercase">{row.getValue('create_time')}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'parser_id',
|
||||||
|
header: t('chunkMethod'),
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="capitalize">{row.getValue('parser_id')}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'run',
|
||||||
|
header: t('parsingStatus'),
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<Button variant="destructive" size={'sm'}>
|
||||||
|
{row.getValue('run')}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
header: t('action'),
|
||||||
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const payment = row.original;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="flex gap-4 items-center">
|
||||||
|
<Switch id="airplane-mode" />
|
||||||
|
<Button variant="secondary" size={'icon'}>
|
||||||
|
<Pencil />
|
||||||
|
</Button>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="secondary" size={'icon'}>
|
||||||
|
<MoreHorizontal />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => navigator.clipboard.writeText(payment.id)}
|
||||||
|
>
|
||||||
|
Copy payment ID
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem>View customer</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>View payment details</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data,
|
data,
|
||||||
|
@ -3,7 +3,7 @@ import { SideBar } from './sidebar';
|
|||||||
|
|
||||||
export default function DatasetWrapper() {
|
export default function DatasetWrapper() {
|
||||||
return (
|
return (
|
||||||
<div className="text-foreground flex">
|
<div className="text-foreground flex flex-1">
|
||||||
<SideBar></SideBar>
|
<SideBar></SideBar>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
@ -2,7 +2,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
||||||
import { useSecondPathName } from '@/hooks/route-hook';
|
import { useSecondPathName } from '@/hooks/route-hook';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { Banknote, LayoutGrid, User } from 'lucide-react';
|
import { Banknote, LayoutGrid, Trash2, User } from 'lucide-react';
|
||||||
import { useHandleMenuClick } from './hooks';
|
import { useHandleMenuClick } from './hooks';
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
@ -29,7 +29,7 @@ export function SideBar() {
|
|||||||
const { handleMenuClick } = useHandleMenuClick();
|
const { handleMenuClick } = useHandleMenuClick();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="w-[303px]">
|
<aside className="w-[303px] relative">
|
||||||
<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"
|
||||||
@ -61,6 +61,13 @@ export function SideBar() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="absolute bottom-6 left-6 right-6 text-colors-text-functional-danger border-colors-text-functional-danger"
|
||||||
|
>
|
||||||
|
<Trash2 />
|
||||||
|
Delete dataset
|
||||||
|
</Button>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ module.exports = {
|
|||||||
'colors-text-core-standard': 'var(--colors-text-core-standard)',
|
'colors-text-core-standard': 'var(--colors-text-core-standard)',
|
||||||
'colors-text-neutral-strong': 'var(--colors-text-neutral-strong)',
|
'colors-text-neutral-strong': 'var(--colors-text-neutral-strong)',
|
||||||
'colors-text-neutral-standard': 'var(--colors-text-neutral-standard)',
|
'colors-text-neutral-standard': 'var(--colors-text-neutral-standard)',
|
||||||
|
'colors-text-functional-danger': 'var(--colors-text-functional-danger)',
|
||||||
|
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: 'hsl(var(--primary))',
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
--colors-text-core-standard: rgba(127, 105, 255, 1);
|
--colors-text-core-standard: rgba(127, 105, 255, 1);
|
||||||
--colors-text-neutral-strong: rgb(130, 121, 121);
|
--colors-text-neutral-strong: rgb(130, 121, 121);
|
||||||
--colors-text-neutral-standard: rgba(230, 227, 246, 1);
|
--colors-text-neutral-standard: rgba(230, 227, 246, 1);
|
||||||
|
--colors-text-functional-danger: rgba(255, 81, 81, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
@ -122,6 +123,7 @@
|
|||||||
--colors-text-core-standard: rgba(137, 126, 255, 1);
|
--colors-text-core-standard: rgba(137, 126, 255, 1);
|
||||||
--colors-text-neutral-strong: rgba(255, 255, 255, 1);
|
--colors-text-neutral-strong: rgba(255, 255, 255, 1);
|
||||||
--colors-text-neutral-standard: rgba(230, 227, 246, 1);
|
--colors-text-neutral-standard: rgba(230, 227, 246, 1);
|
||||||
|
--colors-text-functional-danger: rgba(255, 81, 81, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user