implement pageviews, events, and channels queries

This commit is contained in:
Francis Cao 2025-08-05 00:37:44 -07:00
parent c1cad16cb9
commit 0a0c1f27c6
24 changed files with 521 additions and 86 deletions

View file

@ -5,7 +5,7 @@ import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export type WebsiteExpandedMetricsData = {
label: string;
name: string;
pageviews: number;
visitors: number;
visits: number;

View file

@ -0,0 +1,7 @@
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 300px;
display: block;
}

View file

@ -2,23 +2,25 @@ import { useMessages } from '@/components/hooks';
import { formatShortTime } from '@/lib/format';
import { DataColumn, DataTable } from '@umami/react-zen';
import { ReactNode } from 'react';
import styles from './ListExpandedTable.module.css';
export interface ListExpandedTableProps {
data?: any[];
title?: string;
type?: string;
renderLabel?: (row: any, index: number) => ReactNode;
}
export function ListExpandedTable({ data = [], title, renderLabel }: ListExpandedTableProps) {
export function ListExpandedTable({ data = [], title, type, renderLabel }: ListExpandedTableProps) {
const { formatMessage, labels } = useMessages();
return (
<DataTable data={data}>
<DataColumn id="label" label={title} align="start" width="300px">
<DataColumn id="label" label={title} align="start" className={styles.truncate}>
{row =>
renderLabel
? renderLabel({ x: row?.label, country: row?.['country'] }, Number(row.id))
: (row.label ?? formatMessage(labels.unknown))
? renderLabel({ x: row?.['name'], country: row?.['country'] }, Number(row.id))
: (row?.['name'] ?? formatMessage(labels.unknown))
}
</DataColumn>
<DataColumn id="visitors" label={formatMessage(labels.visitors)} align="end">
@ -30,18 +32,26 @@ export function ListExpandedTable({ data = [], title, renderLabel }: ListExpande
<DataColumn id="pageviews" label={formatMessage(labels.views)} align="end">
{row => row?.['pageviews']?.toLocaleString()}
</DataColumn>
<DataColumn id="bounceRate" label={formatMessage(labels.bounceRate)} align="end">
{row => {
const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100;
return Math.round(+n) + '%';
}}
</DataColumn>
<DataColumn id="visitDuration" label={formatMessage(labels.visitDuration)} align="end">
{row => {
const n = (row?.['totaltime'] / row?.['visits']) * 100;
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
}}
</DataColumn>
{type !== 'exit' && type !== 'entry' ? (
<DataColumn id="bounceRate" label={formatMessage(labels.bounceRate)} align="end">
{row => {
const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100;
return Math.round(+n) + '%';
}}
</DataColumn>
) : (
<></>
)}
{type !== 'exit' && type !== 'entry' ? (
<DataColumn id="visitDuration" label={formatMessage(labels.visitDuration)} align="end">
{row => {
const n = (row?.['totaltime'] / row?.['visits']) * 100;
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
}}
</DataColumn>
) : (
<></>
)}
</DataTable>
);
}

View file

@ -56,7 +56,6 @@ export function MetricsTable({
websiteId,
{
type,
limit: 30,
search: searchFormattedValues ? undefined : search,
...params,
},
@ -111,6 +110,8 @@ export function MetricsTable({
return [];
}, [data, dataFilter, search, limit, formatValue, type]);
const downloadData = expanded ? data : filteredData;
return (
<Column gap="3" justifyContent="space-between">
<LoadingPanel data={data} isFetching={isFetching} isLoading={isLoading} error={error} gap>
@ -118,12 +119,12 @@ export function MetricsTable({
{allowSearch && <SearchField value={search} onSearch={setSearch} delay={300} />}
<Row>
{children}
{allowDownload && <DownloadButton filename={type} data={filteredData} />}
{allowDownload && <DownloadButton filename={type} data={downloadData} />}
</Row>
</Row>
{data &&
(expanded ? (
<ListExpandedTable {...(props as ListExpandedTableProps)} data={data} />
<ListExpandedTable {...(props as ListExpandedTableProps)} data={data} type={type} />
) : (
<ListTable {...(props as ListTableProps)} data={filteredData} />
))}

View file

@ -58,6 +58,7 @@ export function QueryParametersTable({
dataFilter={filters[filter]}
renderLabel={renderLabel}
delay={0}
expanded={false}
>
{allowFilter && <FilterButtons items={buttons} value={filter} onChange={setFilter} />}
</MetricsTable>