mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-22 01:46:58 +01:00
Fixed realtime chart rendering.
This commit is contained in:
parent
7a5f28870f
commit
92a513e4d0
@ -19,9 +19,9 @@ import { RealtimeData } from 'lib/types';
|
||||
import styles from './Realtime.module.css';
|
||||
|
||||
function mergeData(state = [], data = [], time: number) {
|
||||
const ids = state.map(({ __id }) => __id);
|
||||
const ids = state.map(({ id }) => id);
|
||||
return state
|
||||
.concat(data.filter(({ __id }) => !ids.includes(__id)))
|
||||
.concat(data.filter(({ id }) => !ids.includes(id)))
|
||||
.filter(({ timestamp }) => timestamp >= time);
|
||||
}
|
||||
|
||||
@ -38,21 +38,18 @@ export function Realtime({ websiteId }) {
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
if (!currentData) {
|
||||
setCurrentData(data);
|
||||
} else {
|
||||
const date = subMinutes(startOfMinute(new Date()), REALTIME_RANGE);
|
||||
const time = date.getTime();
|
||||
const { pageviews, sessions, events, timestamp } = data;
|
||||
|
||||
setCurrentData(state => ({
|
||||
pageviews: mergeData(state?.pageviews, data.pageviews, time),
|
||||
sessions: mergeData(state?.sessions, data.sessions, time),
|
||||
events: mergeData(state?.events, data.events, time),
|
||||
timestamp: data.timestamp,
|
||||
pageviews: mergeData(state?.pageviews, pageviews, time),
|
||||
sessions: mergeData(state?.sessions, sessions, time),
|
||||
events: mergeData(state?.events, events, time),
|
||||
timestamp,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, [data]);
|
||||
}, [data, currentData]);
|
||||
|
||||
const realtimeData: RealtimeData = useMemo(() => {
|
||||
if (!currentData) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { subMinutes } from 'date-fns';
|
||||
import { startOfMinute, subMinutes } from 'date-fns';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useValidate } from 'lib/middleware';
|
||||
import { NextApiRequestQueryBody, RealtimeInit } from 'lib/types';
|
||||
@ -6,6 +6,8 @@ import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
import { getRealtimeData } from 'queries';
|
||||
import * as yup from 'yup';
|
||||
import { REALTIME_RANGE } from 'lib/constants';
|
||||
|
||||
export interface RealtimeRequestQuery {
|
||||
id: string;
|
||||
startAt: number;
|
||||
@ -32,7 +34,7 @@ export default async (
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
let startTime = subMinutes(new Date(), 30);
|
||||
let startTime = subMinutes(startOfMinute(new Date()), REALTIME_RANGE);
|
||||
|
||||
if (+startAt > startTime.getTime()) {
|
||||
startTime = new Date(+startAt);
|
||||
|
@ -18,6 +18,9 @@ function relationalQuery(websiteId: string, startDate: Date, eventType: number)
|
||||
gte: startDate,
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'asc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -39,6 +42,7 @@ function clickhouseQuery(websiteId: string, startDate: Date, eventType: number)
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at >= {startDate:DateTime64}
|
||||
and event_type = {eventType:UInt32}
|
||||
order by created_at asc
|
||||
`,
|
||||
{
|
||||
websiteId,
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { md5 } from 'next-basics';
|
||||
import { getSessions, getEvents } from 'queries/index';
|
||||
import { EVENT_TYPE } from 'lib/constants';
|
||||
|
||||
@ -9,18 +8,35 @@ export async function getRealtimeData(websiteId: string, startDate: Date) {
|
||||
getEvents(websiteId, startDate, EVENT_TYPE.customEvent),
|
||||
]);
|
||||
|
||||
const decorate = (id: string, data: any[]) => {
|
||||
return data.map((props: { [key: string]: any }) => ({
|
||||
...props,
|
||||
__id: md5(id, ...Object.values(props)),
|
||||
__type: id,
|
||||
timestamp: props.timestamp ? props.timestamp * 1000 : new Date(props.createdAt).getTime(),
|
||||
const decorate = (type: string, data: any[]) => {
|
||||
return data.map((values: { [key: string]: any }) => ({
|
||||
...values,
|
||||
__type: type,
|
||||
timestamp: values.timestamp ? values.timestamp * 1000 : new Date(values.createdAt).getTime(),
|
||||
}));
|
||||
};
|
||||
|
||||
const set = new Set();
|
||||
const uniques = (type: string, data: any[]) => {
|
||||
return data.reduce((arr, values: { [key: string]: any }) => {
|
||||
if (!set.has(values.id)) {
|
||||
set.add(values.id);
|
||||
|
||||
return arr.concat({
|
||||
...values,
|
||||
__type: type,
|
||||
timestamp: values.timestamp
|
||||
? values.timestamp * 1000
|
||||
: new Date(values.createdAt).getTime(),
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}, []);
|
||||
};
|
||||
|
||||
return {
|
||||
pageviews: decorate('pageview', pageviews),
|
||||
sessions: decorate('session', sessions),
|
||||
sessions: uniques('session', sessions),
|
||||
events: decorate('event', events),
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
@ -17,6 +17,9 @@ async function relationalQuery(websiteId: string, startDate: Date) {
|
||||
gte: startDate,
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'asc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -25,7 +28,7 @@ async function clickhouseQuery(websiteId: string, startDate: Date) {
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select distinct
|
||||
select
|
||||
session_id as id,
|
||||
website_id as websiteId,
|
||||
created_at as createdAt,
|
||||
@ -43,6 +46,7 @@ async function clickhouseQuery(websiteId: string, startDate: Date) {
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at >= {startDate:DateTime64}
|
||||
order by created_at asc
|
||||
`,
|
||||
{
|
||||
websiteId,
|
||||
|
Loading…
Reference in New Issue
Block a user