Feat/logs date refactor (#37243)

* Integrate LogsDatePicker into DataTable timerange filter

Replaces DatePickerWithRange with LogsDatePicker in DataTableFilterTimerange, enabling use of helper presets and improved date range selection. Adds support for passing button props and synchronizes filter value logic with the new date picker component.

* Add upgrade prompt for log date range limit

Introduces an upgrade prompt when users select a log date range that exceeds their current plan's retention limits. Uses `maybeShowUpgradePrompt` and `useCurrentOrgPlan` to determine when to show the prompt, improving user awareness of plan restrictions.
This commit is contained in:
Jonathan Summers-Muir authored and GitHub committed 2025-07-17 20:07:00 +08:00
1 parent 78ec1a4c91
commit ef2fbb88c4
2 files changed
+103 -12

No files matched your search

@@ -11,6 +11,7 @@ import TimeSplitInput from 'components/ui/DatePicker/TimeSplitInput'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import {
Button,
ButtonProps,
PopoverContent_Shadcn_,
PopoverTrigger_Shadcn_,
Popover_Shadcn_,
@@ -31,9 +32,17 @@ interface Props {
value: DatePickerValue
helpers: DatetimeHelper[]
onSubmit: (value: DatePickerValue) => void
buttonTriggerProps?: ButtonProps
popoverContentProps?: typeof PopoverContent_Shadcn_
}
export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<Props>) => {
export const LogsDatePicker = ({
onSubmit,
helpers,
value,
buttonTriggerProps,
popoverContentProps,
}: PropsWithChildren<Props>) => {
const [open, setOpen] = useState(false)
// Reset the state when the popover closes
@@ -230,7 +239,7 @@ export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<P
return (
<Popover_Shadcn_ open={open} onOpenChange={setOpen}>
<PopoverTrigger_Shadcn_ asChild>
<Button type="default" icon={<Clock size={12} />}>
<Button type="default" icon={<Clock size={12} />} {...buttonTriggerProps}>
{value.isHelper
? value.text
: `${dayjs(value.from).format('DD MMM, HH:mm')} - ${dayjs(value.to || new Date()).format('DD MMM, HH:mm')}`}
@@ -239,8 +248,9 @@ export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<P
<PopoverContent_Shadcn_
className="flex w-full p-0"
side="bottom"
align="center"
align="end"
portal={true}
{...popoverContentProps}
>
<RadioGroup
onValueChange={handleHelperChange}
@@ -1,9 +1,16 @@
import { useMemo } from 'react'
import { useMemo, useState } from 'react'
import type { DateRange } from 'react-day-picker'
import {
LogsDatePicker,
DatePickerValue,
} from 'components/interfaces/Settings/Logs/Logs.DatePickers'
import { REPORTS_DATEPICKER_HELPERS } from 'components/interfaces/Reports/Reports.constants'
import { maybeShowUpgradePrompt } from 'components/interfaces/Settings/Logs/Logs.utils'
import UpgradePrompt from 'components/interfaces/Settings/Logs/UpgradePrompt'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import type { DataTableTimerangeFilterField } from '../DataTable.types'
import { isArrayOfDates } from '../DataTable.utils'
import { DatePickerWithRange } from '../DatePickerWithRange'
import { useDataTable } from '../providers/DataTableProvider'
export function DataTableFilterTimerange<TData>({
@@ -16,6 +23,9 @@ export function DataTableFilterTimerange<TData>({
const column = table.getColumn(value)
const filterValue = columnFilters.find((i) => i.id === value)?.value
const { plan: orgPlan } = useCurrentOrgPlan()
const [showUpgradePrompt, setShowUpgradePrompt] = useState(false)
const date: DateRange | undefined = useMemo(
() =>
filterValue instanceof Date
@@ -26,17 +36,88 @@ export function DataTableFilterTimerange<TData>({
[filterValue]
)
const setDate = (date: DateRange | undefined) => {
if (!date) return // TODO: remove from search params if columnFilter is removed
if (date.from && !date.to) {
column?.setFilterValue([date.from])
const handleDatePickerChange = (vals: DatePickerValue) => {
// Check if the selected date range exceeds the plan limits
const shouldShowUpgradePrompt = maybeShowUpgradePrompt(vals.from, orgPlan?.id)
if (shouldShowUpgradePrompt) {
setShowUpgradePrompt(true)
return
}
if (date.to && date.from) {
column?.setFilterValue([date.from, date.to])
const startDate = new Date(vals.from)
const endDate = new Date(vals.to)
column?.setFilterValue([startDate, endDate])
}
// Get current selected DatePickerValue based on the date range
const getCurrentDatePickerValue = (): DatePickerValue => {
if (!date?.from || !date?.to) {
// Default to last 60 minutes
const defaultHelper =
REPORTS_DATEPICKER_HELPERS.find((h) => h.default) || REPORTS_DATEPICKER_HELPERS[0]
return {
from: defaultHelper.calcFrom(),
to: defaultHelper.calcTo(),
text: defaultHelper.text,
isHelper: true,
}
}
// Try to match with a helper
const matchingHelper = REPORTS_DATEPICKER_HELPERS.find((helper) => {
const helperFrom = new Date(helper.calcFrom())
const helperTo = new Date(helper.calcTo())
const timeDiff = 60000 // 1 minute tolerance
return (
Math.abs(date.from!.getTime() - helperFrom.getTime()) < timeDiff &&
Math.abs(date.to!.getTime() - helperTo.getTime()) < timeDiff
)
})
if (matchingHelper) {
return {
from: matchingHelper.calcFrom(),
to: matchingHelper.calcTo(),
text: matchingHelper.text,
isHelper: true,
}
}
// Custom range
return {
from: date.from.toISOString(),
to: date.to.toISOString(),
text: `${date.from.toLocaleDateString()} - ${date.to.toLocaleDateString()}`,
isHelper: false,
}
}
return (
<DatePickerWithRange dateRangeDisabled={dateRangeDisabled} {...{ date, setDate, presets }} />
<>
<LogsDatePicker
buttonTriggerProps={{
block: true,
className: 'h-8',
}}
popoverContentProps={{
// TS issue with radix props not propogating
// @ts-expect-error
side: 'bottom',
align: 'start',
}}
onSubmit={handleDatePickerChange}
value={getCurrentDatePickerValue()}
helpers={REPORTS_DATEPICKER_HELPERS}
/>
<UpgradePrompt
show={showUpgradePrompt}
setShowUpgradePrompt={setShowUpgradePrompt}
title="Log date range"
description="Log data can be retained for a maximum of 3 months depending on the plan that your project is on."
source="unifiedLogsDateRange"
/>
</>
)
}