postgrest.tsx174 lines · main
1import { useParams } from 'common'
2import dayjs from 'dayjs'
3import { ArrowRight, RefreshCw } from 'lucide-react'
4import { useEffect, useRef } from 'react'
5
6import ReportFilterBar from '@/components/interfaces/Reports/ReportFilterBar'
7import ReportHeader from '@/components/interfaces/Reports/ReportHeader'
8import ReportPadding from '@/components/interfaces/Reports/ReportPadding'
9import { REPORT_DATERANGE_HELPER_LABELS } from '@/components/interfaces/Reports/Reports.constants'
10import ReportStickyNav from '@/components/interfaces/Reports/ReportStickyNav'
11import { SharedAPIReport } from '@/components/interfaces/Reports/SharedAPIReport/SharedAPIReport'
12import { useSharedAPIReport } from '@/components/interfaces/Reports/SharedAPIReport/SharedAPIReport.constants'
13import {
14 DatePickerValue,
15 LogsDatePicker,
16} from '@/components/interfaces/Settings/Logs/Logs.DatePickers'
17import UpgradePrompt from '@/components/interfaces/Settings/Logs/UpgradePrompt'
18import DefaultLayout from '@/components/layouts/DefaultLayout'
19import ObservabilityLayout from '@/components/layouts/ObservabilityLayout/ObservabilityLayout'
20import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
21import { ObservabilityLink } from '@/components/ui/ObservabilityLink'
22import { useRefreshHandler, useReportDateRange } from '@/hooks/misc/useReportDateRange'
23import { useDatabaseSelectorStateSnapshot } from '@/state/database-selector'
24import type { NextPageWithLayout } from '@/types'
25
26const PostgRESTReport: NextPageWithLayout = () => {
27 return (
28 <ReportPadding>
29 <PostgrestReport />
30 </ReportPadding>
31 )
32}
33
34PostgRESTReport.getLayout = (page) => (
35 <DefaultLayout>
36 <ObservabilityLayout title="PostgREST">{page}</ObservabilityLayout>
37 </DefaultLayout>
38)
39
40export type UpdateDateRange = (from: string, to: string) => void
41export default PostgRESTReport
42
43const PostgrestReport = () => {
44 const { db, chart } = useParams()
45 const {
46 selectedDateRange,
47 datePickerValue,
48 datePickerHelpers,
49 showUpgradePrompt,
50 setShowUpgradePrompt,
51 handleDatePickerChange: handleDatePickerChangeFromHook,
52 } = useReportDateRange(REPORT_DATERANGE_HELPER_LABELS.LAST_60_MINUTES)
53
54 const {
55 data,
56 error,
57 isLoading,
58 refetch,
59 isRefetching,
60 filters,
61 addFilter,
62 removeFilters,
63 isLoadingData,
64 sql,
65 } = useSharedAPIReport({
66 filterBy: 'postgrest',
67 start: selectedDateRange?.period_start?.date,
68 end: selectedDateRange?.period_end?.date,
69 })
70
71 const state = useDatabaseSelectorStateSnapshot()
72
73 const hasStateSyncedFromUrlRef = useRef(false)
74 useEffect(() => {
75 if (hasStateSyncedFromUrlRef.current) return
76 hasStateSyncedFromUrlRef.current = true
77
78 if (db !== undefined) {
79 setTimeout(() => {
80 // [Joshen] Adding a timeout here to support navigation from settings to reports
81 // Both are rendering different instances of ProjectLayout which is where the
82 // DatabaseSelectorContextProvider lies in (unless we reckon shifting the provider up one more level is better)
83 state.setSelectedDatabaseId(db)
84 }, 100)
85 }
86 if (chart !== undefined) {
87 setTimeout(() => {
88 const el = document.getElementById(chart)
89 if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' })
90 }, 200)
91 }
92 }, [state, db, chart])
93
94 const handleDatePickerChange = (values: DatePickerValue) => {
95 handleDatePickerChangeFromHook(values)
96 }
97
98 const onRefreshReport = useRefreshHandler(
99 datePickerValue,
100 datePickerHelpers,
101 handleDatePickerChange,
102 refetch
103 )
104
105 return (
106 <>
107 <ReportHeader showDatabaseSelector={false} title="Data API" />
108 <ReportStickyNav
109 content={
110 <div className="flex flex-col gap-2">
111 <div className="flex gap-2">
112 <ButtonTooltip
113 type="default"
114 disabled={isRefetching}
115 icon={<RefreshCw className={isRefetching ? 'animate-spin' : ''} />}
116 className="w-7"
117 tooltip={{ content: { side: 'bottom', text: 'Refresh report' } }}
118 onClick={onRefreshReport}
119 />
120 <LogsDatePicker
121 onSubmit={handleDatePickerChange}
122 value={datePickerValue}
123 helpers={datePickerHelpers}
124 />
125 <UpgradePrompt
126 show={showUpgradePrompt}
127 setShowUpgradePrompt={setShowUpgradePrompt}
128 title="Report date range"
129 description="Report data can be stored for a maximum of 3 months depending on the plan that your project is on."
130 source="postgrestReportDateRange"
131 />
132 {selectedDateRange && (
133 <div className="flex items-center gap-x-2 text-xs">
134 <p className="text-foreground-light">
135 {dayjs(selectedDateRange.period_start.date).format('MMM D, h:mma')}
136 </p>
137 <p className="text-foreground-light">
138 <ArrowRight size={12} />
139 </p>
140 <p className="text-foreground-light">
141 {dayjs(selectedDateRange.period_end.date).format('MMM D, h:mma')}
142 </p>
143 </div>
144 )}
145 </div>
146 <ReportFilterBar
147 filters={filters}
148 onAddFilter={addFilter}
149 onRemoveFilters={removeFilters}
150 isLoading={isLoadingData || isRefetching}
151 hideDatepicker={true}
152 datepickerHelpers={datePickerHelpers}
153 selectedProduct={'postgrest'}
154 showDatabaseSelector={false}
155 />
156 </div>
157 }
158 >
159 <div className="relative mt-8">
160 <SharedAPIReport
161 data={data}
162 error={error}
163 isLoading={isLoading}
164 isRefetching={isRefetching}
165 sql={sql}
166 />
167 </div>
168 </ReportStickyNav>
169 <div className="py-8">
170 <ObservabilityLink />
171 </div>
172 </>
173 )
174}