PaginationWrapper.jsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. 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. <PaginationItem key="painationItemFirst">
  64. <PaginationLink first onClick={() => { return this.props.changePage(1) }} />
  65. </PaginationItem>,
  66. <PaginationItem key="painationItemPrevious">
  67. <PaginationLink previous onClick={() => { return this.props.changePage(activePage - 1) }} />
  68. </PaginationItem>,
  69. );
  70. }
  71. else {
  72. paginationItems.push(
  73. <PaginationItem key="painationItemFirst" disabled>
  74. <PaginationLink first />
  75. </PaginationItem>,
  76. <PaginationItem key="painationItemPrevious" disabled>
  77. <PaginationLink previous />
  78. </PaginationItem>,
  79. );
  80. }
  81. return paginationItems;
  82. }
  83. /**
  84. * generate Elements of Pagination First Prev
  85. * ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
  86. * this function set numbers
  87. */
  88. generatePaginations(activePage, paginationStart, maxViewPageNum) {
  89. const paginationItems = [];
  90. for (let number = paginationStart; number <= maxViewPageNum; number++) {
  91. paginationItems.push(
  92. <PaginationItem key={`paginationItem-${number}`} active={number === activePage}>
  93. <PaginationLink onClick={() => { return this.props.changePage(number) }}>
  94. {number}
  95. </PaginationLink>
  96. </PaginationItem>,
  97. );
  98. }
  99. return paginationItems;
  100. }
  101. /**
  102. * generate Elements of Pagination First Prev
  103. * ex. << < 1 2 3 > >>
  104. * this function set > & >>
  105. */
  106. generateNextLast(activePage, totalPage) {
  107. const paginationItems = [];
  108. if (totalPage !== activePage) {
  109. paginationItems.push(
  110. <PaginationItem key="painationItemNext">
  111. <PaginationLink next onClick={() => { return this.props.changePage(activePage + 1) }} />
  112. </PaginationItem>,
  113. <PaginationItem key="painationItemLast">
  114. <PaginationLink last onClick={() => { return this.props.changePage(totalPage) }} />
  115. </PaginationItem>,
  116. );
  117. }
  118. else {
  119. paginationItems.push(
  120. <PaginationItem key="painationItemNext" disabled>
  121. <PaginationLink next />
  122. </PaginationItem>,
  123. <PaginationItem key="painationItemLast" disabled>
  124. <PaginationLink last />
  125. </PaginationItem>,
  126. );
  127. }
  128. return paginationItems;
  129. }
  130. render() {
  131. const paginationItems = [];
  132. const activePage = this.state.activePage;
  133. const totalPage = this.state.paginationNumbers.totalPage;
  134. const paginationStart = this.state.paginationNumbers.paginationStart;
  135. const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
  136. const firstPrevItems = this.generateFirstPrev(activePage);
  137. paginationItems.push(firstPrevItems);
  138. const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
  139. paginationItems.push(paginations);
  140. const nextLastItems = this.generateNextLast(activePage, totalPage);
  141. paginationItems.push(nextLastItems);
  142. return (
  143. <React.Fragment>
  144. <Pagination size="sm">{paginationItems}</Pagination>
  145. </React.Fragment>
  146. );
  147. }
  148. }
  149. const PaginationWrappered = (props) => {
  150. return createSubscribedElement(PaginationWrapper, props, [AppContainer]);
  151. };
  152. PaginationWrapper.propTypes = {
  153. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  154. activePage: PropTypes.number.isRequired,
  155. changePage: PropTypes.func.isRequired,
  156. totalItemsCount: PropTypes.number.isRequired,
  157. pagingLimit: PropTypes.number.isRequired,
  158. };
  159. export default withTranslation()(PaginationWrappered);