Merge pull request #91 from acelaya/feature/cities-graph

Feature/cities graph
This commit is contained in:
Alejandro Celaya 2019-01-07 12:02:11 +01:00 committed by GitHub
commit 95220b913a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 13 deletions

View file

@ -8,7 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
#### Added
* *Nothing*
* [#54](https://github.com/shlinkio/shlink-web-client/issues/54) Added stats by city graphic in visits page.
#### Changed

View file

@ -17,6 +17,7 @@ const ShortUrlVisits = ({
processOsStats,
processBrowserStats,
processCountriesStats,
processCitiesStats,
processReferrersStats,
}) => class ShortUrlVisits extends React.Component {
static propTypes = {
@ -70,13 +71,23 @@ const ShortUrlVisits = ({
return (
<div className="row">
<div className="col-md-6">
<div className="col-xl-4 col-lg-6">
<GraphCard title="Operating systems" stats={processOsStats(visits)} />
</div>
<div className="col-md-6">
<div className="col-xl-4 col-lg-6">
<GraphCard title="Browsers" stats={processBrowserStats(visits)} />
</div>
<div className="col-md-6">
<div className="col-xl-4">
<SortableBarGraph
stats={processReferrersStats(visits)}
title="Referrers"
sortingItems={{
name: 'Referrer name',
amount: 'Visits amount',
}}
/>
</div>
<div className="col-lg-6">
<SortableBarGraph
stats={processCountriesStats(visits)}
title="Countries"
@ -86,12 +97,12 @@ const ShortUrlVisits = ({
}}
/>
</div>
<div className="col-md-6">
<div className="col-lg-6">
<SortableBarGraph
stats={processReferrersStats(visits)}
title="Referrers"
stats={processCitiesStats(visits)}
title="Cities"
sortingItems={{
name: 'Referrer name',
name: 'City name',
amount: 'Visits amount',
}}
/>

View file

@ -76,16 +76,20 @@ export const processReferrersStats = (visits) =>
visits,
);
export const processCountriesStats = (visits) =>
const buildLocationStatsProcessorByProperty = (propertyName) => (visits) =>
reduce(
(stats, { visitLocation }) => {
const notHasCountry = isNil(visitLocation)
|| isNil(visitLocation.countryName)
|| isEmpty(visitLocation.countryName);
const country = notHasCountry ? 'Unknown' : visitLocation.countryName;
|| isNil(visitLocation[propertyName])
|| isEmpty(visitLocation[propertyName]);
const country = notHasCountry ? 'Unknown' : visitLocation[propertyName];
return assoc(country, (stats[country] || 0) + 1, stats);
},
{},
visits,
);
export const processCountriesStats = buildLocationStatsProcessorByProperty('countryName');
export const processCitiesStats = buildLocationStatsProcessorByProperty('cityName');

View file

@ -23,6 +23,7 @@ describe('<ShortUrlVisits />', () => {
processCountriesStats: statsProcessor,
processOsStats: statsProcessor,
processReferrersStats: statsProcessor,
processCitiesStats: statsProcessor,
});
wrapper = shallow(
@ -74,7 +75,7 @@ describe('<ShortUrlVisits />', () => {
const wrapper = createComponent({ loading: false, error: false, visits: [{}, {}, {}] });
const graphs = wrapper.find(GraphCard);
const sortableBarGraphs = wrapper.find(SortableBarGraph);
const expectedGraphsCount = 4;
const expectedGraphsCount = 5;
expect(graphs.length + sortableBarGraphs.length).toEqual(expectedGraphsCount);
});

View file

@ -3,6 +3,7 @@ import {
processBrowserStats,
processReferrersStats,
processCountriesStats,
processCitiesStats,
} from '../../../src/visits/services/VisitsParser';
describe('VisitsParser', () => {
@ -12,6 +13,7 @@ describe('VisitsParser', () => {
referer: 'https://google.com',
visitLocation: {
countryName: 'Spain',
cityName: 'Zaragoza',
},
},
{
@ -19,6 +21,7 @@ describe('VisitsParser', () => {
referer: 'https://google.com',
visitLocation: {
countryName: 'United States',
cityName: 'New York',
},
},
{
@ -32,6 +35,7 @@ describe('VisitsParser', () => {
referer: 'https://m.facebook.com',
visitLocation: {
countryName: 'Spain',
cityName: 'Zaragoza',
},
},
{
@ -78,4 +82,14 @@ describe('VisitsParser', () => {
});
});
});
describe('processCitiesStats', () => {
it('properly parses cities stats', () => {
expect(processCitiesStats(visits)).toEqual({
'Zaragoza': 2,
'New York': 1,
'Unknown': 2,
});
});
});
});