From 65630d1b155086c22377e9df6c5475b57e38752c Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 15 Dec 2016 18:33:54 -0300 Subject: [PATCH] Ivan - Add pagination to table [skip ci] --- .../core-components/__tests__/table-test.js | 13 ++- client/src/core-components/menu.scss | 4 + client/src/core-components/pagination.js | 101 ++++++++++++++++++ client/src/core-components/table.js | 15 ++- 4 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 client/src/core-components/pagination.js diff --git a/client/src/core-components/__tests__/table-test.js b/client/src/core-components/__tests__/table-test.js index 99131317..5b61e06f 100644 --- a/client/src/core-components/__tests__/table-test.js +++ b/client/src/core-components/__tests__/table-test.js @@ -1,6 +1,6 @@ -const Menu = ReactMock(); +const Pagination = ReactMock(); const Table = requireUnit('core-components/table', { - 'core-components/menu': Menu + 'core-components/pagination': Pagination }); describe('Table component', function () { @@ -26,7 +26,7 @@ describe('Table component', function () { ); - menu = TestUtils.scryRenderedComponentsWithType(table, Menu)[0]; + menu = TestUtils.scryRenderedComponentsWithType(table, Pagination)[0]; tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr'); 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[1].textContent).to.equal('Row3 header2'); - expect(menu.props.type).to.equal('navigation'); - expect(menu.props.items).to.deep.equal([{content: 1}, {content: 2}, {content: 3}]); + expect(menu.props.pages).to.equal(3); - menu.props.onItemClick(1); + menu.props.onChange(2); tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr'); 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[1].textContent).to.equal('Row6 header2'); - menu.props.onItemClick(2); + menu.props.onChange(3); tr = TestUtils.scryRenderedDOMComponentsWithTag(table, 'tr'); expect(tr.length).to.equal(3); diff --git a/client/src/core-components/menu.scss b/client/src/core-components/menu.scss index 92ae0be3..6fc7486a 100644 --- a/client/src/core-components/menu.scss +++ b/client/src/core-components/menu.scss @@ -69,6 +69,10 @@ $transition: background-color 0.3s ease, color 0.3s ease; border-top-right-radius: 4px; border-bottom-right-radius: 4px; } + + &:focus { + outline: none; + } } .menu__list-item_selected { diff --git a/client/src/core-components/pagination.js b/client/src/core-components/pagination.js new file mode 100644 index 00000000..4b4ad162 --- /dev/null +++ b/client/src/core-components/pagination.js @@ -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 ( + + ); + } + + 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; \ No newline at end of file diff --git a/client/src/core-components/table.js b/client/src/core-components/table.js index 2d0fc757..099557d4 100644 --- a/client/src/core-components/table.js +++ b/client/src/core-components/table.js @@ -2,7 +2,7 @@ import React from 'react'; import _ from 'lodash'; import classNames from 'classnames'; -import Menu from 'core-components/menu'; +import Pagination from 'core-components/pagination'; import Icon from 'core-components/icon'; import Loading from 'core-components/loading'; @@ -97,6 +97,7 @@ class Table extends React.Component { }; return ( + ); } @@ -106,10 +107,8 @@ class Table extends React.Component { } renderNavigation() { - const items = _.range(1, this.getPages()).map((index) => {return {content: index};}); - return ( - + ); } @@ -131,13 +130,13 @@ class Table extends React.Component { return classNames(classes); } - onNavigationItemClick(index) { + onNavigationChange(index) { this.setState({ - page: index + 1 + page: index }); 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() { - 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() {
{row[key]}