Fixed chart rendering when using date nav buttons.

This commit is contained in:
Mike Cao 2025-06-12 23:07:25 -07:00
parent 1649992654
commit 7b5591a3ce
18 changed files with 177 additions and 320 deletions

View file

@ -1,4 +1,5 @@
import { useMemo } from 'react';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { PageviewsChart } from '@/components/metrics/PageviewsChart';
import { useWebsitePageviewsQuery } from '@/components/hooks/queries/useWebsitePageviewsQuery';
import { useDateRange } from '@/components/hooks';
@ -12,7 +13,7 @@ export function WebsiteChart({
}) {
const { dateRange, dateCompare } = useDateRange(websiteId);
const { startDate, endDate, unit, value } = dateRange;
const { data, isLoading } = useWebsitePageviewsQuery(
const { data, isLoading, error } = useWebsitePageviewsQuery(
websiteId,
compareMode ? dateCompare : undefined,
);
@ -46,13 +47,14 @@ export function WebsiteChart({
}, [data, startDate, endDate, unit]);
return (
<PageviewsChart
data={chartData}
minDate={startDate.toISOString()}
maxDate={endDate.toISOString()}
unit={unit}
isLoading={isLoading}
isAllTime={value === 'all'}
/>
<LoadingPanel isLoading={isLoading} error={error}>
<PageviewsChart
key={value}
data={chartData}
minDate={value === 'all' ? undefined : startDate}
maxDate={endDate}
unit={unit}
/>
</LoadingPanel>
);
}

View file

@ -30,7 +30,7 @@ export function SessionProperties({ websiteId }: { websiteId: string }) {
: null;
return (
<LoadingPanel isLoading={isLoading} isFetched={isFetched} data={data} error={error}>
<LoadingPanel isLoading={isLoading} isFetched={isFetched} error={error}>
<div className={styles.container}>
<DataTable data={data} className={styles.table}>
<DataColumn id="propertyName" label={formatMessage(labels.property)}>
@ -45,7 +45,7 @@ export function SessionProperties({ websiteId }: { websiteId: string }) {
{propertyName && (
<div className={styles.chart}>
<div className={styles.title}>{propertyName}</div>
<PieChart key={propertyName} type="doughnut" data={chartData} />
<PieChart key={propertyName} type="doughnut" chartData={chartData} />
</div>
)}
</div>

View file

@ -6,7 +6,7 @@ import { getDayOfWeekAsDate } from '@/lib/date';
import { Focusable, Tooltip, TooltipTrigger } from '@umami/react-zen';
export function SessionsWeekly({ websiteId }: { websiteId: string }) {
const { data, ...props } = useWebsiteSessionsWeeklyQuery(websiteId);
const { data, isLoading, error } = useWebsiteSessionsWeeklyQuery(websiteId);
const { dateLocale } = useLocale();
const { labels, formatMessage } = useMessages();
const { weekStartsOn } = dateLocale.options;
@ -36,7 +36,7 @@ export function SessionsWeekly({ websiteId }: { websiteId: string }) {
: [];
return (
<LoadingPanel {...(props as any)} data={data}>
<LoadingPanel isEmpty={!data?.length} isLoading={isLoading} error={error}>
<Grid columns="repeat(8, 1fr)" gap>
<Grid rows="repeat(25, 20px)" gap="1">
<Row>&nbsp;</Row>

View file

@ -1,21 +0,0 @@
.timeline {
display: flex;
flex-direction: column;
gap: 20px;
}
.row {
display: grid;
grid-template-columns: max-content max-content 1fr;
align-items: center;
gap: 20px;
}
.time {
color: var(--font-color200);
width: 150px;
}
.header {
font-weight: bold;
}

View file

@ -1,9 +1,8 @@
import { isSameDay } from 'date-fns';
import { Loading, Icon, StatusLight } from '@umami/react-zen';
import { Bolt, Eye } from '@/components/icons';
import { Icon, StatusLight, Column, Row, Heading, Text, Button } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Bolt, Eye, FileText } from '@/components/icons';
import { useSessionActivityQuery, useTimezone } from '@/components/hooks';
import styles from './SessionActivity.module.css';
import { Fragment } from 'react';
export function SessionActivity({
websiteId,
@ -17,37 +16,46 @@ export function SessionActivity({
endDate: Date;
}) {
const { formatTimezoneDate } = useTimezone();
const { data, isLoading } = useSessionActivityQuery(websiteId, sessionId, startDate, endDate);
if (isLoading) {
return <Loading position="page" />;
}
const { data, isLoading, error } = useSessionActivityQuery(
websiteId,
sessionId,
startDate,
endDate,
);
let lastDay = null;
return (
<div className={styles.timeline}>
{data.map(({ id, createdAt, urlPath, eventName, visitId }) => {
const showHeader = !lastDay || !isSameDay(new Date(lastDay), new Date(createdAt));
lastDay = createdAt;
<LoadingPanel isEmpty={!data?.length} isLoading={isLoading} error={error}>
<Column gap>
{data?.map(({ eventId, createdAt, urlPath, eventName, visitId, hasData }) => {
const showHeader = !lastDay || !isSameDay(new Date(lastDay), new Date(createdAt));
lastDay = createdAt;
return (
<Fragment key={id}>
{showHeader && (
<div className={styles.header}>{formatTimezoneDate(createdAt, 'PPPP')}</div>
)}
<div className={styles.row}>
<div className={styles.time}>
return (
<Column key={eventId} gap>
{showHeader && <Heading size="2">{formatTimezoneDate(createdAt, 'PPPP')}</Heading>}
<Row alignItems="center" gap="6" height="40px">
<StatusLight color={`#${visitId?.substring(0, 6)}`}>
{formatTimezoneDate(createdAt, 'pp')}
</StatusLight>
</div>
<Icon>{eventName ? <Bolt /> : <Eye />}</Icon>
<div>{eventName || urlPath}</div>
</div>
</Fragment>
);
})}
</div>
<Row alignItems="center" gap>
<Icon>{eventName ? <Bolt /> : <Eye />}</Icon>
<Text>{eventName || urlPath}</Text>
{hasData > 0 && (
<Button variant="quiet">
<Row alignItems="center" gap>
<Icon>
<FileText />
</Icon>
</Row>
</Button>
)}
</Row>
</Row>
</Column>
);
})}
</Column>
</LoadingPanel>
);
}