Added query hooks for website events and metrics.

This commit is contained in:
Mike Cao 2024-01-30 18:25:41 -08:00
parent c5046d0043
commit c7df1063ac
5 changed files with 94 additions and 57 deletions

View File

@ -11,6 +11,8 @@ export * from './queries/useUser';
export * from './queries/useUsers'; export * from './queries/useUsers';
export * from './queries/useWebsite'; export * from './queries/useWebsite';
export * from './queries/useWebsites'; export * from './queries/useWebsites';
export * from './queries/useWebsiteEvents';
export * from './queries/useWebsiteMetrics';
export * from './useCountryNames'; export * from './useCountryNames';
export * from './useDateRange'; export * from './useDateRange';
export * from './useDocumentClick'; export * from './useDocumentClick';

View File

@ -0,0 +1,19 @@
import useApi from './useApi';
import { UseQueryOptions } from '@tanstack/react-query';
export function useWebsiteEvents(
websiteId: string,
params?: { [key: string]: any },
options?: Omit<UseQueryOptions, 'queryKey' | 'queryFn'>,
) {
const { get, useQuery } = useApi();
return useQuery({
queryKey: ['events', { ...params }],
queryFn: () => get(`/websites/${websiteId}/events`, { ...params }),
enabled: !!websiteId,
...options,
});
}
export default useWebsiteEvents;

View File

@ -0,0 +1,34 @@
import useApi from './useApi';
import { UseQueryOptions } from '@tanstack/react-query';
export function useWebsiteMetrics(
websiteId: string,
params?: { [key: string]: any },
options?: Omit<UseQueryOptions, 'queryKey' | 'queryFn'>,
) {
const { get, useQuery } = useApi();
return useQuery({
queryKey: [
'websites:metrics',
{
websiteId,
...params,
},
],
queryFn: async () => {
const filters = { ...params };
filters[params.type] = undefined;
const data = await get(`/websites/${websiteId}/metrics`, {
...filters,
});
return data;
},
...options,
});
}
export default useWebsiteMetrics;

View File

