Skip to content

Commit ef2fbb8

Browse files
authored
Feat/logs date refactor (supabase#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.
1 parent 78ec1a4 commit ef2fbb8

File tree

2 files changed

+103
-12
lines changed

2 files changed

+103
-12
lines changed

apps/studio/components/interfaces/Settings/Logs/Logs.DatePickers.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import TimeSplitInput from 'components/ui/DatePicker/TimeSplitInput'
1111
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
1212
import {
1313
Button,
14+
ButtonProps,
1415
PopoverContent_Shadcn_,
1516
PopoverTrigger_Shadcn_,
1617
Popover_Shadcn_,
@@ -31,9 +32,17 @@ interface Props {
3132
value: DatePickerValue
3233
helpers: DatetimeHelper[]
3334
onSubmit: (value: DatePickerValue) => void
35+
buttonTriggerProps?: ButtonProps
36+
popoverContentProps?: typeof PopoverContent_Shadcn_
3437
}
3538

36-
export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<Props>) => {
39+
export const LogsDatePicker = ({
40+
onSubmit,
41+
helpers,
42+
value,
43+
buttonTriggerProps,
44+
popoverContentProps,
45+
}: PropsWithChildren<Props>) => {
3746
const [open, setOpen] = useState(false)
3847

3948
// Reset the state when the popover closes
@@ -230,7 +239,7 @@ export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<P
230239
return (
231240
<Popover_Shadcn_ open={open} onOpenChange={setOpen}>
232241
<PopoverTrigger_Shadcn_ asChild>
233-
<Button type="default" icon={<Clock size={12} />}>
242+
<Button type="default" icon={<Clock size={12} />} {...buttonTriggerProps}>
234243
{value.isHelper
235244
? value.text
236245
: `${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
239248
<PopoverContent_Shadcn_
240249
className="flex w-full p-0"
241250
side="bottom"
242-
align="center"
251+
align="end"
243252
portal={true}
253+
{...popoverContentProps}
244254
>
245255
<RadioGroup
246256
onValueChange={handleHelperChange}
Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
import { useMemo } from 'react'
1+
import { useMemo, useState } from 'react'
22
import type { DateRange } from 'react-day-picker'
33

4+
import {
5+
LogsDatePicker,
6+
DatePickerValue,
7+
} from 'components/interfaces/Settings/Logs/Logs.DatePickers'
8+
import { REPORTS_DATEPICKER_HELPERS } from 'components/interfaces/Reports/Reports.constants'
9+
import { maybeShowUpgradePrompt } from 'components/interfaces/Settings/Logs/Logs.utils'
10+
import UpgradePrompt from 'components/interfaces/Settings/Logs/UpgradePrompt'
11+
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
412
import type { DataTableTimerangeFilterField } from '../DataTable.types'
513
import { isArrayOfDates } from '../DataTable.utils'
6-
import { DatePickerWithRange } from '../DatePickerWithRange'
714
import { useDataTable } from '../providers/DataTableProvider'
815

916
export function DataTableFilterTimerange<TData>({
@@ -16,6 +23,9 @@ export function DataTableFilterTimerange<TData>({
1623
const column = table.getColumn(value)
1724
const filterValue = columnFilters.find((i) => i.id === value)?.value
1825

26+
const { plan: orgPlan } = useCurrentOrgPlan()
27+
const [showUpgradePrompt, setShowUpgradePrompt] = useState(false)
28+
1929
const date: DateRange | undefined = useMemo(
2030
() =>
2131
filterValue instanceof Date
@@ -26,17 +36,88 @@ export function DataTableFilterTimerange<TData>({
2636
[filterValue]
2737
)
2838

29-
const setDate = (date: DateRange | undefined) => {
30-
if (!date) return // TODO: remove from search params if columnFilter is removed
31-
if (date.from && !date.to) {
32-
column?.setFilterValue([date.from])
39+
const handleDatePickerChange = (vals: DatePickerValue) => {
40+
// Check if the selected date range exceeds the plan limits
41+
const shouldShowUpgradePrompt = maybeShowUpgradePrompt(vals.from, orgPlan?.id)
42+
43+
if (shouldShowUpgradePrompt) {
44+
setShowUpgradePrompt(true)
45+
return
46+
}
47+
48+
const startDate = new Date(vals.from)
49+
const endDate = new Date(vals.to)
50+
column?.setFilterValue([startDate, endDate])
51+
}
52+
53+
// Get current selected DatePickerValue based on the date range
54+
const getCurrentDatePickerValue = (): DatePickerValue => {
55+
if (!date?.from || !date?.to) {
56+
// Default to last 60 minutes
57+
const defaultHelper =
58+
REPORTS_DATEPICKER_HELPERS.find((h) => h.default) || REPORTS_DATEPICKER_HELPERS[0]
59+
return {
60+
from: defaultHelper.calcFrom(),
61+
to: defaultHelper.calcTo(),
62+
text: defaultHelper.text,
63+
isHelper: true,
64+
}
3365
}
34-
if (date.to && date.from) {
35-
column?.setFilterValue([date.from, date.to])
66+
67+
// Try to match with a helper
68+
const matchingHelper = REPORTS_DATEPICKER_HELPERS.find((helper) => {
69+
const helperFrom = new Date(helper.calcFrom())
70+
const helperTo = new Date(helper.calcTo())
71+
const timeDiff = 60000 // 1 minute tolerance
72+
73+
return (
74+
Math.abs(date.from!.getTime() - helperFrom.getTime()) < timeDiff &&
75+
Math.abs(date.to!.getTime() - helperTo.getTime()) < timeDiff
76+
)
77+
})
78+
79+
if (matchingHelper) {
80+
return {
81+
from: matchingHelper.calcFrom(),
82+
to: matchingHelper.calcTo(),
83+
text: matchingHelper.text,
84+
isHelper: true,
85+
}
86+
}
87+
88+
// Custom range
89+
return {
90+
from: date.from.toISOString(),
91+
to: date.to.toISOString(),
92+
text: `${date.from.toLocaleDateString()} - ${date.to.toLocaleDateString()}`,
93+
isHelper: false,
3694
}
3795
}
3896

3997
return (
40-
<DatePickerWithRange dateRangeDisabled={dateRangeDisabled} {...{ date, setDate, presets }} />
98+
<>
99+
<LogsDatePicker
100+
buttonTriggerProps={{
101+
block: true,
102+
className: 'h-8',
103+
}}
104+
popoverContentProps={{
105+
// TS issue with radix props not propogating
106+
// @ts-expect-error
107+
side: 'bottom',
108+
align: 'start',
109+
}}
110+
onSubmit={handleDatePickerChange}
111+
value={getCurrentDatePickerValue()}
112+
helpers={REPORTS_DATEPICKER_HELPERS}
113+
/>
114+
<UpgradePrompt
115+
show={showUpgradePrompt}
116+
setShowUpgradePrompt={setShowUpgradePrompt}
117+
title="Log date range"
118+
description="Log data can be retained for a maximum of 3 months depending on the plan that your project is on."
119+
source="unifiedLogsDateRange"
120+
/>
121+
</>
41122
)
42123
}

0 commit comments

Comments
 (0)