mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-10 19:08:58 +08:00
### What problem does this PR solve? Feat: Modify the dataset list page style #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
6e7dd54a50
commit
fea9d970ec
@ -72,7 +72,7 @@ function CheckboxFormMultiple({
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-8"
|
||||
className="space-y-8 px-5 py-2.5"
|
||||
onReset={() => form.reset()}
|
||||
>
|
||||
{filters.map((x) => (
|
||||
@ -81,9 +81,11 @@ function CheckboxFormMultiple({
|
||||
control={form.control}
|
||||
name={x.field}
|
||||
render={() => (
|
||||
<FormItem>
|
||||
<div className="mb-4">
|
||||
<FormLabel className="text-base">{x.label}</FormLabel>
|
||||
<FormItem className="space-y-4">
|
||||
<div>
|
||||
<FormLabel className="text-base text-text-sub-title-invert">
|
||||
{x.label}
|
||||
</FormLabel>
|
||||
</div>
|
||||
{x.list.map((item) => (
|
||||
<FormField
|
||||
@ -92,10 +94,10 @@ function CheckboxFormMultiple({
|
||||
name={x.field}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center justify-between text-text-title text-xs">
|
||||
<FormItem
|
||||
key={item.id}
|
||||
className="flex flex-row space-x-3 space-y-0 items-center"
|
||||
className="flex flex-row space-x-3 space-y-0 items-center "
|
||||
>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
@ -111,9 +113,7 @@ function CheckboxFormMultiple({
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormLabel className="text-lg">
|
||||
{item.label}
|
||||
</FormLabel>
|
||||
<FormLabel>{item.label}</FormLabel>
|
||||
</FormItem>
|
||||
<span className=" text-sm">{item.count}</span>
|
||||
</div>
|
||||
@ -126,7 +126,7 @@ function CheckboxFormMultiple({
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
<div className="flex justify-between">
|
||||
<div className="flex justify-end gap-5">
|
||||
<Button
|
||||
type="button"
|
||||
variant={'outline'}
|
||||
@ -155,7 +155,7 @@ export function FilterPopover({
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>{children}</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<PopoverContent className="p-0">
|
||||
<CheckboxFormMultiple
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
|
@ -6,12 +6,13 @@ import React, {
|
||||
ReactNode,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { IconFont } from '../icon-font';
|
||||
import { Button, ButtonProps } from '../ui/button';
|
||||
import { SearchInput } from '../ui/input';
|
||||
import { CheckboxFormMultipleProps, FilterPopover } from './filter-popover';
|
||||
|
||||
interface IProps {
|
||||
title?: string;
|
||||
title?: ReactNode;
|
||||
searchString?: string;
|
||||
onSearchChange?: ChangeEventHandler<HTMLInputElement>;
|
||||
showFilter?: boolean;
|
||||
@ -23,8 +24,21 @@ const FilterButton = React.forwardRef<
|
||||
ButtonProps & { count?: number }
|
||||
>(({ count = 0, ...props }, ref) => {
|
||||
return (
|
||||
<Button variant="outline" size={'sm'} {...props} ref={ref}>
|
||||
Filter <span>{count}</span> <ChevronDown />
|
||||
<Button variant="secondary" {...props} ref={ref}>
|
||||
<span
|
||||
className={cn({
|
||||
'text-text-title': count > 0,
|
||||
'text-text-sub-title-invert': count === 0,
|
||||
})}
|
||||
>
|
||||
Filter
|
||||
</span>
|
||||
{count > 0 && (
|
||||
<span className="rounded-full bg-text-badge px-1 text-xs ">
|
||||
{count}
|
||||
</span>
|
||||
)}
|
||||
<ChevronDown />
|
||||
</Button>
|
||||
);
|
||||
});
|
||||
@ -40,8 +54,10 @@ export default function ListFilterBar({
|
||||
onChange,
|
||||
filters,
|
||||
className,
|
||||
icon,
|
||||
}: PropsWithChildren<IProps & Omit<CheckboxFormMultipleProps, 'setOpen'>> & {
|
||||
className?: string;
|
||||
icon?: ReactNode;
|
||||
}) {
|
||||
const filterCount = useMemo(() => {
|
||||
return typeof value === 'object' && value !== null
|
||||
@ -52,9 +68,16 @@ export default function ListFilterBar({
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className={cn('flex justify-between mb-6 items-center', className)}>
|
||||
<span className="text-3xl font-bold ">{leftPanel || title}</span>
|
||||
<div className="flex gap-4 items-center">
|
||||
<div className={cn('flex justify-between mb-5 items-center', className)}>
|
||||
<div className="text-2xl font-semibold flex items-center gap-2.5">
|
||||
{typeof icon === 'string' ? (
|
||||
<IconFont name={icon} className="size-6"></IconFont>
|
||||
) : (
|
||||
icon
|
||||
)}
|
||||
{leftPanel || title}
|
||||
</div>
|
||||
<div className="flex gap-5 items-center">
|
||||
{showFilter && (
|
||||
<FilterPopover value={value} onChange={onChange} filters={filters}>
|
||||
<FilterButton count={filterCount}></FilterButton>
|
||||
@ -64,6 +87,7 @@ export default function ListFilterBar({
|
||||
<SearchInput
|
||||
value={searchString}
|
||||
onChange={onSearchChange}
|
||||
className="w-32"
|
||||
></SearchInput>
|
||||
{children}
|
||||
</div>
|
||||
|
@ -13,7 +13,7 @@ const buttonVariants = cva(
|
||||
destructive:
|
||||
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||
outline:
|
||||
'border border-colors-outline-sentiment-primary bg-background hover:bg-accent hover:text-accent-foreground',
|
||||
'border border-text-sub-title-invert bg-transparent hover:bg-accent hover:text-accent-foreground',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
@ -23,8 +23,8 @@ const buttonVariants = cva(
|
||||
icon: 'bg-colors-background-inverse-standard text-foreground hover:bg-colors-background-inverse-standard/80',
|
||||
},
|
||||
size: {
|
||||
default: 'h-10 px-4 py-2',
|
||||
sm: 'h-9 rounded-md px-3',
|
||||
default: 'h-8 px-2.5 py-1.5 ',
|
||||
sm: 'h-6 rounded-sm px-2',
|
||||
lg: 'h-11 rounded-md px-8',
|
||||
icon: 'h-10 w-10',
|
||||
auto: 'h-full px-1',
|
||||
|
@ -12,7 +12,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
'flex h-10 w-full rounded-md border border-input bg-colors-background-inverse-weak px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'flex h-8 w-full rounded-md border border-input bg-colors-background-inverse-weak px-2 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
@ -28,7 +28,12 @@ export interface ExpandedInputProps extends Omit<InputProps, 'prefix'> {
|
||||
suffix?: React.ReactNode;
|
||||
}
|
||||
|
||||
const ExpandedInput = ({ suffix, prefix, ...props }: ExpandedInputProps) => {
|
||||
const ExpandedInput = ({
|
||||
suffix,
|
||||
prefix,
|
||||
className,
|
||||
...props
|
||||
}: ExpandedInputProps) => {
|
||||
return (
|
||||
<div className="relative">
|
||||
<span
|
||||
@ -39,7 +44,7 @@ const ExpandedInput = ({ suffix, prefix, ...props }: ExpandedInputProps) => {
|
||||
{prefix}
|
||||
</span>
|
||||
<Input
|
||||
className={cn({ 'pr-10': suffix, 'pl-10': prefix })}
|
||||
className={cn({ 'pr-8': !!suffix, 'pl-8': !!prefix }, className)}
|
||||
{...props}
|
||||
></Input>
|
||||
<span
|
||||
@ -54,7 +59,12 @@ const ExpandedInput = ({ suffix, prefix, ...props }: ExpandedInputProps) => {
|
||||
};
|
||||
|
||||
const SearchInput = (props: InputProps) => {
|
||||
return <ExpandedInput suffix={<Search />} {...props}></ExpandedInput>;
|
||||
return (
|
||||
<ExpandedInput
|
||||
prefix={<Search className="size-3.5" />}
|
||||
{...props}
|
||||
></ExpandedInput>
|
||||
);
|
||||
};
|
||||
|
||||
export { ExpandedInput, Input, SearchInput };
|
||||
|
@ -48,6 +48,7 @@ const PaginationLink = ({
|
||||
<a
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
className={cn(
|
||||
'size-8',
|
||||
buttonVariants({
|
||||
variant: isActive ? 'outline' : 'ghost',
|
||||
size,
|
||||
@ -70,7 +71,6 @@ const PaginationPrevious = ({
|
||||
{...props}
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
<span>Previous</span>
|
||||
</PaginationLink>
|
||||
);
|
||||
PaginationPrevious.displayName = 'PaginationPrevious';
|
||||
@ -85,7 +85,6 @@ const PaginationNext = ({
|
||||
className={cn('gap-1 pr-2.5', className)}
|
||||
{...props}
|
||||
>
|
||||
<span>Next</span>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</PaginationLink>
|
||||
);
|
||||
|
@ -98,7 +98,7 @@ export function RAGFlowPagination({
|
||||
}, [pageSize]);
|
||||
|
||||
return (
|
||||
<section className="flex items-center justify-end">
|
||||
<section className="flex items-center justify-end text-text-sub-title-invert ">
|
||||
<span className="mr-4">Total {total}</span>
|
||||
<Pagination className="w-auto mx-0 mr-4">
|
||||
<PaginationContent>
|
||||
@ -108,9 +108,14 @@ export function RAGFlowPagination({
|
||||
{pages.map((x) => (
|
||||
<PaginationItem
|
||||
key={x}
|
||||
className={cn({ ['bg-accent rounded-md']: currentPage === x })}
|
||||
className={cn({
|
||||
['bg-background-header-bar rounded-md text-text-title']:
|
||||
currentPage === x,
|
||||
})}
|
||||
>
|
||||
<PaginationLink onClick={handlePageChange(x)}>{x}</PaginationLink>
|
||||
<PaginationLink onClick={handlePageChange(x)} className="size-8">
|
||||
{x}
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
))}
|
||||
<PaginationItem>
|
||||
@ -126,6 +131,7 @@ export function RAGFlowPagination({
|
||||
options={sizeChangerOptions}
|
||||
value={currentPageSize}
|
||||
onChange={handlePageSizeChange}
|
||||
triggerClassName="bg-background-header-bar"
|
||||
></RAGFlowSelect>
|
||||
)}
|
||||
</section>
|
||||
|
@ -26,7 +26,7 @@ const SelectTrigger = React.forwardRef<
|
||||
<SelectPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-colors-background-inverse-weak px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
||||
'flex h-8 w-full items-center justify-between rounded-md border border-input bg-colors-background-inverse-weak px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -192,6 +192,7 @@ export type RAGFlowSelectProps = Partial<ControllerRenderProps> & {
|
||||
allowClear?: boolean;
|
||||
placeholder?: React.ReactNode;
|
||||
contentProps?: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>;
|
||||
triggerClassName?: string;
|
||||
} & SelectPrimitive.SelectProps;
|
||||
|
||||
/**
|
||||
@ -223,6 +224,7 @@ export const RAGFlowSelect = forwardRef<
|
||||
placeholder,
|
||||
contentProps = {},
|
||||
defaultValue,
|
||||
triggerClassName,
|
||||
},
|
||||
ref,
|
||||
) {
|
||||
@ -259,11 +261,11 @@ export const RAGFlowSelect = forwardRef<
|
||||
<Select onValueChange={handleChange} value={value} key={key}>
|
||||
<FormControlWidget>
|
||||
<SelectTrigger
|
||||
className="bg-colors-background-inverse-weak"
|
||||
value={value}
|
||||
onReset={handleReset}
|
||||
allowClear={allowClear}
|
||||
ref={ref}
|
||||
className={triggerClassName}
|
||||
>
|
||||
<SelectValue placeholder={placeholder} />
|
||||
</SelectTrigger>
|
||||
|
@ -117,7 +117,7 @@ export function Header() {
|
||||
}, [navigate]);
|
||||
|
||||
return (
|
||||
<section className="py-6 px-10 flex justify-between items-center ">
|
||||
<section className="p-5 pr-14 flex justify-between items-center ">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src={'/logo.svg'}
|
||||
|
@ -15,7 +15,6 @@ import * as React from 'react';
|
||||
|
||||
import { ChunkMethodDialog } from '@/components/chunk-method-dialog';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { TableSkeleton } from '@/components/table-skeleton';
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
import {
|
||||
Table,
|
||||
@ -48,7 +47,6 @@ export function DatasetTable({
|
||||
setPagination,
|
||||
rowSelection,
|
||||
setRowSelection,
|
||||
loading,
|
||||
}: DatasetTableProps) {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
@ -142,9 +140,7 @@ export function DatasetTable({
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody className="relative">
|
||||
{loading ? (
|
||||
<TableSkeleton columnsLength={columns.length}></TableSkeleton>
|
||||
) : table.getRowModel().rows?.length ? (
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
|
@ -71,7 +71,7 @@ export default function Dataset() {
|
||||
>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant={'tertiary'} size={'sm'}>
|
||||
<Button size={'sm'}>
|
||||
<Upload />
|
||||
{t('knowledgeDetails.addFile')}
|
||||
</Button>
|
||||
|
@ -85,7 +85,7 @@ export function DatasetCreatingDialog({ hideModal, onOk }: IModalProps<any>) {
|
||||
</DialogHeader>
|
||||
<InputForm onOk={onOk}></InputForm>
|
||||
<DialogFooter>
|
||||
<Button type="submit" variant={'tertiary'} size={'sm'} form={FormId}>
|
||||
<Button type="submit" form={FormId}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
@ -53,18 +53,19 @@ export default function Datasets() {
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="py-8 text-foreground">
|
||||
<section className="py-4 text-foreground">
|
||||
<ListFilterBar
|
||||
title="Datasets"
|
||||
title={t('header.knowledgeBase')}
|
||||
searchString={searchString}
|
||||
onSearchChange={handleInputChange}
|
||||
value={filterValue}
|
||||
filters={owners}
|
||||
onChange={handleFilterSubmit}
|
||||
className="px-8"
|
||||
icon={'data'}
|
||||
>
|
||||
<Button size={'sm'} onClick={showModal}>
|
||||
<Plus className="mr-2 size-2.5" />
|
||||
<Button onClick={showModal}>
|
||||
<Plus className=" size-2.5" />
|
||||
{t('knowledgeList.createKnowledgeBase')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
|
@ -46,6 +46,7 @@ module.exports = {
|
||||
'text-badge': 'var(--text-badge)',
|
||||
'text-title': 'var(--text-title)',
|
||||
'text-sub-title': 'var(--text-sub-title)',
|
||||
'text-sub-title-invert': 'var(--text-sub-title-invert)',
|
||||
'text-title-invert': 'var(--text-title-invert)',
|
||||
'background-header-bar': 'var(--background-header-bar)',
|
||||
'background-card': 'var(--background-card)',
|
||||
|
@ -79,6 +79,7 @@
|
||||
|
||||
--text-title: rgba(22, 22, 24, 1);
|
||||
--text-sub-title: rgba(151, 154, 171, 1);
|
||||
--text-sub-title-invert: rgba(91, 93, 106, 1);
|
||||
|
||||
--background-header-bar: rgba(11, 11, 12, 1);
|
||||
--text-title-invert: rgba(255, 255, 255, 1);
|
||||
@ -182,6 +183,7 @@
|
||||
|
||||
--text-title: rgba(255, 255, 255, 1);
|
||||
--text-sub-title: rgba(91, 93, 106, 1);
|
||||
--text-sub-title-invert: rgba(151, 154, 171, 1);
|
||||
--background-header-bar: rgba(11, 11, 12, 1);
|
||||
|
||||
--text-title-invert: rgba(22, 22, 24, 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user