diff --git a/web/src/components/ui/calendar.tsx b/web/src/components/ui/calendar.tsx new file mode 100644 index 0000000000..fe8fabf815 --- /dev/null +++ b/web/src/components/ui/calendar.tsx @@ -0,0 +1,233 @@ +'use client'; + +import * as React from 'react'; +import { + DayPicker, + getDefaultClassNames, + type DayButton, + type Locale, +} from 'react-day-picker'; + +import { Button, buttonVariants } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { + ChevronDownIcon, + ChevronLeftIcon, + ChevronRightIcon, +} from 'lucide-react'; + +function Calendar({ + className, + classNames, + showOutsideDays = true, + captionLayout = 'label', + buttonVariant = 'ghost', + locale, + formatters, + components, + ...props +}: React.ComponentProps & { + buttonVariant?: React.ComponentProps['variant']; +}) { + const defaultClassNames = getDefaultClassNames(); + + return ( + + date.toLocaleString(locale?.code, { month: 'short' }), + ...formatters, + }} + classNames={{ + root: cn('w-fit', defaultClassNames.root), + months: cn( + 'relative flex flex-col gap-4 md:flex-row', + defaultClassNames.months, + ), + month: cn('flex w-full flex-col gap-4', defaultClassNames.month), + nav: cn( + 'absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', + defaultClassNames.nav, + ), + button_previous: cn( + buttonVariants({ variant: buttonVariant }), + 'w-[var(--cell-size)] h-[var(--cell-size)] p-0 select-none aria-disabled:opacity-50', + defaultClassNames.button_previous, + ), + button_next: cn( + buttonVariants({ variant: buttonVariant }), + 'w-[var(--cell-size)] h-[var(--cell-size)] p-0 select-none aria-disabled:opacity-50', + defaultClassNames.button_next, + ), + month_caption: cn( + 'flex h-[var(--cell-size)] w-full items-center justify-center px-[var(--cell-size)]', + defaultClassNames.month_caption, + ), + dropdowns: cn( + 'flex h-[var(--cell-size)] w-full items-center justify-center gap-1.5 text-sm font-medium', + defaultClassNames.dropdowns, + ), + dropdown_root: cn( + 'cn-calendar-dropdown-root relative rounded-[var(--cell-radius)]', + defaultClassNames.dropdown_root, + ), + dropdown: cn( + 'absolute inset-0 bg-popover opacity-0', + defaultClassNames.dropdown, + ), + caption_label: cn( + 'font-medium select-none', + captionLayout === 'label' + ? 'text-sm' + : 'cn-calendar-caption-label flex items-center gap-1 rounded-[var(--cell-radius)] text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground', + defaultClassNames.caption_label, + ), + table: 'w-full border-collapse', + weekdays: cn('flex', defaultClassNames.weekdays), + weekday: cn( + 'flex-1 rounded-[var(--cell-radius)] text-[0.8rem] font-normal text-muted-foreground select-none', + defaultClassNames.weekday, + ), + week: cn('mt-2 flex w-full', defaultClassNames.week), + week_number_header: cn( + 'w-[var(--cell-size)] select-none', + defaultClassNames.week_number_header, + ), + week_number: cn( + 'text-[0.8rem] text-muted-foreground select-none', + defaultClassNames.week_number, + ), + day: cn( + 'group/day relative aspect-square h-full w-full rounded-[var(--cell-radius)] p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-[var(--cell-radius)]', + props.showWeekNumber + ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-[var(--cell-radius)]' + : '[&:first-child[data-selected=true]_button]:rounded-l-[var(--cell-radius)]', + defaultClassNames.day, + ), + range_start: cn( + 'relative isolate z-0 rounded-l-[var(--cell-radius)] bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted', + defaultClassNames.range_start, + ), + range_middle: cn('rounded-none', defaultClassNames.range_middle), + range_end: cn( + 'relative isolate z-0 rounded-r-[var(--cell-radius)] bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted', + defaultClassNames.range_end, + ), + today: cn( + 'rounded-[var(--cell-radius)] bg-muted text-foreground data-[selected=true]:rounded-none', + defaultClassNames.today, + ), + outside: cn( + 'text-muted-foreground aria-selected:text-muted-foreground', + defaultClassNames.outside, + ), + disabled: cn( + 'text-muted-foreground opacity-50', + defaultClassNames.disabled, + ), + hidden: cn('invisible', defaultClassNames.hidden), + ...classNames, + }} + components={{ + Root: ({ className, rootRef, ...props }) => { + return ( +
+ ); + }, + Chevron: ({ className, orientation, ...props }) => { + if (orientation === 'left') { + return ( + + ); + } + + if (orientation === 'right') { + return ( + + ); + } + + return ( + + ); + }, + DayButton: ({ ...props }) => ( + + ), + WeekNumber: ({ children, ...props }) => { + return ( + +
+ {children} +
+ + ); + }, + ...components, + }} + {...props} + /> + ); +} + +function CalendarDayButton({ + className, + day, + modifiers, + locale, + ...props +}: React.ComponentProps & { locale?: Partial }) { + const defaultClassNames = getDefaultClassNames(); + + const ref = React.useRef(null); + React.useEffect(() => { + if (modifiers.focused) ref.current?.focus(); + }, [modifiers.focused]); + + return ( + + + + + + + ); +} diff --git a/web/src/pages/agents/agent-log-page.tsx b/web/src/pages/agents/agent-log-page.tsx index ca84aeacc4..14f7f1a538 100644 --- a/web/src/pages/agents/agent-log-page.tsx +++ b/web/src/pages/agents/agent-log-page.tsx @@ -1,4 +1,3 @@ -import TimeRangePicker from '@/components/originui/time-range-picker'; import { PageHeader } from '@/components/page-header'; import { Breadcrumb, @@ -11,6 +10,7 @@ import { import { Button } from '@/components/ui/button'; import { SearchInput } from '@/components/ui/input'; import { RAGFlowPagination } from '@/components/ui/ragflow-pagination'; +import { DatePickerWithRange } from '@/components/ui/range-picker'; import { Spin } from '@/components/ui/spin'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { useFetchAgentLog } from '@/hooks/use-agent-request'; @@ -19,6 +19,7 @@ import { IAgentLogResponse, } from '@/interfaces/database/agent'; import { IReferenceObject } from '@/interfaces/database/chat'; +import { formatDate } from '@/utils/date'; import { useQueryClient } from '@tanstack/react-query'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -46,6 +47,7 @@ const getEndOfToday = (): Date => { today.setHours(23, 59, 59, 999); return today; }; + const AgentLogPage: React.FC = () => { const { t } = useTranslation(); const { navigateToAgents, navigateToAgent } = useNavigatePage(); @@ -106,12 +108,18 @@ const AgentLogPage: React.FC = () => { dataIndex: 'update_date', key: 'update_date', sortable: true, + render(text: string) { + return formatDate(text); + }, }, { title: t('flow.createDate'), dataIndex: 'create_date', key: 'create_date', sortable: true, + render(text: string) { + return formatDate(text); + }, }, { title: t('flow.version.version'), @@ -128,11 +136,8 @@ const AgentLogPage: React.FC = () => { to: searchParams.to_date, }); const [keywords, setKeywords] = useState(searchParams.keywords); - const handleDateRangeChange = ({ - from: startDate, - to: endDate, - }: DateRange) => { - setCurrentDate({ from: startDate, to: endDate }); + const handleDateRangeChange = (dateRange: DateRange) => { + setCurrentDate({ from: dateRange.from, to: dateRange.to }); }; const [pagination, setPagination] = useState<{ @@ -271,10 +276,14 @@ const AgentLogPage: React.FC = () => {
Latest Date - + + range.from && + handleDateRangeChange({ from: range.from, to: range.to }) + } + >
- - ); - } - return ( -
-
- {t('chat.chatSetting')} - - -
+ disabled={!hasSingleChatBox} + variant={'ghost'} + size="icon-sm" + data-testid="chat-settings" + > + + + + )} -
- - -
- - - - - -
-
+
+
+ {t('chat.chatSetting')} -
- - -
- - -
+ /> + + + +
+ + +
+ + + + + +
+
+ +
+ + +
+
+ +
+ ); }