diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx index 6c34b97b8..e751743b7 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx @@ -29,11 +29,9 @@ export function SessionModal({ websiteId, ...props }: SessionModalProps) { > - {({ close }) => ( - - close()} /> - - )} + + + diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx index e83c7957f..f8c01137d 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx @@ -1,14 +1,4 @@ -import { - TextField, - Row, - Column, - Tabs, - TabList, - Tab, - TabPanel, - Button, - Icon, -} from '@umami/react-zen'; +import { TextField, Row, Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; import { Avatar } from '@/components/common/Avatar'; import { LoadingPanel } from '@/components/common/LoadingPanel'; import { useMessages, useWebsiteSessionQuery } from '@/components/hooks'; @@ -16,17 +6,8 @@ import { SessionActivity } from './SessionActivity'; import { SessionData } from './SessionData'; import { SessionInfo } from './SessionInfo'; import { SessionStats } from './SessionStats'; -import { X } from 'lucide-react'; -export function SessionProfile({ - websiteId, - sessionId, - onClose, -}: { - websiteId: string; - sessionId: string; - onClose?: () => void; -}) { +export function SessionProfile({ websiteId, sessionId }: { websiteId: string; sessionId: string }) { const { data, isLoading, error } = useWebsiteSessionQuery(websiteId, sessionId); const { formatMessage, labels } = useMessages(); @@ -40,15 +21,6 @@ export function SessionProfile({ > {data && ( - {onClose && ( - - - - )} diff --git a/src/app/api/websites/[websiteId]/session-data/properties/route.ts b/src/app/api/websites/[websiteId]/session-data/properties/route.ts index 64328ce56..704ae5198 100644 --- a/src/app/api/websites/[websiteId]/session-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/properties/route.ts @@ -3,7 +3,6 @@ import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/permissions'; import { getSessionDataProperties } from '@/queries/sql'; -import { filterParams } from '@/lib/schema'; export async function GET( request: Request, @@ -12,7 +11,7 @@ export async function GET( const schema = z.object({ startAt: z.coerce.number().int(), endAt: z.coerce.number().int(), - ...filterParams, + propertyName: z.string().optional(), }); const { auth, query, error } = await parseRequest(request, schema); @@ -27,9 +26,10 @@ export async function GET( return unauthorized(); } + const { propertyName } = query; const filters = await getQueryFilters(query, websiteId); - const data = await getSessionDataProperties(websiteId, filters); + const data = await getSessionDataProperties(websiteId, { ...filters, propertyName }); return json(data); } diff --git a/src/app/api/websites/[websiteId]/session-data/values/route.ts b/src/app/api/websites/[websiteId]/session-data/values/route.ts index 75464ba4b..f95f5d43d 100644 --- a/src/app/api/websites/[websiteId]/session-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/values/route.ts @@ -3,7 +3,6 @@ import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; import { getSessionDataValues } from '@/queries/sql'; import { z } from 'zod'; -import { filterParams } from '@/lib/schema'; export async function GET( request: Request, @@ -13,7 +12,6 @@ export async function GET( startAt: z.coerce.number().int(), endAt: z.coerce.number().int(), propertyName: z.string().optional(), - ...filterParams, }); const { auth, query, error } = await parseRequest(request, schema); diff --git a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts index f3d17f946..af1a1f606 100644 --- a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts @@ -1,9 +1,9 @@ -import { getQueryFilters, parseRequest } from '@/lib/request'; -import { json, unauthorized } from '@/lib/response'; -import { filterParams, timezoneParam } from '@/lib/schema'; -import { canViewWebsite } from '@/permissions'; -import { getWeeklyTraffic } from '@/queries/sql'; import { z } from 'zod'; +import { getQueryFilters, parseRequest } from '@/lib/request'; +import { unauthorized, json } from '@/lib/response'; +import { canViewWebsite } from '@/permissions'; +import { filterParams, pagingParams, timezoneParam } from '@/lib/schema'; +import { getWeeklyTraffic } from '@/queries/sql'; export async function GET( request: Request, @@ -14,6 +14,7 @@ export async function GET( endAt: z.coerce.number().int(), timezone: timezoneParam, ...filterParams, + ...pagingParams, }); const { auth, query, error } = await parseRequest(request, schema); diff --git a/src/components/hooks/queries/useSessionDataPropertiesQuery.ts b/src/components/hooks/queries/useSessionDataPropertiesQuery.ts index 975c728ae..2bb139501 100644 --- a/src/components/hooks/queries/useSessionDataPropertiesQuery.ts +++ b/src/components/hooks/queries/useSessionDataPropertiesQuery.ts @@ -5,22 +5,12 @@ import { ReactQueryOptions } from '@/lib/types'; export function useSessionDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions) { const { get, useQuery } = useApi(); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const filters = useFilterParameters(); return useQuery({ - queryKey: [ - 'websites:session-data:properties', - { websiteId, startAt, endAt, unit, timezone, ...filters }, - ], - queryFn: () => - get(`/websites/${websiteId}/session-data/properties`, { - startAt, - endAt, - unit, - timezone, - ...filters, - }), + queryKey: ['websites:session-data:properties', { websiteId, ...date, ...filters }], + queryFn: () => get(`/websites/${websiteId}/session-data/properties`, { ...date, ...filters }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useSessionDataValuesQuery.ts b/src/components/hooks/queries/useSessionDataValuesQuery.ts index 7df35938a..05373d21a 100644 --- a/src/components/hooks/queries/useSessionDataValuesQuery.ts +++ b/src/components/hooks/queries/useSessionDataValuesQuery.ts @@ -9,23 +9,13 @@ export function useSessionDataValuesQuery( options?: ReactQueryOptions, ) { const { get, useQuery } = useApi(); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const filters = useFilterParameters(); return useQuery({ - queryKey: [ - 'websites:session-data:values', - { websiteId, propertyName, startAt, endAt, unit, timezone, ...filters }, - ], + queryKey: ['websites:session-data:values', { websiteId, propertyName, ...date, ...filters }], queryFn: () => - get(`/websites/${websiteId}/session-data/values`, { - startAt, - endAt, - unit, - timezone, - ...filters, - propertyName, - }), + get(`/websites/${websiteId}/session-data/values`, { ...date, ...filters, propertyName }), enabled: !!(websiteId && propertyName), ...options, }); diff --git a/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts b/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts index 82a7c05f0..9c9aaddc7 100644 --- a/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts @@ -4,13 +4,12 @@ import { useDateParameters } from '../useDateParameters'; export function useWebsiteSessionStatsQuery(websiteId: string, options?: Record) { const { get, useQuery } = useApi(); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const filters = useFilterParameters(); return useQuery({ - queryKey: ['sessions:stats', { websiteId, startAt, endAt, unit, timezone, ...filters }], - queryFn: () => - get(`/websites/${websiteId}/sessions/stats`, { startAt, endAt, unit, timezone, ...filters }), + queryKey: ['sessions:stats', { websiteId, ...date, ...filters }], + queryFn: () => get(`/websites/${websiteId}/sessions/stats`, { ...date, ...filters }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useWebsiteSessionsQuery.ts b/src/components/hooks/queries/useWebsiteSessionsQuery.ts index 31906be90..a3de19ca0 100644 --- a/src/components/hooks/queries/useWebsiteSessionsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionsQuery.ts @@ -1,8 +1,8 @@ import { useApi } from '../useApi'; -import { useDateParameters } from '../useDateParameters'; -import { useFilterParameters } from '../useFilterParameters'; -import { useModified } from '../useModified'; import { usePagedQuery } from '../usePagedQuery'; +import { useModified } from '../useModified'; +import { useFilterParameters } from '../useFilterParameters'; +import { useDateParameters } from '../useDateParameters'; export function useWebsiteSessionsQuery( websiteId: string, @@ -10,20 +10,14 @@ export function useWebsiteSessionsQuery( ) { const { get } = useApi(); const { modified } = useModified(`sessions`); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const filters = useFilterParameters(); return usePagedQuery({ - queryKey: [ - 'sessions', - { websiteId, modified, startAt, endAt, unit, timezone, ...params, ...filters }, - ], + queryKey: ['sessions', { websiteId, modified, ...params, ...date, ...filters }], queryFn: pageParams => { return get(`/websites/${websiteId}/sessions`, { - startAt, - endAt, - unit, - timezone, + ...date, ...filters, ...pageParams, ...params, diff --git a/src/queries/sql/events/getWebsiteEvents.ts b/src/queries/sql/events/getWebsiteEvents.ts index 52113daf5..d4625c2b2 100644 --- a/src/queries/sql/events/getWebsiteEvents.ts +++ b/src/queries/sql/events/getWebsiteEvents.ts @@ -96,10 +96,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { page_title as pageTitle, event_type as eventType, event_name as eventName, - event_id IN (select event_id - from event_data - where website_id = {websiteId:UUID} - ${dateQuery}) as hasData + event_id IN (SELECT event_id FROM event_data where website_id = {websiteId:UUID}) as hasData from website_event ${cohortQuery} where website_id = {websiteId:UUID} diff --git a/src/queries/sql/reports/getRevenue.ts b/src/queries/sql/reports/getRevenue.ts index e13106ced..890717d96 100644 --- a/src/queries/sql/reports/getRevenue.ts +++ b/src/queries/sql/reports/getRevenue.ts @@ -134,15 +134,6 @@ async function clickhouseQuery( currency, }); - const joinQuery = filterQuery - ? `join website_event - on website_event.website_id = website_revenue.website_id - and website_event.session_id = website_revenue.session_id - and website_event.event_id = website_revenue.event_id - and website_event.website_id = {websiteId:UUID} - and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}` - : ''; - const chart = await rawQuery< { x: string; @@ -156,7 +147,12 @@ async function clickhouseQuery( ${getDateSQL('website_revenue.created_at', unit, timezone)} t, sum(website_revenue.revenue) y from website_revenue - ${joinQuery} + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} ${cohortQuery} where website_revenue.website_id = {websiteId:UUID} and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} @@ -179,13 +175,13 @@ async function clickhouseQuery( website_event.country as name, sum(website_revenue.revenue) as value from website_revenue - join website_event + join website_event on website_event.website_id = website_revenue.website_id and website_event.session_id = website_revenue.session_id and website_event.event_id = website_revenue.event_id and website_event.website_id = {websiteId:UUID} and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} - ${cohortQuery} + ${cohortQuery} where website_revenue.website_id = {websiteId:UUID} and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} and website_revenue.currency = {currency:String} @@ -207,7 +203,12 @@ async function clickhouseQuery( uniqExact(website_revenue.event_id) as count, uniqExact(website_revenue.session_id) as unique_count from website_revenue - ${joinQuery} + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} ${cohortQuery} where website_revenue.website_id = {websiteId:UUID} and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} diff --git a/src/queries/sql/sessions/getSessionActivity.ts b/src/queries/sql/sessions/getSessionActivity.ts index 6b79338ee..9f1be24ad 100644 --- a/src/queries/sql/sessions/getSessionActivity.ts +++ b/src/queries/sql/sessions/getSessionActivity.ts @@ -57,16 +57,12 @@ async function clickhouseQuery(websiteId: string, sessionId: string, filters: Qu event_type as eventType, event_name as eventName, visit_id as visitId, - event_id IN (select event_id - from event_data - where website_id = {websiteId:UUID} - and session_id = {sessionId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64}) AS hasData - from website_event - where website_id = {websiteId:UUID} - and session_id = {sessionId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - order by created_at desc + event_id IN (SELECT event_id FROM event_data where website_id = {websiteId:UUID} and session_id = {sessionId:UUID}) AS hasData + from website_event e + where e.website_id = {websiteId:UUID} + and e.session_id = {sessionId:UUID} + and e.created_at between {startDate:DateTime64} and {endDate:DateTime64} + order by e.created_at desc limit 500 `, { websiteId, sessionId, startDate, endDate }, diff --git a/src/queries/sql/sessions/getSessionDataProperties.ts b/src/queries/sql/sessions/getSessionDataProperties.ts index 78e4cba4a..134cf7205 100644 --- a/src/queries/sql/sessions/getSessionDataProperties.ts +++ b/src/queries/sql/sessions/getSessionDataProperties.ts @@ -1,12 +1,12 @@ +import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; -import prisma from '@/lib/prisma'; import { QueryFilters } from '@/lib/types'; const FUNCTION_NAME = 'getSessionDataProperties'; export async function getSessionDataProperties( - ...args: [websiteId: string, filters: QueryFilters] + ...args: [websiteId: string, filters: QueryFilters & { propertyName?: string }] ) { return runQuery({ [PRISMA]: () => relationalQuery(...args), @@ -14,12 +14,17 @@ export async function getSessionDataProperties( }); } -async function relationalQuery(websiteId: string, filters: QueryFilters) { +async function relationalQuery( + websiteId: string, + filters: QueryFilters & { propertyName?: string }, +) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ - ...filters, - websiteId, - }); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( + { ...filters, websiteId }, + { + columns: { propertyName: 'data_key' }, + }, + ); return rawQuery( ` @@ -45,10 +50,15 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { async function clickhouseQuery( websiteId: string, - filters: QueryFilters, + filters: QueryFilters & { propertyName?: string }, ): Promise<{ propertyName: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); + const { filterQuery, cohortQuery, queryParams } = parseFilters( + { ...filters, websiteId }, + { + columns: { propertyName: 'data_key' }, + }, + ); return rawQuery( ` @@ -59,7 +69,6 @@ async function clickhouseQuery( ${cohortQuery} join session_data final on session_data.session_id = website_event.session_id - and session_data.website_id = {websiteId:UUID} where website_event.website_id = {websiteId:UUID} and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} and session_data.data_key != '' diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index efc85090b..8da126690 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -69,7 +69,6 @@ async function clickhouseQuery( ${cohortQuery} join session_data final on session_data.session_id = website_event.session_id - and session_data.website_id = {websiteId:UUID} where website_event.website_id = {websiteId:UUID} and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} and session_data.data_key = {propertyName:String} diff --git a/src/queries/sql/sessions/getWebsiteSessions.ts b/src/queries/sql/sessions/getWebsiteSessions.ts index 302deca6e..44b52d8e9 100644 --- a/src/queries/sql/sessions/getWebsiteSessions.ts +++ b/src/queries/sql/sessions/getWebsiteSessions.ts @@ -98,7 +98,6 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { select session_id as id, website_id as websiteId, - hostname, browser, os, device, @@ -118,7 +117,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { ${dateQuery} ${filterQuery} ${searchQuery} - group by session_id, website_id, hostname, browser, os, device, screen, language, country, region, city + group by session_id, website_id, browser, os, device, screen, language, country, region, city order by lastAt desc `; } else { @@ -126,7 +125,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { select session_id as id, website_id as websiteId, - arrayFirst(x -> 1, hostname) hostname, + hostname, browser, os, device,