implement PaginationListStandalone

This commit is contained in:
AllenFang 2018-12-08 15:18:00 +08:00
parent 5c52412542
commit d42a10bbae
11 changed files with 229 additions and 106 deletions

View File

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import createBaseContext from './src/state-context';
import createDataContext from './src/data-context';
import PaginationListStandalone from './src/pagination-list-standalone';
export default (options = {}) => ({
createContext: createDataContext,
@ -21,3 +22,4 @@ CustomizableProvider.propTypes = {
};
export const PaginationProvider = CustomizableProvider;
export { PaginationListStandalone };

View File

@ -8,12 +8,6 @@ export default ExtendBase =>
return (currPage - 1) < pageStartIndex ? pageStartIndex : currPage - 1;
}
goToNextPage() {
const { currPage } = this.props;
const { lastPage } = this.state;
return (currPage + 1) > lastPage ? lastPage : currPage + 1;
}
initialState() {
const totalPages = this.calculateTotalPage();
const lastPage = this.calculateLastPage(totalPages);
@ -47,8 +41,9 @@ export default ExtendBase =>
}
calculatePages(
totalPages = this.state.totalPages,
lastPage = this.state.lastPage) {
totalPages,
lastPage
) {
const {
currPage,
paginationSize,
@ -94,7 +89,7 @@ export default ExtendBase =>
return pages;
}
calculatePageStatus(pages = [], lastPage = this.state.lastPage) {
calculatePageStatus(pages = [], lastPage) {
const {
currPage,
pageStartIndex,

View File

@ -0,0 +1,78 @@
/* eslint react/prop-types: 0 */
import React, { Component } from 'react';
import pageResolver from './page-resolver';
export default WrappedComponent =>
class PaginationHandler extends pageResolver(Component) {
constructor(props) {
super(props);
this.handleChangePage = this.handleChangePage.bind(this);
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
this.state = this.initialState();
}
componentWillReceiveProps(nextProps) {
const { dataSize, currSizePerPage } = nextProps;
if (currSizePerPage !== this.props.currSizePerPage || dataSize !== this.props.dataSize) {
const totalPages = this.calculateTotalPage(currSizePerPage, dataSize);
const lastPage = this.calculateLastPage(totalPages);
this.setState({ totalPages, lastPage });
}
}
handleChangeSizePerPage(sizePerPage) {
const { currSizePerPage, onSizePerPageChange } = this.props;
const selectedSize = typeof sizePerPage === 'string' ? parseInt(sizePerPage, 10) : sizePerPage;
let { currPage } = this.props;
if (selectedSize !== currSizePerPage) {
const newTotalPages = this.calculateTotalPage(selectedSize);
const newLastPage = this.calculateLastPage(newTotalPages);
if (currPage > newLastPage) currPage = newLastPage;
onSizePerPageChange(selectedSize, currPage);
}
this.closeDropDown();
}
handleChangePage(newPage) {
let page;
const {
currPage,
pageStartIndex,
prePageText,
nextPageText,
lastPageText,
firstPageText,
onPageChange
} = this.props;
const { lastPage } = this.state;
if (newPage === prePageText) {
page = this.backToPrevPage();
} else if (newPage === nextPageText) {
page = (currPage + 1) > lastPage ? lastPage : currPage + 1;
} else if (newPage === lastPageText) {
page = lastPage;
} else if (newPage === firstPageText) {
page = pageStartIndex;
} else {
page = parseInt(newPage, 10);
}
if (page !== currPage) {
onPageChange(page);
}
}
render() {
return (
<WrappedComponent
{ ...this.props }
lastPage={ this.state.lastPage }
totalPages={ this.state.totalPages }
onPageChange={ this.handleChangePage }
onSizePerPageChange={ this.handleChangeSizePerPage }
/>
);
}
};

View File

@ -0,0 +1,20 @@
/* eslint react/prop-types: 0 */
import React, { Component } from 'react';
import pageResolver from './page-resolver';
export default WrappedComponent =>
class PaginationListAdapter extends pageResolver(Component) {
render() {
const { lastPage, totalPages, pageButtonRenderer, onPageChange } = this.props;
const pages = this.calculatePageStatus(this.calculatePages(totalPages, lastPage), lastPage);
return (
<WrappedComponent
pageButtonRenderer={ pageButtonRenderer }
onPageChange={ onPageChange }
pages={ pages }
/>
);
}
};

View File

@ -1,53 +1,12 @@
import React from 'react';
import pageResolver from './page-resolver';
import PaginationList from './pagination-list';
import standaloneAdapter from './standalone-adapter';
import PaginationHandler from './pagination-handler';
import paginationListAdapter from './pagination-list-adapter';
export default class PaginationListStandalone extends pageResolver(React.Component) {
constructor(props) {
super(props);
this.handleChangePage = this.handleChangePage.bind(this);
this.state = this.initialState();
}
const PaginationListStandalone = props => (
<PaginationList { ...props } />
);
handleChangePage(newPage) {
let page;
const {
currPage,
pageStartIndex,
prePageText,
nextPageText,
lastPageText,
firstPageText,
onPageChange
} = this.props;
const { lastPage } = this.state;
if (newPage === prePageText) {
page = this.backToPrevPage();
} else if (newPage === nextPageText) {
page = (currPage + 1) > lastPage ? lastPage : currPage + 1;
} else if (newPage === lastPageText) {
page = lastPage;
} else if (newPage === firstPageText) {
page = pageStartIndex;
} else {
page = parseInt(newPage, 10);
}
if (page !== currPage) {
onPageChange(page);
}
}
render() {
const { totalPages, lastPage } = this.state;
const pages = this.calculatePageStatus(this.calculatePages(totalPages), lastPage);
return (
<PaginationList
pages={ pages }
onPageChange={ this.handleChangePage }
/>
);
}
}
export default
standaloneAdapter(PaginationHandler(paginationListAdapter(PaginationListStandalone)));

View File

@ -146,7 +146,7 @@ class Pagination extends pageResolver(Component) {
paginationTotalRenderer,
hidePageListOnlyOnePage
} = this.props;
const pages = this.calculatePageStatus(this.calculatePages(totalPages), lastPage);
const pages = this.calculatePageStatus(this.calculatePages(totalPages, lastPage), lastPage);
const [from, to] = this.calculateFromTo();
const pageListClass = cs(
'react-bootstrap-table-pagination-list',

View File

@ -1,12 +1,12 @@
/* eslint react/prop-types: 0 */
import React from 'react';
export default Component => ({
export default WrappedComponent => ({
page,
sizePerPage,
...rest
}) => (
<Component
<WrappedComponent
{ ...rest }
currPage={ page }
currSizePerPage={ sizePerPage }

View File

@ -81,35 +81,6 @@ describe('PageResolver', () => {
});
});
describe('goToNextPage', () => {
const props = createMockProps();
describe('when props.currPage is not hitting state.lastPage', () => {
beforeEach(() => {
const mockElement = React.createElement(MockComponent, props, null);
wrapper = shallow(mockElement);
});
it('should getting previous page correctly', () => {
const instance = wrapper.instance();
expect(instance.goToNextPage()).toEqual(props.currPage + 1);
});
});
describe('when props.currPage is hitting state.lastpage', () => {
beforeEach(() => {
props.currPage = 10;
const mockElement = React.createElement(MockComponent, props, null);
wrapper = shallow(mockElement);
});
it('should always getting page which must eq props.pageStartIndex', () => {
const instance = wrapper.instance();
expect(instance.goToNextPage()).toEqual(instance.state.lastPage);
});
});
});
describe('calculateFromTo', () => {
const props = createMockProps();
beforeEach(() => {
@ -192,7 +163,7 @@ describe('PageResolver', () => {
});
describe('calculatePages', () => {
describe('calculate by state.totalPages and state.lastPage', () => {
describe('calculate by totalPages and lastPage', () => {
const props = createMockProps();
beforeEach(() => {
const mockElement = React.createElement(MockComponent, props, null);
@ -201,7 +172,7 @@ describe('PageResolver', () => {
it('should getting pages list correctly', () => {
const instance = wrapper.instance();
expect(instance.calculatePages()).toEqual(
expect(instance.calculatePages(instance.state.totalPages, instance.state.lastPage)).toEqual(
[props.prePageText, 1, 2, 3, 4, 5, props.nextPageText, props.lastPageText]);
expect(instance.calculatePages(4, 4)).toEqual(
@ -218,7 +189,9 @@ describe('PageResolver', () => {
currPages.forEach((currPage) => {
props.currPage = currPage + 1;
wrapper = shallow(<MockComponent { ...props } />);
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
if (props.currPage < 4) {
expect(pageList).toEqual(
@ -253,7 +226,9 @@ describe('PageResolver', () => {
[1, 3, 5, 8, 10].forEach((paginationSize) => {
props.paginationSize = paginationSize;
wrapper = shallow(<MockComponent { ...props } />);
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
const result = pageList.filter(p => indicators.indexOf(p) === -1);
expect(result.length).toEqual(props.paginationSize);
});
@ -267,7 +242,9 @@ describe('PageResolver', () => {
[1, 2, 3, 4, 5, 6, 7].forEach((currPage) => {
props.currPage = currPage;
wrapper = shallow(<MockComponent { ...props } />);
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
expect(pageList.indexOf(props.lastPageText) > -1).toBeTruthy();
});
});
@ -278,7 +255,9 @@ describe('PageResolver', () => {
[10, 9, 8, 7, 6, 5, 4].forEach((currPage) => {
props.currPage = currPage;
wrapper = shallow(<MockComponent { ...props } />);
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
expect(pageList.indexOf(props.firstPageText) > -1).toBeTruthy();
});
});
@ -293,7 +272,9 @@ describe('PageResolver', () => {
props.currPage = currPage + 1;
props.withFirstAndLast = false;
wrapper = shallow(<MockComponent { ...props } />);
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
expect(pageList.indexOf(props.lastPageText) > -1).toBeFalsy();
expect(pageList.indexOf(props.firstPageText) > -1).toBeFalsy();
});
@ -311,7 +292,9 @@ describe('PageResolver', () => {
});
it('should getting last page correctly', () => {
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
expect(pageList).toEqual(
[props.prePageText, -2, -1, 0, 1, 2, props.nextPageText, props.lastPageText]);
});
@ -329,7 +312,9 @@ describe('PageResolver', () => {
});
it('should always having next and previous page indication', () => {
const pageList = wrapper.instance().calculatePages();
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
expect(pageList.indexOf(props.nextPageText) > -1).toBeTruthy();
expect(pageList.indexOf(props.prePageText) > -1).toBeTruthy();
});
@ -345,7 +330,10 @@ describe('PageResolver', () => {
});
it('should getting empty array', () => {
expect(wrapper.instance().calculatePages()).toEqual([]);
const instance = wrapper.instance();
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
expect(pageList).toEqual([]);
});
});
});
@ -360,7 +348,9 @@ describe('PageResolver', () => {
const mockElement = React.createElement(MockComponent, props, null);
wrapper = shallow(mockElement);
instance = wrapper.instance();
pageStatus = instance.calculatePageStatus(instance.calculatePages());
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
pageStatus = instance.calculatePageStatus(pageList, instance.state.lastPage);
});
it('should returning correct format for page status', () => {
@ -388,8 +378,9 @@ describe('PageResolver', () => {
const mockElement = React.createElement(MockComponent, props, null);
wrapper = shallow(mockElement);
instance = wrapper.instance();
const pageList = instance.calculatePages();
pageStatus = instance.calculatePageStatus(pageList);
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
pageStatus = instance.calculatePageStatus(pageList, instance.state.lastPage);
expect(pageStatus.find(p => p.page === props.prePageText)).not.toBeDefined();
});
@ -401,8 +392,9 @@ describe('PageResolver', () => {
const mockElement = React.createElement(MockComponent, props, null);
wrapper = shallow(mockElement);
instance = wrapper.instance();
const pageList = instance.calculatePages();
pageStatus = instance.calculatePageStatus(pageList);
const pageList = instance.calculatePages(
instance.state.totalPages, instance.state.lastPage);
pageStatus = instance.calculatePageStatus(pageList, instance.state.lastPage);
expect(pageStatus.find(p => p.page === props.nextPageText)).not.toBeDefined();
});

View File

@ -0,0 +1,32 @@
import React from 'react';
import { shallow } from 'enzyme';
import paginationListAdapter from '../src/pagination-list-adapter';
const MockComponent = () => null;
const PaginationListAdapter = paginationListAdapter(MockComponent);
describe('paginationListAdapter', () => {
let wrapper;
const props = {
totalPages: 10,
lastPage: 10,
pageButtonRenderer: jest.fn(),
onPageChange: jest.fn()
};
describe('render', () => {
beforeEach(() => {
wrapper = shallow(<PaginationListAdapter { ...props } />);
});
it('should render successfully', () => {
const mockComponent = wrapper.find(MockComponent);
expect(mockComponent).toHaveLength(1);
expect(mockComponent.props().pages).toBeDefined();
expect(mockComponent.props().pageButtonRenderer).toBeDefined();
expect(mockComponent.props().onPageChange).toBeDefined();
});
});
});

View File

@ -54,8 +54,9 @@ describe('Pagination', () => {
it('should rendering PaginationList component successfully', () => {
const paginationList = wrapper.find(PaginationList);
const pageList = instance.calculatePages(instance.state.totalPages, instance.state.lastPage);
expect(paginationList.length).toBe(1);
expect(paginationList.prop('pages')).toEqual(instance.calculatePageStatus(instance.calculatePages()));
expect(paginationList.prop('pages')).toEqual(instance.calculatePageStatus(pageList, instance.state.lastPage));
expect(paginationList.prop('onPageChange')).toEqual(instance.handleChangePage);
});

View File

@ -0,0 +1,44 @@
import React from 'react';
import { shallow } from 'enzyme';
import standaloneAdapter from '../src/standalone-adapter';
const MockStandalone = () => null;
const MockStandaloneWithAdapter = standaloneAdapter(MockStandalone);
describe('standaloneAdapter', () => {
let wrapper;
const props = {
page: 2,
sizePerPage: 10,
name1: 'A',
name2: 'B'
};
describe('render', () => {
beforeEach(() => {
wrapper = shallow(<MockStandaloneWithAdapter { ...props } />);
});
it('should render successfully', () => {
expect(wrapper.find(MockStandalone)).toHaveLength(1);
});
it('should convert props.page as currPage to child component', () => {
const mockStandalone = wrapper.find(MockStandalone);
expect(mockStandalone.props().currPage).toEqual(props.page);
});
it('should convert props.sizePerPage as currSizePerPage to child component', () => {
const mockStandalone = wrapper.find(MockStandalone);
expect(mockStandalone.props().currSizePerPage).toEqual(props.sizePerPage);
});
it('should just pass remain props to child component', () => {
const mockStandalone = wrapper.find(MockStandalone);
const { page, sizePerPage, ...origin } = props;
const { currPage, currSizePerPage, ...rest } = mockStandalone.props();
expect(rest).toEqual(origin);
});
});
});