feat: add others metrics in website detail

This commit is contained in:
moonrailgun 2023-10-07 19:32:46 +08:00
parent 0e71e073fc
commit 086c8ee3df
6 changed files with 85 additions and 29 deletions

View File

@ -3,7 +3,7 @@ import type { AppRouter } from '../../server/trpc/routers';
import { httpBatchLink, TRPCClientErrorLike } from '@trpc/client';
import { getJWT } from './auth';
import { message } from 'antd';
import { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
export const trpc = createTRPCReact<AppRouter>();

View File

@ -1,11 +1,13 @@
import { Table } from 'antd';
import { ColumnsType } from 'antd/es/table/interface';
import React from 'react';
import { trpc } from '../../api/trpc';
import { RouterOutput, trpc } from '../../api/trpc';
import { useCurrentWorkspaceId } from '../../store/user';
import { sum } from 'lodash-es';
import millify from 'millify';
type MetricsItemType = RouterOutput['website']['metrics'][number];
interface MetricsTableProps {
websiteId: string;
title: [string, string];
@ -35,10 +37,11 @@ export const MetricsTable: React.FC<MetricsTableProps> = React.memo((props) => {
const total = sum(metrics.map((m) => m.y));
const columns: ColumnsType<{ x: string; y: number }> = [
const columns: ColumnsType<MetricsItemType> = [
{
title: title[0],
dataIndex: 'x',
render: (val) => val ?? <span className="italic">(None)</span>,
},
{
title: title[1],
@ -55,7 +58,7 @@ export const MetricsTable: React.FC<MetricsTableProps> = React.memo((props) => {
lowercase: true,
})}
</div>
<div className="inline-block w-10 relative border-l ml-1 pl-1">
<div className="inline-block w-12 relative border-l ml-1 px-1">
<div
className="bg-blue-300 absolute h-full bg-opacity-25 left-0 top-0 pointer-events-none"
style={{ width: `${percent}%` }}

View File

@ -1,12 +0,0 @@
import React from 'react';
import { MetricsTable } from './MetricsTable';
interface PagesTableProps {
websiteId: string;
startAt: number;
endAt: number;
}
export const PagesTable: React.FC<PagesTableProps> = React.memo((props) => {
return <MetricsTable {...props} type="url" title={['Pages', 'Views']} />;
});
PagesTable.displayName = 'PagesTable';

View File

@ -6,7 +6,7 @@ import { trpc } from '../../api/trpc';
import { ErrorTip } from '../../components/ErrorTip';
import { Loading } from '../../components/Loading';
import { NotFoundTip } from '../../components/NotFoundTip';
import { PagesTable } from '../../components/website/PagesTable';
import { MetricsTable } from '../../components/website/MetricsTable';
import { WebsiteOverview } from '../../components/website/WebsiteOverview';
import { useCurrentWorkspaceId } from '../../store/user';
@ -30,21 +30,83 @@ export const WebsiteDetail: React.FC = React.memo(() => {
return <NotFoundTip />;
}
const startAt = dayjs().subtract(1, 'day').unix() * 1000;
const endAt = dayjs().unix() * 1000;
return (
<div className="py-6">
<Card>
<Card.Grid hoverable={false} className="!w-full">
<WebsiteOverview website={website} />
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/2">
<PagesTable
<Card.Grid hoverable={false} className="!w-1/2 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
startAt={dayjs().subtract(1, 'day').unix() * 1000}
endAt={dayjs().unix() * 1000}
type="url"
title={['Pages', 'Views']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/2">
right
<Card.Grid hoverable={false} className="!w-1/2 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
type="referrer"
title={['Referrers', 'Views']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/3 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
type="browser"
title={['Browser', 'Visitors']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/3 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
type="os"
title={['OS', 'Visitors']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/3 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
type="device"
title={['Devices', 'Visitors']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-2/3 min-h-[470px]">
{/* Map */}
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/3 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
type="country"
title={['Countries', 'Visitors']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-1/3 min-h-[470px]">
<MetricsTable
websiteId={websiteId}
type="event"
title={['Events', 'Actions']}
startAt={startAt}
endAt={endAt}
/>
</Card.Grid>
<Card.Grid hoverable={false} className="!w-2/3 min-h-[470px]">
{/* Events */}
</Card.Grid>
</Card>
</div>

View File

@ -292,7 +292,7 @@ export async function getSessionMetrics(
const includeCountry = column === 'city' || column === 'subdivision1';
return prisma.$queryRaw`select
${column} x,
${Prisma.sql([`"${column}"`])} x,
count(distinct "WebsiteEvent"."sessionId") y
${includeCountry ? Prisma.sql([', country']) : Prisma.empty}
from "WebsiteEvent"

View File

@ -73,8 +73,8 @@ export const websiteRouter = router({
.output(
z.array(
z.object({
x: z.string(),
y: z.bigint(),
x: z.string().nullable(),
y: z.number(),
})
)
)
@ -137,16 +137,19 @@ export const websiteRouter = router({
}
}
return Object.values(combined);
return Object.values(combined).map((d) => ({
x: d.x,
y: Number(d.y),
}));
}
return data;
return data.map((d) => ({ x: d.x, y: Number(d.y) }));
}
if (EVENT_COLUMNS.includes(type)) {
const data = await getPageviewMetrics(websiteId, column, filters);
return data;
return data.map((d) => ({ x: d.x, y: Number(d.y) }));
}
return [];