mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-28 21:20:04 +00:00
Merge pull request #158 from react-bootstrap-table/enhance/refactoring
Refarcotring Wrapper
This commit is contained in:
@@ -116,7 +116,7 @@ class EmptyTableOverlay extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
handleTableChange = ({ page, sizePerPage }) => {
|
||||
handleTableChange = (type, { page, sizePerPage }) => {
|
||||
const currentIndex = (page - 1) * sizePerPage;
|
||||
setTimeout(() => {
|
||||
this.setState(() => ({
|
||||
|
||||
@@ -127,7 +127,7 @@ class Container extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
handleTableChange = ({ page, sizePerPage }) => {
|
||||
handleTableChange = (type, { page, sizePerPage }) => {
|
||||
const currentIndex = (page - 1) * sizePerPage;
|
||||
setTimeout(() => {
|
||||
this.setState(() => ({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import TextFilter from './components/text';
|
||||
import FilterWrapper from './wrapper';
|
||||
import wrapperFactory from './wrapper';
|
||||
import * as Comparison from './comparison';
|
||||
|
||||
export default (options = {}) => ({
|
||||
FilterWrapper,
|
||||
wrapperFactory,
|
||||
options
|
||||
});
|
||||
|
||||
|
||||
@@ -1,76 +1,66 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import { Component } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { filters } from './filter';
|
||||
import { LIKE } from './comparison';
|
||||
|
||||
export default class FilterWrapper extends Component {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
columns: PropTypes.array.isRequired,
|
||||
baseElement: PropTypes.func.isRequired,
|
||||
onRemoteFilterChange: PropTypes.func.isRequired,
|
||||
// refactoring later
|
||||
_: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { currFilters: {}, isDataChanged: false };
|
||||
this.onFilter = this.onFilter.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// consider to use lodash.isEqual
|
||||
if (JSON.stringify(this.state.currFilters) !== JSON.stringify(nextProps.store.filters)) {
|
||||
this.setState(() => ({ isDataChanged: true, currFilters: nextProps.store.filters }));
|
||||
} else {
|
||||
this.setState(() => ({ isDataChanged: false }));
|
||||
}
|
||||
}
|
||||
|
||||
onFilter(column, filterVal, filterType) {
|
||||
const { store, columns, _, onRemoteFilterChange } = this.props;
|
||||
const currFilters = Object.assign({}, this.state.currFilters);
|
||||
const { dataField, filter } = column;
|
||||
|
||||
if (!_.isDefined(filterVal) || filterVal === '') {
|
||||
delete currFilters[dataField];
|
||||
} else {
|
||||
const { comparator = LIKE } = filter.props;
|
||||
currFilters[dataField] = { filterVal, filterType, comparator };
|
||||
}
|
||||
store.filters = currFilters;
|
||||
|
||||
if (this.isRemote() || this.isPaginationRemote()) {
|
||||
onRemoteFilterChange(this.isPaginationRemote());
|
||||
// when remote filtering is enable, dont set currFilters state
|
||||
// in the componentWillReceiveProps, it's the key point that we can know the filter is changed
|
||||
return;
|
||||
export default (Base, {
|
||||
_,
|
||||
remoteResolver
|
||||
}) =>
|
||||
class FilterWrapper extends remoteResolver(Component) {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
columns: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
store.filteredData = filters(store, columns, _)(currFilters);
|
||||
this.setState(() => ({ currFilters, isDataChanged: true }));
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { currFilters: {}, isDataChanged: false };
|
||||
this.onFilter = this.onFilter.bind(this);
|
||||
}
|
||||
|
||||
// refactoring later
|
||||
isRemote() {
|
||||
const { remote } = this.props;
|
||||
return remote === true || (typeof remote === 'object' && remote.filter);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// consider to use lodash.isEqual
|
||||
if (JSON.stringify(this.state.currFilters) !== JSON.stringify(nextProps.store.filters)) {
|
||||
this.setState(() => ({ isDataChanged: true, currFilters: nextProps.store.filters }));
|
||||
} else {
|
||||
this.setState(() => ({ isDataChanged: false }));
|
||||
}
|
||||
}
|
||||
|
||||
// refactoring later
|
||||
isPaginationRemote() {
|
||||
const { remote } = this.props;
|
||||
return remote === true || (typeof remote === 'object' && remote.pagination);
|
||||
}
|
||||
onFilter(column, filterVal, filterType) {
|
||||
const { store, columns } = this.props;
|
||||
const currFilters = Object.assign({}, this.state.currFilters);
|
||||
const { dataField, filter } = column;
|
||||
|
||||
render() {
|
||||
return this.props.baseElement({
|
||||
...this.props,
|
||||
key: 'table',
|
||||
onFilter: this.onFilter,
|
||||
isDataChanged: this.state.isDataChanged
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!_.isDefined(filterVal) || filterVal === '') {
|
||||
delete currFilters[dataField];
|
||||
} else {
|
||||
const { comparator = LIKE } = filter.props;
|
||||
currFilters[dataField] = { filterVal, filterType, comparator };
|
||||
}
|
||||
store.filters = currFilters;
|
||||
|
||||
if (this.isRemoteFiltering() || this.isRemotePagination()) {
|
||||
this.handleRemoteFilterChange();
|
||||
// when remote filtering is enable, dont set currFilters state
|
||||
// in the componentWillReceiveProps,
|
||||
// it's the key point that we can know the filter is changed
|
||||
return;
|
||||
}
|
||||
|
||||
store.filteredData = filters(store, columns, _)(currFilters);
|
||||
this.setState(() => ({ currFilters, isDataChanged: true }));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Base
|
||||
{ ...this.props }
|
||||
data={ this.props.store.data }
|
||||
onFilter={ this.onFilter }
|
||||
isDataChanged={ this.state.isDataChanged }
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,10 +3,11 @@ import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import _ from 'react-bootstrap-table2/src/utils';
|
||||
import remoteResolver from 'react-bootstrap-table2/src/props-resolver/remote-resolver';
|
||||
import BootstrapTable from 'react-bootstrap-table2/src/bootstrap-table';
|
||||
import Store from 'react-bootstrap-table2/src/store';
|
||||
import filter, { textFilter } from '../src';
|
||||
import FilterWrapper from '../src/wrapper';
|
||||
import wrapperFactory from '../src/wrapper';
|
||||
import { FILTER_TYPE } from '../src/const';
|
||||
|
||||
const data = [];
|
||||
@@ -21,10 +22,10 @@ for (let i = 0; i < 20; i += 1) {
|
||||
describe('Wrapper', () => {
|
||||
let wrapper;
|
||||
let instance;
|
||||
const onRemoteFilterChangeCB = sinon.stub();
|
||||
const onTableChangeCB = sinon.stub();
|
||||
|
||||
afterEach(() => {
|
||||
onRemoteFilterChangeCB.reset();
|
||||
onTableChangeCB.reset();
|
||||
});
|
||||
|
||||
const createTableProps = () => {
|
||||
@@ -46,16 +47,19 @@ describe('Wrapper', () => {
|
||||
filter: filter(),
|
||||
_,
|
||||
store: new Store('id'),
|
||||
onRemoteFilterChange: onRemoteFilterChangeCB
|
||||
onTableChange: onTableChangeCB
|
||||
};
|
||||
tableProps.store.data = data;
|
||||
return tableProps;
|
||||
};
|
||||
|
||||
const pureTable = props => (<BootstrapTable { ...props } />);
|
||||
const FilterWrapper = wrapperFactory(BootstrapTable, {
|
||||
_,
|
||||
remoteResolver
|
||||
});
|
||||
|
||||
const createFilterWrapper = (props, renderFragment = true) => {
|
||||
wrapper = shallow(<FilterWrapper { ...props } baseElement={ pureTable } />);
|
||||
wrapper = shallow(<FilterWrapper { ...props } />);
|
||||
instance = wrapper.instance();
|
||||
if (renderFragment) {
|
||||
const fragment = instance.render();
|
||||
@@ -177,7 +181,7 @@ describe('Wrapper', () => {
|
||||
});
|
||||
|
||||
it('should calling props.onRemoteFilterChange correctly', () => {
|
||||
expect(onRemoteFilterChangeCB.calledOnce).toBeTruthy();
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import PaginationWrapper from './wrapper';
|
||||
import wrapperFactory from './wrapper';
|
||||
|
||||
export default (options = {}) => ({
|
||||
PaginationWrapper,
|
||||
wrapperFactory,
|
||||
options
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
export const getByCurrPage = store => (page, sizePerPage, pageStartIndex) => {
|
||||
export const getByCurrPage = (store, pageStartIndex) => {
|
||||
const dataSize = store.data.length;
|
||||
if (!dataSize) return [];
|
||||
const getNormalizedPage = () => {
|
||||
const offset = Math.abs(1 - pageStartIndex);
|
||||
return page + offset;
|
||||
return store.page + offset;
|
||||
};
|
||||
const end = (getNormalizedPage() * sizePerPage) - 1;
|
||||
const start = end - (sizePerPage - 1);
|
||||
const end = (getNormalizedPage() * store.sizePerPage) - 1;
|
||||
const start = end - (store.sizePerPage - 1);
|
||||
|
||||
const result = [];
|
||||
for (let i = start; i <= end; i += 1) {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint arrow-body-style: 0 */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
@@ -8,172 +6,154 @@ import Const from './const';
|
||||
import Pagination from './pagination';
|
||||
import { getByCurrPage } from './page';
|
||||
|
||||
class PaginationWrapper extends Component {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
baseElement: PropTypes.func.isRequired,
|
||||
onRemotePageChange: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangePage = this.handleChangePage.bind(this);
|
||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||
|
||||
let currPage;
|
||||
let currSizePerPage;
|
||||
const { options } = props.pagination;
|
||||
const sizePerPageList = options.sizePerPageList || Const.SIZE_PER_PAGE_LIST;
|
||||
|
||||
// initialize current page
|
||||
if (typeof options.page !== 'undefined') {
|
||||
currPage = options.page;
|
||||
} else if (typeof options.pageStartIndex !== 'undefined') {
|
||||
currPage = options.pageStartIndex;
|
||||
} else {
|
||||
currPage = Const.PAGE_START_INDEX;
|
||||
export default (Base, {
|
||||
remoteResolver
|
||||
}) =>
|
||||
class PaginationWrapper extends remoteResolver(Component) {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
// initialize current sizePerPage
|
||||
if (typeof options.sizePerPage !== 'undefined') {
|
||||
currSizePerPage = options.sizePerPage;
|
||||
} else if (typeof sizePerPageList[0] === 'object') {
|
||||
currSizePerPage = sizePerPageList[0].value;
|
||||
} else {
|
||||
currSizePerPage = sizePerPageList[0];
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangePage = this.handleChangePage.bind(this);
|
||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||
|
||||
this.state = { currPage, currSizePerPage };
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
}
|
||||
let currPage;
|
||||
let currSizePerPage;
|
||||
const { options } = props.pagination;
|
||||
const sizePerPageList = options.sizePerPageList || Const.SIZE_PER_PAGE_LIST;
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let needNewState = false;
|
||||
let { currPage, currSizePerPage } = this.state;
|
||||
const { page, sizePerPage, pageStartIndex, onPageChange } = nextProps.pagination.options;
|
||||
|
||||
if (typeof page !== 'undefined' && currPage !== page) { // user defined page
|
||||
currPage = page;
|
||||
needNewState = true;
|
||||
} else if (nextProps.isDataChanged) { // user didn't defined page but data change
|
||||
currPage = typeof pageStartIndex !== 'undefined' ? pageStartIndex : Const.PAGE_START_INDEX;
|
||||
needNewState = true;
|
||||
}
|
||||
|
||||
if (typeof sizePerPage !== 'undefined') {
|
||||
currSizePerPage = sizePerPage;
|
||||
needNewState = true;
|
||||
}
|
||||
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
|
||||
if (needNewState) {
|
||||
if (onPageChange) {
|
||||
onPageChange(currPage, currSizePerPage);
|
||||
// initialize current page
|
||||
if (typeof options.page !== 'undefined') {
|
||||
currPage = options.page;
|
||||
} else if (typeof options.pageStartIndex !== 'undefined') {
|
||||
currPage = options.pageStartIndex;
|
||||
} else {
|
||||
currPage = Const.PAGE_START_INDEX;
|
||||
}
|
||||
this.setState(() => ({ currPage, currSizePerPage }));
|
||||
|
||||
// initialize current sizePerPage
|
||||
if (typeof options.sizePerPage !== 'undefined') {
|
||||
currSizePerPage = options.sizePerPage;
|
||||
} else if (typeof sizePerPageList[0] === 'object') {
|
||||
currSizePerPage = sizePerPageList[0].value;
|
||||
} else {
|
||||
currSizePerPage = sizePerPageList[0];
|
||||
}
|
||||
|
||||
this.state = { currPage, currSizePerPage };
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
}
|
||||
}
|
||||
|
||||
saveToStore(page, sizePerPage) {
|
||||
this.props.store.page = page;
|
||||
this.props.store.sizePerPage = sizePerPage;
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let needNewState = false;
|
||||
let { currPage, currSizePerPage } = this.state;
|
||||
const { page, sizePerPage, pageStartIndex, onPageChange } = nextProps.pagination.options;
|
||||
|
||||
isRemote() {
|
||||
const { remote } = this.props;
|
||||
return remote === true || (typeof remote === 'object' && remote.pagination);
|
||||
}
|
||||
if (typeof page !== 'undefined' && currPage !== page) { // user defined page
|
||||
currPage = page;
|
||||
needNewState = true;
|
||||
} else if (nextProps.isDataChanged) { // user didn't defined page but data change
|
||||
currPage = typeof pageStartIndex !== 'undefined' ? pageStartIndex : Const.PAGE_START_INDEX;
|
||||
needNewState = true;
|
||||
}
|
||||
|
||||
handleChangePage(currPage) {
|
||||
const { currSizePerPage } = this.state;
|
||||
const { pagination: { options }, onRemotePageChange } = this.props;
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
if (typeof sizePerPage !== 'undefined') {
|
||||
currSizePerPage = sizePerPage;
|
||||
needNewState = true;
|
||||
}
|
||||
|
||||
if (options.onPageChange) {
|
||||
options.onPageChange(currPage, currSizePerPage);
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
|
||||
if (needNewState) {
|
||||
if (onPageChange) {
|
||||
onPageChange(currPage, currSizePerPage);
|
||||
}
|
||||
this.setState(() => ({ currPage, currSizePerPage }));
|
||||
}
|
||||
}
|
||||
if (this.isRemote()) {
|
||||
onRemotePageChange();
|
||||
return;
|
||||
}
|
||||
this.setState(() => {
|
||||
return {
|
||||
currPage
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
handleChangeSizePerPage(currSizePerPage, currPage) {
|
||||
const { pagination: { options }, onRemotePageChange } = this.props;
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
saveToStore(page, sizePerPage) {
|
||||
this.props.store.page = page;
|
||||
this.props.store.sizePerPage = sizePerPage;
|
||||
}
|
||||
|
||||
if (options.onSizePerPageChange) {
|
||||
options.onSizePerPageChange(currSizePerPage, currPage);
|
||||
handleChangePage(currPage) {
|
||||
const { currSizePerPage } = this.state;
|
||||
const { pagination: { options } } = this.props;
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
|
||||
if (options.onPageChange) {
|
||||
options.onPageChange(currPage, currSizePerPage);
|
||||
}
|
||||
if (this.isRemotePagination()) {
|
||||
this.handleRemotePageChange();
|
||||
return;
|
||||
}
|
||||
this.setState(() => ({ currPage }));
|
||||
}
|
||||
if (this.isRemote()) {
|
||||
onRemotePageChange();
|
||||
return;
|
||||
}
|
||||
this.setState(() => {
|
||||
return {
|
||||
|
||||
handleChangeSizePerPage(currSizePerPage, currPage) {
|
||||
const { pagination: { options } } = this.props;
|
||||
this.saveToStore(currPage, currSizePerPage);
|
||||
|
||||
if (options.onSizePerPageChange) {
|
||||
options.onSizePerPageChange(currSizePerPage, currPage);
|
||||
}
|
||||
if (this.isRemotePagination()) {
|
||||
this.handleRemotePageChange();
|
||||
return;
|
||||
}
|
||||
this.setState(() => ({
|
||||
currPage,
|
||||
currSizePerPage
|
||||
};
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { pagination: { options }, store, baseElement } = this.props;
|
||||
const { currPage, currSizePerPage } = this.state;
|
||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||
Const.SHOW_ALL_PAGE_BTNS : options.alwaysShowAllBtns;
|
||||
const hideSizePerPage = typeof options.hideSizePerPage === 'undefined' ?
|
||||
Const.HIDE_SIZE_PER_PAGE : options.hideSizePerPage;
|
||||
const hidePageListOnlyOnePage = typeof options.hidePageListOnlyOnePage === 'undefined' ?
|
||||
Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE : options.hidePageListOnlyOnePage;
|
||||
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||
render() {
|
||||
const { pagination: { options }, store } = this.props;
|
||||
const { currPage, currSizePerPage } = this.state;
|
||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||
Const.SHOW_ALL_PAGE_BTNS : options.alwaysShowAllBtns;
|
||||
const hideSizePerPage = typeof options.hideSizePerPage === 'undefined' ?
|
||||
Const.HIDE_SIZE_PER_PAGE : options.hideSizePerPage;
|
||||
const hidePageListOnlyOnePage = typeof options.hidePageListOnlyOnePage === 'undefined' ?
|
||||
Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE : options.hidePageListOnlyOnePage;
|
||||
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||
|
||||
const data = this.isRemote() ?
|
||||
this.props.data :
|
||||
getByCurrPage(store)(currPage, currSizePerPage, pageStartIndex);
|
||||
const data = this.isRemotePagination() ?
|
||||
this.props.data :
|
||||
getByCurrPage(store, pageStartIndex);
|
||||
|
||||
const base = baseElement({
|
||||
...this.props,
|
||||
key: 'table',
|
||||
data
|
||||
});
|
||||
|
||||
return [
|
||||
base,
|
||||
<Pagination
|
||||
key="pagination"
|
||||
dataSize={ options.totalSize || store.data.length }
|
||||
currPage={ currPage }
|
||||
currSizePerPage={ currSizePerPage }
|
||||
onPageChange={ this.handleChangePage }
|
||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||
sizePerPageList={ options.sizePerPageList || Const.SIZE_PER_PAGE_LIST }
|
||||
paginationSize={ options.paginationSize || Const.PAGINATION_SIZE }
|
||||
pageStartIndex={ pageStartIndex }
|
||||
withFirstAndLast={ withFirstAndLast }
|
||||
alwaysShowAllBtns={ alwaysShowAllBtns }
|
||||
hideSizePerPage={ hideSizePerPage }
|
||||
hidePageListOnlyOnePage={ hidePageListOnlyOnePage }
|
||||
firstPageText={ options.firstPageText || Const.FIRST_PAGE_TEXT }
|
||||
prePageText={ options.prePageText || Const.PRE_PAGE_TEXT }
|
||||
nextPageText={ options.nextPageText || Const.NEXT_PAGE_TEXT }
|
||||
lastPageText={ options.lastPageText || Const.LAST_PAGE_TEXT }
|
||||
prePageTitle={ options.prePageTitle || Const.PRE_PAGE_TITLE }
|
||||
nextPageTitle={ options.nextPageTitle || Const.NEXT_PAGE_TITLE }
|
||||
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
|
||||
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
|
||||
/>
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export default PaginationWrapper;
|
||||
return [
|
||||
<Base key="table" { ...this.props } data={ data } />,
|
||||
<Pagination
|
||||
key="pagination"
|
||||
dataSize={ options.totalSize || store.data.length }
|
||||
currPage={ currPage }
|
||||
currSizePerPage={ currSizePerPage }
|
||||
onPageChange={ this.handleChangePage }
|
||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||
sizePerPageList={ options.sizePerPageList || Const.SIZE_PER_PAGE_LIST }
|
||||
paginationSize={ options.paginationSize || Const.PAGINATION_SIZE }
|
||||
pageStartIndex={ pageStartIndex }
|
||||
withFirstAndLast={ withFirstAndLast }
|
||||
alwaysShowAllBtns={ alwaysShowAllBtns }
|
||||
hideSizePerPage={ hideSizePerPage }
|
||||
hidePageListOnlyOnePage={ hidePageListOnlyOnePage }
|
||||
firstPageText={ options.firstPageText || Const.FIRST_PAGE_TEXT }
|
||||
prePageText={ options.prePageText || Const.PRE_PAGE_TEXT }
|
||||
nextPageText={ options.nextPageText || Const.NEXT_PAGE_TEXT }
|
||||
lastPageText={ options.lastPageText || Const.LAST_PAGE_TEXT }
|
||||
prePageTitle={ options.prePageTitle || Const.PRE_PAGE_TITLE }
|
||||
nextPageTitle={ options.nextPageTitle || Const.NEXT_PAGE_TITLE }
|
||||
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
|
||||
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
|
||||
/>
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,7 +29,9 @@ describe('Page Functions', () => {
|
||||
|
||||
it('should always return correct data', () => {
|
||||
params.forEach(([page, sizePerPage, pageStartIndex]) => {
|
||||
const rows = getByCurrPage(store)(page, sizePerPage, pageStartIndex);
|
||||
store.page = page;
|
||||
store.sizePerPage = sizePerPage;
|
||||
const rows = getByCurrPage(store, pageStartIndex);
|
||||
expect(rows).toBeDefined();
|
||||
expect(Array.isArray(rows)).toBeTruthy();
|
||||
expect(rows.every(row => !!row)).toBeTruthy();
|
||||
@@ -39,7 +41,9 @@ describe('Page Functions', () => {
|
||||
it('should return empty array when store.data is empty', () => {
|
||||
store.data = [];
|
||||
params.forEach(([page, sizePerPage, pageStartIndex]) => {
|
||||
const rows = getByCurrPage(store)(page, sizePerPage, pageStartIndex);
|
||||
store.page = page;
|
||||
store.sizePerPage = sizePerPage;
|
||||
const rows = getByCurrPage(store, pageStartIndex);
|
||||
expect(rows).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,9 +4,10 @@ import { shallow } from 'enzyme';
|
||||
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table2/src/bootstrap-table';
|
||||
import remoteResolver from 'react-bootstrap-table2/src/props-resolver/remote-resolver';
|
||||
import Store from 'react-bootstrap-table2/src/store';
|
||||
import paginator from '../src';
|
||||
import PaginationWrapper from '../src/wrapper';
|
||||
import wrapperFactory from '../src/wrapper';
|
||||
import Pagination from '../src/pagination';
|
||||
import Const from '../src/const';
|
||||
|
||||
@@ -21,10 +22,10 @@ for (let i = 0; i < 100; i += 1) {
|
||||
describe('Wrapper', () => {
|
||||
let wrapper;
|
||||
let instance;
|
||||
const onRemotePageChangeCB = sinon.stub();
|
||||
const onTableChangeCB = sinon.stub();
|
||||
|
||||
afterEach(() => {
|
||||
onRemotePageChangeCB.reset();
|
||||
onTableChangeCB.reset();
|
||||
});
|
||||
|
||||
const createTableProps = (props = {}) => {
|
||||
@@ -40,16 +41,18 @@ describe('Wrapper', () => {
|
||||
data,
|
||||
pagination: paginator(props.options),
|
||||
store: new Store('id'),
|
||||
onRemotePageChange: onRemotePageChangeCB
|
||||
onTableChange: onTableChangeCB
|
||||
};
|
||||
tableProps.store.data = data;
|
||||
return tableProps;
|
||||
};
|
||||
|
||||
const pureTable = props => (<BootstrapTable { ...props } />);
|
||||
const PaginationWrapper = wrapperFactory(BootstrapTable, {
|
||||
remoteResolver
|
||||
});
|
||||
|
||||
const createPaginationWrapper = (props, renderFragment = true) => {
|
||||
wrapper = shallow(<PaginationWrapper { ...props } baseElement={ pureTable } />);
|
||||
wrapper = shallow(<PaginationWrapper { ...props } />);
|
||||
instance = wrapper.instance();
|
||||
if (renderFragment) {
|
||||
const fragment = instance.render();
|
||||
@@ -504,7 +507,7 @@ describe('Wrapper', () => {
|
||||
beforeEach(() => {
|
||||
props.remote = true;
|
||||
createPaginationWrapper(props, false);
|
||||
onRemotePageChangeCB.reset();
|
||||
onTableChangeCB.reset();
|
||||
instance.handleChangePage(newPage);
|
||||
});
|
||||
|
||||
@@ -513,7 +516,7 @@ describe('Wrapper', () => {
|
||||
});
|
||||
|
||||
it('should calling props.onRemotePageChange correctly', () => {
|
||||
expect(onRemotePageChangeCB.calledOnce).toBeTruthy();
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -551,7 +554,7 @@ describe('Wrapper', () => {
|
||||
beforeEach(() => {
|
||||
props.remote = true;
|
||||
createPaginationWrapper(props, false);
|
||||
onRemotePageChangeCB.reset();
|
||||
onTableChangeCB.reset();
|
||||
instance.handleChangeSizePerPage(newSizePerPage, newPage);
|
||||
});
|
||||
|
||||
@@ -561,68 +564,7 @@ describe('Wrapper', () => {
|
||||
});
|
||||
|
||||
it('should calling props.onRemotePageChange correctly', () => {
|
||||
expect(onRemotePageChangeCB.calledOnce).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRemote', () => {
|
||||
let result;
|
||||
describe('when options.remote is true', () => {
|
||||
const props = createTableProps();
|
||||
props.remote = true;
|
||||
|
||||
beforeEach(() => {
|
||||
createPaginationWrapper(props, false);
|
||||
result = instance.isRemote();
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when options.remote is false', () => {
|
||||
const props = createTableProps();
|
||||
props.remote = false;
|
||||
|
||||
beforeEach(() => {
|
||||
createPaginationWrapper(props, false);
|
||||
result = instance.isRemote();
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when options.remote.pagination is defined as true', () => {
|
||||
const props = createTableProps();
|
||||
props.remote = {};
|
||||
props.remote.pagination = true;
|
||||
|
||||
beforeEach(() => {
|
||||
createPaginationWrapper(props, false);
|
||||
result = instance.isRemote();
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when options.remote.pagination is defined as false', () => {
|
||||
const props = createTableProps();
|
||||
props.remote = {};
|
||||
props.remote.pagination = false;
|
||||
|
||||
beforeEach(() => {
|
||||
createPaginationWrapper(props, false);
|
||||
result = instance.isRemote();
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
expect(result).toBeFalsy();
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,112 +1,96 @@
|
||||
/* eslint arrow-body-style: 0 */
|
||||
/* eslint react/prop-types: 0 */
|
||||
import { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import _ from '../utils';
|
||||
|
||||
import { cellEditElement } from '../table-factory';
|
||||
|
||||
class CellEditWrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.startEditing = this.startEditing.bind(this);
|
||||
this.escapeEditing = this.escapeEditing.bind(this);
|
||||
this.completeEditing = this.completeEditing.bind(this);
|
||||
this.handleCellUpdate = this.handleCellUpdate.bind(this);
|
||||
this.updateEditingWithErr = this.updateEditingWithErr.bind(this);
|
||||
this.state = {
|
||||
ridx: null,
|
||||
cidx: null,
|
||||
message: null,
|
||||
editing: false
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.cellEdit) {
|
||||
if (nextProps.cellEdit.editing) {
|
||||
this.setState(() => {
|
||||
return {
|
||||
...this.state,
|
||||
message: nextProps.cellEdit.errorMessage
|
||||
};
|
||||
});
|
||||
} else {
|
||||
this.escapeEditing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleCellUpdate(row, column, newValue) {
|
||||
const { keyField, cellEdit, onUpdateCell } = this.props;
|
||||
const { beforeSaveCell, afterSaveCell } = cellEdit;
|
||||
const oldValue = _.get(row, column.dataField);
|
||||
const rowId = _.get(row, keyField);
|
||||
if (_.isFunction(beforeSaveCell)) beforeSaveCell(oldValue, newValue, row, column);
|
||||
if (onUpdateCell(rowId, column.dataField, newValue)) {
|
||||
if (_.isFunction(afterSaveCell)) afterSaveCell(oldValue, newValue, row, column);
|
||||
this.completeEditing();
|
||||
}
|
||||
}
|
||||
|
||||
completeEditing() {
|
||||
this.setState(() => {
|
||||
return {
|
||||
export default (Base, parentProps) =>
|
||||
class CellEditWrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.startEditing = this.startEditing.bind(this);
|
||||
this.escapeEditing = this.escapeEditing.bind(this);
|
||||
this.completeEditing = this.completeEditing.bind(this);
|
||||
this.handleCellUpdate = this.handleCellUpdate.bind(this);
|
||||
this.updateEditingWithErr = this.updateEditingWithErr.bind(this);
|
||||
this.state = {
|
||||
ridx: null,
|
||||
cidx: null,
|
||||
message: null,
|
||||
editing: false
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
startEditing(ridx, cidx) {
|
||||
const editing = () => {
|
||||
this.setState(() => {
|
||||
return {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.cellEdit) {
|
||||
if (nextProps.cellEdit.editing) {
|
||||
this.setState(() => ({
|
||||
...this.state,
|
||||
message: nextProps.cellEdit.errorMessage
|
||||
}));
|
||||
} else {
|
||||
this.escapeEditing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleCellUpdate(row, column, newValue) {
|
||||
const { keyField, cellEdit } = this.props;
|
||||
const { beforeSaveCell, afterSaveCell } = cellEdit;
|
||||
const oldValue = _.get(row, column.dataField);
|
||||
const rowId = _.get(row, keyField);
|
||||
if (_.isFunction(beforeSaveCell)) beforeSaveCell(oldValue, newValue, row, column);
|
||||
if (parentProps.onUpdateCell(rowId, column.dataField, newValue)) {
|
||||
if (_.isFunction(afterSaveCell)) afterSaveCell(oldValue, newValue, row, column);
|
||||
this.completeEditing();
|
||||
}
|
||||
}
|
||||
|
||||
completeEditing() {
|
||||
this.setState(() => ({
|
||||
ridx: null,
|
||||
cidx: null,
|
||||
message: null,
|
||||
editing: false
|
||||
}));
|
||||
}
|
||||
|
||||
startEditing(ridx, cidx) {
|
||||
const editing = () => {
|
||||
this.setState(() => ({
|
||||
ridx,
|
||||
cidx,
|
||||
editing: true
|
||||
};
|
||||
});
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
const { selectRow } = this.props;
|
||||
if (!selectRow || (selectRow.clickToEdit || !selectRow.clickToSelect)) editing();
|
||||
}
|
||||
const { selectRow } = this.props;
|
||||
if (!selectRow || (selectRow.clickToEdit || !selectRow.clickToSelect)) editing();
|
||||
}
|
||||
|
||||
escapeEditing() {
|
||||
this.setState(() => {
|
||||
return {
|
||||
escapeEditing() {
|
||||
this.setState(() => ({
|
||||
ridx: null,
|
||||
cidx: null,
|
||||
editing: false
|
||||
};
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
updateEditingWithErr(message) {
|
||||
this.setState(() => {
|
||||
return {
|
||||
updateEditingWithErr(message) {
|
||||
this.setState(() => ({
|
||||
...this.state,
|
||||
message
|
||||
};
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
return cellEditElement({
|
||||
...this.props,
|
||||
onCellUpdate: this.handleCellUpdate,
|
||||
onStartEditing: this.startEditing,
|
||||
onEscapeEditing: this.escapeEditing,
|
||||
currEditCell: { ...this.state }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
CellEditWrapper.propTypes = {
|
||||
onUpdateCell: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default CellEditWrapper;
|
||||
render() {
|
||||
return (
|
||||
<Base
|
||||
{ ...this.props }
|
||||
data={ this.props.store.data }
|
||||
onCellUpdate={ this.handleCellUpdate }
|
||||
onStartEditing={ this.startEditing }
|
||||
onEscapeEditing={ this.escapeEditing }
|
||||
currEditCell={ { ...this.state } }
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
95
packages/react-bootstrap-table2/src/container.js
vendored
95
packages/react-bootstrap-table2/src/container.js
vendored
@@ -2,53 +2,59 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React, { Component } from 'react';
|
||||
import Store from './store';
|
||||
import withSort from './sort/wrapper';
|
||||
import withCellEdit from './cell-edit/wrapper';
|
||||
import withSelection from './row-selection/wrapper';
|
||||
|
||||
import {
|
||||
wrapWithCellEdit,
|
||||
wrapWithSelection,
|
||||
wrapWithFilter,
|
||||
wrapWithSort,
|
||||
wrapWithPagination
|
||||
} from './table-factory';
|
||||
|
||||
import remoteResolver from './props-resolver/remote-resolver';
|
||||
import _ from './utils';
|
||||
|
||||
const withDataStore = Base =>
|
||||
class BootstrapTableContainer extends Component {
|
||||
class BootstrapTableContainer extends remoteResolver(Component) {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.store = new Store(props.keyField);
|
||||
this.store.data = props.data;
|
||||
this.wrapComponents();
|
||||
this.handleUpdateCell = this.handleUpdateCell.bind(this);
|
||||
this.handleRemotePageChange = this.handleRemotePageChange.bind(this);
|
||||
this.handleRemoteFilterChange = this.handleRemoteFilterChange.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.store.data = nextProps.data;
|
||||
}
|
||||
|
||||
getNewestState(state = {}) {
|
||||
return {
|
||||
page: this.store.page,
|
||||
sizePerPage: this.store.sizePerPage,
|
||||
filters: this.store.filters,
|
||||
...state
|
||||
};
|
||||
}
|
||||
|
||||
handleRemotePageChange() {
|
||||
this.props.onTableChange('pagination', this.getNewestState());
|
||||
}
|
||||
|
||||
// refactoring later for isRemotePagination
|
||||
handleRemoteFilterChange(isRemotePagination) {
|
||||
const newState = {};
|
||||
if (isRemotePagination) {
|
||||
const options = this.props.pagination.options || {};
|
||||
newState.page = _.isDefined(options.pageStartIndex) ? options.pageStartIndex : 1;
|
||||
wrapComponents() {
|
||||
this.BaseComponent = Base;
|
||||
const { pagination, columns, filter, selectRow, cellEdit } = this.props;
|
||||
if (pagination) {
|
||||
const { wrapperFactory } = pagination;
|
||||
this.BaseComponent = wrapperFactory(this.BaseComponent, {
|
||||
remoteResolver
|
||||
});
|
||||
}
|
||||
|
||||
if (columns.filter(col => col.sort).length > 0) {
|
||||
this.BaseComponent = withSort(this.BaseComponent);
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
const { wrapperFactory } = filter;
|
||||
this.BaseComponent = wrapperFactory(this.BaseComponent, {
|
||||
_,
|
||||
remoteResolver
|
||||
});
|
||||
}
|
||||
|
||||
if (selectRow) {
|
||||
this.BaseComponent = withSelection(this.BaseComponent);
|
||||
}
|
||||
|
||||
if (cellEdit) {
|
||||
this.BaseComponent = withCellEdit(this.BaseComponent, {
|
||||
ref: node => this.cellEditWrapper = node,
|
||||
onUpdateCell: this.handleUpdateCell
|
||||
});
|
||||
}
|
||||
this.props.onTableChange('filter', this.getNewestState(newState));
|
||||
}
|
||||
|
||||
handleUpdateCell(rowId, dataField, newValue) {
|
||||
@@ -82,30 +88,9 @@ const withDataStore = Base =>
|
||||
store: this.store
|
||||
};
|
||||
|
||||
if (this.props.cellEdit) {
|
||||
return wrapWithCellEdit({
|
||||
ref: node => this.cellEditWrapper = node,
|
||||
onUpdateCell: this.handleUpdateCell,
|
||||
...baseProps
|
||||
});
|
||||
} else if (this.props.selectRow) {
|
||||
return wrapWithSelection(baseProps);
|
||||
} else if (this.props.filter) {
|
||||
return wrapWithFilter({
|
||||
...baseProps,
|
||||
onRemoteFilterChange: this.handleRemoteFilterChange,
|
||||
onRemotePageChange: this.handleRemotePageChange
|
||||
});
|
||||
} else if (this.props.columns.filter(col => col.sort).length > 0) {
|
||||
return wrapWithSort(baseProps);
|
||||
} else if (this.props.pagination) {
|
||||
return wrapWithPagination({
|
||||
...baseProps,
|
||||
onRemotePageChange: this.handleRemotePageChange
|
||||
});
|
||||
}
|
||||
|
||||
return React.createElement(Base, baseProps);
|
||||
return (
|
||||
<this.BaseComponent { ...baseProps } />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
37
packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js
vendored
Normal file
37
packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import _ from '../utils';
|
||||
|
||||
export default ExtendBase =>
|
||||
class RemoteResolver extends ExtendBase {
|
||||
getNewestState(state = {}) {
|
||||
const store = this.store || this.props.store;
|
||||
return {
|
||||
page: store.page,
|
||||
sizePerPage: store.sizePerPage,
|
||||
filters: store.filters,
|
||||
...state
|
||||
};
|
||||
}
|
||||
|
||||
isRemotePagination() {
|
||||
const { remote } = this.props;
|
||||
return remote === true || (_.isObject(remote) && remote.pagination);
|
||||
}
|
||||
|
||||
isRemoteFiltering() {
|
||||
const { remote } = this.props;
|
||||
return remote === true || (_.isObject(remote) && remote.filter);
|
||||
}
|
||||
|
||||
handleRemotePageChange() {
|
||||
this.props.onTableChange('pagination', this.getNewestState());
|
||||
}
|
||||
|
||||
handleRemoteFilterChange() {
|
||||
const newState = {};
|
||||
if (this.isRemotePagination()) {
|
||||
const options = this.props.pagination.options || {};
|
||||
newState.page = _.isDefined(options.pageStartIndex) ? options.pageStartIndex : 1;
|
||||
}
|
||||
this.props.onTableChange('filter', this.getNewestState(newState));
|
||||
}
|
||||
};
|
||||
@@ -1,8 +1,5 @@
|
||||
/* eslint arrow-body-style: 0 */
|
||||
/* eslint react/prop-types: 0 */
|
||||
import { Component } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { selectionElement } from '../table-factory';
|
||||
|
||||
import Const from '../const';
|
||||
import {
|
||||
@@ -13,88 +10,90 @@ import {
|
||||
} from '../store/selection';
|
||||
import { getRowByRowId } from '../store/rows';
|
||||
|
||||
class RowSelectionWrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleRowSelect = this.handleRowSelect.bind(this);
|
||||
this.handleAllRowsSelect = this.handleAllRowsSelect.bind(this);
|
||||
this.state = {
|
||||
selectedRowKeys: props.store.selected
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* row selection handler
|
||||
* @param {String} rowKey - row key of what was selected.
|
||||
* @param {Boolean} checked - next checked status of input button.
|
||||
*/
|
||||
handleRowSelect(rowKey, checked, rowIndex) {
|
||||
const { selectRow: { mode, onSelect }, store } = this.props;
|
||||
const { ROW_SELECT_SINGLE } = Const;
|
||||
|
||||
let currSelected = [...store.selected];
|
||||
|
||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||
currSelected = [rowKey];
|
||||
} else if (checked) { // when select mode is checkbox
|
||||
currSelected.push(rowKey);
|
||||
} else {
|
||||
currSelected = currSelected.filter(value => value !== rowKey);
|
||||
export default Base =>
|
||||
class RowSelectionWrapper extends Component {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
selectRow: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
store.selected = currSelected;
|
||||
|
||||
if (onSelect) {
|
||||
const row = getRowByRowId(store)(rowKey);
|
||||
onSelect(row, checked, rowIndex);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleRowSelect = this.handleRowSelect.bind(this);
|
||||
this.handleAllRowsSelect = this.handleAllRowsSelect.bind(this);
|
||||
this.state = {
|
||||
selectedRowKeys: props.store.selected
|
||||
};
|
||||
}
|
||||
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: currSelected
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* row selection handler
|
||||
* @param {String} rowKey - row key of what was selected.
|
||||
* @param {Boolean} checked - next checked status of input button.
|
||||
*/
|
||||
handleRowSelect(rowKey, checked, rowIndex) {
|
||||
const { selectRow: { mode, onSelect }, store } = this.props;
|
||||
const { ROW_SELECT_SINGLE } = Const;
|
||||
|
||||
/**
|
||||
* handle all rows selection on header cell by store.selected or given specific result.
|
||||
* @param {Boolean} option - customized result for all rows selection
|
||||
*/
|
||||
handleAllRowsSelect(option) {
|
||||
const { store, selectRow: {
|
||||
onSelectAll,
|
||||
nonSelectable
|
||||
} } = this.props;
|
||||
const selected = isAnySelectedRow(store)(nonSelectable);
|
||||
let currSelected = [...store.selected];
|
||||
|
||||
// set next status of all row selected by store.selected or customizing by user.
|
||||
const result = option || !selected;
|
||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||
currSelected = [rowKey];
|
||||
} else if (checked) { // when select mode is checkbox
|
||||
currSelected.push(rowKey);
|
||||
} else {
|
||||
currSelected = currSelected.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
const currSelected = result ?
|
||||
selectableKeys(store)(nonSelectable) :
|
||||
unSelectableKeys(store)(nonSelectable);
|
||||
store.selected = currSelected;
|
||||
|
||||
if (onSelect) {
|
||||
const row = getRowByRowId(store)(rowKey);
|
||||
onSelect(row, checked, rowIndex);
|
||||
}
|
||||
|
||||
store.selected = currSelected;
|
||||
|
||||
if (onSelectAll) {
|
||||
onSelectAll(result, getSelectedRows(store));
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: currSelected
|
||||
}));
|
||||
}
|
||||
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: currSelected
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* handle all rows selection on header cell by store.selected or given specific result.
|
||||
* @param {Boolean} option - customized result for all rows selection
|
||||
*/
|
||||
handleAllRowsSelect(option) {
|
||||
const { store, selectRow: {
|
||||
onSelectAll,
|
||||
nonSelectable
|
||||
} } = this.props;
|
||||
const selected = isAnySelectedRow(store)(nonSelectable);
|
||||
|
||||
render() {
|
||||
return selectionElement({
|
||||
...this.props,
|
||||
onRowSelect: this.handleRowSelect,
|
||||
onAllRowsSelect: this.handleAllRowsSelect
|
||||
});
|
||||
}
|
||||
}
|
||||
// set next status of all row selected by store.selected or customizing by user.
|
||||
const result = option || !selected;
|
||||
|
||||
RowSelectionWrapper.propTypes = {
|
||||
store: PropTypes.object.isRequired
|
||||
};
|
||||
const currSelected = result ?
|
||||
selectableKeys(store)(nonSelectable) :
|
||||
unSelectableKeys(store)(nonSelectable);
|
||||
|
||||
export default RowSelectionWrapper;
|
||||
|
||||
store.selected = currSelected;
|
||||
|
||||
if (onSelectAll) {
|
||||
onSelectAll(result, getSelectedRows(store));
|
||||
}
|
||||
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: currSelected
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Base
|
||||
{ ...this.props }
|
||||
onRowSelect={ this.handleRowSelect }
|
||||
onAllRowsSelect={ this.handleAllRowsSelect }
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,60 +1,55 @@
|
||||
/* eslint arrow-body-style: 0 */
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint no-return-assign: 0 */
|
||||
import { Component } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { sortableElement } from '../table-factory';
|
||||
export default Base =>
|
||||
class SortWrapper extends Component {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
class SortWrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleSort = this.handleSort.bind(this);
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleSort = this.handleSort.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { columns, defaultSorted, store } = this.props;
|
||||
// defaultSorted is an array, it's ready to use as multi / single sort
|
||||
// when we start to support multi sort, please update following code to use array.forEach
|
||||
if (defaultSorted && defaultSorted.length > 0) {
|
||||
const dataField = defaultSorted[0].dataField;
|
||||
const order = defaultSorted[0].order;
|
||||
const column = columns.filter(col => col.dataField === dataField);
|
||||
if (column.length > 0) {
|
||||
store.sortBy(column[0], order);
|
||||
componentWillMount() {
|
||||
const { columns, defaultSorted, store } = this.props;
|
||||
// defaultSorted is an array, it's ready to use as multi / single sort
|
||||
// when we start to support multi sort, please update following code to use array.forEach
|
||||
if (defaultSorted && defaultSorted.length > 0) {
|
||||
const dataField = defaultSorted[0].dataField;
|
||||
const order = defaultSorted[0].order;
|
||||
const column = columns.filter(col => col.dataField === dataField);
|
||||
if (column.length > 0) {
|
||||
store.sortBy(column[0], order);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.isDataChanged) {
|
||||
const sortedColumn = nextProps.columns.find(
|
||||
column => column.dataField === nextProps.store.sortField);
|
||||
if (sortedColumn) {
|
||||
nextProps.store.sortBy(sortedColumn, nextProps.store.sortOrder);
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.isDataChanged) {
|
||||
const sortedColumn = nextProps.columns.find(
|
||||
column => column.dataField === nextProps.store.sortField);
|
||||
if (sortedColumn) {
|
||||
nextProps.store.sortBy(sortedColumn, nextProps.store.sortOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleSort(column) {
|
||||
const { store } = this.props;
|
||||
store.sortBy(column);
|
||||
handleSort(column) {
|
||||
const { store } = this.props;
|
||||
store.sortBy(column);
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
this.table.setState({ data: store.data });
|
||||
}
|
||||
|
||||
render() {
|
||||
return sortableElement({
|
||||
...this.props,
|
||||
ref: node => this.table = node,
|
||||
onSort: this.handleSort,
|
||||
data: this.props.store.data
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SortWrapper.propTypes = {
|
||||
store: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default SortWrapper;
|
||||
render() {
|
||||
return (
|
||||
<Base
|
||||
{ ...this.props }
|
||||
onSort={ this.handleSort }
|
||||
data={ this.props.store.data }
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import _ from './utils';
|
||||
import BootstrapTable from './bootstrap-table';
|
||||
import SortWrapper from './sort/wrapper';
|
||||
import RowSelectionWrapper from './row-selection/wrapper';
|
||||
import CellEditWrapper from './cell-edit/wrapper';
|
||||
|
||||
|
||||
export const wrapWithCellEdit = props =>
|
||||
React.createElement(CellEditWrapper, { ...props });
|
||||
|
||||
export const wrapWithSelection = props =>
|
||||
React.createElement(RowSelectionWrapper, { ...props });
|
||||
|
||||
export const wrapWithSort = props =>
|
||||
React.createElement(SortWrapper, { ...props });
|
||||
|
||||
export const pureTable = props =>
|
||||
React.createElement(BootstrapTable, { ...props });
|
||||
|
||||
export const wrapWithFilter = (props) => {
|
||||
if (props.filter) {
|
||||
const { FilterWrapper } = props.filter;
|
||||
return React.createElement(FilterWrapper, { ...props, baseElement: wrapWithSort, _ });
|
||||
}
|
||||
return wrapWithSort(props);
|
||||
};
|
||||
|
||||
export const wrapWithPagination = (props) => {
|
||||
if (props.pagination) {
|
||||
const { PaginationWrapper } = props.pagination;
|
||||
return React.createElement(PaginationWrapper, { ...props, baseElement: pureTable });
|
||||
}
|
||||
return pureTable(props);
|
||||
};
|
||||
|
||||
export const sortableElement = props => wrapWithPagination(props);
|
||||
|
||||
export const selectionElement = props => wrapWithFilter(props);
|
||||
|
||||
export const cellEditElement = props => wrapWithSelection(props);
|
||||
@@ -3,8 +3,9 @@ import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import Store from '../../src/store';
|
||||
import Container from '../../src';
|
||||
import BootstrapTable from '../../src/bootstrap-table';
|
||||
import CellEditWrapper from '../../src/cell-edit/wrapper';
|
||||
import wrapperFactory from '../../src/cell-edit/wrapper';
|
||||
|
||||
describe('CellEditWrapper', () => {
|
||||
let wrapper;
|
||||
@@ -30,10 +31,14 @@ describe('CellEditWrapper', () => {
|
||||
};
|
||||
|
||||
const keyField = 'id';
|
||||
|
||||
let onUpdateCellCB = sinon.stub();
|
||||
const store = new Store(keyField);
|
||||
store.data = data;
|
||||
|
||||
const CellEditWrapper = wrapperFactory(Container, {
|
||||
onUpdateCell: onUpdateCellCB
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<CellEditWrapper
|
||||
@@ -42,7 +47,6 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -82,7 +86,6 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
wrapper.setProps({ cellEdit: { ...cellEdit, editing: false } });
|
||||
@@ -113,7 +116,6 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
wrapper.setState({ ridx, cidx, editing: true });
|
||||
@@ -167,7 +169,6 @@ describe('CellEditWrapper', () => {
|
||||
cellEdit={ cellEdit }
|
||||
selectRow={ selectRow }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -190,7 +191,6 @@ describe('CellEditWrapper', () => {
|
||||
cellEdit={ cellEdit }
|
||||
selectRow={ selectRow }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -215,13 +215,11 @@ describe('CellEditWrapper', () => {
|
||||
});
|
||||
|
||||
describe('call handleCellUpdate function', () => {
|
||||
let onUpdateCellCallBack;
|
||||
const row = data[0];
|
||||
const column = columns[1];
|
||||
const newValue = 'new name';
|
||||
|
||||
beforeEach(() => {
|
||||
onUpdateCellCallBack = sinon.stub().returns(true);
|
||||
wrapper = shallow(
|
||||
<CellEditWrapper
|
||||
keyField={ keyField }
|
||||
@@ -229,17 +227,14 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ onUpdateCellCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleCellUpdate(row, column, newValue);
|
||||
});
|
||||
|
||||
afterEach(() => { onUpdateCellCallBack.reset(); });
|
||||
|
||||
it('should calling onUpdateCell callback correctly', () => {
|
||||
expect(onUpdateCellCallBack.callCount).toBe(1);
|
||||
expect(onUpdateCellCallBack.calledWith(row.id, column.dataField, newValue)).toBe(true);
|
||||
expect(onUpdateCellCB.callCount).toBe(1);
|
||||
expect(onUpdateCellCB.calledWith(row.id, column.dataField, newValue)).toBe(true);
|
||||
});
|
||||
|
||||
describe('when onUpdateCell function return true', () => {
|
||||
@@ -260,7 +255,6 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ onUpdateCellCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleCellUpdate(row, column, newValue);
|
||||
@@ -279,7 +273,7 @@ describe('CellEditWrapper', () => {
|
||||
const spy = jest.spyOn(CellEditWrapper.prototype, 'completeEditing');
|
||||
|
||||
beforeEach(() => {
|
||||
onUpdateCellCallBack = sinon.stub().returns(false);
|
||||
onUpdateCellCB = sinon.stub().returns(false);
|
||||
wrapper = shallow(
|
||||
<CellEditWrapper
|
||||
keyField={ keyField }
|
||||
@@ -287,7 +281,6 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ onUpdateCellCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleCellUpdate(row, column, newValue);
|
||||
@@ -309,7 +302,6 @@ describe('CellEditWrapper', () => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
store={ store }
|
||||
onUpdateCell={ onUpdateCellCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleCellUpdate(row, column, newValue);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* eslint react/prefer-stateless-function: 0 */
|
||||
/* eslint react/no-multi-comp: 0 */
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import BootstrapTable from '../src';
|
||||
import SortWrapper from '../src/sort/wrapper';
|
||||
import CellEditWrapper from '../src/cell-edit/wrapper';
|
||||
import RowSelectionWrapper from '../src/row-selection/wrapper';
|
||||
import BootstrapTable from '../src/bootstrap-table';
|
||||
import Container from '../src';
|
||||
import { getRowByRowId } from '../src/store/rows';
|
||||
|
||||
describe('withDataStore', () => {
|
||||
describe('container', () => {
|
||||
let wrapper;
|
||||
|
||||
const keyField = 'id';
|
||||
@@ -32,12 +32,16 @@ describe('withDataStore', () => {
|
||||
describe('initialization', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable keyField={ keyField } data={ data } columns={ columns } />
|
||||
<Container keyField={ keyField } data={ data } columns={ columns } />
|
||||
);
|
||||
});
|
||||
|
||||
it('should initialize BaseComponent', () => {
|
||||
expect(wrapper.instance().BaseComponent.name).toBe('BootstrapTable');
|
||||
});
|
||||
|
||||
it('should render BootstrapTable successfully', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find(BootstrapTable)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should creating store successfully', () => {
|
||||
@@ -55,7 +59,7 @@ describe('withDataStore', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
@@ -64,14 +68,16 @@ describe('withDataStore', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render CellEditWrapper component successfully', () => {
|
||||
const component = wrapper.find(CellEditWrapper);
|
||||
expect(component.length).toBe(1);
|
||||
it('should initialize BaseComponent correctly', () => {
|
||||
expect(wrapper.instance().BaseComponent.name).toBe('CellEditWrapper');
|
||||
});
|
||||
|
||||
it('should injecting correct props to CellEditWrapper', () => {
|
||||
const component = wrapper.find(CellEditWrapper);
|
||||
expect(component.props().onUpdateCell).toBeDefined();
|
||||
it('should render CellEditWrapper component successfully', () => {
|
||||
expect(wrapper.find('CellEditWrapper')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should render BootstrapTable component successfully', () => {
|
||||
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
|
||||
});
|
||||
|
||||
describe('for handleUpdateCell function', () => {
|
||||
@@ -100,7 +106,7 @@ describe('withDataStore', () => {
|
||||
beforeEach(() => {
|
||||
cellEdit.onUpdate = sinon.stub().returns(false);
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
@@ -139,7 +145,7 @@ describe('withDataStore', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
@@ -148,20 +154,30 @@ describe('withDataStore', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should initialize BaseComponent correctly', () => {
|
||||
expect(wrapper.instance().BaseComponent.name).toBe('RowSelectionWrapper');
|
||||
});
|
||||
|
||||
it('should render BootstrapTable component successfully', () => {
|
||||
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should render RowSelectionWrapper component successfully', () => {
|
||||
expect(wrapper.find(RowSelectionWrapper).length).toBe(1);
|
||||
expect(wrapper.find('RowSelectionWrapper').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when pagination prop is defined', () => {
|
||||
const PaginationWrapper = () => <div>test</div>;
|
||||
const wrapperFactory = Base => class PaginationWrapper extends React.Component {
|
||||
render() { return <Base { ...this.props } />; }
|
||||
};
|
||||
const pagination = {
|
||||
PaginationWrapper
|
||||
wrapperFactory
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
@@ -170,14 +186,47 @@ describe('withDataStore', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Pagination wrapper successfully', () => {
|
||||
expect(wrapper.find(PaginationWrapper).length).toBe(1);
|
||||
it('should initialize BaseComponent correctly', () => {
|
||||
expect(wrapper.instance().BaseComponent.name).toBe('PaginationWrapper');
|
||||
});
|
||||
|
||||
it('should injecting correct props to Pagination wrapper', () => {
|
||||
const component = wrapper.find(PaginationWrapper);
|
||||
expect(component.props().onRemotePageChange).toBeDefined();
|
||||
expect(component.props().baseElement).toBeDefined();
|
||||
it('should render BootstrapTable component successfully', () => {
|
||||
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should render PaginationWrapper component successfully', () => {
|
||||
expect(wrapper.find('PaginationWrapper').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when filter prop is defined', () => {
|
||||
const wrapperFactory = Base => class FilterWrapper extends React.Component {
|
||||
render() { return <Base { ...this.props } />; }
|
||||
};
|
||||
|
||||
const filter = { wrapperFactory };
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
filter={ filter }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should initialize BaseComponent correctly', () => {
|
||||
expect(wrapper.instance().BaseComponent.name).toBe('FilterWrapper');
|
||||
});
|
||||
|
||||
it('should render BootstrapTable component successfully', () => {
|
||||
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should render FilterWrapper component successfully', () => {
|
||||
expect(wrapper.find('FilterWrapper').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -189,7 +238,7 @@ describe('withDataStore', () => {
|
||||
sort: true
|
||||
}];
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columnsWithSort }
|
||||
@@ -197,103 +246,16 @@ describe('withDataStore', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should initialize BaseComponent correctly', () => {
|
||||
expect(wrapper.instance().BaseComponent.name).toBe('SortWrapper');
|
||||
});
|
||||
|
||||
it('should render BootstrapTable component successfully', () => {
|
||||
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should render SortWrapper component successfully', () => {
|
||||
expect(wrapper.find(SortWrapper).length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleRemotePageChange', () => {
|
||||
const onTableChangeCallBack = sinon.stub();
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
onTableChange={ onTableChangeCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleRemotePageChange();
|
||||
});
|
||||
|
||||
it('should calling onTableChange correctly', () => {
|
||||
expect(onTableChangeCallBack.calledOnce).toBeTruthy();
|
||||
expect(onTableChangeCallBack.calledWith('pagination', wrapper.instance().getNewestState())).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleRemoteFilterChange', () => {
|
||||
const onTableChangeCallBack = sinon.stub();
|
||||
|
||||
beforeEach(() => {
|
||||
onTableChangeCallBack.reset();
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
onTableChange={ onTableChangeCallBack }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
describe('when isRemotePagination argument is false', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.instance().handleRemoteFilterChange(false);
|
||||
});
|
||||
|
||||
it('should calling onTableChange correctly', () => {
|
||||
expect(onTableChangeCallBack.calledOnce).toBeTruthy();
|
||||
expect(onTableChangeCallBack.calledWith('filter', wrapper.instance().getNewestState())).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when isRemotePagination argument is false', () => {
|
||||
describe('and pagination.options.pageStartIndex is defined', () => {
|
||||
const options = { pageStartIndex: 0 };
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
pagination={ { options, PaginationWrapper: () => {} } }
|
||||
onTableChange={ onTableChangeCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleRemoteFilterChange(true);
|
||||
});
|
||||
|
||||
it('should calling onTableChange correctly', () => {
|
||||
expect(onTableChangeCallBack.calledOnce).toBeTruthy();
|
||||
const newState = wrapper.instance().getNewestState();
|
||||
newState.page = options.pageStartIndex;
|
||||
expect(onTableChangeCallBack.calledWith('filter', newState)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('and pagination.options.pageStartIndex is not defined', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
pagination={ { PaginationWrapper: () => {} } }
|
||||
onTableChange={ onTableChangeCallBack }
|
||||
/>
|
||||
);
|
||||
wrapper.instance().handleRemoteFilterChange(true);
|
||||
});
|
||||
|
||||
it('should calling onTableChange correctly', () => {
|
||||
expect(onTableChangeCallBack.calledOnce).toBeTruthy();
|
||||
const newState = wrapper.instance().getNewestState();
|
||||
newState.page = 1;
|
||||
expect(onTableChangeCallBack.calledWith('filter', newState)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
expect(wrapper.find('SortWrapper').length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/* eslint react/prefer-stateless-function: 0 */
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import Container from '../../src/';
|
||||
// import remoteResolver from '../../src/props-resolver/remote-resolver';
|
||||
|
||||
describe('remoteResolver', () => {
|
||||
let wrapper;
|
||||
|
||||
const keyField = 'id';
|
||||
|
||||
const columns = [{
|
||||
dataField: keyField,
|
||||
text: 'ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Name'
|
||||
}];
|
||||
|
||||
const data = [{
|
||||
id: 1,
|
||||
name: 'A'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'B'
|
||||
}];
|
||||
|
||||
const shallowContainer = (props) => {
|
||||
wrapper = shallow(
|
||||
<Container
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
{ ...props }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
describe('isRemotePagination', () => {
|
||||
describe('when remote is false', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer();
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
expect(wrapper.instance().isRemotePagination()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when remote is true', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer({ remote: true });
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
expect(wrapper.instance().isRemotePagination()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when remote.pagination is true', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer({ remote: { pagination: true } });
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
expect(wrapper.instance().isRemotePagination()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRemoteFiltering', () => {
|
||||
describe('when remote is false', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer();
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
expect(wrapper.instance().isRemoteFiltering()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when remote is true', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer({ remote: true });
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
expect(wrapper.instance().isRemoteFiltering()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when remote.filter is true', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer({ remote: { filter: true } });
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
expect(wrapper.instance().isRemoteFiltering()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleRemotePageChange', () => {
|
||||
const onTableChangeCB = sinon.stub();
|
||||
beforeEach(() => {
|
||||
onTableChangeCB.reset();
|
||||
shallowContainer({ onTableChange: onTableChangeCB });
|
||||
wrapper.instance().handleRemotePageChange();
|
||||
});
|
||||
|
||||
it('should calling props.onTableChange correctly', () => {
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
expect(onTableChangeCB.calledWith('pagination', wrapper.instance().getNewestState())).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleRemoteFilterChange', () => {
|
||||
const onTableChangeCB = sinon.stub();
|
||||
|
||||
beforeEach(() => {
|
||||
onTableChangeCB.reset();
|
||||
shallowContainer({ onTableChange: onTableChangeCB });
|
||||
});
|
||||
|
||||
describe('when remote pagination is disabled', () => {
|
||||
it('should calling props.onTableChange correctly', () => {
|
||||
wrapper.instance().handleRemoteFilterChange();
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
expect(onTableChangeCB.calledWith('filter', wrapper.instance().getNewestState())).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when remote pagination is enabled', () => {
|
||||
const wrapperFactory = Base => class FilterWrapper extends React.Component {
|
||||
render() { return <Base { ...this.props } />; }
|
||||
};
|
||||
|
||||
describe('and pagination.options.pageStartIndex is defined', () => {
|
||||
const options = { pageStartIndex: 0 };
|
||||
beforeEach(() => {
|
||||
shallowContainer({
|
||||
remote: true,
|
||||
onTableChange: onTableChangeCB,
|
||||
pagination: { options, wrapperFactory }
|
||||
});
|
||||
wrapper.instance().store.page = 1;
|
||||
wrapper.instance().store.sizePerPage = 10;
|
||||
wrapper.instance().handleRemoteFilterChange();
|
||||
});
|
||||
|
||||
it('should calling onTableChange correctly', () => {
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
const newState = wrapper.instance().getNewestState();
|
||||
newState.page = options.pageStartIndex;
|
||||
expect(onTableChangeCB.calledWith('filter', newState)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('and pagination.options.pageStartIndex is not defined', () => {
|
||||
beforeEach(() => {
|
||||
shallowContainer({
|
||||
remote: true,
|
||||
onTableChange: onTableChangeCB,
|
||||
pagination: { wrapperFactory }
|
||||
});
|
||||
wrapper.instance().handleRemoteFilterChange();
|
||||
});
|
||||
|
||||
it('should calling onTableChange correctly', () => {
|
||||
expect(onTableChangeCB.calledOnce).toBeTruthy();
|
||||
const newState = wrapper.instance().getNewestState();
|
||||
newState.page = 1;
|
||||
expect(onTableChangeCB.calledWith('filter', newState)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@ import { shallow } from 'enzyme';
|
||||
|
||||
import Store from '../../src/store';
|
||||
import BootstrapTable from '../../src/bootstrap-table';
|
||||
import RowSelectionWrapper from '../../src/row-selection/wrapper';
|
||||
import wrapperFactory from '../../src/row-selection/wrapper';
|
||||
|
||||
describe('RowSelectionWrapper', () => {
|
||||
let wrapper;
|
||||
@@ -35,6 +35,7 @@ describe('RowSelectionWrapper', () => {
|
||||
|
||||
const store = new Store(keyField);
|
||||
store.data = data;
|
||||
const RowSelectionWrapper = wrapperFactory(BootstrapTable);
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import Const from '../../src/const';
|
||||
import Store from '../../src/store';
|
||||
import BootstrapTable from '../../src/bootstrap-table';
|
||||
import SortWrapper from '../../src/sort/wrapper';
|
||||
import wrapperFactory from '../../src/sort/wrapper';
|
||||
|
||||
describe('SortWrapper', () => {
|
||||
let wrapper;
|
||||
@@ -34,6 +34,8 @@ describe('SortWrapper', () => {
|
||||
let store = new Store(keyField);
|
||||
store.data = data;
|
||||
|
||||
const SortWrapper = wrapperFactory(BootstrapTable);
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SortWrapper
|
||||
@@ -56,11 +58,10 @@ describe('SortWrapper', () => {
|
||||
|
||||
describe('call handleSort function', () => {
|
||||
const sortColumn = columns[0];
|
||||
|
||||
beforeEach(() => {
|
||||
store = new Store(keyField);
|
||||
store.data = data;
|
||||
wrapper = mount(
|
||||
wrapper = shallow(
|
||||
<SortWrapper
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
@@ -71,10 +72,6 @@ describe('SortWrapper', () => {
|
||||
wrapper.instance().handleSort(sortColumn);
|
||||
});
|
||||
|
||||
it('should sorting data correctly', () => {
|
||||
expect(wrapper.instance().table.state.data[0][keyField]).toEqual(data[1][keyField]);
|
||||
});
|
||||
|
||||
it('should operating on store correctly', () => {
|
||||
expect(store.sortOrder).toEqual(Const.SORT_DESC);
|
||||
expect(store.sortField).toEqual(sortColumn.dataField);
|
||||
|
||||
Reference in New Issue
Block a user