mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-10 21:09:03 +08:00
### What problem does this PR solve? Feat: Bind data to the agent module of the home page #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
c7310f7fb2
commit
5bb1c383ac
@ -1,3 +1,4 @@
|
|||||||
|
import { cn } from '@/lib/utils';
|
||||||
import { ChevronDown } from 'lucide-react';
|
import { ChevronDown } from 'lucide-react';
|
||||||
import React, {
|
import React, {
|
||||||
ChangeEventHandler,
|
ChangeEventHandler,
|
||||||
@ -38,7 +39,10 @@ export default function ListFilterBar({
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
filters,
|
filters,
|
||||||
}: PropsWithChildren<IProps & Omit<CheckboxFormMultipleProps, 'setOpen'>>) {
|
className,
|
||||||
|
}: PropsWithChildren<IProps & Omit<CheckboxFormMultipleProps, 'setOpen'>> & {
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
const filterCount = useMemo(() => {
|
const filterCount = useMemo(() => {
|
||||||
return typeof value === 'object' && value !== null
|
return typeof value === 'object' && value !== null
|
||||||
? Object.values(value).reduce((pre, cur) => {
|
? Object.values(value).reduce((pre, cur) => {
|
||||||
@ -48,7 +52,7 @@ export default function ListFilterBar({
|
|||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between mb-6 items-center">
|
<div className={cn('flex justify-between mb-6 items-center', className)}>
|
||||||
<span className="text-3xl font-bold ">{leftPanel || title}</span>
|
<span className="text-3xl font-bold ">{leftPanel || title}</span>
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex gap-4 items-center">
|
||||||
{showFilter && (
|
{showFilter && (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import { Loader2 } from 'lucide-react';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
import { SkeletonCard } from './skeleton-card';
|
|
||||||
import { TableCell, TableRow } from './ui/table';
|
import { TableCell, TableRow } from './ui/table';
|
||||||
|
|
||||||
type IProps = { columnsLength: number };
|
type IProps = { columnsLength: number };
|
||||||
@ -7,17 +7,22 @@ type IProps = { columnsLength: number };
|
|||||||
function Row({ children, columnsLength }: PropsWithChildren & IProps) {
|
function Row({ children, columnsLength }: PropsWithChildren & IProps) {
|
||||||
return (
|
return (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={columnsLength} className="h-24 text-center ">
|
<TableCell colSpan={columnsLength} className="h-24 text-center">
|
||||||
{children}
|
{children}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TableSkeleton({ columnsLength }: { columnsLength: number }) {
|
export function TableSkeleton({
|
||||||
|
columnsLength,
|
||||||
|
children,
|
||||||
|
}: PropsWithChildren & IProps) {
|
||||||
return (
|
return (
|
||||||
<Row columnsLength={columnsLength}>
|
<Row columnsLength={columnsLength}>
|
||||||
<SkeletonCard></SkeletonCard>
|
{children || (
|
||||||
|
<Loader2 className="animate-spin size-16 inline-block text-gray-400" />
|
||||||
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -99,14 +99,15 @@ export function AsyncTreeSelect({
|
|||||||
<li
|
<li
|
||||||
key={x.id}
|
key={x.id}
|
||||||
onClick={handleNodeClick(x.id)}
|
onClick={handleNodeClick(x.id)}
|
||||||
className="cursor-pointer hover:bg-slate-50 "
|
className="cursor-pointer "
|
||||||
>
|
>
|
||||||
<div className={cn('flex justify-between items-center')}>
|
<div
|
||||||
<span
|
className={cn(
|
||||||
className={cn({ 'bg-cyan-50': value === x.id }, 'flex-1')}
|
'flex justify-between items-center hover:bg-accent py-0.5 px-1 rounded-md ',
|
||||||
>
|
{ 'bg-cyan-50': value === x.id },
|
||||||
{x.title}
|
)}
|
||||||
</span>
|
>
|
||||||
|
<span className={cn('flex-1 ')}>{x.title}</span>
|
||||||
{x.isLeaf || (
|
{x.isLeaf || (
|
||||||
<Button
|
<Button
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
@ -146,10 +147,10 @@ export function AsyncTreeSelect({
|
|||||||
{selectedTitle || (
|
{selectedTitle || (
|
||||||
<span className="text-slate-400">{t('common.pleaseSelect')}</span>
|
<span className="text-slate-400">{t('common.pleaseSelect')}</span>
|
||||||
)}
|
)}
|
||||||
<ChevronDown className="size-5" />
|
<ChevronDown className="size-5 " />
|
||||||
</div>
|
</div>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="p-1">
|
<PopoverContent className="p-1 min-w-[var(--radix-popover-trigger-width)]">
|
||||||
<ul>{renderNodes()}</ul>
|
<ul>{renderNodes()}</ul>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -7,70 +7,100 @@ import {
|
|||||||
PaginationNext,
|
PaginationNext,
|
||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
} from '@/components/ui/pagination';
|
} from '@/components/ui/pagination';
|
||||||
|
import { RAGFlowSelect, RAGFlowSelectOptionType } from '@/components/ui/select';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
export type DatasetsPaginationType = {
|
export type RAGFlowPaginationType = {
|
||||||
showQuickJumper?: boolean;
|
showQuickJumper?: boolean;
|
||||||
onChange?(page: number, pageSize?: number): void;
|
onChange?(page: number, pageSize: number): void;
|
||||||
total?: number;
|
total?: number;
|
||||||
current?: number;
|
current?: number;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
|
showSizeChanger?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function DatasetsPagination({
|
export function RAGFlowPagination({
|
||||||
current = 1,
|
current = 1,
|
||||||
pageSize = 10,
|
pageSize = 10,
|
||||||
total = 0,
|
total = 0,
|
||||||
onChange,
|
onChange,
|
||||||
}: DatasetsPaginationType) {
|
showSizeChanger = true,
|
||||||
|
}: RAGFlowPaginationType) {
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const [currentPageSize, setCurrentPageSize] = useState('10');
|
||||||
|
|
||||||
|
const sizeChangerOptions: RAGFlowSelectOptionType[] = useMemo(() => {
|
||||||
|
return [10, 20, 50, 100].map((x) => ({
|
||||||
|
label: <span>{x} / page</span>,
|
||||||
|
value: x.toString(),
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const pages = useMemo(() => {
|
const pages = useMemo(() => {
|
||||||
const num = Math.ceil(total / pageSize);
|
const num = Math.ceil(total / pageSize);
|
||||||
console.log('🚀 ~ pages ~ num:', num);
|
|
||||||
return new Array(num).fill(0).map((_, idx) => idx + 1);
|
return new Array(num).fill(0).map((_, idx) => idx + 1);
|
||||||
}, [pageSize, total]);
|
}, [pageSize, total]);
|
||||||
|
|
||||||
|
const changePage = useCallback(
|
||||||
|
(page: number) => {
|
||||||
|
onChange?.(page, Number(currentPageSize));
|
||||||
|
},
|
||||||
|
[currentPageSize, onChange],
|
||||||
|
);
|
||||||
|
|
||||||
const handlePreviousPageChange = useCallback(() => {
|
const handlePreviousPageChange = useCallback(() => {
|
||||||
setCurrentPage((page) => {
|
setCurrentPage((page) => {
|
||||||
const previousPage = page - 1;
|
const previousPage = page - 1;
|
||||||
if (previousPage > 0) {
|
if (previousPage > 0) {
|
||||||
|
changePage(previousPage);
|
||||||
return previousPage;
|
return previousPage;
|
||||||
}
|
}
|
||||||
|
changePage(page);
|
||||||
return page;
|
return page;
|
||||||
});
|
});
|
||||||
}, []);
|
}, [changePage]);
|
||||||
|
|
||||||
const handlePageChange = useCallback(
|
const handlePageChange = useCallback(
|
||||||
(page: number) => () => {
|
(page: number) => () => {
|
||||||
|
changePage(page);
|
||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
},
|
},
|
||||||
[],
|
[changePage],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleNextPageChange = useCallback(() => {
|
const handleNextPageChange = useCallback(() => {
|
||||||
setCurrentPage((page) => {
|
setCurrentPage((page) => {
|
||||||
const nextPage = page + 1;
|
const nextPage = page + 1;
|
||||||
if (nextPage <= pages.length) {
|
if (nextPage <= pages.length) {
|
||||||
|
changePage(nextPage);
|
||||||
return nextPage;
|
return nextPage;
|
||||||
}
|
}
|
||||||
|
changePage(page);
|
||||||
return page;
|
return page;
|
||||||
});
|
});
|
||||||
}, [pages.length]);
|
}, [changePage, pages.length]);
|
||||||
|
|
||||||
|
const handlePageSizeChange = useCallback(
|
||||||
|
(size: string) => {
|
||||||
|
onChange?.(currentPage, Number(size));
|
||||||
|
setCurrentPageSize(size);
|
||||||
|
},
|
||||||
|
[currentPage, onChange],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentPage(current);
|
setCurrentPage(current);
|
||||||
}, [current]);
|
}, [current]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onChange?.(currentPage);
|
setCurrentPageSize(pageSize.toString());
|
||||||
}, [currentPage, onChange]);
|
}, [pageSize]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex items-center justify-end">
|
<section className="flex items-center justify-end">
|
||||||
<span className="mr-4">Total {total}</span>
|
<span className="mr-4">Total {total}</span>
|
||||||
<Pagination className="w-auto mx-0">
|
<Pagination className="w-auto mx-0 mr-4">
|
||||||
<PaginationContent>
|
<PaginationContent>
|
||||||
<PaginationItem>
|
<PaginationItem>
|
||||||
<PaginationPrevious onClick={handlePreviousPageChange} />
|
<PaginationPrevious onClick={handlePreviousPageChange} />
|
||||||
@ -78,7 +108,7 @@ export function DatasetsPagination({
|
|||||||
{pages.map((x) => (
|
{pages.map((x) => (
|
||||||
<PaginationItem
|
<PaginationItem
|
||||||
key={x}
|
key={x}
|
||||||
className={cn({ ['bg-red-500']: currentPage === x })}
|
className={cn({ ['bg-accent rounded-md']: currentPage === x })}
|
||||||
>
|
>
|
||||||
<PaginationLink onClick={handlePageChange(x)}>{x}</PaginationLink>
|
<PaginationLink onClick={handlePageChange(x)}>{x}</PaginationLink>
|
||||||
</PaginationItem>
|
</PaginationItem>
|
||||||
@ -91,6 +121,13 @@ export function DatasetsPagination({
|
|||||||
</PaginationItem>
|
</PaginationItem>
|
||||||
</PaginationContent>
|
</PaginationContent>
|
||||||
</Pagination>
|
</Pagination>
|
||||||
|
{showSizeChanger && (
|
||||||
|
<RAGFlowSelect
|
||||||
|
options={sizeChangerOptions}
|
||||||
|
value={currentPageSize}
|
||||||
|
onChange={handlePageSizeChange}
|
||||||
|
></RAGFlowSelect>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-w-[20vw]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { RowSelectionState } from '@tanstack/react-table';
|
import { RowSelectionState } from '@tanstack/react-table';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
export function useRowSelection() {
|
export function useRowSelection() {
|
||||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||||
|
|
||||||
|
const clearRowSelection = useCallback(() => {
|
||||||
|
setRowSelection({});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rowSelection,
|
rowSelection,
|
||||||
setRowSelection,
|
setRowSelection,
|
||||||
rowSelectionIsEmpty: isEmpty(rowSelection),
|
rowSelectionIsEmpty: isEmpty(rowSelection),
|
||||||
|
clearRowSelection,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
web/src/hooks/use-agent-request.ts
Normal file
22
web/src/hooks/use-agent-request.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { IFlow } from '@/interfaces/database/flow';
|
||||||
|
import flowService from '@/services/flow-service';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
export const enum AgentApiAction {
|
||||||
|
FetchAgentList = 'fetchAgentList',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useFetchAgentList = () => {
|
||||||
|
const { data, isFetching: loading } = useQuery<IFlow[]>({
|
||||||
|
queryKey: [AgentApiAction.FetchAgentList],
|
||||||
|
initialData: [],
|
||||||
|
gcTime: 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await flowService.listCanvas();
|
||||||
|
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
@ -26,7 +26,7 @@ export interface IOperatorNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export declare interface IFlow {
|
export declare interface IFlow {
|
||||||
avatar?: null | string;
|
avatar?: string;
|
||||||
canvas_type: null;
|
canvas_type: null;
|
||||||
create_date: string;
|
create_date: string;
|
||||||
create_time: number;
|
create_time: number;
|
||||||
|
@ -15,7 +15,8 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import { ChunkMethodDialog } from '@/components/chunk-method-dialog';
|
import { ChunkMethodDialog } from '@/components/chunk-method-dialog';
|
||||||
import { RenameDialog } from '@/components/rename-dialog';
|
import { RenameDialog } from '@/components/rename-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { TableSkeleton } from '@/components/table-skeleton';
|
||||||
|
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -27,6 +28,7 @@ import {
|
|||||||
import { UseRowSelectionType } from '@/hooks/logic-hooks/use-row-selection';
|
import { UseRowSelectionType } from '@/hooks/logic-hooks/use-row-selection';
|
||||||
import { useFetchDocumentList } from '@/hooks/use-document-request';
|
import { useFetchDocumentList } from '@/hooks/use-document-request';
|
||||||
import { getExtension } from '@/utils/document-util';
|
import { getExtension } from '@/utils/document-util';
|
||||||
|
import { pick } from 'lodash';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { SetMetaDialog } from './set-meta-dialog';
|
import { SetMetaDialog } from './set-meta-dialog';
|
||||||
import { useChangeDocumentParser } from './use-change-document-parser';
|
import { useChangeDocumentParser } from './use-change-document-parser';
|
||||||
@ -36,7 +38,7 @@ import { useSaveMeta } from './use-save-meta';
|
|||||||
|
|
||||||
export type DatasetTableProps = Pick<
|
export type DatasetTableProps = Pick<
|
||||||
ReturnType<typeof useFetchDocumentList>,
|
ReturnType<typeof useFetchDocumentList>,
|
||||||
'documents' | 'setPagination' | 'pagination'
|
'documents' | 'setPagination' | 'pagination' | 'loading'
|
||||||
> &
|
> &
|
||||||
Pick<UseRowSelectionType, 'rowSelection' | 'setRowSelection'>;
|
Pick<UseRowSelectionType, 'rowSelection' | 'setRowSelection'>;
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ export function DatasetTable({
|
|||||||
setPagination,
|
setPagination,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
setRowSelection,
|
setRowSelection,
|
||||||
|
loading,
|
||||||
}: DatasetTableProps) {
|
}: DatasetTableProps) {
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
@ -105,20 +108,6 @@ export function DatasetTable({
|
|||||||
getFilteredRowModel: getFilteredRowModel(),
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
onColumnVisibilityChange: setColumnVisibility,
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
onRowSelectionChange: setRowSelection,
|
onRowSelectionChange: setRowSelection,
|
||||||
onPaginationChange: (updaterOrValue: any) => {
|
|
||||||
if (typeof updaterOrValue === 'function') {
|
|
||||||
const nextPagination = updaterOrValue(currentPagination);
|
|
||||||
setPagination({
|
|
||||||
page: nextPagination.pageIndex + 1,
|
|
||||||
pageSize: nextPagination.pageSize,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setPagination({
|
|
||||||
page: updaterOrValue.pageIndex,
|
|
||||||
pageSize: updaterOrValue.pageSize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
manualPagination: true, //we're doing manual "server-side" pagination
|
manualPagination: true, //we're doing manual "server-side" pagination
|
||||||
state: {
|
state: {
|
||||||
sorting,
|
sorting,
|
||||||
@ -152,8 +141,10 @@ export function DatasetTable({
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody className="relative">
|
||||||
{table.getRowModel().rows?.length ? (
|
{loading ? (
|
||||||
|
<TableSkeleton columnsLength={columns.length}></TableSkeleton>
|
||||||
|
) : table.getRowModel().rows?.length ? (
|
||||||
table.getRowModel().rows.map((row) => (
|
table.getRowModel().rows.map((row) => (
|
||||||
<TableRow
|
<TableRow
|
||||||
key={row.id}
|
key={row.id}
|
||||||
@ -191,22 +182,13 @@ export function DatasetTable({
|
|||||||
{pagination?.total} row(s) selected.
|
{pagination?.total} row(s) selected.
|
||||||
</div>
|
</div>
|
||||||
<div className="space-x-2">
|
<div className="space-x-2">
|
||||||
<Button
|
<RAGFlowPagination
|
||||||
variant="outline"
|
{...pick(pagination, 'current', 'pageSize')}
|
||||||
size="sm"
|
total={pagination.total}
|
||||||
onClick={() => table.previousPage()}
|
onChange={(page, pageSize) => {
|
||||||
disabled={!table.getCanPreviousPage()}
|
setPagination({ page, pageSize });
|
||||||
>
|
}}
|
||||||
Previous
|
></RAGFlowPagination>
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => table.nextPage()}
|
|
||||||
disabled={!table.getCanNextPage()}
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{changeParserVisible && (
|
{changeParserVisible && (
|
||||||
|
@ -38,6 +38,7 @@ export default function Dataset() {
|
|||||||
setPagination,
|
setPagination,
|
||||||
filterValue,
|
filterValue,
|
||||||
handleFilterSubmit,
|
handleFilterSubmit,
|
||||||
|
loading,
|
||||||
} = useFetchDocumentList();
|
} = useFetchDocumentList();
|
||||||
const { filters } = useSelectDatasetFilters();
|
const { filters } = useSelectDatasetFilters();
|
||||||
|
|
||||||
@ -93,6 +94,7 @@ export default function Dataset() {
|
|||||||
setPagination={setPagination}
|
setPagination={setPagination}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
setRowSelection={setRowSelection}
|
setRowSelection={setRowSelection}
|
||||||
|
loading={loading}
|
||||||
></DatasetTable>
|
></DatasetTable>
|
||||||
{documentUploadVisible && (
|
{documentUploadVisible && (
|
||||||
<FileUploadDialog
|
<FileUploadDialog
|
||||||
|
@ -35,16 +35,6 @@ export function useDatasetTableColumns({
|
|||||||
keyPrefix: 'knowledgeDetails',
|
keyPrefix: 'knowledgeDetails',
|
||||||
});
|
});
|
||||||
|
|
||||||
// const onShowRenameModal = (record: IDocumentInfo) => {
|
|
||||||
// setCurrentRecord(record);
|
|
||||||
// showRenameModal();
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const onShowSetMetaModal = useCallback(() => {
|
|
||||||
// setRecord();
|
|
||||||
// showSetMetaModal();
|
|
||||||
// }, [setRecord, showSetMetaModal]);
|
|
||||||
|
|
||||||
const { navigateToChunkParsedResult } = useNavigatePage();
|
const { navigateToChunkParsedResult } = useNavigatePage();
|
||||||
const { setDocumentStatus } = useSetDocumentStatus();
|
const { setDocumentStatus } = useSetDocumentStatus();
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export function SideBar() {
|
|||||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
|
|
||||||
<h3 className="text-lg font-semibold mb-2">{data.name}</h3>
|
<h3 className="text-lg font-semibold mb-2 line-clamp-1">{data.name}</h3>
|
||||||
<div className="text-sm opacity-80">
|
<div className="text-sm opacity-80">
|
||||||
{data.doc_num} files | {data.chunk_num} chunks
|
{data.doc_num} files | {data.chunk_num} chunks
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,17 +26,21 @@ export function DatasetCard({
|
|||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={dataset.id}
|
key={dataset.id}
|
||||||
className="bg-colors-background-inverse-weak flex-1"
|
className="bg-colors-background-inverse-weak w-40"
|
||||||
onClick={navigateToDataset(dataset.id)}
|
onClick={navigateToDataset(dataset.id)}
|
||||||
>
|
>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-2.5 pt-1">
|
||||||
<section className="flex justify-between mb-4">
|
<section className="flex justify-between mb-2">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2 items-center">
|
||||||
<Avatar className="w-[70px] h-[70px] rounded-lg">
|
<Avatar className="size-6 rounded-lg">
|
||||||
<AvatarImage src={dataset.avatar} />
|
<AvatarImage src={dataset.avatar} />
|
||||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
<AvatarFallback className="rounded-lg ">CN</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
{owner && <Badge className="h-5">{owner}</Badge>}
|
{owner && (
|
||||||
|
<Badge className="h-5 rounded-sm px-1 bg-background-badge text-text-badge">
|
||||||
|
{owner}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<DatasetDropdown
|
<DatasetDropdown
|
||||||
showDatasetRenameModal={showDatasetRenameModal}
|
showDatasetRenameModal={showDatasetRenameModal}
|
||||||
@ -48,13 +52,13 @@ export function DatasetCard({
|
|||||||
</DatasetDropdown>
|
</DatasetDropdown>
|
||||||
</section>
|
</section>
|
||||||
<div className="flex justify-between items-end">
|
<div className="flex justify-between items-end">
|
||||||
<div>
|
<div className="w-full">
|
||||||
<h3 className="text-lg font-semibold mb-2 line-clamp-1">
|
<h3 className="text-lg font-semibold mb-2 line-clamp-1">
|
||||||
{dataset.name}
|
{dataset.name}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm opacity-80">{dataset.doc_num} files</p>
|
<p className="text-xs opacity-80">{dataset.doc_num} files</p>
|
||||||
<p className="text-sm opacity-80">
|
<p className="text-xs opacity-80">
|
||||||
Created {formatDate(dataset.update_time)}
|
{formatDate(dataset.update_time)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import ListFilterBar from '@/components/list-filter-bar';
|
import ListFilterBar from '@/components/list-filter-bar';
|
||||||
import { RenameDialog } from '@/components/rename-dialog';
|
import { RenameDialog } from '@/components/rename-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||||
import { useFetchNextKnowledgeListByPage } from '@/hooks/use-knowledge-request';
|
import { useFetchNextKnowledgeListByPage } from '@/hooks/use-knowledge-request';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import { Plus } from 'lucide-react';
|
import { Plus } from 'lucide-react';
|
||||||
@ -8,7 +9,6 @@ import { useCallback } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { DatasetCard } from './dataset-card';
|
import { DatasetCard } from './dataset-card';
|
||||||
import { DatasetCreatingDialog } from './dataset-creating-dialog';
|
import { DatasetCreatingDialog } from './dataset-creating-dialog';
|
||||||
import { DatasetsPagination } from './datasets-pagination';
|
|
||||||
import { useSaveKnowledge } from './hooks';
|
import { useSaveKnowledge } from './hooks';
|
||||||
import { useRenameDataset } from './use-rename-dataset';
|
import { useRenameDataset } from './use-rename-dataset';
|
||||||
import { useSelectOwners } from './use-select-owners';
|
import { useSelectOwners } from './use-select-owners';
|
||||||
@ -53,7 +53,7 @@ export default function Datasets() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="p-8 text-foreground">
|
<section className="py-8 text-foreground">
|
||||||
<ListFilterBar
|
<ListFilterBar
|
||||||
title="Datasets"
|
title="Datasets"
|
||||||
searchString={searchString}
|
searchString={searchString}
|
||||||
@ -61,13 +61,14 @@ export default function Datasets() {
|
|||||||
value={filterValue}
|
value={filterValue}
|
||||||
filters={owners}
|
filters={owners}
|
||||||
onChange={handleFilterSubmit}
|
onChange={handleFilterSubmit}
|
||||||
|
className="px-8"
|
||||||
>
|
>
|
||||||
<Button variant={'tertiary'} size={'sm'} onClick={showModal}>
|
<Button variant={'tertiary'} size={'sm'} onClick={showModal}>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
{t('knowledgeList.createKnowledgeBase')}
|
{t('knowledgeList.createKnowledgeBase')}
|
||||||
</Button>
|
</Button>
|
||||||
</ListFilterBar>
|
</ListFilterBar>
|
||||||
<div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8">
|
<div className="flex flex-wrap gap-4 max-h-[78vh] overflow-auto px-8">
|
||||||
{kbs.map((dataset) => {
|
{kbs.map((dataset) => {
|
||||||
return (
|
return (
|
||||||
<DatasetCard
|
<DatasetCard
|
||||||
@ -78,12 +79,12 @@ export default function Datasets() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-8">
|
<div className="mt-8 px-8">
|
||||||
<DatasetsPagination
|
<RAGFlowPagination
|
||||||
{...pick(pagination, 'current', 'pageSize')}
|
{...pick(pagination, 'current', 'pageSize')}
|
||||||
total={total}
|
total={total}
|
||||||
onChange={handlePageChange}
|
onChange={handlePageChange}
|
||||||
></DatasetsPagination>
|
></RAGFlowPagination>
|
||||||
</div>
|
</div>
|
||||||
{visible && (
|
{visible && (
|
||||||
<DatasetCreatingDialog
|
<DatasetCreatingDialog
|
||||||
|
@ -73,7 +73,7 @@ export function ActionCell({
|
|||||||
</Button>
|
</Button>
|
||||||
<ConfirmDeleteDialog>
|
<ConfirmDeleteDialog>
|
||||||
<Button variant="ghost" size={'icon'}>
|
<Button variant="ghost" size={'icon'}>
|
||||||
<Trash2 />
|
<Trash2 className="text-text-delete-red" />
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmDeleteDialog>
|
</ConfirmDeleteDialog>
|
||||||
{isSupportedPreviewDocumentType(extension) && (
|
{isSupportedPreviewDocumentType(extension) && (
|
||||||
|
@ -19,6 +19,7 @@ import SvgIcon from '@/components/svg-icon';
|
|||||||
import { TableEmpty, TableSkeleton } from '@/components/table-skeleton';
|
import { TableEmpty, TableSkeleton } from '@/components/table-skeleton';
|
||||||
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 { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -39,6 +40,7 @@ import { cn } from '@/lib/utils';
|
|||||||
import { formatFileSize } from '@/utils/common-util';
|
import { formatFileSize } from '@/utils/common-util';
|
||||||
import { formatDate } from '@/utils/date';
|
import { formatDate } from '@/utils/date';
|
||||||
import { getExtension } from '@/utils/document-util';
|
import { getExtension } from '@/utils/document-util';
|
||||||
|
import { pick } from 'lodash';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ActionCell } from './action-cell';
|
import { ActionCell } from './action-cell';
|
||||||
@ -244,20 +246,7 @@ export function FilesTable({
|
|||||||
getFilteredRowModel: getFilteredRowModel(),
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
onColumnVisibilityChange: setColumnVisibility,
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
onRowSelectionChange: setRowSelection,
|
onRowSelectionChange: setRowSelection,
|
||||||
onPaginationChange: (updaterOrValue: any) => {
|
|
||||||
if (typeof updaterOrValue === 'function') {
|
|
||||||
const nextPagination = updaterOrValue(currentPagination);
|
|
||||||
setPagination({
|
|
||||||
page: nextPagination.pageIndex + 1,
|
|
||||||
pageSize: nextPagination.pageSize,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setPagination({
|
|
||||||
page: updaterOrValue.pageIndex,
|
|
||||||
pageSize: updaterOrValue.pageSize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
manualPagination: true, //we're doing manual "server-side" pagination
|
manualPagination: true, //we're doing manual "server-side" pagination
|
||||||
|
|
||||||
state: {
|
state: {
|
||||||
@ -326,23 +315,15 @@ export function FilesTable({
|
|||||||
{table.getFilteredSelectedRowModel().rows.length} of {total} row(s)
|
{table.getFilteredSelectedRowModel().rows.length} of {total} row(s)
|
||||||
selected.
|
selected.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-x-2">
|
<div className="space-x-2">
|
||||||
<Button
|
<RAGFlowPagination
|
||||||
variant="outline"
|
{...pick(pagination, 'current', 'pageSize')}
|
||||||
size="sm"
|
total={total}
|
||||||
onClick={() => table.previousPage()}
|
onChange={(page, pageSize) => {
|
||||||
disabled={!table.getCanPreviousPage()}
|
setPagination({ page, pageSize });
|
||||||
>
|
}}
|
||||||
Previous
|
></RAGFlowPagination>
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => table.nextPage()}
|
|
||||||
disabled={!table.getCanNextPage()}
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{connectToKnowledgeVisible && (
|
{connectToKnowledgeVisible && (
|
||||||
|
@ -50,16 +50,20 @@ export default function Files() {
|
|||||||
handleInputChange,
|
handleInputChange,
|
||||||
} = useFetchFileList();
|
} = useFetchFileList();
|
||||||
|
|
||||||
|
const {
|
||||||
|
rowSelection,
|
||||||
|
setRowSelection,
|
||||||
|
rowSelectionIsEmpty,
|
||||||
|
clearRowSelection,
|
||||||
|
} = useRowSelection();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
showMoveFileModal,
|
showMoveFileModal,
|
||||||
moveFileVisible,
|
moveFileVisible,
|
||||||
onMoveFileOk,
|
onMoveFileOk,
|
||||||
hideMoveFileModal,
|
hideMoveFileModal,
|
||||||
moveFileLoading,
|
moveFileLoading,
|
||||||
} = useHandleMoveFile();
|
} = useHandleMoveFile({ clearRowSelection });
|
||||||
|
|
||||||
const { rowSelection, setRowSelection, rowSelectionIsEmpty } =
|
|
||||||
useRowSelection();
|
|
||||||
|
|
||||||
const { list } = useBulkOperateFile({
|
const { list } = useBulkOperateFile({
|
||||||
files,
|
files,
|
||||||
|
@ -69,7 +69,7 @@ function LinkToDatasetForm({
|
|||||||
name="knowledgeIds"
|
name="knowledgeIds"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Name</FormLabel>
|
<FormLabel>{t('common.name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
options={options}
|
options={options}
|
||||||
|
@ -28,7 +28,7 @@ export function useBulkOperateFile({
|
|||||||
label: t('common.move'),
|
label: t('common.move'),
|
||||||
icon: <FolderInput />,
|
icon: <FolderInput />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
showMoveFileModal(selectedIds);
|
showMoveFileModal(selectedIds, true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
|
import { UseRowSelectionType } from '@/hooks/logic-hooks/use-row-selection';
|
||||||
import { useMoveFile } from '@/hooks/use-file-request';
|
import { useMoveFile } from '@/hooks/use-file-request';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useRef, useState } from 'react';
|
||||||
|
|
||||||
export const useHandleMoveFile = () => {
|
export const useHandleMoveFile = ({
|
||||||
|
clearRowSelection,
|
||||||
|
}: Pick<UseRowSelectionType, 'clearRowSelection'>) => {
|
||||||
const {
|
const {
|
||||||
visible: moveFileVisible,
|
visible: moveFileVisible,
|
||||||
hideModal: hideMoveFileModal,
|
hideModal: hideMoveFileModal,
|
||||||
@ -10,6 +13,7 @@ export const useHandleMoveFile = () => {
|
|||||||
} = useSetModalState();
|
} = useSetModalState();
|
||||||
const { moveFile, loading } = useMoveFile();
|
const { moveFile, loading } = useMoveFile();
|
||||||
const [sourceFileIds, setSourceFileIds] = useState<string[]>([]);
|
const [sourceFileIds, setSourceFileIds] = useState<string[]>([]);
|
||||||
|
const isBulkRef = useRef(false);
|
||||||
|
|
||||||
const onMoveFileOk = useCallback(
|
const onMoveFileOk = useCallback(
|
||||||
async (targetFolderId: string) => {
|
async (targetFolderId: string) => {
|
||||||
@ -19,16 +23,19 @@ export const useHandleMoveFile = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (ret === 0) {
|
if (ret === 0) {
|
||||||
// setSelectedRowKeys([]);
|
if (isBulkRef.current) {
|
||||||
|
clearRowSelection();
|
||||||
|
}
|
||||||
hideMoveFileModal();
|
hideMoveFileModal();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
[moveFile, hideMoveFileModal, sourceFileIds],
|
[moveFile, sourceFileIds, hideMoveFileModal, clearRowSelection],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleShowMoveFileModal = useCallback(
|
const handleShowMoveFileModal = useCallback(
|
||||||
(ids: string[]) => {
|
(ids: string[], isBulk = false) => {
|
||||||
|
isBulkRef.current = isBulk;
|
||||||
setSourceFileIds(ids);
|
setSourceFileIds(ids);
|
||||||
showMoveFileModal();
|
showMoveFileModal();
|
||||||
},
|
},
|
||||||
|
10
web/src/pages/home/agent-list.tsx
Normal file
10
web/src/pages/home/agent-list.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { useFetchAgentList } from '@/hooks/use-agent-request';
|
||||||
|
import { ApplicationCard } from './application-card';
|
||||||
|
|
||||||
|
export function Agents() {
|
||||||
|
const { data } = useFetchAgentList();
|
||||||
|
|
||||||
|
return data
|
||||||
|
.slice(0, 10)
|
||||||
|
.map((x) => <ApplicationCard key={x.id} app={x}></ApplicationCard>);
|
||||||
|
}
|
30
web/src/pages/home/application-card.tsx
Normal file
30
web/src/pages/home/application-card.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
import { formatDate } from '@/utils/date';
|
||||||
|
|
||||||
|
type ApplicationCardProps = {
|
||||||
|
app: {
|
||||||
|
avatar?: string;
|
||||||
|
title: string;
|
||||||
|
update_time: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ApplicationCard({ app }: ApplicationCardProps) {
|
||||||
|
return (
|
||||||
|
<Card className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard w-64">
|
||||||
|
<CardContent className="p-4 flex items-center gap-6">
|
||||||
|
<Avatar className="size-14 rounded-lg">
|
||||||
|
<AvatarImage src={app.avatar === null ? '' : app.avatar} />
|
||||||
|
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="text-lg font-semibold line-clamp-1 mb-1">
|
||||||
|
{app.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm opacity-80">{formatDate(app.update_time)}</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
@ -1,62 +1,58 @@
|
|||||||
import { Button } from '@/components/ui/button';
|
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
|
||||||
import { Segmented, SegmentedValue } from '@/components/ui/segmented';
|
import { Segmented, SegmentedValue } from '@/components/ui/segmented';
|
||||||
import { ChevronRight, Cpu, MessageSquare, Search } from 'lucide-react';
|
import { Routes } from '@/routes';
|
||||||
|
import { Cpu, MessageSquare, Search } from 'lucide-react';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Agents } from './agent-list';
|
||||||
|
import { ApplicationCard } from './application-card';
|
||||||
|
|
||||||
const applications = [
|
const applications = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: 'Jarvis chatbot',
|
title: 'Jarvis chatbot',
|
||||||
type: 'Chat app',
|
type: 'Chat app',
|
||||||
date: '11/24/2024',
|
update_time: '11/24/2024',
|
||||||
icon: <MessageSquare className="h-6 w-6" />,
|
avatar: <MessageSquare className="h-6 w-6" />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
title: 'Search app 01',
|
title: 'Search app 01',
|
||||||
type: 'Search app',
|
type: 'Search app',
|
||||||
date: '11/24/2024',
|
update_time: '11/24/2024',
|
||||||
icon: <Search className="h-6 w-6" />,
|
avatar: <Search className="h-6 w-6" />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
title: 'Chatbot 01',
|
title: 'Chatbot 01',
|
||||||
type: 'Chat app',
|
type: 'Chat app',
|
||||||
date: '11/24/2024',
|
update_time: '11/24/2024',
|
||||||
icon: <MessageSquare className="h-6 w-6" />,
|
avatar: <MessageSquare className="h-6 w-6" />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
title: 'Workflow 01',
|
title: 'Workflow 01',
|
||||||
type: 'Agent',
|
type: 'Agent',
|
||||||
date: '11/24/2024',
|
update_time: '11/24/2024',
|
||||||
icon: <Cpu className="h-6 w-6" />,
|
avatar: <Cpu className="h-6 w-6" />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function Applications() {
|
export function Applications() {
|
||||||
const [val, setVal] = useState('all');
|
const [val, setVal] = useState('all');
|
||||||
const options = useMemo(() => {
|
const { t } = useTranslation();
|
||||||
return [
|
|
||||||
|
const options = useMemo(
|
||||||
|
() => [
|
||||||
{
|
{
|
||||||
label: 'All',
|
label: 'All',
|
||||||
value: 'all',
|
value: 'all',
|
||||||
},
|
},
|
||||||
{
|
{ value: Routes.Chats, label: t('header.chat') },
|
||||||
label: 'Chat',
|
{ value: Routes.Searches, label: t('header.search') },
|
||||||
value: 'chat',
|
{ value: Routes.Agents, label: t('header.flow') },
|
||||||
},
|
],
|
||||||
{
|
[t],
|
||||||
label: 'Search',
|
);
|
||||||
value: 'search',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Agent',
|
|
||||||
value: 'agent',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleChange = (path: SegmentedValue) => {
|
const handleChange = (path: SegmentedValue) => {
|
||||||
setVal(path as string);
|
setVal(path as string);
|
||||||
@ -73,30 +69,13 @@ export function Applications() {
|
|||||||
className="bg-colors-background-inverse-standard text-colors-text-neutral-standard"
|
className="bg-colors-background-inverse-standard text-colors-text-neutral-standard"
|
||||||
></Segmented>
|
></Segmented>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 gap-6">
|
<div className="flex flex-wrap gap-4">
|
||||||
{[...Array(12)].map((_, i) => {
|
{val === Routes.Agents ||
|
||||||
const app = applications[i % 4];
|
[...Array(12)].map((_, i) => {
|
||||||
return (
|
const app = applications[i % 4];
|
||||||
<Card
|
return <ApplicationCard key={i} app={app}></ApplicationCard>;
|
||||||
key={i}
|
})}
|
||||||
className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard"
|
{val === Routes.Agents && <Agents></Agents>}
|
||||||
>
|
|
||||||
<CardContent className="p-4 flex items-center gap-6">
|
|
||||||
<div className="w-[70px] h-[70px] rounded-xl flex items-center justify-center bg-gradient-to-br from-[#45A7FA] via-[#AE63E3] to-[#4433FF]">
|
|
||||||
{app.icon}
|
|
||||||
</div>
|
|
||||||
<div className="flex-1">
|
|
||||||
<h3 className="text-lg font-semibold">{app.title}</h3>
|
|
||||||
<p className="text-sm opacity-80">{app.type}</p>
|
|
||||||
<p className="text-sm opacity-80">{app.date}</p>
|
|
||||||
</div>
|
|
||||||
<Button variant="icon" size="icon">
|
|
||||||
<ChevronRight className="h-6 w-6" />
|
|
||||||
</Button>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -28,7 +28,7 @@ export function Datasets() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex gap-4 flex-1">
|
<div className="flex gap-4 flex-1">
|
||||||
{kbs.slice(0, 4).map((dataset) => (
|
{kbs.slice(0, 6).map((dataset) => (
|
||||||
<DatasetCard
|
<DatasetCard
|
||||||
key={dataset.id}
|
key={dataset.id}
|
||||||
dataset={dataset}
|
dataset={dataset}
|
||||||
|
@ -42,6 +42,9 @@ module.exports = {
|
|||||||
'colors-text-inverse-weak': 'var(--colors-text-inverse-weak)',
|
'colors-text-inverse-weak': 'var(--colors-text-inverse-weak)',
|
||||||
'text-delete-red': 'var(--text-delete-red)',
|
'text-delete-red': 'var(--text-delete-red)',
|
||||||
|
|
||||||
|
'background-badge': 'var(--background-badge)',
|
||||||
|
'text-badge': 'var(--text-badge)',
|
||||||
|
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: 'hsl(var(--primary))',
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
foreground: 'hsl(var(--primary-foreground))',
|
foreground: 'hsl(var(--primary-foreground))',
|
||||||
|
@ -73,6 +73,9 @@
|
|||||||
--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);
|
--background-inverse-strong: rgba(255, 255, 255, 0.15);
|
||||||
|
|
||||||
|
--background-badge: rgba(22, 22, 24, 0.5);
|
||||||
|
--text-badge: rgba(151, 154, 171, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
@ -122,6 +125,9 @@
|
|||||||
--background-core-weak: rgb(101, 75, 248);
|
--background-core-weak: rgb(101, 75, 248);
|
||||||
--background-core-weak-foreground: rgba(255, 255, 255, 1);
|
--background-core-weak-foreground: rgba(255, 255, 255, 1);
|
||||||
|
|
||||||
|
--background-badge: rgba(22, 22, 24, 0.5);
|
||||||
|
--text-badge: rgba(151, 154, 171, 1);
|
||||||
|
|
||||||
--colors-background-core-standard: rgba(137, 126, 255, 1);
|
--colors-background-core-standard: rgba(137, 126, 255, 1);
|
||||||
--colors-background-core-strong: rgba(152, 147, 255, 1);
|
--colors-background-core-strong: rgba(152, 147, 255, 1);
|
||||||
--colors-background-core-weak: rgba(101, 75, 248, 1);
|
--colors-background-core-weak: rgba(101, 75, 248, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user