MyDraftList.jsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import Pagination from 'react-bootstrap/lib/Pagination';
  4. import Draft from '../PageList/Draft';
  5. export default class MyDraftList extends React.Component {
  6. constructor(props) {
  7. super(props);
  8. this.state = {
  9. drafts: [],
  10. currentDrafts: [],
  11. activePage: 1,
  12. paginationNumbers: {},
  13. };
  14. this.getDraftsFromLocalStorage = this.getDraftsFromLocalStorage.bind(this);
  15. this.getCurrentDrafts = this.getCurrentDrafts.bind(this);
  16. this.clearDraft = this.clearDraft.bind(this);
  17. this.clearAllDrafts = this.clearAllDrafts.bind(this);
  18. this.calculatePagination = this.calculatePagination.bind(this);
  19. }
  20. async componentWillMount() {
  21. await this.getDraftsFromLocalStorage();
  22. this.getCurrentDrafts(1);
  23. }
  24. async getDraftsFromLocalStorage() {
  25. const draftsAsObj = JSON.parse(this.props.crowi.localStorage.getItem('draft') || '{}');
  26. const res = await this.props.crowi.apiGet('/pages.exist', {
  27. pages: draftsAsObj,
  28. });
  29. // {'/a': '#a', '/b': '#b'} => [{path: '/a', markdown: '#a'}, {path: '/b', markdown: '#b'}]
  30. const drafts = Object.entries(draftsAsObj).map((d) => {
  31. const path = d[0];
  32. return {
  33. path,
  34. markdown: d[1],
  35. isExist: res.pages[path],
  36. };
  37. });
  38. this.setState({ drafts });
  39. }
  40. getCurrentDrafts(selectPageNumber) {
  41. const limit = this.props.limit;
  42. const totalCount = this.state.drafts.length;
  43. const activePage = selectPageNumber;
  44. const paginationNumbers = this.calculatePagination(limit, totalCount, activePage);
  45. const currentDrafts = this.state.drafts.slice((activePage - 1) * limit, activePage * limit);
  46. this.setState({
  47. currentDrafts,
  48. activePage,
  49. paginationNumbers,
  50. });
  51. }
  52. /**
  53. * generate Elements of Draft
  54. *
  55. * @param {any} drafts Array of pages Model Obj
  56. *
  57. */
  58. generateDraftList(drafts) {
  59. return drafts.map((draft) => {
  60. return (
  61. <Draft
  62. key={draft.path}
  63. crowi={this.props.crowi}
  64. crowiOriginRenderer={this.props.crowiOriginRenderer}
  65. path={draft.path}
  66. markdown={draft.markdown}
  67. isExist={draft.isExist}
  68. clearDraft={this.clearDraft}
  69. />
  70. );
  71. });
  72. }
  73. clearDraft(path) {
  74. this.props.crowi.clearDraft(path);
  75. this.setState((prevState) => {
  76. return {
  77. drafts: prevState.drafts.filter((draft) => { return draft.path !== path }),
  78. currentDrafts: prevState.drafts.filter((draft) => { return draft.path !== path }),
  79. };
  80. });
  81. }
  82. clearAllDrafts() {
  83. this.props.crowi.clearAllDrafts();
  84. this.setState({
  85. drafts: [],
  86. currentDrafts: [],
  87. activePage: 1,
  88. paginationNumbers: {},
  89. });
  90. }
  91. calculatePagination(limit, totalCount, activePage) {
  92. // calc totalPageNumber
  93. const totalPage = Math.floor(totalCount / limit) + (totalCount % limit === 0 ? 0 : 1);
  94. let paginationStart = activePage - 2;
  95. let maxViewPageNum = activePage + 2;
  96. // pagiNation Number area size = 5 , pageNuber calculate in here
  97. // activePage Position calculate ex. 4 5 [6] 7 8 (Page8 over is Max), 3 4 5 [6] 7 (Page7 is Max)
  98. if (paginationStart < 1) {
  99. const diff = 1 - paginationStart;
  100. paginationStart += diff;
  101. maxViewPageNum = Math.min(totalPage, maxViewPageNum + diff);
  102. }
  103. if (maxViewPageNum > totalPage) {
  104. const diff = maxViewPageNum - totalPage;
  105. maxViewPageNum -= diff;
  106. paginationStart = Math.max(1, paginationStart - diff);
  107. }
  108. return {
  109. totalPage,
  110. paginationStart,
  111. maxViewPageNum,
  112. };
  113. }
  114. /**
  115. * generate Elements of Pagination First Prev
  116. * ex. << < 1 2 3 > >>
  117. * this function set << & <
  118. */
  119. generateFirstPrev(activePage) {
  120. const paginationItems = [];
  121. if (activePage !== 1) {
  122. paginationItems.push(
  123. <Pagination.First key="first" onClick={() => { return this.getCurrentDrafts(1) }} />,
  124. );
  125. paginationItems.push(
  126. <Pagination.Prev key="prev" onClick={() => { return this.getCurrentDrafts(this.state.activePage - 1) }} />,
  127. );
  128. }
  129. else {
  130. paginationItems.push(
  131. <Pagination.First key="first" disabled />,
  132. );
  133. paginationItems.push(
  134. <Pagination.Prev key="prev" disabled />,
  135. );
  136. }
  137. return paginationItems;
  138. }
  139. /**
  140. * generate Elements of Pagination First Prev
  141. * ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
  142. * this function set numbers
  143. */
  144. generatePaginations(activePage, paginationStart, maxViewPageNum) {
  145. const paginationItems = [];
  146. for (let number = paginationStart; number <= maxViewPageNum; number++) {
  147. paginationItems.push(
  148. <Pagination.Item key={number} active={number === activePage} onClick={() => { return this.getCurrentDrafts(number) }}>{number}</Pagination.Item>,
  149. );
  150. }
  151. return paginationItems;
  152. }
  153. /**
  154. * generate Elements of Pagination First Prev
  155. * ex. << < 1 2 3 > >>
  156. * this function set > & >>
  157. */
  158. generateNextLast(activePage, totalPage) {
  159. const paginationItems = [];
  160. if (totalPage !== activePage) {
  161. paginationItems.push(
  162. <Pagination.Next key="next" onClick={() => { return this.getCurrentDrafts(this.state.activePage + 1) }} />,
  163. );
  164. paginationItems.push(
  165. <Pagination.Last key="last" onClick={() => { return this.getCurrentDrafts(totalPage) }} />,
  166. );
  167. }
  168. else {
  169. paginationItems.push(
  170. <Pagination.Next key="next" disabled />,
  171. );
  172. paginationItems.push(
  173. <Pagination.Last key="last" disabled />,
  174. );
  175. }
  176. return paginationItems;
  177. }
  178. render() {
  179. const draftList = this.generateDraftList(this.state.currentDrafts);
  180. const paginationItems = [];
  181. const activePage = this.state.activePage;
  182. const totalPage = this.state.paginationNumbers.totalPage;
  183. const paginationStart = this.state.paginationNumbers.paginationStart;
  184. const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
  185. const firstPrevItems = this.generateFirstPrev(activePage);
  186. paginationItems.push(firstPrevItems);
  187. const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
  188. paginationItems.push(paginations);
  189. const nextLastItems = this.generateNextLast(activePage, totalPage);
  190. paginationItems.push(nextLastItems);
  191. return (
  192. <div className="page-list-container-create">
  193. <button type="button" className="btn-danger mb-3" onClick={this.clearAllDrafts}>Delete All</button>
  194. <div className="tab-pane m-t-30 accordion" id="draft-list">
  195. {draftList}
  196. </div>
  197. <Pagination bsSize="small">{paginationItems}</Pagination>
  198. </div>
  199. );
  200. }
  201. }
  202. MyDraftList.propTypes = {
  203. limit: PropTypes.number,
  204. crowi: PropTypes.object.isRequired,
  205. crowiOriginRenderer: PropTypes.object.isRequired,
  206. };