mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-04-24 07:26:22 +00:00
Migrated VisitsParser to TS
This commit is contained in:
@@ -1,75 +0,0 @@
|
||||
import { isNil, map } from 'ramda';
|
||||
import { extractDomain, parseUserAgent } from '../../utils/helpers/visits';
|
||||
import { hasValue } from '../../utils/utils';
|
||||
|
||||
const visitHasProperty = (visit, propertyName) => !isNil(visit) && hasValue(visit[propertyName]);
|
||||
|
||||
const updateOsStatsForVisit = (osStats, { os }) => {
|
||||
osStats[os] = (osStats[os] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateBrowsersStatsForVisit = (browsersStats, { browser }) => {
|
||||
browsersStats[browser] = (browsersStats[browser] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateReferrersStatsForVisit = (referrersStats, { referer: domain }) => {
|
||||
referrersStats[domain] = (referrersStats[domain] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateLocationsStatsForVisit = (propertyName) => (stats, visit) => {
|
||||
const hasLocationProperty = visitHasProperty(visit, propertyName);
|
||||
const value = hasLocationProperty ? visit[propertyName] : 'Unknown';
|
||||
|
||||
stats[value] = (stats[value] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('country');
|
||||
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('city');
|
||||
|
||||
const updateCitiesForMapForVisit = (citiesForMapStats, visit) => {
|
||||
if (!visitHasProperty(visit, 'city') || visit.city === 'Unknown') {
|
||||
return;
|
||||
}
|
||||
|
||||
const { city, latitude, longitude } = visit;
|
||||
const currentCity = citiesForMapStats[city] || {
|
||||
cityName: city,
|
||||
count: 0,
|
||||
latLong: [ parseFloat(latitude), parseFloat(longitude) ],
|
||||
};
|
||||
|
||||
currentCity.count++;
|
||||
|
||||
citiesForMapStats[city] = currentCity;
|
||||
};
|
||||
|
||||
export const processStatsFromVisits = (normalizedVisits) =>
|
||||
normalizedVisits.reduce(
|
||||
(stats, visit) => {
|
||||
// We mutate the original object because it has a big performance impact when large data sets are processed
|
||||
updateOsStatsForVisit(stats.os, visit);
|
||||
updateBrowsersStatsForVisit(stats.browsers, visit);
|
||||
updateReferrersStatsForVisit(stats.referrers, visit);
|
||||
updateCountriesStatsForVisit(stats.countries, visit);
|
||||
updateCitiesStatsForVisit(stats.cities, visit);
|
||||
updateCitiesForMapForVisit(stats.citiesForMap, visit);
|
||||
|
||||
return stats;
|
||||
},
|
||||
{ os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} },
|
||||
);
|
||||
|
||||
export const normalizeVisits = map(({ userAgent, date, referer, visitLocation }) => {
|
||||
const { browser, os } = parseUserAgent(userAgent);
|
||||
|
||||
return {
|
||||
date,
|
||||
browser,
|
||||
os,
|
||||
referer: extractDomain(referer),
|
||||
country: (visitLocation && visitLocation.countryName) || 'Unknown',
|
||||
city: (visitLocation && visitLocation.cityName) || 'Unknown',
|
||||
latitude: visitLocation && visitLocation.latitude,
|
||||
longitude: visitLocation && visitLocation.longitude,
|
||||
};
|
||||
});
|
||||
79
src/visits/services/VisitsParser.ts
Normal file
79
src/visits/services/VisitsParser.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { isNil, map, reduce } from 'ramda';
|
||||
import { extractDomain, parseUserAgent } from '../../utils/helpers/visits';
|
||||
import { hasValue } from '../../utils/utils';
|
||||
import { CityStats, NormalizedVisit, Stats, Visit, VisitsStats } from '../types';
|
||||
|
||||
const visitHasProperty = (visit: NormalizedVisit, propertyName: keyof NormalizedVisit) =>
|
||||
!isNil(visit) && hasValue(visit[propertyName]);
|
||||
|
||||
const optionalNumericToNumber = (numeric: string | number | null | undefined): number => {
|
||||
if (typeof numeric === 'number') {
|
||||
return numeric;
|
||||
}
|
||||
|
||||
return numeric ? parseFloat(numeric) : 0;
|
||||
};
|
||||
|
||||
const updateOsStatsForVisit = (osStats: Stats, { os }: NormalizedVisit) => {
|
||||
osStats[os] = (osStats[os] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateBrowsersStatsForVisit = (browsersStats: Stats, { browser }: NormalizedVisit) => {
|
||||
browsersStats[browser] = (browsersStats[browser] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateReferrersStatsForVisit = (referrersStats: Stats, { referer: domain }: NormalizedVisit) => {
|
||||
referrersStats[domain] = (referrersStats[domain] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateLocationsStatsForVisit = (propertyName: 'country' | 'city') => (stats: Stats, visit: NormalizedVisit) => {
|
||||
const hasLocationProperty = visitHasProperty(visit, propertyName);
|
||||
const value = hasLocationProperty ? visit[propertyName] : 'Unknown';
|
||||
|
||||
stats[value] = (stats[value] || 0) + 1;
|
||||
};
|
||||
|
||||
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('country');
|
||||
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('city');
|
||||
|
||||
const updateCitiesForMapForVisit = (citiesForMapStats: Record<string, CityStats>, visit: NormalizedVisit) => {
|
||||
if (!visitHasProperty(visit, 'city') || visit.city === 'Unknown') {
|
||||
return;
|
||||
}
|
||||
|
||||
const { city, latitude, longitude } = visit;
|
||||
const currentCity = citiesForMapStats[city] || {
|
||||
cityName: city,
|
||||
count: 0,
|
||||
latLong: [ optionalNumericToNumber(latitude), optionalNumericToNumber(longitude) ],
|
||||
};
|
||||
|
||||
currentCity.count++;
|
||||
|
||||
citiesForMapStats[city] = currentCity;
|
||||
};
|
||||
|
||||
export const processStatsFromVisits = reduce(
|
||||
(stats: VisitsStats, visit: NormalizedVisit) => {
|
||||
// We mutate the original object because it has a big performance impact when large data sets are processed
|
||||
updateOsStatsForVisit(stats.os, visit);
|
||||
updateBrowsersStatsForVisit(stats.browsers, visit);
|
||||
updateReferrersStatsForVisit(stats.referrers, visit);
|
||||
updateCountriesStatsForVisit(stats.countries, visit);
|
||||
updateCitiesStatsForVisit(stats.cities, visit);
|
||||
updateCitiesForMapForVisit(stats.citiesForMap, visit);
|
||||
|
||||
return stats;
|
||||
},
|
||||
{ os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} },
|
||||
);
|
||||
|
||||
export const normalizeVisits = map(({ userAgent, date, referer, visitLocation }: Visit): NormalizedVisit => ({
|
||||
date,
|
||||
...parseUserAgent(userAgent),
|
||||
referer: extractDomain(referer),
|
||||
country: visitLocation?.countryName ?? 'Unknown',
|
||||
city: visitLocation?.cityName ?? 'Unknown',
|
||||
latitude: visitLocation?.latitude,
|
||||
longitude: visitLocation?.longitude,
|
||||
}));
|
||||
Reference in New Issue
Block a user