Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.96.0 Realtime dashboard #296

Merged
merged 32 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b4ea70a
Fix event colors. Updated packages.
mikecao Oct 8, 2020
5f5335e
feat: add link to changelog when clicking version
phiilu Oct 8, 2020
e64a555
Renamed methods. Initial work on realtime dashboard.
mikecao Oct 8, 2020
fdc92d0
Update realtime chart.
mikecao Oct 9, 2020
9737127
Updated polling logic.
mikecao Oct 9, 2020
db9b238
Updated merge logic.
mikecao Oct 9, 2020
b682e41
RealtimeLog component.
mikecao Oct 9, 2020
8e0ea48
Updated log table rendering.
mikecao Oct 9, 2020
5b8bfc9
Add finnish translation
endormi Oct 9, 2020
5dd3110
Updated log merge logic to prevent duplicates.
mikecao Oct 9, 2020
aecb3ee
Merge pull request #286 from endormi/master
mikecao Oct 9, 2020
0ccae74
Update realtime chart animation.
mikecao Oct 9, 2020
ed65681
Merge remote-tracking branch 'origin/dev' into dev
mikecao Oct 9, 2020
69b3173
Updated fetch hook API.
mikecao Oct 9, 2020
e30f2df
Realtime header component.
mikecao Oct 10, 2020
910481e
Added grid layout components.
mikecao Oct 10, 2020
51955c6
Added Finnish language.
mikecao Oct 10, 2020
8912daa
Refactored data tables. Added realtime tables.
mikecao Oct 10, 2020
a039f40
Refactored realtime components.
mikecao Oct 10, 2020
f2cfab5
Updated realtime logs component.
mikecao Oct 10, 2020
689184b
fix: link to github releases without tag
phiilu Oct 10, 2020
ebd00a8
Merge pull request #283 from phiilu/feat/add-link-to-changelog
mikecao Oct 10, 2020
b72a4c0
Refactored realtime API. Add dot component and colored dots in log.
mikecao Oct 10, 2020
3374f87
Merge remote-tracking branch 'origin/dev' into dev
mikecao Oct 10, 2020
1fcb610
Updated fetch hook.
mikecao Oct 11, 2020
4119e80
Update table components.
mikecao Oct 11, 2020
5a73c22
Created share token hook.
mikecao Oct 11, 2020
f162478
Added filter buttons for realtime.
mikecao Oct 12, 2020
876c8f7
Update language keys.
mikecao Oct 13, 2020
360a676
Updated packages.
mikecao Oct 14, 2020
56ccdf8
Allow tracker script to load even if tracking is disabled.
mikecao Oct 14, 2020
e0a7fd9
Fix tracker regex for events.
mikecao Oct 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Updated log merge logic to prevent duplicates.
  • Loading branch information
mikecao committed Oct 9, 2020
commit 5dd3110fbf489ace3dbe4f8edf324fa3d5465c84
1 change: 1 addition & 0 deletions components/common/Table.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
}

.row {
display: flex;
border-bottom: 1px solid var(--gray300);
padding: 10px 0;
}
Expand Down
2 changes: 1 addition & 1 deletion components/metrics/RealtimeLog.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default function RealtimeLog({ data, websites }) {
return (
<FormattedMessage
id="message.log.visitor"
defaultMessage="A visitor from {country} using {browser} on {os} {device}"
defaultMessage="Visitor from {country} using {browser} on {os} {device}"
values={{ country: countryNames[country], browser: BROWSERS[browser], os, device }}
/>
);
Expand Down
22 changes: 12 additions & 10 deletions components/pages/RealtimeDashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ import RealtimeLog from '../metrics/RealtimeLog';
const REALTIME_RANGE = 30;
const REALTIME_INTERVAL = 5000;

function filterTime(data, time) {
return data.filter(({ created_at }) => new Date(created_at).getTime() >= time);
function mergeData(state, data, time) {
const ids = state.map(({ __id }) => __id);
return state
.concat(data.filter(({ __id }) => !ids.includes(__id)))
.filter(({ created_at }) => new Date(created_at).getTime() >= time);
}

export default function RealtimeDashboard() {
const [data, setData] = useState();
const [website, setWebsite] = useState();
const [lastTime, setLastTime] = useState();
const { data: init, loading } = useFetch('/api/realtime', { type: 'init' });
const { data: updates } = useFetch(
'/api/realtime',
{ type: 'update', start_at: lastTime },
{ type: 'update', start_at: data?.timestamp },
{
disabled: !init?.token,
disabled: !init?.token || !data,
interval: REALTIME_INTERVAL,
headers: { 'x-umami-token': init?.token },
},
Expand All @@ -34,15 +36,15 @@ export default function RealtimeDashboard() {
if (init && !data) {
setData(init.data);
} else if (updates) {
const { pageviews, sessions, events } = updates;
const { pageviews, sessions, events, timestamp } = updates;
const minTime = subMinutes(startOfMinute(new Date()), REALTIME_RANGE).getTime();
setData(state => ({
pageviews: filterTime(state.pageviews.concat(pageviews), minTime),
sessions: filterTime(state.sessions.concat(sessions), minTime),
events: filterTime(state.events.concat(events), minTime),
pageviews: mergeData(state.pageviews, pageviews, minTime),
sessions: mergeData(state.sessions, sessions, minTime),
events: mergeData(state.events, events, minTime),
timestamp,
}));
}
setLastTime(Date.now());
}, [init, updates]);

if (!init || loading || !data) {
Expand Down
3 changes: 2 additions & 1 deletion pages/api/collect.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { createToken } from 'lib/crypto';
import { getIpAddress } from '../../lib/request';

export default async (req, res) => {
await useCors(req, res);

if (isBot(req.headers['user-agent'])) {
return ok(res);
}
Expand All @@ -19,7 +21,6 @@ export default async (req, res) => {
}
}

await useCors(req, res);
await useSession(req, res);

const { type, payload } = req.body;
Expand Down
33 changes: 28 additions & 5 deletions pages/api/realtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,30 @@ export default async (req, res) => {
await useAuth(req, res);

async function getData(websites, time) {
return Promise.all([
const [pageviews, sessions, events] = await Promise.all([
getPageviews(websites, time),
getSessions(websites, time),
getEvents(websites, time),
]);

return {
pageviews: pageviews.map(({ view_id, ...props }) => ({
__id: `p${view_id}`,
view_id,
...props,
})),
sessions: sessions.map(({ session_id, ...props }) => ({
__id: `s${session_id}`,
session_id,
...props,
})),
events: events.map(({ event_id, ...props }) => ({
__id: `e${event_id}`,
event_id,
...props,
})),
timestamp: Date.now(),
};
}

if (req.method === 'GET') {
Expand All @@ -22,10 +41,14 @@ export default async (req, res) => {
if (type === 'init') {
const websites = await getUserWebsites(user_id);
const ids = websites.map(({ website_id }) => website_id);
const [pageviews, sessions, events] = await getData(ids, subMinutes(new Date(), 30));
const token = await createToken({ websites: ids });
const data = await getData(ids, subMinutes(new Date(), 30));

return ok(res, { websites, token, data: { pageviews, sessions, events } });
return ok(res, {
websites,
token,
data,
});
}

if (type === 'update') {
Expand All @@ -37,9 +60,9 @@ export default async (req, res) => {

const { websites } = await parseToken(token);

const [pageviews, sessions, events] = await getData(websites, new Date(+start_at));
const data = await getData(websites, new Date(+start_at));

return ok(res, { pageviews, sessions, events });
return ok(res, data);
}

return badRequest(res);
Expand Down