fix pagination broken when bootstrap4

This commit is contained in:
AllenFang 2018-07-22 17:32:41 +08:00
parent 495875792f
commit 3f957db56b
7 changed files with 232 additions and 92 deletions

View File

@ -0,0 +1,6 @@
import React from 'react';
// consider to have a common lib?1
export const BootstrapContext = React.createContext({
bootstrap4: false
});

View File

@ -5,6 +5,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Const from './const'; import Const from './const';
import { BootstrapContext } from './bootstrap';
import Pagination from './pagination'; import Pagination from './pagination';
import { getByCurrPage, alignPage } from './page'; import { getByCurrPage, alignPage } from './page';
@ -123,7 +124,7 @@ export default (
render() { render() {
let { data } = this.props; let { data } = this.props;
const { pagination: { options } } = this.props; const { pagination: { options }, bootstrap4 } = this.props;
const { currPage, currSizePerPage } = this; const { currPage, currSizePerPage } = this;
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ? const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
Const.With_FIRST_AND_LAST : options.withFirstAndLast; Const.With_FIRST_AND_LAST : options.withFirstAndLast;
@ -148,6 +149,7 @@ export default (
return ( return (
<PaginationContext.Provider value={ { data } }> <PaginationContext.Provider value={ { data } }>
{ this.props.children } { this.props.children }
<BootstrapContext.Provider value={ { bootstrap4 } }>
<Pagination <Pagination
key="pagination" key="pagination"
dataSize={ options.totalSize || this.props.data.length } dataSize={ options.totalSize || this.props.data.length }
@ -173,6 +175,7 @@ export default (
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE } firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE } lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
/> />
</BootstrapContext.Provider>
</PaginationContext.Provider> </PaginationContext.Provider>
); );
} }

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import cs from 'classnames'; import cs from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { BootstrapContext } from './bootstrap';
import SizePerPageOption from './size-per-page-option'; import SizePerPageOption from './size-per-page-option';
const sizePerPageDefaultClass = 'react-bs-table-sizePerPage-dropdown'; const sizePerPageDefaultClass = 'react-bs-table-sizePerPage-dropdown';
@ -20,14 +21,18 @@ const SizePerPageDropDown = (props) => {
} = props; } = props;
const dropDownStyle = { visibility: hidden ? 'hidden' : 'visible' }; const dropDownStyle = { visibility: hidden ? 'hidden' : 'visible' };
const openClass = open ? 'open show' : '';
const dropdownClasses = cs( const dropdownClasses = cs(
open ? 'open show' : '', openClass,
sizePerPageDefaultClass, sizePerPageDefaultClass,
variation, variation,
className, className,
); );
return ( return (
<BootstrapContext.Consumer>
{
({ bootstrap4 }) => (
<span <span
style={ dropDownStyle } style={ dropDownStyle }
className={ dropdownClasses } className={ dropdownClasses }
@ -41,23 +46,35 @@ const SizePerPageDropDown = (props) => {
onBlur={ onBlur } onBlur={ onBlur }
> >
{ currSizePerPage } { currSizePerPage }
<span>
{ ' ' } { ' ' }
{
bootstrap4 ? null : (
<span>
<span className="caret" /> <span className="caret" />
</span> </span>
)
}
</button> </button>
<ul className="dropdown-menu" role="menu" aria-labelledby="pageDropDown"> <ul
className={ `dropdown-menu ${openClass}` }
role="menu"
aria-labelledby="pageDropDown"
>
{ {
options.map(option => ( options.map(option => (
<SizePerPageOption <SizePerPageOption
{ ...option } { ...option }
key={ option.text } key={ option.text }
bootstrap4={ bootstrap4 }
onSizePerPageChange={ onSizePerPageChange } onSizePerPageChange={ onSizePerPageChange }
/> />
)) ))
} }
</ul> </ul>
</span> </span>
)
}
</BootstrapContext.Consumer>
); );
}; };

View File

