From 0c1f533747366181765d6c9096937fccd970e11b Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 10 Jan 2019 19:50:25 +0100 Subject: [PATCH 1/4] Updated short URL visits loading so that it loads visits in several requests --- src/utils/services/ShlinkApiClient.js | 6 +++--- src/visits/reducers/shortUrlVisits.js | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/utils/services/ShlinkApiClient.js b/src/utils/services/ShlinkApiClient.js index 72ddfca8..42d27512 100644 --- a/src/utils/services/ShlinkApiClient.js +++ b/src/utils/services/ShlinkApiClient.js @@ -22,9 +22,9 @@ export default class ShlinkApiClient { .then((resp) => resp.data); }; - getShortUrlVisits = (shortCode, dates) => - this._performRequest(`/short-urls/${shortCode}/visits`, 'GET', dates) - .then((resp) => resp.data.visits.data); + getShortUrlVisits = (shortCode, query) => + this._performRequest(`/short-urls/${shortCode}/visits`, 'GET', query) + .then((resp) => resp.data.visits); getShortUrl = (shortCode) => this._performRequest(`/short-urls/${shortCode}`, 'GET') diff --git a/src/visits/reducers/shortUrlVisits.js b/src/visits/reducers/shortUrlVisits.js index 8bdedc33..32a86f47 100644 --- a/src/visits/reducers/shortUrlVisits.js +++ b/src/visits/reducers/shortUrlVisits.js @@ -46,10 +46,23 @@ export const getShortUrlVisits = (buildShlinkApiClient) => (shortCode, dates) => dispatch({ type: GET_SHORT_URL_VISITS_START }); const { selectedServer } = getState(); - const shlinkApiClient = buildShlinkApiClient(selectedServer); + const { getShortUrlVisits } = buildShlinkApiClient(selectedServer); + const itemsPerPage = 5000; + const isLastPage = ({ currentPage, pagesCount }) => currentPage >= pagesCount; + + const loadVisits = async (page = 1) => { + const { pagination, data } = await getShortUrlVisits(shortCode, { ...dates, page, itemsPerPage }); + + // If pagination was not returned, then this is an older shlink version. Just return data + if (!pagination || isLastPage(pagination)) { + return data; + } + + return data.concat(await loadVisits(page + 1)); + }; try { - const visits = await shlinkApiClient.getShortUrlVisits(shortCode, dates); + const visits = await loadVisits(); dispatch({ visits, type: GET_SHORT_URL_VISITS }); } catch (e) { From dee5994b1efd708b491788be6d69e26c75338db5 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 10 Jan 2019 20:05:02 +0100 Subject: [PATCH 2/4] Fixed tests --- test/utils/services/ShlinkApiClient.test.js | 2 +- test/visits/reducers/shortUrlVisits.test.js | 30 +++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/test/utils/services/ShlinkApiClient.test.js b/test/utils/services/ShlinkApiClient.test.js index 24f17858..f41d324b 100644 --- a/test/utils/services/ShlinkApiClient.test.js +++ b/test/utils/services/ShlinkApiClient.test.js @@ -64,7 +64,7 @@ describe('ShlinkApiClient', () => { const lastAxiosCall = last(axiosSpy.getCalls()); const axiosArgs = head(lastAxiosCall.args); - expect(expectedVisits).toEqual(actualVisits); + expect({ data: expectedVisits }).toEqual(actualVisits); expect(axiosArgs.url).toContain('/short-urls/abc123/visits'); expect(axiosArgs.method).toEqual('GET'); }); diff --git a/test/visits/reducers/shortUrlVisits.test.js b/test/visits/reducers/shortUrlVisits.test.js index 48c8dc9d..7075cd73 100644 --- a/test/visits/reducers/shortUrlVisits.test.js +++ b/test/visits/reducers/shortUrlVisits.test.js @@ -47,7 +47,7 @@ describe('shortUrlVisitsReducer', () => { describe('getShortUrlVisits', () => { const buildApiClientMock = (returned) => ({ - getShortUrlVisits: sinon.fake.returns(returned), + getShortUrlVisits: typeof returned === 'function' ? sinon.fake(returned) : sinon.fake.returns(returned), }); const dispatchMock = sinon.spy(); const getState = () => ({}); @@ -74,7 +74,13 @@ describe('shortUrlVisitsReducer', () => { it('dispatches start and success when promise is resolved', async () => { const resolvedVisits = [{}, {}]; - const ShlinkApiClient = buildApiClientMock(Promise.resolve(resolvedVisits)); + const ShlinkApiClient = buildApiClientMock(Promise.resolve({ + data: resolvedVisits, + pagination: { + currentPage: 1, + pagesCount: 1, + }, + })); const expectedDispatchCalls = 2; await getShortUrlVisits(() => ShlinkApiClient)('abc123')(dispatchMock, getState); @@ -91,5 +97,25 @@ describe('shortUrlVisitsReducer', () => { expect(secondCallType).toEqual(GET_SHORT_URL_VISITS); expect(visits).toEqual(resolvedVisits); }); + + it('performs two API requests when response contains more pages', async () => { + const expectedRequests = 3; + const ShlinkApiClient = buildApiClientMock((shortCode, { page }) => + Promise.resolve({ + data: [{}, {}], + pagination: { + currentPage: page, + pagesCount: expectedRequests, + }, + })); + + await getShortUrlVisits(() => ShlinkApiClient)('abc123')(dispatchMock, getState); + + const [ secondCallArg ] = dispatchMock.getCall(1).args; + const { visits } = secondCallArg; + + expect(ShlinkApiClient.getShortUrlVisits.callCount).toEqual(expectedRequests); + expect(visits).toEqual([{}, {}, {}, {}, {}, {}]); + }); }); }); From daaf91b83680160a929cef32d5f2c1ed75ece39a Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 10 Jan 2019 20:06:57 +0100 Subject: [PATCH 3/4] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a298931d..68e10e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), #### Changed * [#87](https://github.com/shlinkio/shlink-web-client/issues/87) and [#89](https://github.com/shlinkio/shlink-web-client/issues/89) Updated all dependencies to latest major versions. +* [#96](https://github.com/shlinkio/shlink-web-client/issues/96) Updated visits page to load visits in multiple paginated requests of `5000` visits when used shlink server supports it. This will prevent shlink to hang when trying to load big amounts of visits. #### Deprecated From f58b815ef86702cb783fbd9627e49ce9f5955495 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 10 Jan 2019 20:11:32 +0100 Subject: [PATCH 4/4] Fixed typo --- test/visits/reducers/shortUrlVisits.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/visits/reducers/shortUrlVisits.test.js b/test/visits/reducers/shortUrlVisits.test.js index 7075cd73..676490e7 100644 --- a/test/visits/reducers/shortUrlVisits.test.js +++ b/test/visits/reducers/shortUrlVisits.test.js @@ -98,7 +98,7 @@ describe('shortUrlVisitsReducer', () => { expect(visits).toEqual(resolvedVisits); }); - it('performs two API requests when response contains more pages', async () => { + it('performs multiple API requests when response contains more pages', async () => { const expectedRequests = 3; const ShlinkApiClient = buildApiClientMock((shortCode, { page }) => Promise.resolve({