From 334297f194178778f1d833e475758a32cc7f8370 Mon Sep 17 00:00:00 2001 From: emma Date: Sun, 7 May 2023 14:56:39 -0400 Subject: [PATCH] attempt fetching custom event data for data table --- components/metrics/MetricsTable.js | 9 ++++-- pages/api/websites/[id]/metrics.ts | 29 ++++++++++++++++-- .../analytics/pageview/getPageviewMetrics.ts | 2 +- umami-pr-1.session copy.sql | 2 ++ umami-pr-1.session.sql | 30 +++++++++++++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 umami-pr-1.session copy.sql create mode 100644 umami-pr-1.session.sql diff --git a/components/metrics/MetricsTable.js b/components/metrics/MetricsTable.js index 97deb39d..3b9c6ca8 100644 --- a/components/metrics/MetricsTable.js +++ b/components/metrics/MetricsTable.js @@ -6,6 +6,7 @@ import classNames from 'classnames'; import useApi from 'hooks/useApi'; import { percentFilter } from 'lib/filters'; import useDateRange from 'hooks/useDateRange'; +import useTimezone from 'hooks/useTimezone'; import usePageQuery from 'hooks/usePageQuery'; import ErrorMessage from 'components/common/ErrorMessage'; import DataTable from './DataTable'; @@ -26,7 +27,8 @@ export function MetricsTable({ delay = null, ...props }) { - const [{ startDate, endDate, modified }] = useDateRange(websiteId); + const [{ startDate, endDate, modified, unit }] = useDateRange(websiteId); + const [timezone] = useTimezone(); const { resolveUrl, router, @@ -53,6 +55,9 @@ export function MetricsTable({ country, region, city, + unit, + timezone, + includeEventData: type === 'event', }), { onSuccess: onDataLoad, retryDelay: delay || DEFAULT_ANIMATION_DURATION }, ); @@ -69,7 +74,7 @@ export function MetricsTable({ return items.sort(firstBy('y', -1).thenBy('x')); } return []; - }, [data, error, dataFilter, filterOptions]); + }, [data, dataFilter, filterOptions, limit]); const { dir } = useLocale(); return ( diff --git a/pages/api/websites/[id]/metrics.ts b/pages/api/websites/[id]/metrics.ts index 5cf818a0..98d03314 100644 --- a/pages/api/websites/[id]/metrics.ts +++ b/pages/api/websites/[id]/metrics.ts @@ -1,10 +1,12 @@ import { NextApiResponse } from 'next'; -import { methodNotAllowed, ok, unauthorized } from 'next-basics'; +import { methodNotAllowed, ok, unauthorized, badRequest } from 'next-basics'; import { WebsiteMetric, NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; import { useAuth, useCors } from 'lib/middleware'; import { SESSION_COLUMNS, EVENT_COLUMNS, FILTER_COLUMNS } from 'lib/constants'; -import { getPageviewMetrics, getSessionMetrics } from 'queries'; +import { getEventMetrics, getPageviewMetrics, getSessionMetrics } from 'queries'; +import moment from 'moment-timezone'; +const unitTypes = ['year', 'month', 'hour', 'day']; export interface WebsiteMetricsRequestQuery { id: string; @@ -47,6 +49,9 @@ export default async ( country, region, city, + includeEventData, + timezone, + unit, } = req.query; if (req.method === 'GET') { @@ -54,6 +59,15 @@ export default async ( return unauthorized(res); } + if ( + typeof timezone !== 'string' || + typeof unit !== 'string' || + !moment.tz.zone(String(timezone)) || + !unitTypes.includes(String(unit)) + ) { + return badRequest(res); + } + const startDate = new Date(+startAt); const endDate = new Date(+endAt); @@ -114,6 +128,17 @@ export default async ( filters[type] = undefined; + if (type === 'event' && includeEventData) { + const data = await getEventMetrics(websiteId, { + startDate, + endDate, + timezone, + unit, + filters: { url: filters.url, eventName: undefined }, + }); + + return ok(res, data); + } const data = await getPageviewMetrics(websiteId, { startDate, endDate, diff --git a/queries/analytics/pageview/getPageviewMetrics.ts b/queries/analytics/pageview/getPageviewMetrics.ts index db82720d..c95c5ecd 100644 --- a/queries/analytics/pageview/getPageviewMetrics.ts +++ b/queries/analytics/pageview/getPageviewMetrics.ts @@ -102,7 +102,7 @@ async function clickhouseQuery( where website_id = {websiteId:UUID} and event_type = {eventType:UInt32} and created_at >= ${getDateFormat(resetDate)} - and ${getBetweenDates('created_at', startDate, endDate)} + and ${getBetweenDates('created_at', startDate, endDate)} ${excludeDomain} ${filterQuery} group by x diff --git a/umami-pr-1.session copy.sql b/umami-pr-1.session copy.sql new file mode 100644 index 00000000..bd51082e --- /dev/null +++ b/umami-pr-1.session copy.sql @@ -0,0 +1,2 @@ +select * +from event_data -- WHERE event_data.website_event_id = '91bac2f4-4039-4b2a-a2ab-8c86f71ef95d' diff --git a/umami-pr-1.session.sql b/umami-pr-1.session.sql new file mode 100644 index 00000000..b76a456d --- /dev/null +++ b/umami-pr-1.session.sql @@ -0,0 +1,30 @@ +WITH event_data_query AS ( + SELECT d.website_event_id, + jsonb_object_agg( + d.event_key, + CASE + d.event_data_type + when 1 then to_jsonb(d.event_string_value) -- string + when 2 then to_jsonb(d.event_numeric_value) -- number + when 3 then to_jsonb(d.event_bool_value) -- boolean + when 4 then to_jsonb(d.event_date_value) -- date + when 5 then d.event_string_value::jsonb -- array + end + ) filter ( + where d.event_key is not null + ) as event_data + FROM event_data d + GROUP BY d.website_event_id +) +select e.event_name x, + to_char( + date_trunc('hour', e.created_at), + 'YYYY-MM-DD HH24:00:00' + ) c, + edq.event_data::jsonb->'data.target' t, + edq.event_data::jsonb->'data.release' r +from website_event e + LEFT JOIN event_data_query edq ON e.event_id = edq.website_event_id +where e.event_name = 'Outbound click' + or e.event_name = 'NewSong PRO click' +order by c desc