Ivan - Add pagination to table [skip ci]
This commit is contained in:
parent
abea0bbb97
commit
65630d1b15
|
@ -1,6 +1,6 @@
|
||||||
const Menu = ReactMock();
|
const Pagination = ReactMock();
|
||||||
const Table = requireUnit('core-components/table', {
|
const Table = requireUnit('core-components/table', {
|
||||||
'core-components/menu': Menu
|
'core-components/pagination': Pagination
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Table component', function () {
|
describe('Table component', function () {
|
||||||
|
@ -26,7 +26,7 @@ describe('Table component', function () {
|
||||||
<Table headers={headers} rows={rows} {...props} />
|
<Table headers={headers} rows={rows} {...props} />
|
||||||
);
|
);
|
||||||
|
|
||||||
menu = TestUtils.scryRenderedComponentsWithType(table, Menu)[0];
|
menu = TestUtils.scryRenderedComponentsWithType(table, Pagination)[0];
|
||||||
tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr');
|
tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr');
|
||||||
th = TestUtils.scryRenderedDOMComponentsWithTag(table, 'th');
|
th = TestUtils.scryRenderedDOMComponentsWithTag(table, 'th');
|
||||||
}
|
}
|
||||||
|
@ -82,10 +82,9 @@ describe('Table component', function () {
|
||||||
expect(tr[3].children[0].textContent).to.equal('Row3 header1');
|
expect(tr[3].children[0].textContent).to.equal('Row3 header1');
|
||||||
expect(tr[3].children[1].textContent).to.equal('Row3 header2');
|
expect(tr[3].children[1].textContent).to.equal('Row3 header2');
|
||||||
|
|
||||||
expect(menu.props.type).to.equal('navigation');
|
expect(menu.props.pages).to.equal(3);
|
||||||
expect(menu.props.items).to.deep.equal([{content: 1}, {content: 2}, {content: 3}]);
|
|
||||||
|
|
||||||
menu.props.onItemClick(1);
|
menu.props.onChange(2);
|
||||||
tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr');
|
tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr');
|
||||||
|
|
||||||
expect(tr.length).to.equal(4);
|
expect(tr.length).to.equal(4);
|
||||||
|
@ -96,7 +95,7 @@ describe('Table component', function () {
|
||||||
expect(tr[3].children[0].textContent).to.equal('Row6 header1');
|
expect(tr[3].children[0].textContent).to.equal('Row6 header1');
|
||||||
expect(tr[3].children[1].textContent).to.equal('Row6 header2');
|
expect(tr[3].children[1].textContent).to.equal('Row6 header2');
|
||||||
|
|
||||||
menu.props.onItemClick(2);
|
menu.props.onChange(3);
|
||||||
tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr');
|
tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr');
|
||||||
|
|
||||||
expect(tr.length).to.equal(3);
|
expect(tr.length).to.equal(3);
|
||||||
|
|
|
@ -69,6 +69,10 @@ $transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
border-top-right-radius: 4px;
|
border-top-right-radius: 4px;
|
||||||
border-bottom-right-radius: 4px;
|
border-bottom-right-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__list-item_selected {
|
.menu__list-item_selected {
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import Menu from 'core-components/menu';
|
||||||
|
|
||||||
|
class Pagination extends React.Component {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
pages: React.PropTypes.number.isRequired,
|
||||||
|
pageRangeDisplayed: React.PropTypes.number,
|
||||||
|
marginPagesDisplayed: React.PropTypes.number,
|
||||||
|
page: React.PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
pageRangeDisplayed: 5,
|
||||||
|
marginPagesDisplayed: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
page: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Menu {...this.getProps()}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProps() {
|
||||||
|
let props = _.clone(this.props);
|
||||||
|
let pageList = this.getItems();
|
||||||
|
|
||||||
|
props.items = pageList.map(page => {return {content: page}});
|
||||||
|
props.selectedIndex = _.indexOf(pageList, this.getPage());
|
||||||
|
props.onItemClick = this.onItemClick.bind(this);
|
||||||
|
props.type = 'navigation';
|
||||||
|
|
||||||
|
delete props.page;
|
||||||
|
delete props.pages;
|
||||||
|
delete props.pageRangeDisplayed;
|
||||||
|
delete props.marginPagesDisplayed;
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
getItems() {
|
||||||
|
const pages = this.props.pages;
|
||||||
|
const pageRangeDisplayed = this.props.pageRangeDisplayed;
|
||||||
|
const marginPagesDisplayed = this.props.marginPagesDisplayed;
|
||||||
|
const page = this.getPage();
|
||||||
|
|
||||||
|
let totalItems = [];
|
||||||
|
|
||||||
|
if(pages <= pageRangeDisplayed + 2 * marginPagesDisplayed) {
|
||||||
|
return _.range(1, pages + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page <= pageRangeDisplayed) {
|
||||||
|
totalItems = totalItems.concat(_.range(1, (page > pageRangeDisplayed - marginPagesDisplayed + 1) ? pageRangeDisplayed +1 + marginPagesDisplayed : pageRangeDisplayed + 1));
|
||||||
|
totalItems.push('...');
|
||||||
|
totalItems = totalItems.concat(_.range(pages - marginPagesDisplayed + 1, pages + 1));
|
||||||
|
} else {
|
||||||
|
totalItems = totalItems.concat(_.range(1, marginPagesDisplayed + 1));
|
||||||
|
totalItems.push('...');
|
||||||
|
|
||||||
|
if(page > pages - pageRangeDisplayed) {
|
||||||
|
totalItems = totalItems.concat(_.range((page < pages - pageRangeDisplayed + marginPagesDisplayed) ? pages - pageRangeDisplayed - marginPagesDisplayed + 1 : pages - pageRangeDisplayed + 1, pages + 1));
|
||||||
|
} else {
|
||||||
|
totalItems = totalItems.concat(_.range(page - Math.floor(pageRangeDisplayed / 2), page + Math.floor(pageRangeDisplayed / 2) + 1));
|
||||||
|
totalItems.push('...');
|
||||||
|
totalItems = totalItems.concat(_.range(pages - marginPagesDisplayed + 1, pages + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemClick(index) {
|
||||||
|
let items = this.getItems();
|
||||||
|
let page;
|
||||||
|
|
||||||
|
if(items[index] === '...') {
|
||||||
|
page = Math.floor((items[index-1] + items[index+1]) / 2);
|
||||||
|
} else {
|
||||||
|
page = items[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({page});
|
||||||
|
|
||||||
|
if(this.props.onChange) {
|
||||||
|
this.props.onChange(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPage() {
|
||||||
|
return (this.props.page !== undefined) ? this.props.page : this.state.page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Pagination;
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import Menu from 'core-components/menu';
|
import Pagination from 'core-components/pagination';
|
||||||
import Icon from 'core-components/icon';
|
import Icon from 'core-components/icon';
|
||||||
import Loading from 'core-components/loading';
|
import Loading from 'core-components/loading';
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ class Table extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<td className={classNames(classes)} key={key}>{row[key]}</td>
|
<td className={classNames(classes)} key={key}>{row[key]}</td>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -106,10 +107,8 @@ class Table extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNavigation() {
|
renderNavigation() {
|
||||||
const items = _.range(1, this.getPages()).map((index) => {return {content: index};});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu className="table__navigation" type="navigation" items={items} selectedIndex={this.getPageNumber() - 1} onItemClick={this.onNavigationItemClick.bind(this)} tabbable/>
|
<Pagination className="table__navigation" page={this.getPageNumber()} pages={this.getPages()} onChange={this.onNavigationChange.bind(this)} tabbable/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,13 +130,13 @@ class Table extends React.Component {
|
||||||
return classNames(classes);
|
return classNames(classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
onNavigationItemClick(index) {
|
onNavigationChange(index) {
|
||||||
this.setState({
|
this.setState({
|
||||||
page: index + 1
|
page: index
|
||||||
});
|
});
|
||||||
|
|
||||||
if(this.props.onPageChange) {
|
if(this.props.onPageChange) {
|
||||||
this.props.onPageChange({target: {value: index + 1}});
|
this.props.onPageChange({target: {value: index}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +157,7 @@ class Table extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
getPages() {
|
getPages() {
|
||||||
return (this.props.pages !== undefined) ? this.props.pages + 1 : Math.ceil(this.props.rows.length / this.props.pageSize) + 1;
|
return (this.props.pages !== undefined) ? this.props.pages : Math.ceil(this.props.rows.length / this.props.pageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPageNumber() {
|
getPageNumber() {
|
||||||
|
|
Loading…
Reference in New Issue