Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 95 additions & 7 deletions app/addons/replication/__tests__/api.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,14 +548,58 @@ 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?startkey=%22_designZ%22&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");
});
});

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', () => {
Expand All @@ -565,16 +609,60 @@ 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?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)
.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());
});
});

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);
});
});
});
});
});
58 changes: 47 additions & 11 deletions app/addons/replication/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
createReplicatorDB
} from './api';


export const initReplicator = (routeLocalSource, localSource) => dispatch => {
if (routeLocalSource && routeLocalSource !== localSource) {
dispatch({
Expand Down Expand Up @@ -82,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") {
Expand All @@ -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
});
});
};
Expand Down Expand Up @@ -198,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;
Expand Down Expand Up @@ -233,7 +229,7 @@ export const deleteDocs = (docs) => dispatch => {
});

dispatch(clearSelectedDocs());
dispatch(getReplicationActivity());
dispatch(getReplicationActivity(pagination));
})
.catch(resp => {
resp.json()
Expand Down Expand Up @@ -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));
};
};
5 changes: 4 additions & 1 deletion app/addons/replication/actiontypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
};
40 changes: 34 additions & 6 deletions app/addons/replication/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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?startkey=%22_designZ%22&${app.utils.queryParams(params)}`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I know what is this suppose to do? When I run locally your branch, I don't have anything in my replicator activity and I suspect this line to the be the cause.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fetches all the docs in the replicator db except the design doc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @popojargo - because of the startkey param, the query won't return any docs whose ID starts with a number or uppercased letter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only viable solution I see is splitting the request in two API calls. One to fetch documents before the _design (?endkey="_design*") and another one to fetch documents after design docs (startkey="_designZ"

.then((res) => {
if (res.error) {
return [];
Expand All @@ -308,20 +316,40 @@ export const fetchReplicationDocs = () => {
});

if (!newApi) {
return docsPromise;
return docsPromise
.then(docs => {
const {
finalDocList,
canShowNext
} = removeOverflowDocsAndCalculateHasNext(docs, false, docsPerPage + 1);
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 [];
Expand Down
9 changes: 8 additions & 1 deletion app/addons/replication/assets/less/replication.less
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,11 @@ td.replication__empty-row {

.replication__activity-caveat {
padding-left: 80px;
}
}

.replication__paginate-footer {
position: fixed;
bottom: 0px;
right: 0px;
width: 100%;
}
31 changes: 29 additions & 2 deletions app/addons/replication/components/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -48,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();
}

Expand All @@ -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;
Expand All @@ -90,6 +98,25 @@ export default class Activity extends React.Component {
column={activitySort.column}
changeSort={changeActivitySort}
/>
<div className="replication__paginate-footer">
<PaginationFooter
hasResults={true}
showPrioritizedEnabled={false}
prioritizedEnabled={false}
canShowNext={pagination.canShowNext}
canShowPrevious={pagination.page > 1}
perPage={docsPerPage}
toggleShowAllColumns={false}
docs={this.props.docs}
pageStart={pageStart}
pageEnd={pageEnd}
updatePerPageResults={updatePerPageResults}
paginateNext={paginateNext}
paginatePrevious={paginatePrevious}
queryOptionsParams={{}}
fetchParams={pagination}
/>
</div>
<DeleteModal
isReplicationDB={true}
multipleDocs={this.numDocsSelected()}
Expand Down
2 changes: 1 addition & 1 deletion app/addons/replication/components/common-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ export class ReplicationTable extends React.Component {
render () {

return (
<Table striped>
<Table striped style={{marginBottom: '100px'}}>
<thead>
<tr>
<th className="replication__table-bulk-select">
Expand Down
Loading