From e45d014042694145bd921a654bcb75dbb5522b40 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Mon, 14 Aug 2023 22:18:21 -0700 Subject: [PATCH 1/3] use functions to convert dates to string --- queries/analytics/reports/getRetention.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/queries/analytics/reports/getRetention.ts b/queries/analytics/reports/getRetention.ts index 9b18df49..ee7e4619 100644 --- a/queries/analytics/reports/getRetention.ts +++ b/queries/analytics/reports/getRetention.ts @@ -25,7 +25,7 @@ async function relationalQuery( }, ): Promise< { - date: Date; + date: string; day: number; visitors: number; returnVisitors: number; @@ -33,13 +33,15 @@ async function relationalQuery( }[] > { const { startDate, endDate } = dateRange; - const { rawQuery } = prisma; + const { getDateQuery, rawQuery } = prisma; + const timezone = 'utc'; + const unit = 'day'; return rawQuery( ` WITH cohort_items AS ( select session_id, - date_trunc('day', created_at)::date as cohort_date + ${getDateQuery('created_at', unit, timezone)} as cohort_date from session where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} @@ -47,7 +49,7 @@ async function relationalQuery( user_activities AS ( select distinct w.session_id, - (date_trunc('day', w.created_at)::date - c.cohort_date::date) as day_number + (${getDateQuery('created_at', unit, timezone)}::date - c.cohort_date::date) as day_number from website_event w join cohort_items c on w.session_id = c.session_id @@ -98,7 +100,7 @@ async function clickhouseQuery( }, ): Promise< { - date: Date; + date: string; day: number; visitors: number; returnVisitors: number; @@ -106,13 +108,15 @@ async function clickhouseQuery( }[] > { const { startDate, endDate } = dateRange; - const { rawQuery } = clickhouse; + const { getDateQuery, getDateStringQuery, rawQuery } = clickhouse; + const timezone = 'UTC'; + const unit = 'day'; return rawQuery( ` WITH cohort_items AS ( select - min(date_trunc('day', created_at)) as cohort_date, + min(${getDateQuery('created_at', unit, timezone)}) as cohort_date, session_id from website_event where website_id = {websiteId:UUID} @@ -122,7 +126,7 @@ async function clickhouseQuery( user_activities AS ( select distinct w.session_id, - (date_trunc('day', w.created_at) - c.cohort_date) / 86400 as day_number + (${getDateQuery('created_at', unit, timezone)} - c.cohort_date) / 86400 as day_number from website_event w join cohort_items c on w.session_id = c.session_id @@ -147,7 +151,7 @@ async function clickhouseQuery( group by 1, 2 ) select - c.cohort_date as date, + ${getDateStringQuery('c.cohort_date', unit)} as date, c.day_number as day, s.visitors as visitors, c.visitors returnVisitors, From 29a943df9c39dfd5d916173636a95f266eef125d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 14 Aug 2023 22:36:18 -0700 Subject: [PATCH 2/3] Add timezone to report queries. --- components/messages.js | 2 ++ components/pages/reports/Report.js | 2 ++ .../pages/reports/retention/RetentionTable.js | 13 +++++++++++-- .../reports/retention/RetentionTable.module.css | 4 ++++ hooks/useReport.js | 4 +++- lib/date.js | 10 +++++++--- pages/api/reports/retention.ts | 3 +++ 7 files changed, 32 insertions(+), 6 deletions(-) diff --git a/components/messages.js b/components/messages.js index f47513e8..6b4cbb51 100644 --- a/components/messages.js +++ b/components/messages.js @@ -172,6 +172,8 @@ export const labels = defineMessages({ browser: { id: 'label.browser', defaultMessage: 'Browser' }, device: { id: 'label.device', defaultMessage: 'Device' }, pageTitle: { id: 'label.pageTitle', defaultMessage: 'Page title' }, + day: { id: 'label.day', defaultMessage: 'Day' }, + date: { id: 'label.date', defaultMessage: 'Date' }, }); export const messages = defineMessages({ diff --git a/components/pages/reports/Report.js b/components/pages/reports/Report.js index 0a98ef75..685ebb9f 100644 --- a/components/pages/reports/Report.js +++ b/components/pages/reports/Report.js @@ -8,6 +8,8 @@ export const ReportContext = createContext(null); export function Report({ reportId, defaultParameters, children, ...props }) { const report = useReport(reportId, defaultParameters); + //console.log({ report }); + return ( diff --git a/components/pages/reports/retention/RetentionTable.js b/components/pages/reports/retention/RetentionTable.js index 7d0f2522..01a84a01 100644 --- a/components/pages/reports/retention/RetentionTable.js +++ b/components/pages/reports/retention/RetentionTable.js @@ -2,9 +2,12 @@ import { useContext } from 'react'; import { GridTable, GridColumn } from 'react-basics'; import { ReportContext } from '../Report'; import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; +import { useMessages } from 'hooks'; +import { dateFormat } from 'lib/date'; import styles from './RetentionTable.module.css'; export function RetentionTable() { + const { formatMessage, labels } = useMessages(); const { report } = useContext(ReportContext); const { data } = report || {}; @@ -19,21 +22,27 @@ export function RetentionTable() { return arr; }, []); - const days = Array(14).fill(null); + const days = Array(32).fill(null); return ( <>
+
{formatMessage(labels.date)}
{days.map((n, i) => (
- Day {i} + {formatMessage(labels.day)} {i}
))}
{dates.map((date, i) => { return (
+
+ {dateFormat(date, 'P')} +
+ {date} +
{days.map((n, day) => { return (
diff --git a/components/pages/reports/retention/RetentionTable.module.css b/components/pages/reports/retention/RetentionTable.module.css index 785582a0..0943ffc0 100644 --- a/components/pages/reports/retention/RetentionTable.module.css +++ b/components/pages/reports/retention/RetentionTable.module.css @@ -26,3 +26,7 @@ background: var(--blue100); border-radius: var(--border-radius); } + +.date { + min-width: 200px; +} diff --git a/hooks/useReport.js b/hooks/useReport.js index e036fc3a..72f90af3 100644 --- a/hooks/useReport.js +++ b/hooks/useReport.js @@ -1,5 +1,6 @@ import { produce } from 'immer'; import { useCallback, useEffect, useState } from 'react'; +import { useTimezone } from './useTimezone'; import useApi from './useApi'; const baseParameters = { @@ -12,6 +13,7 @@ export function useReport(reportId, defaultParameters) { const [report, setReport] = useState(null); const [isRunning, setIsRunning] = useState(false); const { get, post } = useApi(); + const [timezone] = useTimezone(); const loadReport = async id => { const data = await get(`/reports/${id}`); @@ -33,7 +35,7 @@ export function useReport(reportId, defaultParameters) { const { type } = report; - const data = await post(`/reports/${type}`, parameters); + const data = await post(`/reports/${type}`, { ...parameters, timezone }); setReport( produce(state => { diff --git a/lib/date.js b/lib/date.js index bf5dd90a..8a023822 100644 --- a/lib/date.js +++ b/lib/date.js @@ -250,9 +250,13 @@ export const customFormats = { }; export function dateFormat(date, str, locale = 'en-US') { - return format(date, customFormats?.[locale]?.[str] || str, { - locale: getDateLocale(locale), - }); + return format( + typeof date === 'string' ? new Date(date) : date, + customFormats?.[locale]?.[str] || str, + { + locale: getDateLocale(locale), + }, + ); } export function maxDate(...args) { diff --git a/pages/api/reports/retention.ts b/pages/api/reports/retention.ts index 83ed0b57..40b3266b 100644 --- a/pages/api/reports/retention.ts +++ b/pages/api/reports/retention.ts @@ -8,6 +8,7 @@ import { getRetention } from 'queries'; export interface RetentionRequestBody { websiteId: string; dateRange: { window; startDate: string; endDate: string }; + timezone: string; } export interface RetentionResponse { @@ -26,6 +27,7 @@ export default async ( const { websiteId, dateRange: { startDate, endDate }, + timezone, } = req.body; if (!(await canViewWebsite(req.auth, websiteId))) { @@ -35,6 +37,7 @@ export default async ( const data = await getRetention(websiteId, { startDate: new Date(startDate), endDate: new Date(endDate), + timezone, }); return ok(res, data); From 1d78cc4950a0ae80229aad1b1d0ae807146ebeb1 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Mon, 14 Aug 2023 23:07:39 -0700 Subject: [PATCH 3/3] fix UTC timezone for CH query --- queries/analytics/events/getEventMetrics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/queries/analytics/events/getEventMetrics.ts b/queries/analytics/events/getEventMetrics.ts index 09a85946..778cfee1 100644 --- a/queries/analytics/events/getEventMetrics.ts +++ b/queries/analytics/events/getEventMetrics.ts @@ -41,7 +41,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { } async function clickhouseQuery(websiteId: string, filters: QueryFilters) { - const { timezone = 'utc', unit = 'day' } = filters; + const { timezone = 'UTC', unit = 'day' } = filters; const { rawQuery, getDateQuery, parseFilters } = clickhouse; const { filterQuery, params } = await parseFilters(websiteId, { ...filters,