Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Mike Cao 2025-10-14 21:59:45 -07:00
commit 5c3a6ce8ce
12 changed files with 91 additions and 44 deletions

2
pnpm-lock.yaml generated
View file

@ -364,8 +364,6 @@ importers:
specifier: ^5.9.3
version: 5.9.3
dist: {}
packages:
'@ampproject/remapping@2.3.0':

View file

@ -24,22 +24,26 @@ export async function GET(request: Request) {
const teams = await getTeams(
{
include: {
_count: {
select: {
members: true,
websites: true,
},
},
members: {
select: {
include: {
user: {
omit: {
password: true,
select: {
id: true,
username: true,
},
},
},
where: {
role: 'team-owner',
},
_count: {
select: {
websites: {
where: { deletedAt: null },
},
members: {
where: {
user: { deletedAt: null },
},
},
},
},
},

View file

@ -1,6 +1,6 @@
import { z } from 'zod';
import { uuid } from '@/lib/crypto';
import { pagingParams, reportSchema } from '@/lib/schema';
import { pagingParams, reportSchema, reportTypeParam } from '@/lib/schema';
import { parseRequest } from '@/lib/request';
import { canViewWebsite, canUpdateWebsite } from '@/permissions';
import { unauthorized, json } from '@/lib/response';
@ -9,7 +9,7 @@ import { getReports, createReport } from '@/queries/prisma';
export async function GET(request: Request) {
const schema = z.object({
websiteId: z.uuid(),
type: z.string().optional(),
type: reportTypeParam.optional(),
...pagingParams,
});

View file

@ -26,9 +26,9 @@ export async function GET(request: Request, { params }: { params: Promise<{ user
export async function POST(request: Request, { params }: { params: Promise<{ userId: string }> }) {
const schema = z.object({
username: z.string().max(255),
username: z.string().max(255).optional(),
password: z.string().max(255).optional(),
role: userRoleParam,
role: userRoleParam.optional(),
});
const { auth, body, error } = await parseRequest(request, schema);

View file

@ -3,15 +3,16 @@ import { getQueryFilters, parseRequest } from '@/lib/request';
import { unauthorized, json } from '@/lib/response';
import { canViewWebsite } from '@/permissions';
import { getEventDataProperties } from '@/queries/sql';
import { dateRangeParams, filterParams } from '@/lib/schema';
export async function GET(
request: Request,
{ params }: { params: Promise<{ websiteId: string }> },
) {
const schema = z.object({
startAt: z.coerce.number().int(),
endAt: z.coerce.number().int(),
propertyName: z.string().optional(),
...dateRangeParams,
...filterParams,
});
const { auth, query, error } = await parseRequest(request, schema);

View file

@ -3,16 +3,17 @@ import { getQueryFilters, parseRequest } from '@/lib/request';
import { unauthorized, json } from '@/lib/response';
import { canViewWebsite } from '@/permissions';
import { getEventDataValues } from '@/queries/sql';
import { dateRangeParams, filterParams } from '@/lib/schema';
export async function GET(
request: Request,
{ params }: { params: Promise<{ websiteId: string }> },
) {
const schema = z.object({
startAt: z.coerce.number().int(),
endAt: z.coerce.number().int(),
eventName: z.string().optional(),
propertyName: z.string().optional(),
...dateRangeParams,
...filterParams,
});
const { auth, query, error } = await parseRequest(request, schema);

View file

@ -5,12 +5,22 @@ import { ReactQueryOptions } from '@/lib/types';
export function useEventDataEventsQuery(websiteId: string, options?: ReactQueryOptions) {
const { get, useQuery } = useApi();
const date = useDateParameters();
const { startAt, endAt, unit, timezone } = useDateParameters();
const filters = useFilterParameters();
return useQuery({
queryKey: ['websites:event-data:events', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/event-data/events`, { ...date, ...filters }),
queryKey: [
'websites:event-data:events',
{ websiteId, startAt, endAt, unit, timezone, ...filters },
],
queryFn: () =>
get(`/websites/${websiteId}/event-data/events`, {
startAt,
endAt,
unit,
timezone,
...filters,
}),
enabled: !!websiteId,
...options,
});

View file

@ -5,12 +5,22 @@ import { ReactQueryOptions } from '@/lib/types';
export function useEventDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions) {
const { get, useQuery } = useApi();
const date = useDateParameters();
const { startAt, endAt, unit, timezone } = useDateParameters();
const filters = useFilterParameters();
return useQuery<any>({
queryKey: ['websites:event-data:properties', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/event-data/properties`, { ...date, ...filters }),
queryKey: [
'websites:event-data:properties',
{ websiteId, startAt, endAt, unit, timezone, ...filters },
],
queryFn: () =>
get(`/websites/${websiteId}/event-data/properties`, {
startAt,
endAt,
unit,
timezone,
...filters,
}),
enabled: !!websiteId,
...options,
});

View file

@ -5,12 +5,22 @@ import { ReactQueryOptions } from '@/lib/types';
export function useEventDataQuery(websiteId: string, eventId: string, options?: ReactQueryOptions) {
const { get, useQuery } = useApi();
const date = useDateParameters();
const { startAt, endAt, unit, timezone } = useDateParameters();
const params = useFilterParameters();
return useQuery({
queryKey: ['websites:event-data', { websiteId, eventId, ...date, ...params }],
queryFn: () => get(`/websites/${websiteId}/event-data/${eventId}`, { ...date, ...params }),
queryKey: [
'websites:event-data',
{ websiteId, eventId, startAt, endAt, unit, timezone, ...params },
],
queryFn: () =>
get(`/websites/${websiteId}/event-data/${eventId}`, {
startAt,
endAt,
unit,
timezone,
...params,
}),
enabled: !!(websiteId && eventId),
...options,
});

View file

@ -1,7 +1,7 @@
import { useApi } from '../useApi';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
import { useApi } from '../useApi';
import { useDateParameters } from '../useDateParameters';
import { useFilterParameters } from '../useFilterParameters';
export function useEventDataValuesQuery(
websiteId: string,
@ -10,17 +10,20 @@ export function useEventDataValuesQuery(
options?: ReactQueryOptions,
) {
const { get, useQuery } = useApi();
const date = useDateParameters();
const { startAt, endAt, unit, timezone } = useDateParameters();
const filters = useFilterParameters();
return useQuery<any>({
queryKey: [
'websites:event-data:values',
{ websiteId, eventName, propertyName, ...date, ...filters },
{ websiteId, eventName, propertyName, startAt, endAt, unit, timezone, ...filters },
],
queryFn: () =>
get(`/websites/${websiteId}/event-data/values`, {
...date,
startAt,
endAt,
unit,
timezone,
...filters,
eventName,
propertyName,

View file

@ -68,10 +68,15 @@ async function clickhouseQuery(
event_name as eventName,
data_key as propertyName,
count(*) as total
from event_data website_event
from event_data
join website_event
on website_event.event_id = event_data.event_id
and website_event.website_id = event_data.website_id
and website_event.website_id = {websiteId:UUID}
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
where event_data.website_id = {websiteId:UUID}
and event_data.created_at between {startDate:DateTime64} and {endDate:DateTime64}
${filterQuery}
group by event_name, data_key
order by 1, 3 desc

View file

@ -75,12 +75,17 @@ async function clickhouseQuery(
data_type = 4, toString(date_trunc('hour', date_value)),
string_value) as "value",
count(*) as "total"
from event_data website_event
from event_data
join website_event
on website_event.event_id = event_data.event_id
and website_event.website_id = event_data.website_id
and website_event.website_id = {websiteId:UUID}
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and data_key = {propertyName:String}
and event_name = {eventName:String}
where event_data.website_id = {websiteId:UUID}
and event_data.created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_data.data_key = {propertyName:String}
and event_data.event_name = {eventName:String}
${filterQuery}
group by value
order by 2 desc