Skip to content

Commit

Permalink
feat(PaginationV2): introduce itemsPerPageFollowsText prop (carbon-de…
Browse files Browse the repository at this point in the history
…sign-system#842)

* feat(PaginationV2): introduce itemsPerPageFollowsText prop

It works as `itemsPerPageText` and colon combined, that allows consumer to translate the combination.

Fixes carbon-design-system#835.

* docs(PagenationV2): add descriptions for props
  • Loading branch information
asudoh authored and tw15egan committed May 4, 2018
1 parent eca9681 commit a15e5b8
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 32 deletions.
96 changes: 65 additions & 31 deletions src/components/PaginationV2/PaginationV2-test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import React from 'react';
import Icon from '../Icon';
import Pagination from '../Pagination';
import PaginationV2 from '../PaginationV2';
import Select from '../Select';
import SelectItem from '../SelectItem';
import { shallow, mount } from 'enzyme';

describe('Pagination', () => {
describe('renders as expected', () => {
const pagination = shallow(
<Pagination className="extra-class" pageSizes={[5, 10]} totalItems={50} />
const paginationV2 = shallow(
<PaginationV2
className="extra-class"
pageSizes={[5, 10]}
totalItems={50}
/>
);

beforeEach(() => {
paginationV2.setProps('itemsPerPageFollowsText', undefined);
});

describe('icons', () => {
const icons = pagination.find(Icon);
const icons = paginationV2.find(Icon);

it('should have 3 icons', () => {
expect(icons.length).toEqual(2);
Expand All @@ -29,13 +37,13 @@ describe('Pagination', () => {

describe('pagination container', () => {
it('should render the expected classes', () => {
expect(pagination.hasClass('bx--pagination')).toBe(true);
expect(pagination.hasClass('extra-class')).toBe(true);
expect(paginationV2.hasClass('bx--pagination')).toBe(true);
expect(paginationV2.hasClass('extra-class')).toBe(true);
});
});

describe('pagination size container', () => {
const left = pagination.find('.bx--pagination__left');
const left = paginationV2.find('.bx--pagination__left');

it('should render a left container', () => {
expect(left.length).toBe(1);
Expand All @@ -52,17 +60,26 @@ describe('Pagination', () => {

it('should label the dropdown', () => {
const label = left.find('.bx--pagination__text').first();
expect(label.text()).toBe('items per page\u00a0\u00a0|\u00a0\u00a0');
expect(label.text()).toBe('Items per page:\u00a0\u00a0');
});

it('should support translated label with colon', () => {
paginationV2.setProps({ itemsPerPageFollowsText: 'foo' });
const label = paginationV2
.find('.bx--pagination__left')
.find('.bx--pagination__text')
.first();
expect(label.text()).toBe('foo\u00a0\u00a0');
});

it('should show the item range out of the total', () => {
const label = left.find('.bx--pagination__text').at(1);
expect(label.text()).toBe('1-5 of 50 items');
expect(label.text()).toBe('\u00a0|\u00a0\u00a01-5 of 50 items');
});

describe('pagination size container when total pages unknown', () => {
const pager = mount(
<Pagination pageSizes={[5, 10]} pagesUnknown={true} />
<PaginationV2 pageSizes={[5, 10]} pagesUnknown={true} />
);
const left = pager.find('.bx--pagination__left');

Expand All @@ -81,12 +98,21 @@ describe('Pagination', () => {

it('should label the dropdown', () => {
const label = left.find('.bx--pagination__text').first();
expect(label.text()).toBe('items per page\u00a0\u00a0|\u00a0\u00a0');
expect(label.text()).toBe('Items per page:\u00a0\u00a0');
});

it('should support translated label with colon', () => {
paginationV2.setProps({ itemsPerPageFollowsText: 'foo' });
const label = paginationV2
.find('.bx--pagination__left')
.find('.bx--pagination__text')
.first();
expect(label.text()).toBe('foo\u00a0\u00a0');
});

it('should show the item range without the total', () => {
const label = left.find('.bx--pagination__text').at(1);
expect(label.text()).toBe('1-5 items');
expect(label.text()).toBe('\u00a0|\u00a0\u00a01-5 items');
});
});

Expand All @@ -97,20 +123,25 @@ describe('Pagination', () => {
actualPageSize = pageSize;
};
const pager = mount(
<Pagination
<PaginationV2
pageSizes={[5, 10]}
totalItems={50}
onChange={handler}
/>
);
expect(pager.state().pageSize).toBe(5);
pager.find('select').simulate('change', { target: { value: 10 } });
pager
.find('select')
.first()
.simulate('change', { target: { value: 10 } });
expect(actualPageSize).toBe(10);
expect(pager.state().pageSize).toBe(10);

// Text updates after change
const labels = pager.find('.bx--pagination__text');
expect(labels.at(1).text()).toBe('1-10 of 50 items');
expect(labels.at(1).text()).toBe(
'\u00a0|\u00a0\u00a01-10 of 50 items'
);
expect(labels.at(2).text()).toBe('1 of 5 pages');
});

Expand All @@ -120,22 +151,25 @@ describe('Pagination', () => {
actualPage = page;
};
const pager = mount(
<Pagination
<PaginationV2
pageSizes={[5, 10]}
totalItems={50}
onChange={handler}
/>
);
pager.setState({ page: 2 });
expect(pager.state().page).toBe(2);
pager.find('select').simulate('change', { target: { value: 10 } });
pager
.find('select')
.first()
.simulate('change', { target: { value: 10 } });
expect(actualPage).toBe(1);
expect(pager.state().page).toBe(1);
});

it('should return to first page on changes to pageSizes', () => {
const pager = mount(
<Pagination pageSizes={[5, 10]} totalItems={50} />
<PaginationV2 pageSizes={[5, 10]} totalItems={50} />
);
pager.setState({ page: 2 });
pager.setProps({ pageSizes: [3, 6] });
Expand All @@ -144,14 +178,14 @@ describe('Pagination', () => {

it('should default to pageSize if pageSize is provided', () => {
const pager = mount(
<Pagination pageSizes={[5, 10]} pageSize={10} totalItems={50} />
<PaginationV2 pageSizes={[5, 10]} pageSize={10} totalItems={50} />
);
expect(pager.state().pageSize).toEqual(10);
});

it('should default to pageSize if on change to pageSize', () => {
const pager = mount(
<Pagination pageSizes={[5, 10]} totalItems={50} />
<PaginationV2 pageSizes={[5, 10]} totalItems={50} />
);
pager.setProps({ pageSize: 10 });
expect(pager.state().pageSize).toEqual(10);
Expand All @@ -160,7 +194,7 @@ describe('Pagination', () => {
});

describe('pagination paging container', () => {
const right = pagination.find('.bx--pagination__right');
const right = paginationV2.find('.bx--pagination__right');

it('should render a right container', () => {
expect(right.length).toBe(1);
Expand Down Expand Up @@ -190,7 +224,7 @@ describe('Pagination', () => {

it('should disable forward navigation for the last page', () => {
const smallPage = shallow(
<Pagination
<PaginationV2
className="extra-class"
pageSizes={[100]}
totalItems={50}
Expand All @@ -203,7 +237,7 @@ describe('Pagination', () => {

describe('pagination paging container when total pages unknown', () => {
const pager = mount(
<Pagination pageSizes={[5, 10]} pagesUnknown={true} />
<PaginationV2 pageSizes={[5, 10]} pagesUnknown={true} />
);

const right = pager.find('.bx--pagination__right');
Expand Down Expand Up @@ -236,7 +270,7 @@ describe('Pagination', () => {

it('should disable forward navigation for the last page', () => {
const smallPage = shallow(
<Pagination
<PaginationV2
pageSizes={[100]}
pagesUnknown={true}
isLastPage={true}
Expand All @@ -249,7 +283,7 @@ describe('Pagination', () => {

it('should hide text input if disabled', () => {
const noTextInput = shallow(
<Pagination
<PaginationV2
pageSizes={[100]}
pagesUnknown={true}
pageInputDisabled={true}
Expand All @@ -269,7 +303,7 @@ describe('Pagination', () => {
actualPage = page;
};
const pager = mount(
<Pagination
<PaginationV2
pageSizes={[5, 10]}
totalItems={50}
onChange={handler}
Expand All @@ -287,7 +321,7 @@ describe('Pagination', () => {
actualPage = page;
};
const pager = mount(
<Pagination
<PaginationV2
pageSizes={[5, 10]}
totalItems={50}
onChange={handler}
Expand All @@ -306,15 +340,15 @@ describe('Pagination', () => {
actualPage = page;
};
const pager = mount(
<Pagination
<PaginationV2
pageSizes={[5, 10]}
totalItems={50}
onChange={handler}
/>
);
expect(pager.state().page).toBe(1);
pager
.find('.bx--text__input')
.find('select')
.last()
.simulate('change', { target: { value: 2 } });
expect(actualPage).toBe(2);
Expand All @@ -323,14 +357,14 @@ describe('Pagination', () => {

it('should jump to page number if prop page is provided', () => {
const pager = mount(
<Pagination pageSizes={[5, 10]} totalItems={50} page={3} />
<PaginationV2 pageSizes={[5, 10]} totalItems={50} page={3} />
);
expect(pager.state().page).toBe(3);
pager.setProps({ page: 2 });
expect(pager.state().page).toBe(2);
});
it('should not increment page if there is only 1 page', () => {
const pager = mount(<Pagination pageSizes={[10]} totalItems={5} />);
const pager = mount(<PaginationV2 pageSizes={[10]} totalItems={5} />);
const buttons = pager.find('.bx--pagination__button');
expect(buttons.at(1).props().disabled).toBe(true);
});
Expand Down
81 changes: 80 additions & 1 deletion src/components/PaginationV2/PaginationV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,102 @@ let instanceId = 0;

export default class PaginationV2 extends Component {
static propTypes = {
/**
* The description for the backward icon.
*/
backwardText: PropTypes.string,

/**
* The CSS class names.
*/
className: PropTypes.string,

/**
* The function returning a translatable text showing where the current page is,
* in a manner of the range of items.
*/
itemRangeText: PropTypes.func,

/**
* The description for the forward icon.
*/
forwardText: PropTypes.string,

/**
* The unique ID of this component instance.
*/
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

/**
* The translatable text indicating the number of items per page.
*/
itemsPerPageText: PropTypes.string,

/**
* A variant of `itemsPerPageText`, with a sign indicating that the number follows, e.g. ':'.
*/
itemsPerPageFollowsText: PropTypes.string,

/**
* A variant of `itemRangeText`, used if the total number of items is unknown.
*/
itemText: PropTypes.func,

/**
* The callback function called when the current page changes.
*/
onChange: PropTypes.func,

pageNumberText: PropTypes.string,

/**
* A function returning PII showing where the current page is.
*/
pageRangeText: PropTypes.func,

/**
* The translatable text showing the current page.
*/
pageText: PropTypes.func,

/**
* The choices for `pageSize`.
*/
pageSizes: PropTypes.arrayOf(PropTypes.number).isRequired,

/**
* The total number of items.
*/
totalItems: PropTypes.number,

/**
* `true` if the backward/forward buttons should be disabled.
*/
disabled: PropTypes.bool,

/**
* The current page.
*/
page: PropTypes.number,

/**
* The number dictating how many items a page contains.
*/
pageSize: PropTypes.number,

/**
* `true` if the total number of items is unknown.
*/
pagesUnknown: PropTypes.bool,

/**
* `true` if the current page should be the last page.
*/
isLastPage: PropTypes.bool,

/**
* `true` if the select box to change the page should be disabled.
*/
pageInputDisabled: PropTypes.bool,
};

Expand Down Expand Up @@ -125,6 +203,7 @@ export default class PaginationV2 extends Component {
forwardText,
id,
itemsPerPageText,
itemsPerPageFollowsText,
itemRangeText,
pageRangeText,
pageSize, // eslint-disable-line no-unused-vars
Expand Down Expand Up @@ -159,7 +238,7 @@ export default class PaginationV2 extends Component {
<div className={classNames} {...other}>
<div className="bx--pagination__left">
<span className="bx--pagination__text">
{itemsPerPageText}:&nbsp;&nbsp;
{itemsPerPageFollowsText || `${itemsPerPageText}:`}&nbsp;&nbsp;
</span>
<Select
id={`bx-pagination-select-${inputId}`}
Expand Down

0 comments on commit a15e5b8

Please sign in to comment.