RevisionComparerContainer.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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 (RevisionCompare.jsx)
  7. * @extends {Container} unstated Container
  8. */
  9. export default class RevisionComparerContainer extends Container {
  10. constructor(appContainer, pageContainer) {
  11. super();
  12. this.appContainer = appContainer;
  13. this.pageContainer = pageContainer;
  14. this.state = {
  15. errMessage: null,
  16. sourceRevision: null,
  17. targetRevision: null,
  18. latestRevision: null,
  19. };
  20. this.initRevisions = this.initRevisions.bind(this);
  21. }
  22. /**
  23. * Workaround for the mangling in production build to break constructor.name
  24. */
  25. static getClassName() {
  26. return 'RevisionComparerContainer';
  27. }
  28. /**
  29. * Initialize the revisions
  30. */
  31. async initRevisions() {
  32. const latestRevision = await this.fetchLatestRevision();
  33. const [sourceRevisionId, targetRevisionId] = this.getRevisionIDsToCompareAsParam();
  34. const sourceRevision = sourceRevisionId ? await this.fetchRevision(sourceRevisionId) : latestRevision;
  35. const targetRevision = targetRevisionId ? await this.fetchRevision(targetRevisionId) : latestRevision;
  36. const compareWithLatest = targetRevisionId ? false : this.state.compareWithLatest;
  37. this.setState({
  38. sourceRevision, targetRevision, latestRevision, compareWithLatest,
  39. });
  40. }
  41. /**
  42. * Get the IDs of the comparison source and target from "window.location" as an array
  43. */
  44. getRevisionIDsToCompareAsParam() {
  45. const searchParams = {};
  46. for (const param of window.location.search?.substr(1)?.split('&')) {
  47. const [k, v] = param.split('=');
  48. searchParams[k] = v;
  49. }
  50. if (!searchParams.compare) {
  51. return [];
  52. }
  53. return searchParams.compare.split('...') || [];
  54. }
  55. /**
  56. * Fetch the latest revision
  57. */
  58. async fetchLatestRevision() {
  59. const { pageId, shareLinkId } = this.pageContainer.state;
  60. try {
  61. const res = await this.appContainer.apiv3Get('/revisions/list', {
  62. pageId, shareLinkId, page: 1, limit: 1,
  63. });
  64. return res.data.docs[0];
  65. }
  66. catch (err) {
  67. toastError(err);
  68. this.setState({ errorMessage: err.message });
  69. logger.error(err);
  70. }
  71. return null;
  72. }
  73. /**
  74. * Fetch the revision of the specified ID
  75. * @param {string} revision ID
  76. */
  77. async fetchRevision(revisionId) {
  78. const { pageId, shareLinkId } = this.pageContainer.state;
  79. try {
  80. const res = await this.appContainer.apiv3Get(`/revisions/${revisionId}`, {
  81. pageId, shareLinkId,
  82. });
  83. return res.data.revision;
  84. }
  85. catch (err) {
  86. toastError(err);
  87. this.setState({ errorMessage: err.message });
  88. logger.error(err);
  89. }
  90. return null;
  91. }
  92. }