Events filtering. Closes #3356

This commit is contained in:
Mike Cao 2025-04-25 18:06:41 -07:00
parent b8a582c8da
commit d4b786380b
4 changed files with 59 additions and 21 deletions

View file

@ -4,27 +4,33 @@ import EventsDataTable from './EventsDataTable';
import EventsMetricsBar from './EventsMetricsBar';
import EventsChart from '@/components/metrics/EventsChart';
import { GridRow } from '@/components/layout/Grid';
import MetricsTable from '@/components/metrics/MetricsTable';
import EventsTable from '@/components/metrics/EventsTable';
import { useMessages } from '@/components/hooks';
import { Item, Tabs } from 'react-basics';
import { useState } from 'react';
import EventProperties from './EventProperties';
export default function EventsPage({ websiteId }) {
const [label, setLabel] = useState(null);
const [tab, setTab] = useState('activity');
const { formatMessage, labels } = useMessages();
const handleLabelClick = (value: string) => {
setLabel(value !== label ? value : '');
};
return (
<>
<WebsiteHeader websiteId={websiteId} />
<EventsMetricsBar websiteId={websiteId} />
<GridRow columns="two-one">
<EventsChart websiteId={websiteId} />
<MetricsTable
<EventsChart websiteId={websiteId} focusLabel={label} />
<EventsTable
websiteId={websiteId}
type="event"
title={formatMessage(labels.events)}
metric={formatMessage(labels.actions)}
onLabelClick={handleLabelClick}
/>
</GridRow>
<div>

View file

@ -34,7 +34,7 @@ export function Chart({
className,
chartOptions,
}: ChartProps) {
const canvas = useRef();
const canvas = useRef(null);
const chart = useRef(null);
const [legendItems, setLegendItems] = useState([]);
@ -86,7 +86,7 @@ export function Chart({
dataset.data = data?.datasets[index]?.data;
if (chart.current.legend.legendItems[index]) {
chart.current.legend.legendItems[index].text = data?.datasets[index]?.label;
chart.current.legend.legendItems[index].text = data.datasets[index]?.label;
}
}
});
@ -95,6 +95,12 @@ export function Chart({
}
}
if (data.focusLabel !== null) {
chart.current.data.datasets.forEach(ds => {
ds.hidden = data.focusLabel ? ds.label !== data.focusLabel : false;
});
}
chart.current.options = options;
// Allow config changes before update
@ -105,16 +111,6 @@ export function Chart({
setLegendItems(chart.current.legend.legendItems);
};
useEffect(() => {
if (data) {
if (!chart.current) {
createChart(data);
} else {
updateChart(data);
}
}
}, [data, options]);
const handleLegendClick = (item: LegendItem) => {
if (type === 'bar') {
const { datasetIndex } = item;
@ -136,6 +132,16 @@ export function Chart({
setLegendItems(chart.current.legend.legendItems);
};
useEffect(() => {
if (data) {
if (!chart.current) {
createChart(data);
} else {
updateChart(data);
}
}
}, [data, options]);
return (
<>
<div className={classNames(styles.chart, className)}>

View file

@ -1,21 +1,23 @@
import { useMemo, useState, useEffect } from 'react';
import { colord } from 'colord';
import BarChart from '@/components/charts/BarChart';
import { useDateRange, useLocale, useWebsiteEventsSeries } from '@/components/hooks';
import { renderDateLabels } from '@/lib/charts';
import { CHART_COLORS } from '@/lib/constants';
import { useMemo } from 'react';
export interface EventsChartProps {
websiteId: string;
className?: string;
focusLabel?: string;
}
export function EventsChart({ websiteId, className }: EventsChartProps) {
export function EventsChart({ websiteId, className, focusLabel }: EventsChartProps) {
const {
dateRange: { startDate, endDate, unit, value },
} = useDateRange(websiteId);
const { locale } = useLocale();
const { data, isLoading } = useWebsiteEventsSeries(websiteId);
const [label, setLabel] = useState<string>(focusLabel);
const chartData = useMemo(() => {
if (!data) return [];
@ -42,8 +44,15 @@ export function EventsChart({ websiteId, className }: EventsChartProps) {
borderWidth: 1,
};
}),
focusLabel,
};
}, [data, startDate, endDate, unit]);
}, [data, startDate, endDate, unit, focusLabel]);
useEffect(() => {
if (label !== focusLabel) {
setLabel(focusLabel);
}
}, [focusLabel]);
return (
<BarChart

View file

@ -1,12 +1,28 @@
import MetricsTable, { MetricsTableProps } from './MetricsTable';
import { useMessages } from '@/components/hooks';
export function EventsTable(props: MetricsTableProps) {
export interface EventsTableProps extends MetricsTableProps {
onLabelClick?: (value: string) => void;
}
export function EventsTable({ onLabelClick, ...props }: EventsTableProps) {
const { formatMessage, labels } = useMessages();
function handleDataLoad(data: any) {
const handleDataLoad = (data: any) => {
props.onDataLoad?.(data);
}
};
const renderLabel = ({ x: label }) => {
if (onLabelClick) {
return (
<div onClick={() => onLabelClick(label)} style={{ cursor: 'pointer' }}>
{label}
</div>
);
}
return label;
};
return (
<MetricsTable
@ -15,6 +31,7 @@ export function EventsTable(props: MetricsTableProps) {
type="event"
metric={formatMessage(labels.actions)}
onDataLoad={handleDataLoad}
renderLabel={renderLabel}
/>
);
}