PaginationWrapper.jsx 5.8 KB

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