Ivan - Add pagination to table [skip ci]

This commit is contained in:
ivan 2016-12-15 18:33:54 -03:00
parent abea0bbb97
commit 65630d1b15
4 changed files with 118 additions and 15 deletions

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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() {