mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-10 09:33:51 +00:00
Optimized visits parser to act over the normalized list of visits
This commit is contained in:
@@ -87,8 +87,8 @@ const ShortUrlVisits = ({ processStatsFromVisits, normalizeVisits }, OpenMapModa
|
|||||||
const showTableControls = !loading && visits.length > 0;
|
const showTableControls = !loading && visits.length > 0;
|
||||||
const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]);
|
const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]);
|
||||||
const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo(
|
const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo(
|
||||||
() => processStatsFromVisits(visits),
|
() => processStatsFromVisits(normalizedVisits),
|
||||||
[ visits ]
|
[ normalizedVisits ]
|
||||||
);
|
);
|
||||||
const mapLocations = values(citiesForMap);
|
const mapLocations = values(citiesForMap);
|
||||||
|
|
||||||
|
|||||||
@@ -1,60 +1,52 @@
|
|||||||
import { isEmpty, isNil, map } from 'ramda';
|
import { isNil, map } from 'ramda';
|
||||||
import { browserFromUserAgent, extractDomain, osFromUserAgent } from '../../utils/helpers/visits';
|
import { browserFromUserAgent, extractDomain, osFromUserAgent } from '../../utils/helpers/visits';
|
||||||
|
import { hasValue } from '../../utils/utils';
|
||||||
|
|
||||||
const visitLocationHasProperty = (visitLocation, propertyName) =>
|
const visitHasProperty = (visit, propertyName) => !isNil(visit) && hasValue(visit[propertyName]);
|
||||||
!isNil(visitLocation)
|
|
||||||
&& !isNil(visitLocation[propertyName])
|
|
||||||
&& !isEmpty(visitLocation[propertyName]);
|
|
||||||
|
|
||||||
const updateOsStatsForVisit = (osStats, { userAgent }) => {
|
|
||||||
const os = osFromUserAgent(userAgent);
|
|
||||||
|
|
||||||
|
const updateOsStatsForVisit = (osStats, { os }) => {
|
||||||
osStats[os] = (osStats[os] || 0) + 1;
|
osStats[os] = (osStats[os] || 0) + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateBrowsersStatsForVisit = (browsersStats, { userAgent }) => {
|
const updateBrowsersStatsForVisit = (browsersStats, { browser }) => {
|
||||||
const browser = browserFromUserAgent(userAgent);
|
|
||||||
|
|
||||||
browsersStats[browser] = (browsersStats[browser] || 0) + 1;
|
browsersStats[browser] = (browsersStats[browser] || 0) + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateReferrersStatsForVisit = (referrersStats, { referer }) => {
|
const updateReferrersStatsForVisit = (referrersStats, { referer: domain }) => {
|
||||||
const domain = extractDomain(referer);
|
|
||||||
|
|
||||||
referrersStats[domain] = (referrersStats[domain] || 0) + 1;
|
referrersStats[domain] = (referrersStats[domain] || 0) + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateLocationsStatsForVisit = (propertyName) => (stats, { visitLocation }) => {
|
const updateLocationsStatsForVisit = (propertyName) => (stats, visit) => {
|
||||||
const hasLocationProperty = visitLocationHasProperty(visitLocation, propertyName);
|
const hasLocationProperty = visitHasProperty(visit, propertyName);
|
||||||
const value = hasLocationProperty ? visitLocation[propertyName] : 'Unknown';
|
const value = hasLocationProperty ? visit[propertyName] : 'Unknown';
|
||||||
|
|
||||||
stats[value] = (stats[value] || 0) + 1;
|
stats[value] = (stats[value] || 0) + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('countryName');
|
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('country');
|
||||||
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('cityName');
|
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('city');
|
||||||
|
|
||||||
const updateCitiesForMapForVisit = (citiesForMapStats, { visitLocation }) => {
|
const updateCitiesForMapForVisit = (citiesForMapStats, visit) => {
|
||||||
if (!visitLocationHasProperty(visitLocation, 'cityName')) {
|
if (!visitHasProperty(visit, 'city') || visit.city === 'Unknown') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { cityName, latitude, longitude } = visitLocation;
|
const { city, latitude, longitude } = visit;
|
||||||
const currentCity = citiesForMapStats[cityName] || {
|
const currentCity = citiesForMapStats[city] || {
|
||||||
cityName,
|
cityName: city,
|
||||||
count: 0,
|
count: 0,
|
||||||
latLong: [ parseFloat(latitude), parseFloat(longitude) ],
|
latLong: [ parseFloat(latitude), parseFloat(longitude) ],
|
||||||
};
|
};
|
||||||
|
|
||||||
currentCity.count++;
|
currentCity.count++;
|
||||||
|
|
||||||
citiesForMapStats[cityName] = currentCity;
|
citiesForMapStats[city] = currentCity;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const processStatsFromVisits = (visits) =>
|
export const processStatsFromVisits = (normalizedVisits) =>
|
||||||
visits.reduce(
|
normalizedVisits.reduce(
|
||||||
(stats, visit) => {
|
(stats, visit) => {
|
||||||
// We mutate the original object because it has a big side effect when large data sets are processed
|
// We mutate the original object because it has a big performance impact when large data sets are processed
|
||||||
updateOsStatsForVisit(stats.os, visit);
|
updateOsStatsForVisit(stats.os, visit);
|
||||||
updateBrowsersStatsForVisit(stats.browsers, visit);
|
updateBrowsersStatsForVisit(stats.browsers, visit);
|
||||||
updateReferrersStatsForVisit(stats.referrers, visit);
|
updateReferrersStatsForVisit(stats.referrers, visit);
|
||||||
@@ -74,4 +66,6 @@ export const normalizeVisits = map(({ userAgent, date, referer, visitLocation })
|
|||||||
referer: extractDomain(referer),
|
referer: extractDomain(referer),
|
||||||
country: (visitLocation && visitLocation.countryName) || 'Unknown',
|
country: (visitLocation && visitLocation.countryName) || 'Unknown',
|
||||||
city: (visitLocation && visitLocation.cityName) || 'Unknown',
|
city: (visitLocation && visitLocation.cityName) || 'Unknown',
|
||||||
|
latitude: visitLocation && visitLocation.latitude,
|
||||||
|
longitude: visitLocation && visitLocation.longitude,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ describe('VisitsParser', () => {
|
|||||||
visitLocation: {
|
visitLocation: {
|
||||||
countryName: 'Spain',
|
countryName: 'Spain',
|
||||||
cityName: 'Zaragoza',
|
cityName: 'Zaragoza',
|
||||||
latitude: '123.45',
|
latitude: 123.45,
|
||||||
longitude: '-543.21',
|
longitude: -543.21,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -18,8 +18,8 @@ describe('VisitsParser', () => {
|
|||||||
visitLocation: {
|
visitLocation: {
|
||||||
countryName: 'United States',
|
countryName: 'United States',
|
||||||
cityName: 'New York',
|
cityName: 'New York',
|
||||||
latitude: '1029',
|
latitude: 1029,
|
||||||
longitude: '6758',
|
longitude: 6758,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -34,8 +34,8 @@ describe('VisitsParser', () => {
|
|||||||
visitLocation: {
|
visitLocation: {
|
||||||
countryName: 'Spain',
|
countryName: 'Spain',
|
||||||
cityName: 'Zaragoza',
|
cityName: 'Zaragoza',
|
||||||
latitude: '123.45',
|
latitude: 123.45,
|
||||||
longitude: '-543.21',
|
longitude: -543.21,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -47,7 +47,7 @@ describe('VisitsParser', () => {
|
|||||||
let stats;
|
let stats;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
stats = processStatsFromVisits(visits);
|
stats = processStatsFromVisits(normalizeVisits(visits));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('properly parses OS stats', () => {
|
it('properly parses OS stats', () => {
|
||||||
@@ -132,6 +132,8 @@ describe('VisitsParser', () => {
|
|||||||
country: 'Spain',
|
country: 'Spain',
|
||||||
city: 'Zaragoza',
|
city: 'Zaragoza',
|
||||||
date: undefined,
|
date: undefined,
|
||||||
|
latitude: 123.45,
|
||||||
|
longitude: -543.21,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
browser: 'Firefox',
|
browser: 'Firefox',
|
||||||
@@ -140,6 +142,8 @@ describe('VisitsParser', () => {
|
|||||||
country: 'United States',
|
country: 'United States',
|
||||||
city: 'New York',
|
city: 'New York',
|
||||||
date: undefined,
|
date: undefined,
|
||||||
|
latitude: 1029,
|
||||||
|
longitude: 6758,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
browser: 'Chrome',
|
browser: 'Chrome',
|
||||||
@@ -148,6 +152,8 @@ describe('VisitsParser', () => {
|
|||||||
country: 'Spain',
|
country: 'Spain',
|
||||||
city: 'Unknown',
|
city: 'Unknown',
|
||||||
date: undefined,
|
date: undefined,
|
||||||
|
latitude: undefined,
|
||||||
|
longitude: undefined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
browser: 'Chrome',
|
browser: 'Chrome',
|
||||||
@@ -156,6 +162,8 @@ describe('VisitsParser', () => {
|
|||||||
country: 'Spain',
|
country: 'Spain',
|
||||||
city: 'Zaragoza',
|
city: 'Zaragoza',
|
||||||
date: undefined,
|
date: undefined,
|
||||||
|
latitude: 123.45,
|
||||||
|
longitude: -543.21,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
browser: 'Opera',
|
browser: 'Opera',
|
||||||
@@ -164,6 +172,8 @@ describe('VisitsParser', () => {
|
|||||||
country: 'Unknown',
|
country: 'Unknown',
|
||||||
city: 'Unknown',
|
city: 'Unknown',
|
||||||
date: undefined,
|
date: undefined,
|
||||||
|
latitude: undefined,
|
||||||
|
longitude: undefined,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user