2023-10-14 16:39:14 +00:00
|
|
|
import { router, workspaceOwnerProcedure, workspaceProcedure } from '../trpc';
|
2023-09-28 10:01:04 +00:00
|
|
|
import { z } from 'zod';
|
|
|
|
import { getWebsiteOnlineUserCount } from '../../model/website';
|
2023-10-06 07:04:55 +00:00
|
|
|
import { prisma } from '../../model/_client';
|
2023-10-06 14:08:15 +00:00
|
|
|
import {
|
|
|
|
EVENT_COLUMNS,
|
|
|
|
FILTER_COLUMNS,
|
|
|
|
SESSION_COLUMNS,
|
|
|
|
} from '../../utils/const';
|
|
|
|
import { parseDateRange } from '../../utils/common';
|
|
|
|
import { getSessionMetrics, getPageviewMetrics } from '../../model/website';
|
2023-09-28 10:01:04 +00:00
|
|
|
|
|
|
|
export const websiteRouter = router({
|
|
|
|
onlineCount: workspaceProcedure
|
|
|
|
.input(
|
|
|
|
z.object({
|
|
|
|
websiteId: z.string(),
|
|
|
|
})
|
|
|
|
)
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
const websiteId = input.websiteId;
|
|
|
|
|
|
|
|
const count = await getWebsiteOnlineUserCount(websiteId);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}),
|
2023-10-06 07:04:55 +00:00
|
|
|
info: workspaceProcedure
|
|
|
|
.input(
|
|
|
|
z.object({
|
|
|
|
websiteId: z.string(),
|
|
|
|
})
|
|
|
|
)
|
|
|
|
.query(async ({ input }) => {
|
2023-10-06 14:08:15 +00:00
|
|
|
const { websiteId } = input;
|
2023-10-06 07:04:55 +00:00
|
|
|
|
|
|
|
const website = await prisma.website.findUnique({
|
|
|
|
where: {
|
|
|
|
id: websiteId,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
return website;
|
|
|
|
}),
|
2023-10-06 14:08:15 +00:00
|
|
|
metrics: workspaceProcedure
|
|
|
|
.input(
|
|
|
|
z.object({
|
|
|
|
websiteId: z.string(),
|
|
|
|
type: z.enum([
|
|
|
|
'url',
|
|
|
|
'language',
|
|
|
|
'referrer',
|
|
|
|
'browser',
|
|
|
|
'os',
|
|
|
|
'device',
|
|
|
|
'country',
|
|
|
|
'event',
|
|
|
|
]),
|
|
|
|
startAt: z.number(),
|
|
|
|
endAt: z.number(),
|
|
|
|
url: z.string().optional(),
|
|
|
|
referrer: z.string().optional(),
|
|
|
|
title: z.string().optional(),
|
|
|
|
os: z.string().optional(),
|
|
|
|
browser: z.string().optional(),
|
|
|
|
device: z.string().optional(),
|
|
|
|
country: z.string().optional(),
|
|
|
|
region: z.string().optional(),
|
|
|
|
city: z.string().optional(),
|
|
|
|
language: z.string().optional(),
|
|
|
|
event: z.string().optional(),
|
|
|
|
})
|
|
|
|
)
|
2023-10-07 09:28:30 +00:00
|
|
|
.output(
|
|
|
|
z.array(
|
|
|
|
z.object({
|
2023-10-07 11:32:46 +00:00
|
|
|
x: z.string().nullable(),
|
|
|
|
y: z.number(),
|
2023-10-07 09:28:30 +00:00
|
|
|
})
|
|
|
|
)
|
|
|
|
)
|
2023-10-06 14:08:15 +00:00
|
|
|
.query(async ({ input }) => {
|
|
|
|
const {
|
|
|
|
websiteId,
|
|
|
|
type,
|
|
|
|
startAt,
|
|
|
|
endAt,
|
|
|
|
url,
|
|
|
|
referrer,
|
|
|
|
title,
|
|
|
|
os,
|
|
|
|
browser,
|
|
|
|
device,
|
|
|
|
country,
|
|
|
|
region,
|
|
|
|
city,
|
|
|
|
language,
|
|
|
|
event,
|
|
|
|
} = input;
|
|
|
|
|
|
|
|
const { startDate, endDate } = await parseDateRange({
|
|
|
|
websiteId,
|
|
|
|
startAt,
|
|
|
|
endAt,
|
|
|
|
});
|
|
|
|
|
|
|
|
const filters = {
|
|
|
|
startDate,
|
|
|
|
endDate,
|
|
|
|
url,
|
|
|
|
referrer,
|
|
|
|
title,
|
|
|
|
os,
|
|
|
|
browser,
|
|
|
|
device,
|
|
|
|
country,
|
|
|
|
region,
|
|
|
|
city,
|
|
|
|
language,
|
|
|
|
event,
|
|
|
|
};
|
|
|
|
|
|
|
|
const column = FILTER_COLUMNS[type] || type;
|
|
|
|
|
|
|
|
if (SESSION_COLUMNS.includes(type)) {
|
|
|
|
const data = await getSessionMetrics(websiteId, column, filters);
|
|
|
|
|
|
|
|
if (type === 'language') {
|
|
|
|
const combined: Record<string, any> = {};
|
|
|
|
|
|
|
|
for (const { x, y } of data) {
|
|
|
|
const key = String(x).toLowerCase().split('-')[0];
|
|
|
|
|
|
|
|
if (combined[key] === undefined) {
|
|
|
|
combined[key] = { x: key, y };
|
|
|
|
} else {
|
|
|
|
combined[key].y += y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-07 11:32:46 +00:00
|
|
|
return Object.values(combined).map((d) => ({
|
|
|
|
x: d.x,
|
|
|
|
y: Number(d.y),
|
|
|
|
}));
|
2023-10-06 14:08:15 +00:00
|
|
|
}
|
|
|
|
|
2023-10-07 11:32:46 +00:00
|
|
|
return data.map((d) => ({ x: d.x, y: Number(d.y) }));
|
2023-10-06 14:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (EVENT_COLUMNS.includes(type)) {
|
|
|
|
const data = await getPageviewMetrics(websiteId, column, filters);
|
|
|
|
|
2023-10-07 11:32:46 +00:00
|
|
|
return data.map((d) => ({ x: d.x, y: Number(d.y) }));
|
2023-10-06 14:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return [];
|
|
|
|
}),
|
2023-10-14 16:39:14 +00:00
|
|
|
updateInfo: workspaceOwnerProcedure
|
|
|
|
.input(
|
|
|
|
z.object({
|
|
|
|
websiteId: z.string().cuid(),
|
|
|
|
name: z.string().max(100),
|
|
|
|
domain: z.union([z.string().max(500).url(), z.string().max(500).ip()]),
|
|
|
|
})
|
|
|
|
)
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
const { workspaceId, websiteId, name, domain } = input;
|
|
|
|
|
|
|
|
const websiteInfo = await prisma.website.update({
|
|
|
|
where: {
|
|
|
|
id: websiteId,
|
|
|
|
workspaceId,
|
|
|
|
},
|
|
|
|
data: {
|
|
|
|
name,
|
|
|
|
domain,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
return websiteInfo;
|
|
|
|
}),
|
2023-09-28 10:01:04 +00:00
|
|
|
});
|