feat: make pageviewstats can return data

This commit is contained in:
moonrailgun 2023-09-15 00:53:03 +08:00
parent 78133b7227
commit ba0b398719
6 changed files with 51 additions and 19 deletions

6
src/server/init.ts Normal file
View File

@ -0,0 +1,6 @@
(BigInt.prototype as any).toJSON = function () {
const int = Number.parseInt(this.toString());
return int ?? this.toString();
};
export {};

View File

@ -1,4 +1,5 @@
import 'dotenv/config';
import './init';
import express from 'express';
import 'express-async-errors';
import ViteExpress from 'vite-express';

View File

@ -1,6 +1,7 @@
import { prisma } from './_client';
import { QueryFilters, parseFilters, getDateQuery } from '../utils/prisma';
import { DEFAULT_RESET_DATE, EVENT_TYPE } from '../utils/const';
import { Prisma } from '@prisma/client';
export async function getWorkspaceUser(workspaceId: string, userId: string) {
const info = await prisma.workspacesOnUsers.findFirst({
@ -115,15 +116,14 @@ export async function getWorkspaceWebsitePageviewStats(
return prisma.$queryRaw`
select
${getDateQuery('website_event.created_at', unit, timezone)} x,
count(*) y
from website_event
${joinSession}
where website_event.website_id = ${params.websiteId}
and website_event.created_at
between ${params.startDate} and ${(params as any).endDate}
and event_type = {{eventType}}
${filterQuery}
${getDateQuery('"WebsiteEvent"."createdAt"', unit, timezone)} x,
count(1) y
from "WebsiteEvent"
${joinSession ? Prisma.sql([joinSession]) : Prisma.empty}
where "WebsiteEvent"."websiteId" = ${params.websiteId}::uuid
and "WebsiteEvent"."createdAt"
between ${params.startDate}::timestamptz and ${params.endDate}::timestamptz
and "WebsiteEvent"."eventType" = ${EVENT_TYPE.pageView}
group by 1
`;
}

View File

@ -139,7 +139,9 @@ workspaceRouter.get(
'/:workspaceId/website/:websiteId/pageviews',
validate(
param('workspaceId').isUUID().withMessage('workspaceId should be UUID'),
param('websiteId').isUUID().withMessage('workspaceId should be UUID')
param('websiteId').isUUID().withMessage('workspaceId should be UUID'),
query('startAt').isNumeric().withMessage('startAt should be number'),
query('endAt').isNumeric().withMessage('startAt should be number')
),
auth(),
workspacePermission(),
@ -184,11 +186,15 @@ workspaceRouter.get(
city,
};
const website = await getWorkspaceWebsitePageviewStats(
console.log('filters', filters);
const stats = await getWorkspaceWebsitePageviewStats(
websiteId,
filters as QueryFilters
);
res.json({ website });
console.log('stats', stats);
res.json({ stats });
}
);

View File

@ -3,10 +3,13 @@ import crypto from 'crypto';
import { DATA_TYPE } from './const';
import { DynamicDataType } from './types';
import dayjs from 'dayjs';
import minMax from 'dayjs/plugin/minMax';
import jwt from 'jsonwebtoken';
import _ from 'lodash';
import { getWorkspaceWebsiteDateRange } from '../model/workspace';
dayjs.extend(minMax);
export function isUuid(value: string) {
return validate(value);
}
@ -152,7 +155,7 @@ export function parseToken(token: string, secret = jwtSecret) {
}
export function maxDate(...args: any[]) {
return _.max(args.filter((n) => dayjs(n).isValid()));
return dayjs.max(args.filter((n) => dayjs(n).isValid()));
}
export async function parseDateRange({

View File

@ -1,3 +1,5 @@
import { Prisma } from '@prisma/client';
import dayjs from 'dayjs';
import _ from 'lodash';
import { loadWebsite } from '../model/website';
import { maxDate } from './common';
@ -50,14 +52,22 @@ export async function parseFilters(
return {
joinSession:
options?.joinSession ||
Object.keys(filters).find((key) => SESSION_COLUMNS.includes(key))
? `inner join session on website_event.session_id = session.session_id`
Object.entries(filters).find(
([key, value]) =>
typeof value !== 'undefined' && SESSION_COLUMNS.includes(key)
)
? `inner join "WebsiteSession" on "WebsiteEvent"."sessionId" = "WebsiteSession"."id"`
: '',
filterQuery: getFilterQuery(filters, options),
params: {
...normalizeFilters(filters),
websiteId,
startDate: maxDate(filters.startDate, website.resetAt),
startDate: dayjs(
maxDate(filters.startDate, website.resetAt)
).toISOString(),
endDate: filters.endDate
? dayjs(filters.endDate).toISOString()
: undefined,
websiteDomain: website.domain,
},
};
@ -82,6 +92,8 @@ export function getFilterQuery(
const operator = value?.filter ?? OPERATORS.equals;
const column = _.get(FILTER_COLUMNS, name, options?.columns?.[name]);
// TODO
if (value !== undefined && column) {
arr.push(`and ${mapFilter(column, operator, name)}`);
@ -118,9 +130,13 @@ export function getDateQuery(
field: string,
unit: keyof typeof POSTGRESQL_DATE_FORMATS,
timezone?: string
): string {
) {
if (timezone) {
return `to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${POSTGRESQL_DATE_FORMATS[unit]}')`;
return Prisma.sql([
`to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${POSTGRESQL_DATE_FORMATS[unit]}')`,
]);
}
return `to_char(date_trunc('${unit}', ${field}), '${POSTGRESQL_DATE_FORMATS[unit]}')`;
return Prisma.sql([
`to_char(date_trunc('${unit}', ${field}), '${POSTGRESQL_DATE_FORMATS[unit]}')`,
]);
}