@ -3,7 +3,13 @@ import { Loading } from 'react-basics';
import { colord } from 'colord'; import { colord } from 'colord';
import BarChart from './BarChart'; import BarChart from './BarChart';
import { getDateArray } from 'lib/date'; import { getDateArray } from 'lib/date';
import { useApi, useLocale, useDateRange, useTimezone, useNavigation } from 'components/hooks'; import {
useLocale,
useDateRange,
useTimezone,
useNavigation,
useWebsiteEvents,
} from 'components/hooks';
import { EVENT_COLORS } from 'lib/constants'; import { EVENT_COLORS } from 'lib/constants';
import { renderDateLabels, renderStatusTooltipPopup } from 'lib/charts'; import { renderDateLabels, renderStatusTooltipPopup } from 'lib/charts';
@ -14,34 +20,29 @@ export interface EventsChartProps {
} }
export function EventsChart({ websiteId, className, token }: EventsChartProps) { export function EventsChart({ websiteId, className, token }: EventsChartProps) {
const { get, useQuery } = useApi(); const [{ startDate, endDate, unit, offset }] = useDateRange(websiteId);
const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId);
const { locale } = useLocale(); const { locale } = useLocale();
const [timezone] = useTimezone(); const [timezone] = useTimezone();
const { const {
query: { url, event }, query: { url, event },
} = useNavigation(); } = useNavigation();
const { data, isLoading } = useQuery({ const { data, isLoading } = useWebsiteEvents(websiteId, {
queryKey: ['events', websiteId, modified, event], startAt: +startDate,
queryFn: () => endAt: +endDate,
get(`/websites/${websiteId}/events`, { unit,
startAt: +startDate, timezone,
endAt: +endDate, url,
unit, event,
timezone, token,
url, offset,
event,
token,
}),
enabled: !!websiteId,
}); });
const datasets = useMemo(() => { const datasets = useMemo(() => {
if (!data) return []; if (!data) return [];
if (isLoading) return data; if (isLoading) return data;
const map = data.reduce((obj, { x, t, y }) => { const map = (data as any[]).reduce((obj, { x, t, y }) => {
if (!obj[x]) { if (!obj[x]) {
obj[x] = []; obj[x] = [];
} }
@ -75,7 +76,7 @@ export function EventsChart({ websiteId, className, token }: EventsChartProps) {
return ( return (
<BarChart <BarChart
className={className} className={className}
datasets={datasets} datasets={datasets as any[]}
unit={unit} unit={unit}
stacked={true} stacked={true}
renderXLabel={renderDateLabels(unit, locale)} renderXLabel={renderDateLabels(unit, locale)}

View File

@ -1,7 +1,6 @@
import { ReactNode, useMemo, useState } from 'react'; import { ReactNode, useMemo, useState } from 'react';
import { Loading, Icon, Text, SearchField } from 'react-basics'; import { Loading, Icon, Text, SearchField } from 'react-basics';
import classNames from 'classnames'; import classNames from 'classnames';
import { useApi } from 'components/hooks';
import { percentFilter } from 'lib/filters'; import { percentFilter } from 'lib/filters';
import { useDateRange } from 'components/hooks'; import { useDateRange } from 'components/hooks';
import { useNavigation } from 'components/hooks'; import { useNavigation } from 'components/hooks';
@ -14,6 +13,7 @@ import { useMessages } from 'components/hooks';
import { useLocale } from 'components/hooks'; import { useLocale } from 'components/hooks';
import useFormat from 'components//hooks/useFormat'; import useFormat from 'components//hooks/useFormat';
import styles from './MetricsTable.module.css'; import styles from './MetricsTable.module.css';
import useWebsiteMetrics from 'components/hooks/queries/useWebsiteMetrics';
export interface MetricsTableProps extends ListTableProps { export interface MetricsTableProps extends ListTableProps {
websiteId: string; websiteId: string;
@ -43,55 +43,36 @@ export function MetricsTable({
}: MetricsTableProps) { }: MetricsTableProps) {
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const { formatValue } = useFormat(); const { formatValue } = useFormat();
const [{ startDate, endDate, modified }] = useDateRange(websiteId); const [{ startDate, endDate }] = useDateRange(websiteId);
const { const {
renderUrl, renderUrl,
query: { url, referrer, title, os, browser, device, country, region, city }, query: { url, referrer, title, os, browser, device, country, region, city },
} = useNavigation(); } = useNavigation();
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const { get, useQuery } = useApi();
const { dir } = useLocale(); const { dir } = useLocale();
const { data, isLoading, isFetched, error } = useQuery({
queryKey: [
'websites:metrics',
{
websiteId,
type,
modified,
url,
referrer,
os,
title,
browser,
device,
country,
region,
city,
},
],
queryFn: async () => {
const filters = { url, title, referrer, os, browser, device, country, region, city };
filters[type] = undefined; const { data, isLoading, isFetched, error } = useWebsiteMetrics(
websiteId,
const data = await get(`/websites/${websiteId}/metrics`, { {
type, type,
startAt: +startDate, startAt: +startDate,
endAt: +endDate, endAt: +endDate,
limit, url,
...filters, referrer,
}); os,
title,
onDataLoad?.(data); browser,
device,
return data; country,
region,
city,
}, },
retryDelay: delay || DEFAULT_ANIMATION_DURATION, { retryDelay: delay || DEFAULT_ANIMATION_DURATION },
}); );
const filteredData = useMemo(() => { const filteredData = useMemo(() => {
if (data) { if (data) {
let items: any[] = data; let items = data as any[];
if (dataFilter) { if (dataFilter) {
if (Array.isArray(dataFilter)) { if (Array.isArray(dataFilter)) {