PaginationWrapper.jsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import Pagination from 'react-bootstrap/lib/Pagination';
  5. import { createSubscribedElement } from './UnstatedUtils';
  6. import AppContainer from '../services/AppContainer';
  7. class PaginationWrapper extends React.Component {
  8. constructor(props) {
  9. super(props);
  10. this.state = {
  11. totalItemsCount: 0,
  12. activePage: 1,
  13. paginationNumbers: {},
  14. limit: Infinity,
  15. };
  16. this.calculatePagination = this.calculatePagination.bind(this);
  17. }
  18. componentWillReceiveProps(nextProps) {
  19. this.setState({
  20. activePage: nextProps.activePage,
  21. totalItemsCount: nextProps.totalItemsCount,
  22. limit: nextProps.pagingLimit,
  23. }, () => {
  24. const activePage = this.state.activePage;
  25. const totalCount = this.state.totalItemsCount;
  26. const limit = this.state.limit;
  27. const paginationNumbers = this.calculatePagination(limit, totalCount, activePage);
  28. this.setState({ paginationNumbers });
  29. });
  30. }
  31. calculatePagination(limit, totalCount, activePage) {
  32. // calc totalPageNumber
  33. const totalPage = Math.floor(totalCount / limit) + (totalCount % limit === 0 ? 0 : 1);
  34. let paginationStart = activePage - 2;
  35. let maxViewPageNum = activePage + 2;
  36. // if pagiNation Number area size = 5 , pageNumber is calculated here
  37. // activePage Position calculate ex. 4 5 [6] 7 8 (Page8 over is Max), 3 4 5 [6] 7 (Page7 is Max)
  38. if (paginationStart < 1) {
  39. const diff = 1 - paginationStart;
  40. paginationStart += diff;
  41. maxViewPageNum = Math.min(totalPage, maxViewPageNum + diff);
  42. }
  43. if (maxViewPageNum > totalPage) {
  44. const diff = maxViewPageNum - totalPage;
  45. maxViewPageNum -= diff;
  46. paginationStart = Math.max(1, paginationStart - diff);
  47. }
  48. return {
  49. totalPage,
  50. paginationStart,
  51. maxViewPageNum,
  52. };
  53. }
  54. /**
  55. * generate Elements of Pagination First Prev
  56. * ex. << < 1 2 3 > >>
  57. * this function set << & <
  58. */
  59. generateFirstPrev(activePage) {
  60. const paginationItems = [];
  61. if (activePage !== 1) {
  62. paginationItems.push(
  63. <Pagination.First key="first" onClick={() => { return this.props.changePage(1) }} />,
  64. );
  65. paginationItems.push(
  66. <Pagination.Prev key="prev" onClick={() => { return this.props.changePage(activePage - 1) }} />,
  67. );
  68. }
  69. else {
  70. paginationItems.push(
  71. <Pagination.First key="first" disabled />,
  72. );
  73. paginationItems.push(
  74. <Pagination.Prev key="prev" disabled />,
  75. );
  76. }
  77. return paginationItems;
  78. }
  79. /**
  80. * generate Elements of Pagination First Prev
  81. * ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
  82. * this function set numbers
  83. */
  84. generatePaginations(activePage, paginationStart, maxViewPageNum) {
  85. const paginationItems = [];
  86. for (let number = paginationStart; number <= maxViewPageNum; number++) {
  87. paginationItems.push(
  88. <Pagination.Item key={number} active={number === activePage} onClick={() => { return this.props.changePage(number) }}>{number}</Pagination.Item>,
  89. );
  90. }
  91. return paginationItems;
  92. }
  93. /**
  94. * generate Elements of Pagination First Prev
  95. * ex. << < 1 2 3 > >>
  96. * this function set > & >>
  97. */
  98. generateNextLast(activePage, totalPage) {
  99. const paginationItems = [];
  100. if (totalPage !== activePage) {
  101. paginationItems.push(
  102. <Pagination.Next key="next" onClick={() => { return this.props.changePage(activePage + 1) }} />,
  103. );
  104. paginationItems.push(
  105. <Pagination.Last key="last" onClick={() => { return this.props.changePage(totalPage) }} />,
  106. );
  107. }
  108. else {
  109. paginationItems.push(
  110. <Pagination.Next key="next" disabled />,
  111. );
  112. paginationItems.push(
  113. <Pagination.Last key="last" disabled />,
  114. );
  115. }
  116. return paginationItems;
  117. }
  118. render() {
  119. const paginationItems = [];
  120. const activePage = this.state.activePage;
  121. const totalPage = this.state.paginationNumbers.totalPage;
  122. const paginationStart = this.state.paginationNumbers.paginationStart;
  123. const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
  124. const firstPrevItems = this.generateFirstPrev(activePage);
  125. paginationItems.push(firstPrevItems);
  126. const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
  127. paginationItems.push(paginations);
  128. const nextLastItems = this.generateNextLast(activePage, totalPage);
  129. paginationItems.push(nextLastItems);
  130. return (
  131. <React.Fragment>
  132. <div>
  133. <Pagination bsSize="small">{paginationItems}</Pagination>
  134. </div>
  135. </React.Fragment>
  136. );
  137. }
  138. }
  139. const PaginationWrappered = (props) => {
  140. return createSubscribedElement(PaginationWrapper, props, [AppContainer]);
  141. };
  142. PaginationWrapper.propTypes = {
  143. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  144. activePage: PropTypes.number.isRequired,
  145. changePage: PropTypes.func.isRequired,
  146. totalItemsCount: PropTypes.number.isRequired,
  147. pagingLimit: PropTypes.number.isRequired,
  148. };
  149. export default withTranslation()(PaginationWrappered);