feat: dashboard v2, esm, upgrades (#211)
* esm * wip * wip * wip * wip * wip * wip * subscription notice * wip * wip * wip * fix envs * fix: update docker build * fix * esm/types * delete dashboard :D * add patches to dockerfiles * update packages + catalogs + ts * wip * remove native libs * ts * improvements * fix redirects and fetching session * try fix favicon * fixes * fix * order and resize reportds within a dashboard * improvements * wip * added userjot to dashboard * fix * add op * wip * different cache key * improve date picker * fix table * event details loading * redo onboarding completely * fix login * fix * fix * extend session, billing and improve bars * fix * reduce price on 10M
This commit is contained in:
committed by
GitHub
parent
436e81ecc9
commit
81a7e5d62e
@@ -1,5 +1,5 @@
|
||||
import { flatten, map, pipe, prop, range, sort, uniq } from 'ramda';
|
||||
import { escape } from 'sqlstring';
|
||||
import sqlstring from 'sqlstring';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
@@ -52,6 +52,80 @@ function utc(date: string | Date) {
|
||||
const cacher = cacheMiddleware(60);
|
||||
|
||||
export const chartRouter = createTRPCRouter({
|
||||
projectCard: protectedProcedure
|
||||
.use(cacheMiddleware(60 * 5))
|
||||
.input(
|
||||
z.object({
|
||||
projectId: z.string(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ input: { projectId } }) => {
|
||||
const chartPromise = chQuery<{ value: number; date: Date }>(
|
||||
`SELECT
|
||||
uniqHLL12(profile_id) as value,
|
||||
toStartOfDay(created_at) as date
|
||||
FROM ${TABLE_NAMES.sessions}
|
||||
WHERE
|
||||
sign = 1 AND
|
||||
project_id = ${sqlstring.escape(projectId)} AND
|
||||
created_at >= now() - interval '3 month'
|
||||
GROUP BY date
|
||||
ORDER BY date ASC
|
||||
WITH FILL FROM toStartOfDay(now() - interval '1 month')
|
||||
TO toStartOfDay(now())
|
||||
STEP INTERVAL 1 day
|
||||
`,
|
||||
);
|
||||
|
||||
const metricsPromise = clix(ch)
|
||||
.select<{
|
||||
months_3: number;
|
||||
months_3_prev: number;
|
||||
month: number;
|
||||
day: number;
|
||||
day_prev: number;
|
||||
}>([
|
||||
'uniqHLL12(if(created_at >= (now() - toIntervalMonth(3)), profile_id, null)) AS months_3',
|
||||
'uniqHLL12(if(created_at >= (now() - toIntervalMonth(6)) AND created_at < (now() - toIntervalMonth(3)), profile_id, null)) AS months_3_prev',
|
||||
'uniqHLL12(if(created_at >= (now() - toIntervalMonth(1)), profile_id, null)) AS month',
|
||||
'uniqHLL12(if(created_at >= (now() - toIntervalDay(1)), profile_id, null)) AS day',
|
||||
'uniqHLL12(if(created_at >= (now() - toIntervalDay(2)) AND created_at < (now() - toIntervalDay(1)), profile_id, null)) AS day_prev',
|
||||
])
|
||||
.from(TABLE_NAMES.sessions)
|
||||
.where('project_id', '=', projectId)
|
||||
.where('created_at', '>=', clix.exp('now() - toIntervalMonth(6)'))
|
||||
.execute();
|
||||
|
||||
const [chart, [metrics]] = await Promise.all([
|
||||
chartPromise,
|
||||
metricsPromise,
|
||||
]);
|
||||
|
||||
const change =
|
||||
metrics && metrics.months_3_prev > 0 && metrics.months_3 > 0
|
||||
? Math.round(
|
||||
((metrics.months_3 - metrics.months_3_prev) /
|
||||
metrics.months_3_prev) *
|
||||
100,
|
||||
)
|
||||
: null;
|
||||
|
||||
const trend =
|
||||
change === null
|
||||
? { direction: 'neutral' as const, percentage: null as number | null }
|
||||
: change > 0
|
||||
? { direction: 'up' as const, percentage: change }
|
||||
: change < 0
|
||||
? { direction: 'down' as const, percentage: Math.abs(change) }
|
||||
: { direction: 'neutral' as const, percentage: 0 };
|
||||
|
||||
return {
|
||||
chart: chart.map((d) => ({ ...d, date: new Date(d.date) })),
|
||||
metrics,
|
||||
trend,
|
||||
};
|
||||
}),
|
||||
|
||||
events: protectedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
@@ -61,7 +135,7 @@ export const chartRouter = createTRPCRouter({
|
||||
.query(async ({ input: { projectId } }) => {
|
||||
const [events, meta] = await Promise.all([
|
||||
chQuery<{ name: string; count: number }>(
|
||||
`SELECT name, count(name) as count FROM ${TABLE_NAMES.event_names_mv} WHERE project_id = ${escape(projectId)} GROUP BY name ORDER BY count DESC, name ASC`,
|
||||
`SELECT name, count(name) as count FROM ${TABLE_NAMES.event_names_mv} WHERE project_id = ${sqlstring.escape(projectId)} GROUP BY name ORDER BY count DESC, name ASC`,
|
||||
),
|
||||
getEventMetasCached(projectId),
|
||||
]);
|
||||
@@ -376,9 +450,9 @@ export const chartRouter = createTRPCRouter({
|
||||
|
||||
const whereEventNameIs = (event: string[]) => {
|
||||
if (event.length === 1) {
|
||||
return `name = ${escape(event[0])}`;
|
||||
return `name = ${sqlstring.escape(event[0])}`;
|
||||
}
|
||||
return `name IN (${event.map((e) => escape(e)).join(',')})`;
|
||||
return `name IN (${event.map((e) => sqlstring.escape(e)).join(',')})`;
|
||||
};
|
||||
|
||||
const cohortQuery = `
|
||||
@@ -390,7 +464,7 @@ export const chartRouter = createTRPCRouter({
|
||||
${sqlToStartOf}(created_at) AS cohort_interval
|
||||
FROM ${TABLE_NAMES.cohort_events_mv}
|
||||
WHERE ${whereEventNameIs(firstEvent)}
|
||||
AND project_id = ${escape(projectId)}
|
||||
AND project_id = ${sqlstring.escape(projectId)}
|
||||
AND created_at BETWEEN toDate('${utc(dates.startDate)}') AND toDate('${utc(dates.endDate)}')
|
||||
),
|
||||
last_event AS
|
||||
@@ -401,7 +475,7 @@ export const chartRouter = createTRPCRouter({
|
||||
toDate(created_at) AS event_date
|
||||
FROM cohort_events_mv
|
||||
WHERE ${whereEventNameIs(secondEvent)}
|
||||
AND project_id = ${escape(projectId)}
|
||||
AND project_id = ${sqlstring.escape(projectId)}
|
||||
AND created_at BETWEEN toDate('${utc(dates.startDate)}') AND toDate('${utc(dates.endDate)}') + INTERVAL ${diffInterval} ${sqlInterval}
|
||||
),
|
||||
retention_matrix AS
|
||||
|
||||
Reference in New Issue
Block a user