@ -5,9 +5,28 @@ import PropTypes from 'prop-types';
const SizePerPageOption = ({ const SizePerPageOption = ({
text, text,
page, page,
onSizePerPageChange onSizePerPageChange,
}) => ( bootstrap4
<li key={ text } role="presentation" className="dropdown-item"> }) => (bootstrap4 ? (
<a
href="#"
tabIndex="-1"
role="menuitem"
className="dropdown-item"
data-page={ page }
onMouseDown={ (e) => {
e.preventDefault();
onSizePerPageChange(page);
} }
>
{ text }
</a>
) : (
<li
key={ text }
role="presentation"
className="dropdown-item"
>
<a <a
href="#" href="#"
tabIndex="-1" tabIndex="-1"
@ -21,12 +40,17 @@ const SizePerPageOption = ({
{ text } { text }
</a> </a>
</li> </li>
); ));
SizePerPageOption.propTypes = { SizePerPageOption.propTypes = {
text: PropTypes.string.isRequired, text: PropTypes.string.isRequired,
page: PropTypes.number.isRequired, page: PropTypes.number.isRequired,
onSizePerPageChange: PropTypes.func.isRequired onSizePerPageChange: PropTypes.func.isRequired,
bootstrap4: PropTypes.bool
};
SizePerPageOption.defaultProps = {
bootstrap4: false
}; };
export default SizePerPageOption; export default SizePerPageOption;

View File

@ -5,6 +5,12 @@ import { shallow } from 'enzyme';
import SizePerPageOption from '../src/size-per-page-option'; import SizePerPageOption from '../src/size-per-page-option';
import SizePerPageDropDown from '../src/size-per-page-dropdown'; import SizePerPageDropDown from '../src/size-per-page-dropdown';
const shallowWithContext = (elem, context = {}) => {
const wrapper = shallow(elem);
const Children = wrapper.props().children(context);
return shallow(Children);
};
describe('SizePerPageDropDown', () => { describe('SizePerPageDropDown', () => {
let wrapper; let wrapper;
const currSizePerPage = '25'; const currSizePerPage = '25';
@ -28,8 +34,9 @@ describe('SizePerPageDropDown', () => {
describe('default SizePerPageDropDown component', () => { describe('default SizePerPageDropDown component', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } /> <SizePerPageDropDown { ...props } />,
{ bootstrap4: false }
); );
}); });
@ -47,6 +54,7 @@ describe('SizePerPageDropDown', () => {
const option = options[i]; const option = options[i];
expect(sizePerPage.prop('text')).toEqual(option.text); expect(sizePerPage.prop('text')).toEqual(option.text);
expect(sizePerPage.prop('page')).toEqual(option.page); expect(sizePerPage.prop('page')).toEqual(option.page);
expect(sizePerPage.prop('bootstrap4')).toBeFalsy();
expect(sizePerPage.prop('onSizePerPageChange')).toEqual(onSizePerPageChange); expect(sizePerPage.prop('onSizePerPageChange')).toEqual(onSizePerPageChange);
}); });
}); });
@ -61,10 +69,52 @@ describe('SizePerPageDropDown', () => {
}); });
}); });
describe('when bootstrap4 context is true', () => {
beforeEach(() => {
wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } />,
{ bootstrap4: true }
);
});
it('should rendering SizePerPageDropDown correctly', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find('button').length).toBe(1);
expect(wrapper.find('button').text()).toEqual(`${currSizePerPage} `);
});
it('should rendering SizePerPageOption successfully', () => {
expect(wrapper.find('ul.dropdown-menu').length).toBe(1);
const sizePerPageOptions = wrapper.find(SizePerPageOption);
expect(sizePerPageOptions.length).toBe(options.length);
sizePerPageOptions.forEach((sizePerPage, i) => {
const option = options[i];
expect(sizePerPage.prop('text')).toEqual(option.text);
expect(sizePerPage.prop('page')).toEqual(option.page);
expect(sizePerPage.prop('bootstrap4')).toBeTruthy();
expect(sizePerPage.prop('onSizePerPageChange')).toEqual(onSizePerPageChange);
});
});
it('no need to render caret', () => {
expect(wrapper.find('.caret')).toHaveLength(0);
});
it('default variation is dropdown', () => {
expect(wrapper.hasClass('dropdown')).toBeTruthy();
});
it('default dropdown is not open', () => {
expect(wrapper.hasClass('open show')).toBeFalsy();
expect(wrapper.find('[aria-expanded=false]').length).toBe(1);
});
});
describe('when open prop is true', () => { describe('when open prop is true', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } open /> <SizePerPageDropDown { ...props } open />,
{ bootstrap4: false }
); );
}); });
@ -76,8 +126,9 @@ describe('SizePerPageDropDown', () => {
describe('when hidden prop is true', () => { describe('when hidden prop is true', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } hidden /> <SizePerPageDropDown { ...props } hidden />,
{ bootstrap4: false }
); );
}); });
@ -89,8 +140,9 @@ describe('SizePerPageDropDown', () => {
describe('when btnContextual prop is defined', () => { describe('when btnContextual prop is defined', () => {
const contextual = 'btn-warning'; const contextual = 'btn-warning';
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } btnContextual={ contextual } /> <SizePerPageDropDown { ...props } btnContextual={ contextual } />,
{ bootstrap4: false }
); );
}); });
@ -102,8 +154,9 @@ describe('SizePerPageDropDown', () => {
describe('when variation prop is defined', () => { describe('when variation prop is defined', () => {
const variation = 'dropup'; const variation = 'dropup';
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } variation={ variation } /> <SizePerPageDropDown { ...props } variation={ variation } />,
{ bootstrap4: false }
); );
}); });
@ -115,8 +168,9 @@ describe('SizePerPageDropDown', () => {
describe('when className prop is defined', () => { describe('when className prop is defined', () => {
const className = 'custom-class'; const className = 'custom-class';
beforeEach(() => { beforeEach(() => {
wrapper = shallow( wrapper = shallowWithContext(
<SizePerPageDropDown { ...props } className={ className } /> <SizePerPageDropDown { ...props } className={ className } />,
{ bootstrap4: false }
); );
}); });

View File

@ -10,6 +10,11 @@ describe('SizePerPageOption', () => {
const page = 1; const page = 1;
const onSizePerPageChange = sinon.stub(); const onSizePerPageChange = sinon.stub();
beforeEach(() => {
onSizePerPageChange.reset();
});
describe('when bootstrap4 prop is true', () => {
beforeEach(() => { beforeEach(() => {
const props = { text, page, onSizePerPageChange }; const props = { text, page, onSizePerPageChange };
wrapper = shallow( wrapper = shallow(
@ -19,7 +24,7 @@ describe('SizePerPageOption', () => {
it('should render SizePerPageOption correctly', () => { it('should render SizePerPageOption correctly', () => {
expect(wrapper.length).toBe(1); expect(wrapper.length).toBe(1);
expect(wrapper.find('.dropdown-item').length).toBe(1); expect(wrapper.find('li.dropdown-item').length).toBe(1);
expect(wrapper.find(`[data-page=${page}]`).length).toBe(1); expect(wrapper.find(`[data-page=${page}]`).length).toBe(1);
expect(wrapper.text()).toEqual(text); expect(wrapper.text()).toEqual(text);
}); });
@ -36,4 +41,34 @@ describe('SizePerPageOption', () => {
expect(onSizePerPageChange.calledWith(page)).toBeTruthy(); expect(onSizePerPageChange.calledWith(page)).toBeTruthy();
}); });
}); });
});
describe('when bootstrap4 prop is true', () => {
beforeEach(() => {
const props = { text, page, onSizePerPageChange };
wrapper = shallow(
<SizePerPageOption { ...props } bootstrap4 />
);
});
it('should render SizePerPageOption correctly', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find('a.dropdown-item').length).toBe(1);
expect(wrapper.find(`[data-page=${page}]`).length).toBe(1);
expect(wrapper.text()).toEqual(text);
});
describe('when MouseDown event happen', () => {
const preventDefault = sinon.stub();
beforeEach(() => {
wrapper.find('a').simulate('mousedown', { preventDefault });
});
it('should calling props.onSizePerPageChange correctly', () => {
expect(preventDefault.calledOnce).toBeTruthy();
expect(onSizePerPageChange.calledOnce).toBeTruthy();
expect(onSizePerPageChange.calledWith(page)).toBeTruthy();
});
});
});
}); });

View File

@ -155,6 +155,7 @@ const withContext = Base =>
ref={ n => this.paginationContext = n } ref={ n => this.paginationContext = n }
pagination={ this.props.pagination } pagination={ this.props.pagination }
data={ rootProps.getData(filterProps, searchProps, sortProps) } data={ rootProps.getData(filterProps, searchProps, sortProps) }
bootstrap4={ this.props.bootstrap4 }
> >
<this.PaginationContext.Consumer> <this.PaginationContext.Consumer>
{ {