mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-19 11:45:10 +08:00
Fix:Some bugs (#12648)
### What problem does this PR solve? Fix: Modified and optimized the metadata condition card component. Fix: Use startOfDay and endOfDay to ensure the date range includes a full day. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -1,4 +1,3 @@
|
|||||||
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -18,13 +17,16 @@ import { Separator } from '@/components/ui/separator';
|
|||||||
import { SwitchLogicOperator, SwitchOperatorOptions } from '@/constants/agent';
|
import { SwitchLogicOperator, SwitchOperatorOptions } from '@/constants/agent';
|
||||||
import { useBuildSwitchOperatorOptions } from '@/hooks/logic-hooks/use-build-operator-options';
|
import { useBuildSwitchOperatorOptions } from '@/hooks/logic-hooks/use-build-operator-options';
|
||||||
import { useFetchKnowledgeMetadata } from '@/hooks/use-knowledge-request';
|
import { useFetchKnowledgeMetadata } from '@/hooks/use-knowledge-request';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
import { PromptEditor } from '@/pages/agent/form/components/prompt-editor';
|
import { PromptEditor } from '@/pages/agent/form/components/prompt-editor';
|
||||||
import { Plus, X } from 'lucide-react';
|
import { Plus, X } from 'lucide-react';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useFieldArray, useFormContext, useWatch } from 'react-hook-form';
|
import { useFieldArray, useFormContext, useWatch } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { LogicalOperator } from '../logical-operator';
|
import { LogicalOperator } from '../logical-operator';
|
||||||
|
import { Card, CardContent } from '../ui/card';
|
||||||
import { InputSelect } from '../ui/input-select';
|
import { InputSelect } from '../ui/input-select';
|
||||||
|
import { RAGFlowSelect } from '../ui/select';
|
||||||
|
|
||||||
export function MetadataFilterConditions({
|
export function MetadataFilterConditions({
|
||||||
kbIds,
|
kbIds,
|
||||||
@ -62,13 +64,14 @@ export function MetadataFilterConditions({
|
|||||||
[append, fields.length, form, logic],
|
[append, fields.length, form, logic],
|
||||||
);
|
);
|
||||||
|
|
||||||
const RenderField = ({
|
function ConditionCards({
|
||||||
fieldName,
|
fieldName,
|
||||||
index,
|
index,
|
||||||
}: {
|
}: {
|
||||||
fieldName: string;
|
fieldName: string;
|
||||||
index: number;
|
index: number;
|
||||||
}) => {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
const key = useWatch({ name: fieldName });
|
const key = useWatch({ name: fieldName });
|
||||||
const valueOptions = useMemo(() => {
|
const valueOptions = useMemo(() => {
|
||||||
@ -83,14 +86,18 @@ export function MetadataFilterConditions({
|
|||||||
}, [key]);
|
}, [key]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex gap-2">
|
<div className="flex gap-1">
|
||||||
<div className="flex-1 flex flex-col gap-2 min-w-0">
|
<Card
|
||||||
<div className="flex items-center gap-1">
|
className={cn(
|
||||||
|
'relative bg-transparent border-input-border border flex-1 min-w-0',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<section className="p-2 bg-bg-card flex justify-between items-center">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={fieldName}
|
name={fieldName}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="flex-1 overflow-hidden min-w-0">
|
<FormItem className="flex-1 min-w-0">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
{...field}
|
{...field}
|
||||||
@ -101,55 +108,61 @@ export function MetadataFilterConditions({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Separator className="w-1 text-text-secondary" />
|
<div className="flex items-center">
|
||||||
|
<Separator orientation="vertical" className="h-2.5" />
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`${name}.${index}.op`}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<RAGFlowSelect
|
||||||
|
{...field}
|
||||||
|
options={switchOperatorOptions}
|
||||||
|
onlyShowSelectedIcon
|
||||||
|
triggerClassName="w-30 bg-transparent border-none"
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<CardContent className="p-4 ">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={`${name}.${index}.op`}
|
name={`${name}.${index}.value`}
|
||||||
render={({ field }) => (
|
render={({ field: valueField }) => (
|
||||||
<FormItem className="flex-1 overflow-hidden min-w-0">
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SelectWithSearch
|
{canReference ? (
|
||||||
{...field}
|
<PromptEditor
|
||||||
options={switchOperatorOptions}
|
{...valueField}
|
||||||
></SelectWithSearch>
|
multiLine={false}
|
||||||
|
showToolbar={false}
|
||||||
|
></PromptEditor>
|
||||||
|
) : (
|
||||||
|
<InputSelect
|
||||||
|
placeholder={t('common.pleaseInput')}
|
||||||
|
{...valueField}
|
||||||
|
options={valueOptions}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</CardContent>
|
||||||
<FormField
|
</Card>
|
||||||
control={form.control}
|
|
||||||
name={`${name}.${index}.value`}
|
|
||||||
render={({ field: valueField }) => (
|
|
||||||
<FormItem className="flex-1 overflow-hidden min-w-0">
|
|
||||||
<FormControl>
|
|
||||||
{canReference ? (
|
|
||||||
<PromptEditor
|
|
||||||
{...valueField}
|
|
||||||
multiLine={false}
|
|
||||||
showToolbar={false}
|
|
||||||
></PromptEditor>
|
|
||||||
) : (
|
|
||||||
<InputSelect
|
|
||||||
placeholder={t('common.pleaseInput')}
|
|
||||||
{...valueField}
|
|
||||||
options={valueOptions}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button variant={'ghost'} onClick={() => remove(index)}>
|
<Button variant={'ghost'} onClick={() => remove(index)}>
|
||||||
<X className="text-text-sub-title-invert " />
|
<X />
|
||||||
</Button>
|
</Button>
|
||||||
</section>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
return (
|
return (
|
||||||
<section className="flex flex-col gap-2">
|
<section className="flex flex-col gap-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@ -177,7 +190,11 @@ export function MetadataFilterConditions({
|
|||||||
{fields.map((field, index) => {
|
{fields.map((field, index) => {
|
||||||
const typeField = `${name}.${index}.key`;
|
const typeField = `${name}.${index}.key`;
|
||||||
return (
|
return (
|
||||||
<RenderField key={field.id} fieldName={typeField} index={index} />
|
<ConditionCards
|
||||||
|
key={field.id}
|
||||||
|
fieldName={typeField}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,15 +1,3 @@
|
|||||||
import {
|
|
||||||
endOfMonth,
|
|
||||||
endOfYear,
|
|
||||||
format,
|
|
||||||
startOfMonth,
|
|
||||||
startOfYear,
|
|
||||||
subDays,
|
|
||||||
subMonths,
|
|
||||||
subYears,
|
|
||||||
} from 'date-fns';
|
|
||||||
import { useEffect, useId, useState } from 'react';
|
|
||||||
|
|
||||||
import { Calendar, DateRange } from '@/components/originui/calendar';
|
import { Calendar, DateRange } from '@/components/originui/calendar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
@ -18,7 +6,20 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from '@/components/ui/popover';
|
} from '@/components/ui/popover';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import {
|
||||||
|
endOfDay,
|
||||||
|
endOfMonth,
|
||||||
|
endOfYear,
|
||||||
|
format,
|
||||||
|
startOfDay,
|
||||||
|
startOfMonth,
|
||||||
|
startOfYear,
|
||||||
|
subDays,
|
||||||
|
subMonths,
|
||||||
|
subYears,
|
||||||
|
} from 'date-fns';
|
||||||
import { CalendarIcon } from 'lucide-react';
|
import { CalendarIcon } from 'lucide-react';
|
||||||
|
import { useEffect, useId, useState } from 'react';
|
||||||
|
|
||||||
const CalendarComp = ({
|
const CalendarComp = ({
|
||||||
selectDateRange,
|
selectDateRange,
|
||||||
@ -27,20 +28,20 @@ const CalendarComp = ({
|
|||||||
}: ITimeRangePickerProps) => {
|
}: ITimeRangePickerProps) => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const yesterday = {
|
const yesterday = {
|
||||||
from: subDays(today, 1),
|
from: startOfDay(subDays(today, 1)),
|
||||||
to: subDays(today, 1),
|
to: endOfDay(subDays(today, 1)),
|
||||||
};
|
};
|
||||||
const last7Days = {
|
const last7Days = {
|
||||||
from: subDays(today, 6),
|
from: startOfDay(subDays(today, 6)),
|
||||||
to: today,
|
to: endOfDay(today),
|
||||||
};
|
};
|
||||||
const last30Days = {
|
const last30Days = {
|
||||||
from: subDays(today, 29),
|
from: startOfDay(subDays(today, 29)),
|
||||||
to: today,
|
to: endOfDay(today),
|
||||||
};
|
};
|
||||||
const monthToDate = {
|
const monthToDate = {
|
||||||
from: startOfMonth(today),
|
from: startOfMonth(today),
|
||||||
to: today,
|
to: endOfDay(today),
|
||||||
};
|
};
|
||||||
const lastMonth = {
|
const lastMonth = {
|
||||||
from: startOfMonth(subMonths(today, 1)),
|
from: startOfMonth(subMonths(today, 1)),
|
||||||
@ -48,7 +49,7 @@ const CalendarComp = ({
|
|||||||
};
|
};
|
||||||
const yearToDate = {
|
const yearToDate = {
|
||||||
from: startOfYear(today),
|
from: startOfYear(today),
|
||||||
to: today,
|
to: endOfDay(today),
|
||||||
};
|
};
|
||||||
const lastYear = {
|
const lastYear = {
|
||||||
from: startOfYear(subYears(today, 1)),
|
from: startOfYear(subYears(today, 1)),
|
||||||
@ -65,9 +66,7 @@ const CalendarComp = ({
|
|||||||
];
|
];
|
||||||
const [month, setMonth] = useState(today);
|
const [month, setMonth] = useState(today);
|
||||||
const [date, setDate] = useState<DateRange>(selectDateRange || last7Days);
|
const [date, setDate] = useState<DateRange>(selectDateRange || last7Days);
|
||||||
useEffect(() => {
|
|
||||||
onSelect?.(date);
|
|
||||||
}, [date, onSelect]);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="rounded-md border">
|
<div className="rounded-md border">
|
||||||
@ -80,11 +79,13 @@ const CalendarComp = ({
|
|||||||
size="sm"
|
size="sm"
|
||||||
className="w-full justify-start"
|
className="w-full justify-start"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDate({
|
const newDateRange = {
|
||||||
from: today,
|
from: startOfDay(today),
|
||||||
to: today,
|
to: endOfDay(today),
|
||||||
});
|
};
|
||||||
|
setDate(newDateRange);
|
||||||
setMonth(today);
|
setMonth(today);
|
||||||
|
onSelect?.(newDateRange);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Today
|
Today
|
||||||
@ -98,6 +99,7 @@ const CalendarComp = ({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDate(dateRange.value);
|
setDate(dateRange.value);
|
||||||
setMonth(dateRange.value.to);
|
setMonth(dateRange.value.to);
|
||||||
|
onSelect?.(dateRange.value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{dateRange.key}
|
{dateRange.key}
|
||||||
@ -111,7 +113,13 @@ const CalendarComp = ({
|
|||||||
selected={date}
|
selected={date}
|
||||||
onSelect={(newDate) => {
|
onSelect={(newDate) => {
|
||||||
if (newDate) {
|
if (newDate) {
|
||||||
setDate(newDate as DateRange);
|
const dateRange = newDate as DateRange;
|
||||||
|
const newDateRange = {
|
||||||
|
from: startOfDay(dateRange.from),
|
||||||
|
to: dateRange.to ? endOfDay(dateRange.to) : undefined,
|
||||||
|
};
|
||||||
|
setDate(newDateRange);
|
||||||
|
onSelect?.(newDateRange);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
month={month}
|
month={month}
|
||||||
@ -130,7 +138,7 @@ const CalendarComp = ({
|
|||||||
|
|
||||||
export type ITimeRangePickerProps = {
|
export type ITimeRangePickerProps = {
|
||||||
onSelect: (e: DateRange) => void;
|
onSelect: (e: DateRange) => void;
|
||||||
selectDateRange: DateRange;
|
selectDateRange?: DateRange;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
const TimeRangePicker = ({
|
const TimeRangePicker = ({
|
||||||
@ -140,11 +148,40 @@ const TimeRangePicker = ({
|
|||||||
}: ITimeRangePickerProps) => {
|
}: ITimeRangePickerProps) => {
|
||||||
const id = useId();
|
const id = useId();
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
|
|
||||||
|
// Initialize without timezone conversion
|
||||||
const [date, setDate] = useState<DateRange | undefined>(
|
const [date, setDate] = useState<DateRange | undefined>(
|
||||||
selectDateRange || { from: today, to: today },
|
selectDateRange
|
||||||
|
? {
|
||||||
|
from: startOfDay(selectDateRange.from),
|
||||||
|
to: selectDateRange.to ? endOfDay(selectDateRange.to) : undefined,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
from: startOfDay(today),
|
||||||
|
to: endOfDay(today),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDate(selectDateRange);
|
if (!selectDateRange || !selectDateRange.from) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fromDate = new Date(selectDateRange.from);
|
||||||
|
const toDate = selectDateRange.to
|
||||||
|
? new Date(selectDateRange.to)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (isNaN(fromDate.getTime())) return;
|
||||||
|
|
||||||
|
if (toDate && isNaN(toDate.getTime())) return;
|
||||||
|
|
||||||
|
setDate({
|
||||||
|
from: startOfDay(fromDate),
|
||||||
|
to: toDate ? endOfDay(toDate) : undefined,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating date range from props:', error);
|
||||||
|
}
|
||||||
}, [selectDateRange]);
|
}, [selectDateRange]);
|
||||||
const onChange = (e: DateRange | undefined) => {
|
const onChange = (e: DateRange | undefined) => {
|
||||||
if (!e) return;
|
if (!e) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user