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
143
packages/trpc/src/routers/realtime.ts
Normal file
143
packages/trpc/src/routers/realtime.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
type EventMeta,
|
||||
TABLE_NAMES,
|
||||
ch,
|
||||
chQuery,
|
||||
clix,
|
||||
db,
|
||||
formatClickhouseDate,
|
||||
getEventList,
|
||||
} from '@openpanel/db';
|
||||
|
||||
import { subMinutes } from 'date-fns';
|
||||
import sqlstring from 'sqlstring';
|
||||
import { createTRPCRouter, protectedProcedure } from '../trpc';
|
||||
|
||||
export const realtimeRouter = createTRPCRouter({
|
||||
coordinates: protectedProcedure
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
const res = await chQuery<{
|
||||
city: string;
|
||||
country: string;
|
||||
long: number;
|
||||
lat: number;
|
||||
}>(
|
||||
`SELECT DISTINCT country, city, longitude as long, latitude as lat FROM ${TABLE_NAMES.events} WHERE project_id = ${sqlstring.escape(input.projectId)} AND created_at >= '${formatClickhouseDate(subMinutes(new Date(), 30))}' ORDER BY created_at DESC`,
|
||||
);
|
||||
|
||||
return res;
|
||||
}),
|
||||
activeSessions: protectedProcedure
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
return getEventList({
|
||||
projectId: input.projectId,
|
||||
take: 30,
|
||||
select: {
|
||||
name: true,
|
||||
path: true,
|
||||
origin: true,
|
||||
referrer: true,
|
||||
referrerName: true,
|
||||
referrerType: true,
|
||||
country: true,
|
||||
device: true,
|
||||
os: true,
|
||||
browser: true,
|
||||
createdAt: true,
|
||||
profile: true,
|
||||
meta: true,
|
||||
},
|
||||
});
|
||||
}),
|
||||
paths: protectedProcedure
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
const res = await clix(ch)
|
||||
.select<{
|
||||
origin: string;
|
||||
path: string;
|
||||
count: number;
|
||||
avg_duration: number;
|
||||
}>([
|
||||
'origin',
|
||||
'path',
|
||||
'COUNT(*) as count',
|
||||
'round(avg(duration)/1000, 2) as avg_duration',
|
||||
])
|
||||
.from(TABLE_NAMES.events)
|
||||
.where('project_id', '=', input.projectId)
|
||||
.where('path', '!=', '')
|
||||
.where(
|
||||
'created_at',
|
||||
'>=',
|
||||
formatClickhouseDate(subMinutes(new Date(), 30)),
|
||||
)
|
||||
.groupBy(['path', 'origin'])
|
||||
.orderBy('count', 'DESC')
|
||||
.limit(100)
|
||||
.execute();
|
||||
|
||||
return res;
|
||||
}),
|
||||
referrals: protectedProcedure
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
const res = await clix(ch)
|
||||
.select<{
|
||||
referrer_name: string;
|
||||
count: number;
|
||||
avg_duration: number;
|
||||
}>([
|
||||
'referrer_name',
|
||||
'COUNT(*) as count',
|
||||
'round(avg(duration)/1000, 2) as avg_duration',
|
||||
])
|
||||
.from(TABLE_NAMES.events)
|
||||
.where('project_id', '=', input.projectId)
|
||||
.where('referrer_name', 'IS NOT NULL')
|
||||
.where(
|
||||
'created_at',
|
||||
'>=',
|
||||
formatClickhouseDate(subMinutes(new Date(), 30)),
|
||||
)
|
||||
.groupBy(['referrer_name'])
|
||||
.orderBy('count', 'DESC')
|
||||
.limit(100)
|
||||
.execute();
|
||||
|
||||
return res;
|
||||
}),
|
||||
geo: protectedProcedure
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
const res = await clix(ch)
|
||||
.select<{
|
||||
country: string;
|
||||
city: string;
|
||||
count: number;
|
||||
avg_duration: number;
|
||||
}>([
|
||||
'country',
|
||||
'city',
|
||||
'COUNT(*) as count',
|
||||
'round(avg(duration)/1000, 2) as avg_duration',
|
||||
])
|
||||
.from(TABLE_NAMES.events)
|
||||
.where('project_id', '=', input.projectId)
|
||||
.where(
|
||||
'created_at',
|
||||
'>=',
|
||||
formatClickhouseDate(subMinutes(new Date(), 30)),
|
||||
)
|
||||
.groupBy(['country', 'city'])
|
||||
.orderBy('count', 'DESC')
|
||||
.limit(100)
|
||||
.execute();
|
||||
|
||||
return res;
|
||||
}),
|
||||
});
|
||||
Reference in New Issue
Block a user