'use client' import type { Dayjs } from 'dayjs' import type { TriggerProps } from '@/app/components/base/date-and-time-picker/types' import type { I18nKeysWithPrefix } from '@/types/i18n' import { cn } from '@langgenius/dify-ui/cn' import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger, } from '@langgenius/dify-ui/select' import dayjs from 'dayjs' import { noop } from 'es-toolkit/function' import { useState } from 'react' import { useTranslation } from 'react-i18next' import DatePicker from '@/app/components/base/date-and-time-picker/date-picker' import { useLocale } from '@/context/i18n' import { formatToLocalTime } from '@/utils/format' export type AgentMonitoringPeriod = { name: string query: { start: string end: string } } type TimeRangeKey = 'today' | 'last7days' | 'last30days' type TimeRangeOption = { value: TimeRangeKey days: number nameKey: I18nKeysWithPrefix<'agentV2', 'agentDetail.monitoring.timeRanges.'> } type AgentMonitoringTimeRangePickerProps = { value: AgentMonitoringPeriod onChange: (period: AgentMonitoringPeriod) => void } const today = dayjs() const queryDateFormat = 'YYYY-MM-DD HH:mm' const timeRangeOptions: TimeRangeOption[] = [ { value: 'today', days: 0, nameKey: 'agentDetail.monitoring.timeRanges.today' }, { value: 'last7days', days: 7, nameKey: 'agentDetail.monitoring.timeRanges.last7days' }, { value: 'last30days', days: 30, nameKey: 'agentDetail.monitoring.timeRanges.last30days' }, ] const getRangePeriod = (option: TimeRangeOption): AgentMonitoringPeriod => { const end = today.endOf('day') const start = option.days === 0 ? today.startOf('day') : today.subtract(option.days, 'day').startOf('day') return { name: option.value, query: { start: start.format(queryDateFormat), end: end.format(queryDateFormat), }, } } function DateRangePart({ start, end, onStartChange, onEndChange, }: { start: Dayjs end: Dayjs onStartChange: (date?: Dayjs) => void onEndChange: (date?: Dayjs) => void }) { const locale = useLocale() const renderDate = ({ value, handleClickTrigger, isOpen }: TriggerProps) => (
{ if (event.key !== 'Enter' && event.key !== ' ') return event.preventDefault() event.currentTarget.click() }} > {value ? formatToLocalTime(value, locale, 'MMM D') : ''}
) const availableStartDate = end.subtract(30, 'day') const isStartDateDisabled = (date: Dayjs) => { if (date.isAfter(today, 'date')) return true return !( (date.isAfter(availableStartDate, 'date') || date.isSame(availableStartDate, 'date')) && (date.isBefore(end, 'date') || date.isSame(end, 'date')) ) } const availableEndDate = start.add(30, 'day') const isEndDateDisabled = (date: Dayjs) => { if (date.isAfter(today, 'date')) return true return !( (date.isAfter(start, 'date') || date.isSame(start, 'date')) && (date.isBefore(availableEndDate, 'date') || date.isSame(availableEndDate, 'date')) ) } return (
-
) } export function AgentMonitoringTimeRangePicker({ value, onChange, }: AgentMonitoringTimeRangePickerProps) { const { t } = useTranslation('agentV2') const locale = useLocale() const [selectedRange, setSelectedRange] = useState('today') const [start, setStart] = useState(() => dayjs(value.query.start)) const [end, setEnd] = useState(() => dayjs(value.query.end)) const selectedOption = timeRangeOptions.find((option) => option.value === selectedRange) const handleRangeChange = (nextValue: TimeRangeKey | null) => { if (!nextValue) return const option = timeRangeOptions.find((item) => item.value === nextValue) if (!option) return const nextPeriod = getRangePeriod(option) setSelectedRange(option.value) setStart(dayjs(nextPeriod.query.start)) setEnd(dayjs(nextPeriod.query.end)) onChange({ ...nextPeriod, name: t(($) => $[option.nameKey]), }) } const handleDateChange = (type: 'start' | 'end') => (date?: Dayjs) => { if (!date) return if (type === 'start' && date.isSame(start)) return if (type === 'end' && date.isSame(end)) return const nextStart = type === 'start' ? date : start const nextEnd = type === 'end' ? date : end const nextName = `${formatToLocalTime(nextStart, locale, 'MMM D')} - ${formatToLocalTime(nextEnd, locale, 'MMM D')}` setSelectedRange('custom') setStart(nextStart) setEnd(nextEnd) onChange({ name: nextName, query: { start: nextStart.format(queryDateFormat), end: nextEnd.format(queryDateFormat), }, }) } return (
value={selectedRange === 'custom' ? null : selectedRange} onValueChange={handleRangeChange} > $['agentDetail.monitoring.timeRangeLabel'])} className="w-fit shrink-0 cursor-pointer gap-1.5 pr-2 pl-3" > {selectedRange === 'custom' ? t(($) => $['agentDetail.monitoring.timeRanges.custom']) : selectedOption ? t(($) => $[selectedOption.nameKey]) : value.name} {timeRangeOptions.map((option) => ( {t(($) => $[option.nameKey])} ))}
) }