fix: improvements for frontend

This commit is contained in:
Carl-Gerhard Lindesvärd
2025-11-04 11:03:32 +01:00
parent 3474fbd12d
commit b51bc8f3f6
38 changed files with 487 additions and 415 deletions

View File

@@ -680,12 +680,10 @@ clix.toStartOf = (node: string, interval: IInterval, timezone?: string) => {
return `toStartOfDay(${node})`;
}
case 'week': {
// Does not respect timezone settings (session_timezone) so we need to pass it manually
return `toStartOfWeek(${node}${timezone ? `, 1, '${timezone}'` : ''})`;
return `toStartOfWeek(toDateTime(${node}))`;
}
case 'month': {
// Does not respect timezone settings (session_timezone) so we need to pass it manually
return `toStartOfMonth(${node}${timezone ? `, '${timezone}'` : ''})`;
return `toStartOfMonth(toDateTime(${node}))`;
}
}
};

View File

@@ -1,4 +1,4 @@
import { path, assocPath, last, mergeDeepRight } from 'ramda';
import { path, assocPath, last, mergeDeepRight, uniq } from 'ramda';
import sqlstring from 'sqlstring';
import { v4 as uuid } from 'uuid';
@@ -561,6 +561,15 @@ export async function getEventList(options: GetEventListOptions) {
...sb.where,
...getEventFiltersWhereClause(filters),
};
// Join profiles table if any filter uses profile fields
const profileFilters = filters
.filter((f) => f.name.startsWith('profile.'))
.map((f) => f.name.replace('profile.', ''));
if (profileFilters.length > 0) {
sb.joins.profiles = `LEFT ANY JOIN (SELECT id, ${uniq(profileFilters.map((f) => f.split('.')[0])).join(', ')} FROM ${TABLE_NAMES.profiles} FINAL WHERE project_id = ${sqlstring.escape(projectId)}) as profile on profile.id = profile_id`;
}
}
sb.orderBy.created_at =
@@ -622,6 +631,15 @@ export async function getEventsCount({
...sb.where,
...getEventFiltersWhereClause(filters),
};
// Join profiles table if any filter uses profile fields
const profileFilters = filters
.filter((f) => f.name.startsWith('profile.'))
.map((f) => f.name.replace('profile.', ''));
if (profileFilters.length > 0) {
sb.joins.profiles = `LEFT ANY JOIN (SELECT id, ${uniq(profileFilters.map((f) => f.split('.')[0])).join(', ')} FROM ${TABLE_NAMES.profiles} FINAL WHERE project_id = ${sqlstring.escape(projectId)}) as profile on profile.id = profile_id`;
}
}
const res = await chQuery<{ count: number }>(
@@ -701,6 +719,7 @@ class EventService {
select,
limit,
orderBy,
filters,
}: {
projectId: string;
profileId?: string;
@@ -715,7 +734,14 @@ class EventService {
};
limit?: number;
orderBy?: keyof IClickhouseEvent;
filters?: IChartEventFilter[];
}) {
// Extract profile filters if any
const profileFilters =
filters
?.filter((f) => f.name.startsWith('profile.'))
.map((f) => f.name.replace('profile.', '')) ?? [];
const events = clix(this.client)
.select<
Partial<IClickhouseEvent> & {
@@ -744,6 +770,12 @@ class EventService {
])
.from('events e')
.where('project_id', '=', projectId)
.when(profileFilters.length > 0, (q) => {
q.leftJoin(
`(SELECT id, ${uniq(profileFilters.map((f) => f.split('.')[0])).join(', ')} FROM ${TABLE_NAMES.profiles} FINAL WHERE project_id = ${sqlstring.escape(projectId)}) as profile`,
'profile.id = e.profile_id',
);
})
.when(!!where?.event, where?.event)
// Do not limit if profileId, we will limit later since we need the "correct" profileId
.when(!!limit && !profileId, (q) => q.limit(limit!))
@@ -941,6 +973,7 @@ class EventService {
profileId,
limit,
orderBy: 'created_at',
filters,
select: {
event: {
deviceId: true,

View File

@@ -200,6 +200,12 @@ export class OverviewService {
])
.rawWhere(this.getRawWhereClause('events', filters));
// Use toDate for month/week intervals, toDateTime for others
const rollupDate =
interval === 'month' || interval === 'week'
? clix.date('1970-01-01')
: clix.datetime('1970-01-01 00:00:00');
return clix(this.client, timezone)
.with('session_agg', sessionAggQuery)
.with(
@@ -207,14 +213,14 @@ export class OverviewService {
clix(this.client, timezone)
.select(['bounce_rate'])
.from('session_agg')
.where('date', '=', clix.datetime('1970-01-01 00:00:00')),
.where('date', '=', rollupDate),
)
.with(
'daily_stats',
clix(this.client, timezone)
.select(['date', 'bounce_rate'])
.from('session_agg')
.where('date', '!=', clix.datetime('1970-01-01 00:00:00')),
.where('date', '!=', rollupDate),
)
.with('overall_unique_visitors', overallUniqueVisitorsQuery)
.select<{

View File

@@ -172,7 +172,7 @@ export const eventRouter = createTRPCRouter({
data: items,
meta: {
next:
items.length === 50 && lastItem
items.length > 0 && lastItem
? lastItem.createdAt.toISOString()
: null,
},
@@ -190,12 +190,19 @@ export const eventRouter = createTRPCRouter({
cursor: z.string().optional(),
startDate: z.date().optional(),
endDate: z.date().optional(),
events: z.array(z.string()).optional(),
}),
)
.query(async ({ input }) => {
const conversions = await getConversionEventNames(input.projectId);
const filteredConversions = conversions.filter((event) => {
if (input.events && input.events.length > 0) {
return input.events.includes(event.name);
}
return true;
});
if (conversions.length === 0) {
if (filteredConversions.length === 0) {
return {
data: [],
meta: {
@@ -220,7 +227,7 @@ export const eventRouter = createTRPCRouter({
origin: true,
},
custom: (sb) => {
sb.where.name = `name IN (${conversions.map((event) => sqlstring.escape(event.name)).join(',')})`;
sb.where.name = `name IN (${filteredConversions.map((event) => sqlstring.escape(event.name)).join(',')})`;
},
});
@@ -249,7 +256,7 @@ export const eventRouter = createTRPCRouter({
data: items,
meta: {
next:
items.length === 50 && lastItem
items.length > 0 && lastItem
? lastItem.createdAt.toISOString()
: null,
},
@@ -354,15 +361,11 @@ export const eventRouter = createTRPCRouter({
)
.query(async ({ input }) => {
const res = await chQuery<{ origin: string }>(
`SELECT DISTINCT origin FROM ${TABLE_NAMES.events} WHERE project_id = ${sqlstring.escape(
`SELECT DISTINCT origin, count(id) as count FROM ${TABLE_NAMES.events} WHERE project_id = ${sqlstring.escape(
input.projectId,
)} AND origin IS NOT NULL AND origin != '' AND toDate(created_at) > now() - INTERVAL 30 DAY ORDER BY origin ASC`,
)} AND origin IS NOT NULL AND origin != '' AND toDate(created_at) > now() - INTERVAL 30 DAY GROUP BY origin ORDER BY count DESC LIMIT 3`,
);
return res.sort((a, b) =>
a.origin
.replace(/https?:\/\//, '')
.localeCompare(b.origin.replace(/https?:\/\//, '')),
);
return res;
}),
});