Refactored realtime page. Fixed render issue.

This commit is contained in:
Mike Cao 2024-03-08 01:11:03 -08:00
parent 42f184584f
commit 35fde36b61
11 changed files with 152 additions and 172 deletions

View file

@ -2,6 +2,7 @@ export * from './queries/useApi';
export * from './queries/useConfig';
export * from './queries/useFilterQuery';
export * from './queries/useLogin';
export * from './queries/useRealtime';
export * from './queries/useReport';
export * from './queries/useReports';
export * from './queries/useShareToken';

View file

@ -0,0 +1,87 @@
import { useMemo, useRef } from 'react';
import { RealtimeData } from 'lib/types';
import { useApi } from 'components/hooks';
import { REALTIME_INTERVAL, REALTIME_RANGE } from 'lib/constants';
import { startOfMinute, subMinutes } from 'date-fns';
import { percentFilter } from 'lib/filters';
import thenby from 'thenby';
function mergeData(state = [], data = [], time: number) {
const ids = state.map(({ id }) => id);
return state
.concat(data.filter(({ id }) => !ids.includes(id)))
.filter(({ timestamp }) => timestamp >= time);
}
export function useRealtime(websiteId: string) {
const currentData = useRef({
pageviews: [],
sessions: [],
events: [],
countries: [],
visitors: [],
timestamp: 0,
});
const { get, useQuery } = useApi();
const { data, isLoading, error } = useQuery<RealtimeData>({
queryKey: ['realtime', websiteId],
queryFn: async () => {
const state = currentData.current;
const data = await get(`/realtime/${websiteId}`, { startAt: state?.timestamp || 0 });
const date = subMinutes(startOfMinute(new Date()), REALTIME_RANGE);
const time = date.getTime();
const { pageviews, sessions, events, timestamp } = data;
return {
pageviews: mergeData(state?.pageviews, pageviews, time),
sessions: mergeData(state?.sessions, sessions, time),
events: mergeData(state?.events, events, time),
timestamp,
};
},
enabled: !!websiteId,
refetchInterval: REALTIME_INTERVAL,
});
const realtimeData: RealtimeData = useMemo(() => {
if (!data) {
return { pageviews: [], sessions: [], events: [], countries: [], visitors: [], timestamp: 0 };
}
data.countries = percentFilter(
data.sessions
.reduce((arr, data) => {
if (!arr.find(({ id }) => id === data.id)) {
return arr.concat(data);
}
return arr;
}, [])
.reduce((arr: { x: any; y: number }[], { country }: any) => {
if (country) {
const row = arr.find(({ x }) => x === country);
if (!row) {
arr.push({ x: country, y: 1 });
} else {
row.y += 1;
}
}
return arr;
}, [])
.sort(thenby.firstBy('y', -1)),
);
data.visitors = data.sessions.reduce((arr, val) => {
if (!arr.find(({ id }) => id === val.id)) {
return arr.concat(val);
}
return arr;
}, []);
return data;
}, [data]);
return { data: realtimeData, isLoading, error };
}
export default useRealtime;

View file

@ -21,6 +21,7 @@ export interface BarChartProps {
XAxisType?: string;
YAxisType?: string;
renderTooltipPopup?: (setTooltipPopup: (data: any) => void, model: any) => void;
updateMode?: string;
onCreate?: (chart: any) => void;
onUpdate?: (chart: any) => void;
className?: string;
@ -37,6 +38,7 @@ export function BarChart({
XAxisType = 'time',
YAxisType = 'linear',
renderTooltipPopup,
updateMode,
onCreate,
onUpdate,
className,
@ -136,25 +138,16 @@ export function BarChart({
const updateChart = (datasets: any[]) => {
setTooltipPopup(null);
const diff = chart.current.data.datasets.reduce(
(found: boolean, dataset: { data: any[] }, set: number) => {
if (!found) {
return dataset.data.find((value, index) => {
return datasets[set].data[index].y !== value.y;
});
}
return found;
},
false,
);
chart.current.data.datasets.forEach((dataset: { data: any }, index: string | number) => {
dataset.data = datasets[index].data;
});
if (diff) {
chart.current.data.datasets = datasets;
chart.current.options = getOptions();
chart.current.update();
chart.current.options = getOptions();
onUpdate?.(chart.current);
}
// Allow config changes before update
onUpdate?.(chart.current);
chart.current.update(updateMode);
};
useEffect(() => {