diff --git a/README.md b/README.md index d0a0b7ee..7b8bbb33 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ As of today (2023-12-12) I have more then 1.2 million events in PSQL and perform - [ ] Area - [ ] Support funnels - [ ] Support multiple breakdowns -- [ ] Aggregations (sum, average...) +- [x] Aggregations (sum, average...) ### SDK diff --git a/apps/web/src/components/report/sidebar/ReportEvents.tsx b/apps/web/src/components/report/sidebar/ReportEvents.tsx index 5dea0574..87302819 100644 --- a/apps/web/src/components/report/sidebar/ReportEvents.tsx +++ b/apps/web/src/components/report/sidebar/ReportEvents.tsx @@ -87,6 +87,10 @@ export function ReportEvents() { value: 'user', label: 'Unique users', }, + { + value: 'user_average', + label: 'Unique users (average)', + }, ]} label="Segment" > @@ -95,6 +99,10 @@ export function ReportEvents() { <> Unique users + ) : event.segment === 'user_average' ? ( + <> + Average per user + ) : ( <> All events diff --git a/apps/web/src/server/api/routers/chart.ts b/apps/web/src/server/api/routers/chart.ts index e157ec83..c1265691 100644 --- a/apps/web/src/server/api/routers/chart.ts +++ b/apps/web/src/server/api/routers/chart.ts @@ -236,20 +236,24 @@ function getDatesFromRange(range: IChartRange) { } if (isFloat(range)) { - const startDate = new Date(Date.now() - 1000 * 60 * (range * 100)); + const startDate = new Date( + Date.now() - 1000 * 60 * (range * 100) + ).toISOString(); const endDate = new Date().toISOString(); return { - startDate: startDate.toISOString(), - endDate: endDate, + startDate, + endDate, }; } - const startDate = getDaysOldDate(range).toISOString(); - const endDate = new Date().toISOString(); + const startDate = getDaysOldDate(range); + startDate.setUTCHours(0, 0, 0, 0); + const endDate = new Date(); + endDate.setUTCHours(23, 59, 59, 999); return { - startDate, - endDate, + startDate: startDate.toISOString(), + endDate: endDate.toISOString(), }; } @@ -271,6 +275,8 @@ function getChartSql({ if (event.segment === 'event') { select.push(`count(*)::int as count`); + } else if (event.segment === 'user_average') { + select.push(`COUNT(*)::float / COUNT(DISTINCT profile_id)::float as count`); } else { select.push(`count(DISTINCT profile_id)::int as count`); } @@ -396,6 +402,8 @@ function getChartSql({ sql.push(`ORDER BY ${orderBy.join(', ')}`); } + console.log('SQL ->', sql.join('\n')); + return sql.join('\n'); } diff --git a/apps/web/src/utils/validation.ts b/apps/web/src/utils/validation.ts index fed48ef1..0e5d3962 100644 --- a/apps/web/src/utils/validation.ts +++ b/apps/web/src/utils/validation.ts @@ -10,7 +10,7 @@ function objectToZodEnums(obj: Record): [K, ...K[]] { export const zChartEvent = z.object({ id: z.string(), name: z.string(), - segment: z.enum(['event', 'user']), + segment: z.enum(['event', 'user', 'user_average']), filters: z.array( z.object({ id: z.string(),