mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
Merge pull request #500 from react-bootstrap-table/develop
20180821 release
This commit is contained in:
commit
6e526f455b
@ -52,6 +52,7 @@
|
||||
"css-loader": "0.28.1",
|
||||
"enzyme": "3.3.0",
|
||||
"enzyme-adapter-react-16": "1.1.1",
|
||||
"enzyme-to-json": "3.3.4",
|
||||
"eslint": "4.5.0",
|
||||
"eslint-config-airbnb": "15.1.0",
|
||||
"eslint-loader": "1.9.0",
|
||||
|
||||
@ -22,8 +22,19 @@ const columns = [{
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||
|
||||
// ...
|
||||
const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
|
||||
const NoDataIndication = () => (
|
||||
<div className="spinner">
|
||||
<div className="rect1" />
|
||||
<div className="rect2" />
|
||||
<div className="rect3" />
|
||||
<div className="rect4" />
|
||||
<div className="rect5" />
|
||||
</div>
|
||||
);
|
||||
|
||||
const Table = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
remote
|
||||
@ -32,12 +43,13 @@ const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize })
|
||||
columns={ columns }
|
||||
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
|
||||
onTableChange={ onTableChange }
|
||||
noDataIndication={ () => <NoDataIndication /> }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
|
||||
class Container extends React.Component {
|
||||
class EmptyTableOverlay extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -47,7 +59,7 @@ class Container extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
handleTableChange = ({ page, sizePerPage }) => {
|
||||
handleTableChange = (type, { page, sizePerPage }) => {
|
||||
const currentIndex = (page - 1) * sizePerPage;
|
||||
setTimeout(() => {
|
||||
this.setState(() => ({
|
||||
@ -55,13 +67,14 @@ class Container extends React.Component {
|
||||
data: products.slice(currentIndex, currentIndex + sizePerPage),
|
||||
sizePerPage
|
||||
}));
|
||||
}, 2000);
|
||||
}, 3000);
|
||||
this.setState(() => ({ data: [] }));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, sizePerPage, page } = this.state;
|
||||
return (
|
||||
<RemotePagination
|
||||
<Table
|
||||
data={ data }
|
||||
page={ page }
|
||||
sizePerPage={ sizePerPage }
|
||||
|
||||
@ -54,31 +54,22 @@ export default (
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let needNewState = false;
|
||||
let { currPage, currSizePerPage } = this;
|
||||
const { page, sizePerPage, onPageChange } = nextProps.pagination.options;
|
||||
let { currPage } = this;
|
||||
const { currSizePerPage } = this;
|
||||
const { onPageChange } = nextProps.pagination.options;
|
||||
|
||||
const pageStartIndex = typeof nextProps.pagination.options.pageStartIndex !== 'undefined' ?
|
||||
nextProps.pagination.options.pageStartIndex : Const.PAGE_START_INDEX;
|
||||
|
||||
if (typeof page !== 'undefined' && currPage !== page) { // user defined page
|
||||
currPage = page;
|
||||
needNewState = true;
|
||||
} else {
|
||||
// user should align the page when the page is not fit to the data size when remote enable
|
||||
if (!isRemotePagination()) {
|
||||
const newPage = alignPage(nextProps.data, currPage, currSizePerPage, pageStartIndex);
|
||||
if (currPage !== newPage) {
|
||||
currPage = newPage;
|
||||
needNewState = true;
|
||||
}
|
||||
// user should align the page when the page is not fit to the data size when remote enable
|
||||
if (!isRemotePagination()) {
|
||||
const newPage = alignPage(nextProps.data, currPage, currSizePerPage, pageStartIndex);
|
||||
if (currPage !== newPage) {
|
||||
currPage = newPage;
|
||||
needNewState = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof sizePerPage !== 'undefined' && currSizePerPage !== sizePerPage) {
|
||||
currSizePerPage = sizePerPage;
|
||||
needNewState = true;
|
||||
}
|
||||
|
||||
if (needNewState) {
|
||||
if (onPageChange) {
|
||||
onPageChange(currPage, currSizePerPage);
|
||||
|
||||
@ -23,10 +23,9 @@ export const alignPage = (
|
||||
sizePerPage,
|
||||
pageStartIndex
|
||||
) => {
|
||||
const end = endIndex(page, sizePerPage, pageStartIndex);
|
||||
const dataSize = data.length;
|
||||
|
||||
if (end - 1 > dataSize) {
|
||||
if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) {
|
||||
return pageStartIndex;
|
||||
}
|
||||
return page;
|
||||
|
||||
@ -126,69 +126,6 @@ describe('PaginationContext', () => {
|
||||
let instance;
|
||||
let nextProps;
|
||||
|
||||
describe('when nextProps.pagination.options.page is existing', () => {
|
||||
const onPageChange = jest.fn();
|
||||
afterEach(() => {
|
||||
onPageChange.mockReset();
|
||||
});
|
||||
|
||||
describe('and if it is different with currPage', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext());
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: {
|
||||
options: {
|
||||
page: 2,
|
||||
onPageChange
|
||||
}
|
||||
}
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('should call options.onPageChange', () => {
|
||||
expect(onPageChange).toHaveBeenCalledTimes(1);
|
||||
expect(onPageChange).toHaveBeenCalledWith(
|
||||
instance.currPage,
|
||||
instance.currSizePerPage
|
||||
);
|
||||
});
|
||||
|
||||
it('should set correct currPage', () => {
|
||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and if it is same as currPage', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext());
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: {
|
||||
options: {
|
||||
page: 1,
|
||||
onPageChange
|
||||
}
|
||||
}
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('shouldn\'t call options.onPageChange', () => {
|
||||
expect(onPageChange).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('should have correct currPage', () => {
|
||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nextProps.pagination.options.page is not existing', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
@ -206,69 +143,6 @@ describe('PaginationContext', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nextProps.pagination.options.sizePerPage is existing', () => {
|
||||
const onPageChange = jest.fn();
|
||||
afterEach(() => {
|
||||
onPageChange.mockReset();
|
||||
});
|
||||
|
||||
describe('and if it is different with currSizePerPage', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext());
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: {
|
||||
options: {
|
||||
sizePerPage: Const.SIZE_PER_PAGE_LIST[2],
|
||||
onPageChange
|
||||
}
|
||||
}
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('should call options.onPageChange', () => {
|
||||
expect(onPageChange).toHaveBeenCalledTimes(1);
|
||||
expect(onPageChange).toHaveBeenCalledWith(
|
||||
instance.currPage,
|
||||
instance.currSizePerPage
|
||||
);
|
||||
});
|
||||
|
||||
it('should set correct currSizePerPage', () => {
|
||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and if it is same as currSizePerPage', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext());
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: {
|
||||
options: {
|
||||
sizePerPage: Const.SIZE_PER_PAGE_LIST[0],
|
||||
onPageChange
|
||||
}
|
||||
}
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('shouldn\'t call options.onPageChange', () => {
|
||||
expect(onPageChange).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('should have correct currSizePerPage', () => {
|
||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nextProps.pagination.options.sizePerPage is not existing', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
@ -281,10 +155,53 @@ describe('PaginationContext', () => {
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('should not set currPage', () => {
|
||||
it('should not set currSizePerPage', () => {
|
||||
expect(instance.currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when page is not align', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
...defaultPagination,
|
||||
page: 2
|
||||
}));
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data: [],
|
||||
pagination: { ...defaultPagination }
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('should reset currPage to first page', () => {
|
||||
expect(instance.currPage).toEqual(1);
|
||||
});
|
||||
|
||||
describe('if options.onPageChange is defined', () => {
|
||||
const onPageChange = jest.fn();
|
||||
beforeEach(() => {
|
||||
onPageChange.mockClear();
|
||||
wrapper = shallow(shallowContext({
|
||||
...defaultPagination,
|
||||
page: 2
|
||||
}));
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data: [],
|
||||
pagination: { ...defaultPagination, options: { onPageChange } }
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('should call options.onPageChange correctly', () => {
|
||||
expect(onPageChange).toHaveBeenCalledTimes(1);
|
||||
expect(onPageChange).toHaveBeenCalledWith(instance.currPage, instance.currSizePerPage);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleChangePage', () => {
|
||||
|
||||
@ -45,8 +45,8 @@ describe('Page Functions', () => {
|
||||
describe('alignPage', () => {
|
||||
const pageStartIndex = 1;
|
||||
const sizePerPage = 10;
|
||||
const page = 2;
|
||||
describe('if the length of store.data is less than the end page index', () => {
|
||||
const page = 3;
|
||||
describe('if the page does not fit the pages interval calculated from the length of store.data', () => {
|
||||
beforeEach(() => {
|
||||
data = [];
|
||||
for (let i = 0; i < 15; i += 1) {
|
||||
|
||||
@ -20,11 +20,26 @@ export default (options = {
|
||||
searchText: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.performRemoteSearch = props.searchText !== '';
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (isRemoteSearch()) {
|
||||
if (nextProps.searchText !== this.props.searchText) {
|
||||
this.performRemoteSearch = true;
|
||||
} else {
|
||||
this.performRemoteSearch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
search() {
|
||||
const { data, columns } = this.props;
|
||||
let { searchText } = this.props;
|
||||
|
||||
if (isRemoteSearch()) {
|
||||
if (isRemoteSearch() && this.performRemoteSearch) {
|
||||
handleRemoteSearchChange(searchText);
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -75,6 +75,7 @@ export default class SelectionCell extends Component {
|
||||
checked={ selected }
|
||||
disabled={ disabled }
|
||||
className={ bootstrap4 ? 'selection-input-4' : '' }
|
||||
onChange={ () => {} }
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ export const CheckBox = ({ className, checked, indeterminate }) => (
|
||||
ref={ (input) => {
|
||||
if (input) input.indeterminate = indeterminate; // eslint-disable-line no-param-reassign
|
||||
} }
|
||||
onChange={ () => {} }
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<SelectionCell /> render should render component correctly 1`] = `
|
||||
<td
|
||||
onClick={[Function]}
|
||||
>
|
||||
<input
|
||||
checked={true}
|
||||
className=""
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<CheckBox /> render should render component correctly 1`] = `
|
||||
<input
|
||||
checked={true}
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
`;
|
||||
@ -1,6 +1,7 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import toJson from 'enzyme-to-json';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import { shallowWithContext } from '../test-helpers/new-context';
|
||||
@ -61,7 +62,8 @@ describe('<SelectionCell />', () => {
|
||||
mode={ mode }
|
||||
rowIndex={ rowIndex }
|
||||
onRowSelect={ mockOnRowSelect }
|
||||
/>, { bootstrap4: false }
|
||||
/>,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
wrapper.find('td').simulate('click');
|
||||
});
|
||||
@ -72,9 +74,7 @@ describe('<SelectionCell />', () => {
|
||||
|
||||
it('should calling onRowSelect callback correctly', () => {
|
||||
expect(mockOnRowSelect.calledOnce).toBe(true);
|
||||
expect(
|
||||
mockOnRowSelect.calledWith(rowKey, !selected, rowIndex)
|
||||
).toBe(true);
|
||||
expect(mockOnRowSelect.calledWith(rowKey, !selected, rowIndex)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -88,7 +88,8 @@ describe('<SelectionCell />', () => {
|
||||
rowIndex={ rowIndex }
|
||||
onRowSelect={ mockOnRowSelect }
|
||||
disabled
|
||||
/>, { bootstrap4: false }
|
||||
/>,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
wrapper.find('td').simulate('click');
|
||||
});
|
||||
@ -111,7 +112,8 @@ describe('<SelectionCell />', () => {
|
||||
mode="radio"
|
||||
rowIndex={ rowIndex }
|
||||
onRowSelect={ mockOnRowSelect }
|
||||
/>, { bootstrap4: false }
|
||||
/>,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -132,11 +134,12 @@ describe('<SelectionCell />', () => {
|
||||
rowIndex={ rowIndex }
|
||||
selected
|
||||
onRowSelect={ mockOnRowSelect }
|
||||
/>, { bootstrap4: false }
|
||||
/>,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
it('should be called with correct paramters', () => {
|
||||
it('should be called with correct parameters', () => {
|
||||
// first click
|
||||
wrapper.find('td').simulate('click');
|
||||
expect(mockOnRowSelect.callCount).toBe(1);
|
||||
@ -151,12 +154,8 @@ describe('<SelectionCell />', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallowWithContext(
|
||||
<SelectionCell
|
||||
rowKey={ 1 }
|
||||
mode={ mode }
|
||||
rowIndex={ rowIndex }
|
||||
selected={ selected }
|
||||
/>, { bootstrap4: false }
|
||||
<SelectionCell rowKey={ 1 } mode={ mode } rowIndex={ rowIndex } selected={ selected } />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -165,6 +164,7 @@ describe('<SelectionCell />', () => {
|
||||
expect(wrapper.find('input')).toHaveLength(1);
|
||||
expect(wrapper.find('input').get(0).props.type).toBe(mode);
|
||||
expect(wrapper.find('input').get(0).props.checked).toBe(selected);
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('when disabled prop give as true', () => {
|
||||
@ -176,7 +176,8 @@ describe('<SelectionCell />', () => {
|
||||
rowIndex={ rowIndex }
|
||||
selected={ selected }
|
||||
disabled
|
||||
/>, { bootstrap4: false }
|
||||
/>,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -198,7 +199,8 @@ describe('<SelectionCell />', () => {
|
||||
rowIndex={ rowIndex }
|
||||
selected={ selected }
|
||||
selectionRenderer={ selectionRenderer }
|
||||
/>, { bootstrap4: false }
|
||||
/>,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -219,12 +221,8 @@ describe('<SelectionCell />', () => {
|
||||
describe('when bootstrap4 context is true', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallowWithContext(
|
||||
<SelectionCell
|
||||
rowKey={ 1 }
|
||||
mode={ mode }
|
||||
rowIndex={ rowIndex }
|
||||
selected={ selected }
|
||||
/>, { bootstrap4: true }
|
||||
<SelectionCell rowKey={ 1 } mode={ mode } rowIndex={ rowIndex } selected={ selected } />,
|
||||
{ bootstrap4: true }
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import toJson from 'enzyme-to-json';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import { shallowWithContext } from '../test-helpers/new-context';
|
||||
@ -201,6 +202,7 @@ describe('<CheckBox />', () => {
|
||||
expect(wrapper.find('input').length).toBe(1);
|
||||
expect(wrapper.find('input').prop('checked')).toBe(checked);
|
||||
expect(wrapper.find('input').prop('type')).toBe('checkbox');
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2711,6 +2711,12 @@ enzyme-adapter-utils@^1.3.0:
|
||||
object.assign "^4.1.0"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
enzyme-to-json@3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.4.tgz#67c6040e931182f183418af2eb9f4323258aa77f"
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
|
||||
enzyme@3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.3.0.tgz#0971abd167f2d4bf3f5bd508229e1c4b6dc50479"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user