From 73f8f15bb3ff30a8ab63b6f55c8d3326f703b0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= Date: Tue, 3 Sep 2019 16:41:05 +0200 Subject: [PATCH] Create Pagination and ProductOrderSelect components (https://github.com/woocommerce/woocommerce-blocks/pull/926) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create ProductOrderSelect component * Create Pagination component * Add description to props * Use BEM class name * Use < > instead of ← → * Update product order select options to match Shop core page * Refactor pagination so it behaves like core pagination * Update snapshots --- .../assets/js/base/components/label/index.js | 2 +- .../label/test/__snapshots__/index.js.snap | 4 +- .../js/base/components/pagination/index.js | 135 ++++++++++++++++++ .../js/base/components/pagination/style.scss | 22 +++ .../base/components/pagination/test/index.js | 28 ++++ .../js/base/components/pagination/utils.js | 17 +++ .../components/product-order-select/index.js | 41 ++++++ 7 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/pagination/index.js create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/pagination/style.scss create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/pagination/test/index.js create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/pagination/utils.js create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/product-order-select/index.js diff --git a/plugins/woocommerce-blocks/assets/js/base/components/label/index.js b/plugins/woocommerce-blocks/assets/js/base/components/label/index.js index 9079b225a91..7b068aa429f 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/label/index.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/label/index.js @@ -32,7 +32,7 @@ const Label = ( { label, screenReaderLabel, wrapperElement, wrapperProps } ) => if ( label && screenReaderLabel && label !== screenReaderLabel ) { return ( - + diff --git a/plugins/woocommerce-blocks/assets/js/base/components/label/test/__snapshots__/index.js.snap b/plugins/woocommerce-blocks/assets/js/base/components/label/test/__snapshots__/index.js.snap index 980093315ad..d21e7d5609a 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/label/test/__snapshots__/index.js.snap +++ b/plugins/woocommerce-blocks/assets/js/base/components/label/test/__snapshots__/index.js.snap @@ -6,7 +6,7 @@ exports[`Label with wrapperElement should render both label and screen reader la data-foo="bar" > Lorem @@ -39,7 +39,7 @@ exports[`Label with wrapperElement should render only the screen reader label 1` exports[`Label without wrapperElement should render both label and screen reader label 1`] = ` Array [ Lorem , diff --git a/plugins/woocommerce-blocks/assets/js/base/components/pagination/index.js b/plugins/woocommerce-blocks/assets/js/base/components/pagination/index.js new file mode 100644 index 00000000000..7acebb97368 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/pagination/index.js @@ -0,0 +1,135 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +/** + * Internal dependencies + */ +import Label from '../label'; +import { getIndexes } from './utils.js'; +import './style.scss'; + +const Pagination = ( { currentPage, displayFirstAndLastPages, displayNextAndPreviousArrows, pagesToDisplay, onPageChange, totalPages } ) => { + const { minIndex, maxIndex } = getIndexes( pagesToDisplay, currentPage, totalPages ); + const pages = []; + for ( let i = minIndex; i <= maxIndex; i++ ) { + pages.push( i ); + } + const showFirstPage = displayFirstAndLastPages && Boolean( minIndex !== 1 ); + const showLastPage = displayFirstAndLastPages && Boolean( maxIndex !== totalPages ); + const showFirstPageEllipsis = displayFirstAndLastPages && Boolean( minIndex > 2 ); + const showLastPageEllipsis = displayFirstAndLastPages && Boolean( maxIndex < totalPages - 1 ); + const showPreviousArrow = displayNextAndPreviousArrows && Boolean( currentPage !== 1 ); + const showNextArrow = displayNextAndPreviousArrows && Boolean( currentPage !== totalPages ); + + return ( +
+
+ ); +}; + +Pagination.propTypes = { + /** + * Number of the page currently being displayed. + */ + currentPage: PropTypes.number.isRequired, + /** + * Total number of pages. + */ + totalPages: PropTypes.number.isRequired, + /** + * Displays first and last pages if they are not in the current range of pages displayed. + */ + displayFirstAndLastPages: PropTypes.bool, + /** + * Displays arrows to navigate to the previous and next pages. + */ + displayNextAndPreviousArrows: PropTypes.bool, + /** + * Callback function called when the user triggers a page change. + */ + onPageChange: PropTypes.func, + /** + * Number of pages to display at the same time, including the active page + * and the pages displayed before and after it. It doesn't include the first + * and last pages. + */ + pagesToDisplay: PropTypes.number, +}; + +Pagination.defaultProps = { + displayFirstAndLastPages: true, + displayNextAndPreviousArrows: true, + pagesToDisplay: 3, +}; + +export default Pagination; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/pagination/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/pagination/style.scss new file mode 100644 index 00000000000..744d9ac4d29 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/pagination/style.scss @@ -0,0 +1,22 @@ +.wc-block-pagination-page, +.wc-block-pagination-ellipsis { + color: #333; + display: inline-block; + font-size: 1em; + font-weight: normal; +} + +.wc-block-pagination-page { + background-color: transparent; + border-color: transparent; + padding: 0.3em 0.6em; + min-width: 2.2em; +} + +.wc-block-pagination-ellipsis { + padding: 0.3em; +} + +.wc-block-pagination-page--active { + font-weight: bold; +} diff --git a/plugins/woocommerce-blocks/assets/js/base/components/pagination/test/index.js b/plugins/woocommerce-blocks/assets/js/base/components/pagination/test/index.js new file mode 100644 index 00000000000..b95357d2030 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/pagination/test/index.js @@ -0,0 +1,28 @@ +/** + * Internal dependencies + */ +import { getIndexes } from '../utils.js'; + +describe( 'getIndexes', () => { + describe( 'when on the first page', () => { + test( 'indexes include the first pages available', () => { + expect( getIndexes( 5, 1, 100 ) ).toEqual( { minIndex: 1, maxIndex: 5 } ); + } ); + + test( 'indexes include the only available page if there is only one', () => { + expect( getIndexes( 5, 1, 1 ) ).toEqual( { minIndex: 1, maxIndex: 1 } ); + } ); + } ); + + describe( 'when on a page in the middle', () => { + test( 'indexes include pages before and after the current page', () => { + expect( getIndexes( 5, 50, 100 ) ).toEqual( { minIndex: 48, maxIndex: 52 } ); + } ); + } ); + + describe( 'when on the last page', () => { + test( 'indexes include the last pages available', () => { + expect( getIndexes( 5, 100, 100 ) ).toEqual( { minIndex: 96, maxIndex: 100 } ); + } ); + } ); +} ); diff --git a/plugins/woocommerce-blocks/assets/js/base/components/pagination/utils.js b/plugins/woocommerce-blocks/assets/js/base/components/pagination/utils.js new file mode 100644 index 00000000000..10279151e9a --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/pagination/utils.js @@ -0,0 +1,17 @@ +/** + * Given the number of pages to display, the current page and the total pages, + * returns the min and max index of the pages to display in the pagination component. + * + * @param {integer} pagesToDisplay Maximum number of pages to display in the pagination component. + * @param {integer} currentPage Page currently visible. + * @param {integer} totalPages Total pages available. + * @return {object} Object containing the min and max index to display in the pagination component. + */ +export const getIndexes = ( pagesToDisplay, currentPage, totalPages ) => { + const extraPagesToDisplay = pagesToDisplay - 1; + const tentativeMinIndex = Math.max( Math.floor( currentPage - ( extraPagesToDisplay / 2 ) ), 1 ); + const maxIndex = Math.min( Math.ceil( currentPage + ( extraPagesToDisplay - ( currentPage - tentativeMinIndex ) ) ), totalPages ); + const minIndex = Math.max( Math.floor( currentPage - ( extraPagesToDisplay - ( maxIndex - currentPage ) ) ), 1 ); + + return { minIndex, maxIndex }; +}; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/product-order-select/index.js b/plugins/woocommerce-blocks/assets/js/base/components/product-order-select/index.js new file mode 100644 index 00000000000..88d869a124c --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/product-order-select/index.js @@ -0,0 +1,41 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import PropTypes from 'prop-types'; + +/** + * Internal dependencies + */ +import OrderSelect from '../order-select'; + +const ProductOrderSelect = ( { defaultValue, onChange, readOnly, value } ) => { + return ( + + ); +}; + +ProductOrderSelect.propTypes = { + defaultValue: PropTypes.oneOf( [ 'menu_order', 'popularity', 'rating', 'date', 'price', 'price-desc' ] ), + onChange: PropTypes.func, + readOnly: PropTypes.bool, + value: PropTypes.oneOf( [ 'menu_order', 'popularity', 'rating', 'date', 'price', 'price-desc' ] ), +}; + +export default ProductOrderSelect;