1
|
|
|
import { isNil, map } from 'ramda'; |
2
|
|
|
import { extractDomain, parseUserAgent } from '../../utils/helpers/visits'; |
3
|
|
|
import { hasValue } from '../../utils/utils'; |
4
|
|
|
|
5
|
15 |
|
const visitHasProperty = (visit, propertyName) => !isNil(visit) && hasValue(visit[propertyName]); |
6
|
|
|
|
7
|
1 |
|
const updateOsStatsForVisit = (osStats, { os }) => { |
8
|
5 |
|
osStats[os] = (osStats[os] || 0) + 1; |
9
|
|
|
}; |
10
|
|
|
|
11
|
1 |
|
const updateBrowsersStatsForVisit = (browsersStats, { browser }) => { |
12
|
5 |
|
browsersStats[browser] = (browsersStats[browser] || 0) + 1; |
13
|
|
|
}; |
14
|
|
|
|
15
|
1 |
|
const updateReferrersStatsForVisit = (referrersStats, { referer: domain }) => { |
|
|
|
|
16
|
5 |
|
referrersStats[domain] = (referrersStats[domain] || 0) + 1; |
|
|
|
|
17
|
|
|
}; |
18
|
|
|
|
19
|
2 |
|
const updateLocationsStatsForVisit = (propertyName) => (stats, visit) => { |
20
|
10 |
|
const hasLocationProperty = visitHasProperty(visit, propertyName); |
21
|
10 |
|
const value = hasLocationProperty ? visit[propertyName] : 'Unknown'; |
22
|
|
|
|
23
|
10 |
|
stats[value] = (stats[value] || 0) + 1; |
24
|
|
|
}; |
25
|
|
|
|
26
|
1 |
|
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('country'); |
27
|
1 |
|
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('city'); |
28
|
|
|
|
29
|
1 |
|
const updateCitiesForMapForVisit = (citiesForMapStats, visit) => { |
30
|
5 |
|
if (!visitHasProperty(visit, 'city') || visit.city === 'Unknown') { |
31
|
2 |
|
return; |
32
|
|
|
} |
33
|
|
|
|
34
|
3 |
|
const { city, latitude, longitude } = visit; |
35
|
3 |
|
const currentCity = citiesForMapStats[city] || { |
36
|
|
|
cityName: city, |
37
|
|
|
count: 0, |
38
|
|
|
latLong: [ parseFloat(latitude), parseFloat(longitude) ], |
39
|
|
|
}; |
40
|
|
|
|
41
|
3 |
|
currentCity.count++; |
42
|
|
|
|
43
|
3 |
|
citiesForMapStats[city] = currentCity; |
44
|
|
|
}; |
45
|
|
|
|
46
|
1 |
|
export const processStatsFromVisits = (normalizedVisits) => |
47
|
1 |
|
normalizedVisits.reduce( |
48
|
|
|
(stats, visit) => { |
49
|
|
|
// We mutate the original object because it has a big performance impact when large data sets are processed |
50
|
5 |
|
updateOsStatsForVisit(stats.os, visit); |
51
|
5 |
|
updateBrowsersStatsForVisit(stats.browsers, visit); |
52
|
5 |
|
updateReferrersStatsForVisit(stats.referrers, visit); |
53
|
5 |
|
updateCountriesStatsForVisit(stats.countries, visit); |
54
|
5 |
|
updateCitiesStatsForVisit(stats.cities, visit); |
55
|
5 |
|
updateCitiesForMapForVisit(stats.citiesForMap, visit); |
56
|
|
|
|
57
|
5 |
|
return stats; |
58
|
|
|
}, |
59
|
|
|
{ os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} } |
60
|
|
|
); |
61
|
|
|
|
62
|
1 |
|
export const normalizeVisits = map(({ userAgent, date, referer, visitLocation }) => { |
63
|
10 |
|
const { browser, os } = parseUserAgent(userAgent); |
64
|
|
|
|
65
|
10 |
|
return { |
66
|
|
|
date, |
67
|
|
|
browser, |
68
|
|
|
os, |
69
|
|
|
referer: extractDomain(referer), |
70
|
|
|
country: (visitLocation && visitLocation.countryName) || 'Unknown', |
71
|
|
|
city: (visitLocation && visitLocation.cityName) || 'Unknown', |
72
|
|
|
latitude: visitLocation && visitLocation.latitude, |
73
|
|
|
longitude: visitLocation && visitLocation.longitude, |
74
|
|
|
}; |
75
|
|
|
}); |
76
|
|
|
|
This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.