mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-17 11:09:06 +08:00
### What problem does this PR solve? Feat: Filter document by running status and file type. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -281,7 +281,10 @@ export function ChunkMethodDialog({
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<DatasetConfigurationContainer show={showOne || showMaxTokenNumber}>
|
||||
<DatasetConfigurationContainer
|
||||
show={showOne || showMaxTokenNumber}
|
||||
className="space-y-3"
|
||||
>
|
||||
{showOne && <LayoutRecognizeFormField></LayoutRecognizeFormField>}
|
||||
{showMaxTokenNumber && (
|
||||
<>
|
||||
@ -298,6 +301,7 @@ export function ChunkMethodDialog({
|
||||
</DatasetConfigurationContainer>
|
||||
<DatasetConfigurationContainer
|
||||
show={showAutoKeywords(selectedTag) || showExcelToHtml}
|
||||
className="space-y-3"
|
||||
>
|
||||
{showAutoKeywords(selectedTag) && (
|
||||
<>
|
||||
|
||||
163
web/src/components/list-filter-bar/filter-popover.tsx
Normal file
163
web/src/components/list-filter-bar/filter-popover.tsx
Normal file
@ -0,0 +1,163 @@
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/components/ui/popover';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { PropsWithChildren, useCallback, useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { ZodArray, ZodString, z } from 'zod';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { FilterChange, FilterCollection, FilterValue } from './interface';
|
||||
|
||||
export type CheckboxFormMultipleProps = {
|
||||
filters?: FilterCollection[];
|
||||
value?: FilterValue;
|
||||
onChange?: FilterChange;
|
||||
};
|
||||
|
||||
function CheckboxFormMultiple({
|
||||
filters = [],
|
||||
value,
|
||||
onChange,
|
||||
}: CheckboxFormMultipleProps) {
|
||||
const fieldsDict = filters?.reduce<Record<string, Array<any>>>((pre, cur) => {
|
||||
pre[cur.field] = [];
|
||||
return pre;
|
||||
}, {});
|
||||
|
||||
const FormSchema = z.object(
|
||||
filters.reduce<Record<string, ZodArray<ZodString, 'many'>>>((pre, cur) => {
|
||||
pre[cur.field] = z.array(z.string());
|
||||
|
||||
// .refine((value) => value.some((item) => item), {
|
||||
// message: 'You have to select at least one item.',
|
||||
// });
|
||||
return pre;
|
||||
}, {}),
|
||||
);
|
||||
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: fieldsDict,
|
||||
});
|
||||
|
||||
function onSubmit(data: z.infer<typeof FormSchema>) {
|
||||
console.log('🚀 ~ onSubmit ~ data:', data);
|
||||
// setOwnerIds(data.items);
|
||||
onChange?.(data);
|
||||
}
|
||||
|
||||
const onReset = useCallback(() => {
|
||||
onChange?.(fieldsDict);
|
||||
}, [fieldsDict, onChange]);
|
||||
|
||||
useEffect(() => {
|
||||
form.reset(value);
|
||||
}, [form, value]);
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-8"
|
||||
onReset={() => form.reset()}
|
||||
>
|
||||
{filters.map((x) => (
|
||||
<FormField
|
||||
key={x.field}
|
||||
control={form.control}
|
||||
name={x.field}
|
||||
render={() => (
|
||||
<FormItem>
|
||||
<div className="mb-4">
|
||||
<FormLabel className="text-base">{x.label}</FormLabel>
|
||||
</div>
|
||||
{x.list.map((item) => (
|
||||
<FormField
|
||||
key={item.id}
|
||||
control={form.control}
|
||||
name={x.field}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<FormItem
|
||||
key={item.id}
|
||||
className="flex flex-row space-x-3 space-y-0 items-center"
|
||||
>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={field.value?.includes(item.id)}
|
||||
onCheckedChange={(checked) => {
|
||||
return checked
|
||||
? field.onChange([...field.value, item.id])
|
||||
: field.onChange(
|
||||
field.value?.filter(
|
||||
(value) => value !== item.id,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormLabel className="text-lg">
|
||||
{item.label}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<span className=" text-sm">{item.count}</span>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
<div className="flex justify-between">
|
||||
<Button
|
||||
type="button"
|
||||
variant={'outline'}
|
||||
size={'sm'}
|
||||
onClick={onReset}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
<Button type="submit" size={'sm'}>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
export function FilterPopover({
|
||||
children,
|
||||
value,
|
||||
onChange,
|
||||
filters,
|
||||
}: PropsWithChildren & CheckboxFormMultipleProps) {
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>{children}</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<CheckboxFormMultiple
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
filters={filters}
|
||||
></CheckboxFormMultiple>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@ -1,19 +1,18 @@
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import React, {
|
||||
ChangeEventHandler,
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { Button, ButtonProps } from './ui/button';
|
||||
import { SearchInput } from './ui/input';
|
||||
import { Button, ButtonProps } from '../ui/button';
|
||||
import { SearchInput } from '../ui/input';
|
||||
import { CheckboxFormMultipleProps, FilterPopover } from './filter-popover';
|
||||
|
||||
interface IProps {
|
||||
title?: string;
|
||||
FilterPopover?: FunctionComponent<any>;
|
||||
searchString?: string;
|
||||
onSearchChange?: ChangeEventHandler<HTMLInputElement>;
|
||||
count?: number;
|
||||
showFilter?: boolean;
|
||||
leftPanel?: ReactNode;
|
||||
}
|
||||
@ -32,25 +31,31 @@ const FilterButton = React.forwardRef<
|
||||
export default function ListFilterBar({
|
||||
title,
|
||||
children,
|
||||
FilterPopover,
|
||||
searchString,
|
||||
onSearchChange,
|
||||
count,
|
||||
showFilter = true,
|
||||
leftPanel,
|
||||
}: PropsWithChildren<IProps>) {
|
||||
value,
|
||||
onChange,
|
||||
filters,
|
||||
}: PropsWithChildren<IProps & CheckboxFormMultipleProps>) {
|
||||
const filterCount = useMemo(() => {
|
||||
return typeof value === 'object' && value !== null
|
||||
? Object.values(value).reduce((pre, cur) => {
|
||||
return pre + cur.length;
|
||||
}, 0)
|
||||
: 0;
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className="flex justify-between mb-6 items-center">
|
||||
<span className="text-3xl font-bold ">{leftPanel || title}</span>
|
||||
<div className="flex gap-4 items-center">
|
||||
{showFilter &&
|
||||
(FilterPopover ? (
|
||||
<FilterPopover>
|
||||
<FilterButton count={count}></FilterButton>
|
||||
</FilterPopover>
|
||||
) : (
|
||||
<FilterButton></FilterButton>
|
||||
))}
|
||||
{showFilter && (
|
||||
<FilterPopover value={value} onChange={onChange} filters={filters}>
|
||||
<FilterButton count={filterCount}></FilterButton>
|
||||
</FilterPopover>
|
||||
)}
|
||||
|
||||
<SearchInput
|
||||
value={searchString}
|
||||
15
web/src/components/list-filter-bar/interface.ts
Normal file
15
web/src/components/list-filter-bar/interface.ts
Normal file
@ -0,0 +1,15 @@
|
||||
export type FilterType = {
|
||||
id: string;
|
||||
label: string;
|
||||
count: number;
|
||||
};
|
||||
|
||||
export type FilterCollection = {
|
||||
field: string;
|
||||
label: string;
|
||||
list: FilterType[];
|
||||
};
|
||||
|
||||
export type FilterValue = Record<string, Array<string>>;
|
||||
|
||||
export type FilterChange = (value: FilterValue) => void;
|
||||
@ -0,0 +1,12 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { FilterChange, FilterValue } from './interface';
|
||||
|
||||
export function useHandleFilterSubmit() {
|
||||
const [filterValue, setFilterValue] = useState<FilterValue>({});
|
||||
|
||||
const handleFilterSubmit: FilterChange = useCallback((value) => {
|
||||
setFilterValue(value);
|
||||
}, []);
|
||||
|
||||
return { filterValue, setFilterValue, handleFilterSubmit };
|
||||
}
|
||||
@ -76,7 +76,7 @@ const RaptorFormFields = () => {
|
||||
)}
|
||||
/>
|
||||
{useRaptor && (
|
||||
<>
|
||||
<div className="space-y-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={'parser_config.raptor.prompt'}
|
||||
@ -137,7 +137,7 @@ const RaptorFormFields = () => {
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user