PageHistoryContainer.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { Container } from 'unstated';
  2. import loggerFactory from '@alias/logger';
  3. import { toastError } from '../util/apiNotification';
  4. const logger = loggerFactory('growi:PageHistoryContainer');
  5. /**
  6. * Service container for personal settings page (PageHistory.jsx)
  7. * @extends {Container} unstated Container
  8. */
  9. export default class PageHistoryContainer extends Container {
  10. constructor(appContainer, pageContainer) {
  11. super();
  12. this.appContainer = appContainer;
  13. this.pageContainer = pageContainer;
  14. this.dummyRevisions = 0;
  15. this.state = {
  16. errorMessage: null,
  17. // set dummy rivisions for using suspense
  18. revisions: this.dummyRevisions,
  19. diffOpened: {},
  20. totalPages: 0,
  21. activePage: 1,
  22. pagingLimit: this.appContainer.getConfig().pageLimitationS,
  23. };
  24. this.retrieveRevisions = this.retrieveRevisions.bind(this);
  25. this.onDiffOpenClicked = this.onDiffOpenClicked.bind(this);
  26. this.getPreviousRevision = this.getPreviousRevision.bind(this);
  27. this.fetchPageRevisionBody = this.fetchPageRevisionBody.bind(this);
  28. }
  29. /**
  30. * Workaround for the mangling in production build to break constructor.name
  31. */
  32. static getClassName() {
  33. return 'PageHistoryContainer';
  34. }
  35. /**
  36. * syncRevisions of selectedPage
  37. * @param {number} selectedPage
  38. */
  39. async retrieveRevisions(selectedPage) {
  40. const { pageId, shareLinkId } = this.pageContainer.state;
  41. const { pagingLimit } = this.state;
  42. if (!pageId) {
  43. return;
  44. }
  45. const res = await this.appContainer.apiv3Get('/revisions/list', {
  46. pageId, shareLinkId, selectedPage, pagingLimit,
  47. });
  48. const rev = res.data.docs;
  49. // set Pagination state
  50. this.setState({
  51. activePage: selectedPage,
  52. totalPages: res.data.totalDocs,
  53. });
  54. const diffOpened = {};
  55. const lastId = rev.length - 1;
  56. res.data.docs.forEach((revision, i) => {
  57. const user = revision.author;
  58. if (user) {
  59. rev[i].author = user;
  60. }
  61. if (i === 0 || i === lastId) {
  62. diffOpened[revision._id] = true;
  63. }
  64. else {
  65. diffOpened[revision._id] = false;
  66. }
  67. });
  68. this.setState({ revisions: rev });
  69. this.setState({ diffOpened });
  70. // load 0, and last default
  71. if (rev[0]) {
  72. this.fetchPageRevisionBody(rev[0]);
  73. }
  74. if (rev[1]) {
  75. this.fetchPageRevisionBody(rev[1]);
  76. }
  77. if (lastId !== 0 && lastId !== 1 && rev[lastId]) {
  78. this.fetchPageRevisionBody(rev[lastId]);
  79. }
  80. return;
  81. }
  82. onDiffOpenClicked(revision) {
  83. const { diffOpened } = this.state;
  84. const revisionId = revision._id;
  85. diffOpened[revisionId] = !(diffOpened[revisionId]);
  86. this.setState(diffOpened);
  87. this.fetchPageRevisionBody(revision);
  88. this.fetchPageRevisionBody(this.getPreviousRevision(revision));
  89. }
  90. getPreviousRevision(currentRevision) {
  91. let cursor = null;
  92. for (const revision of this.state.revisions) {
  93. // comparing ObjectId
  94. // eslint-disable-next-line eqeqeq
  95. if (cursor && cursor._id == currentRevision._id) {
  96. cursor = revision;
  97. break;
  98. }
  99. cursor = revision;
  100. }
  101. return cursor;
  102. }
  103. /**
  104. * fetch page revision body by revision in argument
  105. * @param {object} revision
  106. */
  107. async fetchPageRevisionBody(revision) {
  108. const { pageId, shareLinkId } = this.pageContainer.state;
  109. if (revision.body) {
  110. return;
  111. }
  112. try {
  113. const res = await this.appContainer.apiv3Get(`/revisions/${revision._id}`, { pageId, shareLinkId });
  114. this.setState({
  115. revisions: this.state.revisions.map((rev) => {
  116. // comparing ObjectId
  117. // eslint-disable-next-line eqeqeq
  118. if (rev._id == res.data.revision._id) {
  119. return res.data.revision;
  120. }
  121. return rev;
  122. }),
  123. });
  124. }
  125. catch (err) {
  126. toastError(err);
  127. this.setState({ errorMessage: err.message });
  128. logger.error(err);
  129. }
  130. }
  131. }