From adceece9de18a18443d5f1ac1c4002afe9ed09f0 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Tue, 24 Apr 2018 16:03:09 +0200 Subject: [PATCH 1/6] paginate for activity page --- .../components/pagination/PaginationFooter.js | 1 + app/addons/replication/actions.js | 52 ++++++++++++--- app/addons/replication/actiontypes.js | 5 +- app/addons/replication/api.js | 40 +++++++++-- .../replication/assets/less/replication.less | 9 ++- app/addons/replication/components/activity.js | 29 +++++++- app/addons/replication/container.js | 27 ++++++-- app/addons/replication/controller.js | 22 +++++-- app/addons/replication/reducers.js | 66 ++++++++++++++++++- 9 files changed, 221 insertions(+), 30 deletions(-) diff --git a/app/addons/documents/index-results/components/pagination/PaginationFooter.js b/app/addons/documents/index-results/components/pagination/PaginationFooter.js index 5f1c663ba..8c9a117e7 100644 --- a/app/addons/documents/index-results/components/pagination/PaginationFooter.js +++ b/app/addons/documents/index-results/components/pagination/PaginationFooter.js @@ -40,6 +40,7 @@ export default class PaginationFooter extends React.Component { const { canShowNext, fetchParams, queryOptionsParams, paginateNext, perPage } = this.props; if (canShowNext) { + console.log('FOOTER NEXT', fetchParams, queryOptionsParams, perPage); paginateNext(fetchParams, queryOptionsParams, perPage); } } diff --git a/app/addons/replication/actions.js b/app/addons/replication/actions.js index 08e073333..98797fbb6 100644 --- a/app/addons/replication/actions.js +++ b/app/addons/replication/actions.js @@ -25,7 +25,6 @@ import { createReplicatorDB } from './api'; - export const initReplicator = (routeLocalSource, localSource) => dispatch => { if (routeLocalSource && routeLocalSource !== localSource) { dispatch({ @@ -108,19 +107,16 @@ export const clearReplicationForm = () => { return { type: ActionTypes.REPLICATION_CLEAR_FORM }; }; -export const getReplicationActivity = () => dispatch => { +export const getReplicationActivity = (params) => dispatch => { dispatch({ type: ActionTypes.REPLICATION_FETCHING_STATUS, }); - supportNewApi() - .then(supportNewApi => { - return fetchReplicationDocs(supportNewApi); - }) - .then(docs => { + fetchReplicationDocs(params) + .then(docsInfo => { dispatch({ type: ActionTypes.REPLICATION_STATUS, - options: docs + options: docsInfo }); }); }; @@ -402,3 +398,43 @@ export const checkForNewApi = () => dispatch => { }); }); }; + +export const updatePerPageResults = (amount) => { + const newPaginate = { + page: 1, + docsPerPage: amount + }; + return (dispatch) => { + dispatch({ + type: ActionTypes.REPLICATION_UPDATE_PER_PAGE_RESULTS, + options: amount + }); + + dispatch(getReplicationActivity(newPaginate)); + }; +}; + +export const paginateNext = (paginate) => { + return dispatch => { + dispatch({ + type: ActionTypes.REPLICATION_NEXT_PAGE + }); + + paginate.page += 1; + dispatch(getReplicationActivity(paginate)); + }; +}; + +export const paginatePrevious = (paginate) => { + return dispatch => { + dispatch({ + type: ActionTypes.REPLICATION_PREVIOUS_PAGE + }); + + if (paginate.page > 1) { + paginate.page -= 1; + } + + dispatch(getReplicationActivity(paginate)); + }; +}; diff --git a/app/addons/replication/actiontypes.js b/app/addons/replication/actiontypes.js index 714386863..e5d56e94f 100644 --- a/app/addons/replication/actiontypes.js +++ b/app/addons/replication/actiontypes.js @@ -38,5 +38,8 @@ export default { REPLICATION_CLEAR_SELECTED_REPLICATES: 'REPLICATION_CLEAR_SELECTED_REPLICATES', REPLICATION_FETCHING_FORM_STATE: 'REPLICATION_FETCHING_FORM_STATE', REPLICATION_HIDE_PASSWORD_MODAL: 'REPLICATION_HIDE_PASSWORD_MODAL', - REPLICATION_SHOW_PASSWORD_MODAL: 'REPLICATION_SHOW_PASSWORD_MODAL' + REPLICATION_SHOW_PASSWORD_MODAL: 'REPLICATION_SHOW_PASSWORD_MODAL', + REPLICATION_UPDATE_PER_PAGE_RESULTS: 'REPLICATION_UPDATE_PER_PAGE_RESULTS', + REPLICATION_NEXT_PAGE: 'REPLICATION_NEXT_PAGE', + REPLICATION_PREVIOUS_PAGE: 'REPLICATION_PREVIOUS_PAGE' }; diff --git a/app/addons/replication/api.js b/app/addons/replication/api.js index 363228d82..1173d3edf 100644 --- a/app/addons/replication/api.js +++ b/app/addons/replication/api.js @@ -13,9 +13,11 @@ import '@webcomponents/url'; import Constants from './constants'; import FauxtonAPI from '../../core/api'; +import app from '../../app'; import {get, post, put} from '../../core/ajax'; import base64 from 'base-64'; import _ from 'lodash'; +import { removeOverflowDocsAndCalculateHasNext } from '../documents/index-results/actions/fetch'; let newApiPromise = null; export const supportNewApi = (forceCheck) => { @@ -295,10 +297,16 @@ export const combineDocsAndScheduler = (docs, schedulerDocs) => { }); }; -export const fetchReplicationDocs = () => { +export const fetchReplicationDocs = ({docsPerPage, page}) => { + const params = { + limit: docsPerPage + 1, + skip: (page - 1) * docsPerPage, + include_docs: true + }; + return supportNewApi() .then(newApi => { - const docsPromise = get('/_replicator/_all_docs?include_docs=true&limit=100') + const docsPromise = get(`/_replicator/_all_docs?${app.utils.queryParams(params)}`) .then((res) => { if (res.error) { return []; @@ -308,20 +316,40 @@ export const fetchReplicationDocs = () => { }); if (!newApi) { - return docsPromise; + return docsPromise + .then(docs => { + const { + finalDocList, + canShowNext + } = removeOverflowDocsAndCalculateHasNext(docs, false, docsPerPage); + return { + docs: finalDocList, + canShowNext + }; + }); } - const schedulerPromise = fetchSchedulerDocs(); + const schedulerPromise = fetchSchedulerDocs(params); return FauxtonAPI.Promise.join(docsPromise, schedulerPromise, (docs, schedulerDocs) => { return combineDocsAndScheduler(docs, schedulerDocs); }) + .then(docs => { + const { + finalDocList, + canShowNext + } = removeOverflowDocsAndCalculateHasNext(docs, false, docsPerPage + 1); + return { + docs: finalDocList, + canShowNext + }; + }) .catch(() => { return []; }); }); }; -export const fetchSchedulerDocs = () => { - return get('/_scheduler/docs?include_docs=true') +export const fetchSchedulerDocs = (params) => { + return get(`/_scheduler/docs?${app.utils.queryParams(params)}`) .then((res) => { if (res.error) { return []; diff --git a/app/addons/replication/assets/less/replication.less b/app/addons/replication/assets/less/replication.less index 6a8a1aab1..44a4a7427 100644 --- a/app/addons/replication/assets/less/replication.less +++ b/app/addons/replication/assets/less/replication.less @@ -349,4 +349,11 @@ td.replication__empty-row { .replication__activity-caveat { padding-left: 80px; -} \ No newline at end of file +} + +.replication__paginate-footer { + position: absolute; + bottom: 0px; + right: 0px; + width: 100%; +} diff --git a/app/addons/replication/components/activity.js b/app/addons/replication/components/activity.js index 0d1ae981a..0dad752e1 100644 --- a/app/addons/replication/components/activity.js +++ b/app/addons/replication/components/activity.js @@ -15,6 +15,7 @@ import React from 'react'; import {DeleteModal} from './modals'; import {ReplicationTable} from './common-table'; import {ReplicationHeader} from './common-activity'; +import PaginationFooter from '../../documents/index-results/components/pagination/paginationfooter'; export default class Activity extends React.Component { constructor (props) { @@ -66,7 +67,14 @@ export default class Activity extends React.Component { selectAllDocs, someDocsSelected, allDocsSelected, - selectDoc + selectDoc, + pageStart, + pageEnd, + docsPerPage, + updatePerPageResults, + paginateNext, + paginatePrevious, + pagination } = this.props; const {modalVisible} = this.state; @@ -90,6 +98,25 @@ export default class Activity extends React.Component { column={activitySort.column} changeSort={changeActivitySort} /> +
+ 1} + perPage={docsPerPage} + toggleShowAllColumns={false} + docs={this.props.docs} + pageStart={pageStart} + pageEnd={pageEnd} + updatePerPageResults={updatePerPageResults} + paginateNext={paginateNext} + paginatePrevious={paginatePrevious} + queryOptionsParams={{}} + fetchParams={pagination} + /> +
{ @@ -99,7 +107,13 @@ const mapStateToProps = ({replication}, ownProps) => { replicateLoading: isReplicateInfoLoading(replication), replicateInfo: getReplicateInfo(replication), allReplicateSelected: getAllReplicateSelected(replication), - someReplicateSelected: someReplicateSelected(replication) + someReplicateSelected: someReplicateSelected(replication), + pagination: getPagination(replication), + pageStart: getPageStart(replication), + pageEnd: getPageEnd(replication), + docsPerPage: getDocsPerPage(replication), + canShowNext: canShowNext(replication) + }; }; @@ -111,7 +125,7 @@ const mapDispatchToProps = (dispatch) => { }, clearReplicationForm: () => dispatch(clearReplicationForm()), initReplicator: (localSource) => dispatch(initReplicator(localSource)), - getReplicationActivity: () => dispatch(getReplicationActivity()), + getReplicationActivity: (params) => dispatch(getReplicationActivity(params)), getReplicateActivity: () => dispatch(getReplicateActivity()), getReplicationStateFrom: (id) => dispatch(getReplicationStateFrom(id)), getDatabasesList: () => dispatch(getDatabasesList()), @@ -126,7 +140,10 @@ const mapDispatchToProps = (dispatch) => { changeActivitySort: (sort) => dispatch(changeActivitySort(sort)), selectAllReplicates: () => dispatch(selectAllReplicates()), deleteReplicates: (replicates) => dispatch(deleteReplicates(replicates)), - selectReplicate: (replicate) => dispatch(selectReplicate(replicate)) + selectReplicate: (replicate) => dispatch(selectReplicate(replicate)), + updatePerPageResults: (amount) => dispatch(updatePerPageResults(amount)), + paginateNext: (params) => dispatch(paginateNext(params)), + paginatePrevious: (params) => dispatch(paginatePrevious(params)) }; }; diff --git a/app/addons/replication/controller.js b/app/addons/replication/controller.js index a65febe87..31abfd8d5 100644 --- a/app/addons/replication/controller.js +++ b/app/addons/replication/controller.js @@ -26,7 +26,7 @@ export default class ReplicationController extends React.Component { loadReplicationInfo (props, oldProps) { this.props.initReplicator(props.routeLocalSource, props.localSource); - this.getAllActivity(); + this.getAllActivity(props.pagination); this.loadReplicationStateFrom(props, oldProps); } @@ -37,8 +37,8 @@ export default class ReplicationController extends React.Component { } } - getAllActivity () { - this.props.getReplicationActivity(); + getAllActivity (pagination) { + this.props.getReplicationActivity(pagination); this.props.getReplicateActivity(); } @@ -70,7 +70,8 @@ export default class ReplicationController extends React.Component { hideConflictModal, isConflictModalVisible, filterDocs, filterReplicate, replicate, clearReplicationForm, selectAllDocs, changeActivitySort, selectDoc, deleteDocs, deleteReplicates, selectAllReplicates, selectReplicate, - sourceAuthType, sourceAuth, targetAuthType, targetAuth + sourceAuthType, sourceAuth, targetAuthType, targetAuth, pageStart, pageEnd, docsPerPage, + updatePerPageResults, paginateNext, pagination, paginatePrevious } = this.props; if (tabSection === 'new replication') { @@ -123,6 +124,8 @@ export default class ReplicationController extends React.Component { activitySort={activitySort} changeActivitySort={changeActivitySort} deleteDocs={deleteReplicates} + pageStart={pageStart} + pageEnd={pageEnd} />; } @@ -141,6 +144,13 @@ export default class ReplicationController extends React.Component { deleteDocs={deleteDocs} activitySort={activitySort} changeActivitySort={changeActivitySort} + pageStart={pageStart} + pageEnd={pageEnd} + docsPerPage={docsPerPage} + updatePerPageResults={updatePerPageResults} + paginateNext={paginateNext} + paginatePrevious={paginatePrevious} + pagination={pagination} />; } @@ -160,10 +170,10 @@ export default class ReplicationController extends React.Component { max={600} startValue={300} stepSize={60} - onPoll={this.getAllActivity.bind(this)} + onPoll={this.getAllActivity.bind(this, this.props.pagination)} /> ); diff --git a/app/addons/replication/reducers.js b/app/addons/replication/reducers.js index 15b6a53c5..4889df095 100644 --- a/app/addons/replication/reducers.js +++ b/app/addons/replication/reducers.js @@ -34,6 +34,20 @@ const loadActivitySort = () => { return sort; }; +const loadDocsPerPage = () => { + let docsPerPage = app.utils.localStorageGet('replication-docs-per-page'); + + if (!docsPerPage) { + docsPerPage = 10; + } + + return docsPerPage; +}; + +const saveDocsPerPage = (docsPerPage) => { + app.utils.localStorageSet('replication-docs-per-page', docsPerPage); +}; + const validFieldMap = { remoteSource: 'remoteSource', remoteTarget: 'remoteTarget', @@ -87,7 +101,12 @@ const initialState = { replicateInfo: [], checkingAPI: true, - activitySort: loadActivitySort() + activitySort: loadActivitySort(), + pagination: { + docsPerPage: loadDocsPerPage(), + page: 1, + canShowNext: false + } }; const clearForm = (state) => { @@ -254,10 +273,15 @@ const replication = (state = initialState, {type, options}) => { }; case ActionTypes.REPLICATION_STATUS: + console.log('STATUS', options); return { ...state, activityLoading: false, - statusDocs: options + statusDocs: options.docs, + pagination: { + ...state.pagination, + canShowNext: options.canShowNext + } }; case ActionTypes.REPLICATION_FILTER_DOCS: @@ -344,6 +368,38 @@ const replication = (state = initialState, {type, options}) => { allReplicateSelected: false }; + case ActionTypes.REPLICATION_UPDATE_PER_PAGE_RESULTS: + const newResultsState = { ...state }; + newResultsState.pagination.docsPerPage = options; + saveDocsPerPage(options); + return { + ...state, + pagination: { + ...state.pagination, + docsPerPage: options, + page: 1, + canShowNext: false + } + }; + + case ActionTypes.REPLICATION_NEXT_PAGE: + return { + ...state, + pagination: { + docsPerPage: state.pagination.docsPerPage, + page: state.pagination.page + 1 + } + }; + + case ActionTypes.REPLICATION_PREVIOUS_PAGE: + return { + ...state, + pagination: { + docsPerPage: state.pagination.docsPerPage, + page: state.pagination.page - 1 + } + }; + default: return state; } @@ -402,4 +458,10 @@ export const getReplicateInfo = (state) => { }); }; +export const getPagination = (state) => state.pagination; +export const getPageStart = (state) => 1 + (state.pagination.page - 1) * state.pagination.docsPerPage; +export const getPageEnd = (state) => state.pagination.docsPerPage + (state.pagination.page - 1) * state.pagination.docsPerPage; +export const getDocsPerPage = (state) => state.pagination.docsPerPage; +export const canShowNext = (state) => state.pagination.canShowNext; + export default replication; From 3e398873adc1469a33995665a7f02f1dfa8a9866 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Wed, 25 Apr 2018 11:11:04 +0200 Subject: [PATCH 2/6] fix css for footer --- app/addons/replication/assets/less/replication.less | 2 +- app/addons/replication/components/common-table.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/addons/replication/assets/less/replication.less b/app/addons/replication/assets/less/replication.less index 44a4a7427..cef5ecbf3 100644 --- a/app/addons/replication/assets/less/replication.less +++ b/app/addons/replication/assets/less/replication.less @@ -352,7 +352,7 @@ td.replication__empty-row { } .replication__paginate-footer { - position: absolute; + position: fixed; bottom: 0px; right: 0px; width: 100%; diff --git a/app/addons/replication/components/common-table.js b/app/addons/replication/components/common-table.js index 136581724..03ec4a747 100644 --- a/app/addons/replication/components/common-table.js +++ b/app/addons/replication/components/common-table.js @@ -370,7 +370,7 @@ export class ReplicationTable extends React.Component { render () { return ( - +
From 5db87795a39afb16bc232b0480e929fce286a9d1 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Wed, 25 Apr 2018 11:55:00 +0200 Subject: [PATCH 3/6] fix tests --- .../components/pagination/PaginationFooter.js | 1 - app/addons/replication/__tests__/api.tests.js | 14 +++++++------- app/addons/replication/reducers.js | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/addons/documents/index-results/components/pagination/PaginationFooter.js b/app/addons/documents/index-results/components/pagination/PaginationFooter.js index 8c9a117e7..5f1c663ba 100644 --- a/app/addons/documents/index-results/components/pagination/PaginationFooter.js +++ b/app/addons/documents/index-results/components/pagination/PaginationFooter.js @@ -40,7 +40,6 @@ export default class PaginationFooter extends React.Component { const { canShowNext, fetchParams, queryOptionsParams, paginateNext, perPage } = this.props; if (canShowNext) { - console.log('FOOTER NEXT', fetchParams, queryOptionsParams, perPage); paginateNext(fetchParams, queryOptionsParams, perPage); } } diff --git a/app/addons/replication/__tests__/api.tests.js b/app/addons/replication/__tests__/api.tests.js index 113c75b34..0f022f004 100644 --- a/app/addons/replication/__tests__/api.tests.js +++ b/app/addons/replication/__tests__/api.tests.js @@ -548,10 +548,10 @@ describe('Replication API', () => { it("returns parsedReplicationDocs and ignores all design docs", () => { fetchMock.getOnce('/_scheduler/jobs', 404); - fetchMock.get('/_replicator/_all_docs?include_docs=true&limit=100', _repDocs); + fetchMock.get('/_replicator/_all_docs?limit=6&skip=0&include_docs=true', _repDocs); return supportNewApi(true) - .then(fetchReplicationDocs) - .then(docs => { + .then(() => fetchReplicationDocs({docsPerPage: 5, page: 1})) + .then(({docs}) => { assert.deepEqual(docs.length, 1); assert.deepEqual(docs[0]._id, "c94d4839d1897105cb75e1251e0003ea"); }); @@ -565,11 +565,11 @@ describe('Replication API', () => { it("returns parsedReplicationDocs", () => { fetchMock.getOnce('/_scheduler/jobs', 200); - fetchMock.get('/_replicator/_all_docs?include_docs=true&limit=100', _repDocs); - fetchMock.get('/_scheduler/docs?include_docs=true', _schedDocs); + fetchMock.get('/_replicator/_all_docs?limit=6&skip=0&include_docs=true', _repDocs); + fetchMock.get('/_scheduler/docs?limit=6&skip=0&include_docs=true', _schedDocs); return supportNewApi(true) - .then(fetchReplicationDocs) - .then(docs => { + .then(() => fetchReplicationDocs({docsPerPage: 5, page: 1})) + .then(({docs}) => { assert.deepEqual(docs.length, 1); assert.deepEqual(docs[0]._id, "c94d4839d1897105cb75e1251e0003ea"); assert.deepEqual(docs[0].stateTime.toDateString(), (new Date('2017-03-07T14:46:17')).toDateString()); diff --git a/app/addons/replication/reducers.js b/app/addons/replication/reducers.js index 4889df095..1f71e6b04 100644 --- a/app/addons/replication/reducers.js +++ b/app/addons/replication/reducers.js @@ -273,7 +273,6 @@ const replication = (state = initialState, {type, options}) => { }; case ActionTypes.REPLICATION_STATUS: - console.log('STATUS', options); return { ...state, activityLoading: false, From ac38a49de855152f840524a26886bdbd82013162 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Wed, 25 Apr 2018 12:19:02 +0200 Subject: [PATCH 4/6] fixes for old api support --- app/addons/replication/__tests__/api.tests.js | 4 ++-- app/addons/replication/api.js | 4 ++-- app/addons/replication/components/activity.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/addons/replication/__tests__/api.tests.js b/app/addons/replication/__tests__/api.tests.js index 0f022f004..7bf55e7de 100644 --- a/app/addons/replication/__tests__/api.tests.js +++ b/app/addons/replication/__tests__/api.tests.js @@ -548,7 +548,7 @@ describe('Replication API', () => { it("returns parsedReplicationDocs and ignores all design docs", () => { fetchMock.getOnce('/_scheduler/jobs', 404); - fetchMock.get('/_replicator/_all_docs?limit=6&skip=0&include_docs=true', _repDocs); + fetchMock.get('/_replicator/_all_docs?startkey=%22_designZ%22&limit=6&skip=0&include_docs=true', _repDocs); return supportNewApi(true) .then(() => fetchReplicationDocs({docsPerPage: 5, page: 1})) .then(({docs}) => { @@ -565,7 +565,7 @@ describe('Replication API', () => { it("returns parsedReplicationDocs", () => { fetchMock.getOnce('/_scheduler/jobs', 200); - fetchMock.get('/_replicator/_all_docs?limit=6&skip=0&include_docs=true', _repDocs); + fetchMock.get('/_replicator/_all_docs?startkey=%22_designZ%22&limit=6&skip=0&include_docs=true', _repDocs); fetchMock.get('/_scheduler/docs?limit=6&skip=0&include_docs=true', _schedDocs); return supportNewApi(true) .then(() => fetchReplicationDocs({docsPerPage: 5, page: 1})) diff --git a/app/addons/replication/api.js b/app/addons/replication/api.js index 1173d3edf..abc65a1a0 100644 --- a/app/addons/replication/api.js +++ b/app/addons/replication/api.js @@ -306,7 +306,7 @@ export const fetchReplicationDocs = ({docsPerPage, page}) => { return supportNewApi() .then(newApi => { - const docsPromise = get(`/_replicator/_all_docs?${app.utils.queryParams(params)}`) + const docsPromise = get(`/_replicator/_all_docs?startkey=%22_designZ%22&${app.utils.queryParams(params)}`) .then((res) => { if (res.error) { return []; @@ -321,7 +321,7 @@ export const fetchReplicationDocs = ({docsPerPage, page}) => { const { finalDocList, canShowNext - } = removeOverflowDocsAndCalculateHasNext(docs, false, docsPerPage); + } = removeOverflowDocsAndCalculateHasNext(docs, false, docsPerPage + 1); return { docs: finalDocList, canShowNext diff --git a/app/addons/replication/components/activity.js b/app/addons/replication/components/activity.js index 0dad752e1..c6f43d0ad 100644 --- a/app/addons/replication/components/activity.js +++ b/app/addons/replication/components/activity.js @@ -15,7 +15,7 @@ import React from 'react'; import {DeleteModal} from './modals'; import {ReplicationTable} from './common-table'; import {ReplicationHeader} from './common-activity'; -import PaginationFooter from '../../documents/index-results/components/pagination/paginationfooter'; +import PaginationFooter from '../../documents/index-results/components/pagination/PaginationFooter'; export default class Activity extends React.Component { constructor (props) { From 48f31008528b4170954c49afc1079ea321dc81fc Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Thu, 26 Apr 2018 11:18:46 +0200 Subject: [PATCH 5/6] add tests --- app/addons/replication/__tests__/api.tests.js | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/app/addons/replication/__tests__/api.tests.js b/app/addons/replication/__tests__/api.tests.js index 7bf55e7de..772c0280d 100644 --- a/app/addons/replication/__tests__/api.tests.js +++ b/app/addons/replication/__tests__/api.tests.js @@ -556,6 +556,50 @@ describe('Replication API', () => { assert.deepEqual(docs[0]._id, "c94d4839d1897105cb75e1251e0003ea"); }); }); + + it("paginates to page 2 correctly", () => { + fetchMock.getOnce('/_scheduler/jobs', 200); + fetchMock.get('/_replicator/_all_docs?startkey=%22_designZ%22&limit=11&skip=10&include_docs=true', _repDocs); + fetchMock.get('/_scheduler/docs?limit=11&skip=10&include_docs=true', _schedDocs); + return supportNewApi(true) + .then(() => fetchReplicationDocs({docsPerPage: 10, page: 2})) + .then(({canShowNext}) => { + assert.notOk(canShowNext); + }); + }); + + it("sets canShowNext true and trims docs correctly", () => { + const clonedDoc = _repDocs.rows[2]; + const repDocs = { + ..._repDocs, + "total_rows":4, + "offset":0, + rows: [{ + ...clonedDoc, + _id: '1', + }, { + ...clonedDoc, + _id: '2', + }, { + + ...clonedDoc, + _id: '3', + }, { + ...clonedDoc, + _id: '4', + }] + }; + + fetchMock.getOnce('/_scheduler/jobs', 200); + fetchMock.get('/_replicator/_all_docs?startkey=%22_designZ%22&limit=4&skip=6&include_docs=true', repDocs); + fetchMock.get('/_scheduler/docs?limit=4&skip=6&include_docs=true', _schedDocs); + return supportNewApi(true) + .then(() => fetchReplicationDocs({docsPerPage: 3, page: 3})) + .then(({docs, canShowNext}) => { + assert.ok(canShowNext); + assert.deepEqual(docs.length, 3); + }); + }); }); describe('new api', () => { @@ -575,6 +619,50 @@ describe('Replication API', () => { assert.deepEqual(docs[0].stateTime.toDateString(), (new Date('2017-03-07T14:46:17')).toDateString()); }); }); + + it("paginates to page 2 correctly", () => { + fetchMock.getOnce('/_scheduler/jobs', 200); + fetchMock.get('/_replicator/_all_docs?startkey=%22_designZ%22&limit=11&skip=10&include_docs=true', _repDocs); + fetchMock.get('/_scheduler/docs?limit=11&skip=10&include_docs=true', _schedDocs); + return supportNewApi(true) + .then(() => fetchReplicationDocs({docsPerPage: 10, page: 2})) + .then(({canShowNext}) => { + assert.notOk(canShowNext); + }); + }); + + it("sets canShowNext true and trims docs correctly", () => { + const clonedDoc = _repDocs.rows[2]; + const repDocs = { + ..._repDocs, + "total_rows":4, + "offset":0, + rows: [{ + ...clonedDoc, + _id: '1', + }, { + ...clonedDoc, + _id: '2', + }, { + + ...clonedDoc, + _id: '3', + }, { + ...clonedDoc, + _id: '4', + }] + }; + + fetchMock.getOnce('/_scheduler/jobs', 200); + fetchMock.get('/_replicator/_all_docs?startkey=%22_designZ%22&limit=4&skip=6&include_docs=true', repDocs); + fetchMock.get('/_scheduler/docs?limit=4&skip=6&include_docs=true', _schedDocs); + return supportNewApi(true) + .then(() => fetchReplicationDocs({docsPerPage: 3, page: 3})) + .then(({docs, canShowNext}) => { + assert.ok(canShowNext); + assert.deepEqual(docs.length, 3); + }); + }); }); }); }); From 56865e92b16762cd92faa32119064cf5e4dc08f9 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Mon, 11 Jun 2018 16:22:36 +0200 Subject: [PATCH 6/6] fixes from review --- app/addons/replication/actions.js | 6 +++--- app/addons/replication/components/activity.js | 2 +- app/addons/replication/components/newreplication.js | 6 ++++-- app/addons/replication/container.js | 2 +- app/addons/replication/controller.js | 1 + 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/addons/replication/actions.js b/app/addons/replication/actions.js index 98797fbb6..ff41f1798 100644 --- a/app/addons/replication/actions.js +++ b/app/addons/replication/actions.js @@ -81,7 +81,7 @@ export const replicate = (params) => dispatch => { clear: true }); - dispatch(getReplicationActivity()); + dispatch(getReplicationActivity(params.pagination)); }) .catch(json => { if (json.error && json.error === "not_found") { @@ -194,7 +194,7 @@ export const clearSelectedReplicates = () => { }; }; -export const deleteDocs = (docs) => dispatch => { +export const deleteDocs = (docs, pagination) => dispatch => { const bulkDocs = docs.map(({raw: doc}) => { doc._deleted = true; return doc; @@ -229,7 +229,7 @@ export const deleteDocs = (docs) => dispatch => { }); dispatch(clearSelectedDocs()); - dispatch(getReplicationActivity()); + dispatch(getReplicationActivity(pagination)); }) .catch(resp => { resp.json() diff --git a/app/addons/replication/components/activity.js b/app/addons/replication/components/activity.js index c6f43d0ad..680605d85 100644 --- a/app/addons/replication/components/activity.js +++ b/app/addons/replication/components/activity.js @@ -49,7 +49,7 @@ export default class Activity extends React.Component { docs = this.props.docs.filter(doc => doc.selected); } - this.props.deleteDocs(docs); + this.props.deleteDocs(docs, this.props.pagination); this.closeModal(); } diff --git a/app/addons/replication/components/newreplication.js b/app/addons/replication/components/newreplication.js index 87b37e237..ce5524793 100644 --- a/app/addons/replication/components/newreplication.js +++ b/app/addons/replication/components/newreplication.js @@ -236,7 +236,8 @@ export default class NewReplicationController extends React.Component { sourceAuthType, sourceAuth, targetAuthType, - targetAuth + targetAuth, + pagination } = this.props; let _rev; @@ -260,7 +261,8 @@ export default class NewReplicationController extends React.Component { sourceAuthType, sourceAuth, targetAuthType, - targetAuth + targetAuth, + pagination }); } diff --git a/app/addons/replication/container.js b/app/addons/replication/container.js index 9ab0f4b17..a61ee772f 100644 --- a/app/addons/replication/container.js +++ b/app/addons/replication/container.js @@ -135,7 +135,7 @@ const mapDispatchToProps = (dispatch) => { filterReplicate: (filter) => dispatch(filterReplicate(filter)), filterDocs: (filter) => dispatch(filterDocs(filter)), selectDoc: (doc) => dispatch(selectDoc(doc)), - deleteDocs: (docs) => dispatch(deleteDocs(docs)), + deleteDocs: (docs, pagination) => dispatch(deleteDocs(docs, pagination)), selectAllDocs: () => dispatch(selectAllDocs()), changeActivitySort: (sort) => dispatch(changeActivitySort(sort)), selectAllReplicates: () => dispatch(selectAllReplicates()), diff --git a/app/addons/replication/controller.js b/app/addons/replication/controller.js index 31abfd8d5..f66753264 100644 --- a/app/addons/replication/controller.js +++ b/app/addons/replication/controller.js @@ -105,6 +105,7 @@ export default class ReplicationController extends React.Component { checkReplicationDocID={checkReplicationDocID} authenticated={authenticated} submittedNoChange={submittedNoChange} + pagination={pagination} />; }