PageHistory.jsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import loggerFactory from '@alias/logger';
  4. import { withTranslation } from 'react-i18next';
  5. import PageRevisionList from './PageHistory/PageRevisionList';
  6. const logger = loggerFactory('growi:PageHistory');
  7. class PageHistory extends React.Component {
  8. constructor(props) {
  9. super(props);
  10. this.state = {
  11. isLoaded: false,
  12. isLoading: false,
  13. errorMessage: null,
  14. revisions: [],
  15. diffOpened: {},
  16. };
  17. this.getPreviousRevision = this.getPreviousRevision.bind(this);
  18. this.onDiffOpenClicked = this.onDiffOpenClicked.bind(this);
  19. }
  20. async componentWillMount() {
  21. const pageId = this.props.pageId;
  22. if (!pageId) {
  23. return;
  24. }
  25. let res;
  26. try {
  27. this.setState({ isLoading: true });
  28. res = await this.props.crowi.apiGet('/revisions.ids', { page_id: pageId });
  29. }
  30. catch (err) {
  31. logger.error(err);
  32. this.setState({ errorMessage: err });
  33. return;
  34. }
  35. finally {
  36. this.setState({ isLoading: false });
  37. }
  38. const rev = res.revisions;
  39. const diffOpened = {};
  40. const lastId = rev.length - 1;
  41. res.revisions.forEach((revision, i) => {
  42. const user = revision.author;
  43. if (user) {
  44. rev[i].author = user;
  45. }
  46. if (i === 0 || i === lastId) {
  47. diffOpened[revision._id] = true;
  48. }
  49. else {
  50. diffOpened[revision._id] = false;
  51. }
  52. });
  53. this.setState({
  54. isLoaded: true,
  55. revisions: rev,
  56. diffOpened,
  57. });
  58. // load 0, and last default
  59. if (rev[0]) {
  60. this.fetchPageRevisionBody(rev[0]);
  61. }
  62. if (rev[1]) {
  63. this.fetchPageRevisionBody(rev[1]);
  64. }
  65. if (lastId !== 0 && lastId !== 1 && rev[lastId]) {
  66. this.fetchPageRevisionBody(rev[lastId]);
  67. }
  68. }
  69. getPreviousRevision(currentRevision) {
  70. let cursor = null;
  71. for (const revision of this.state.revisions) {
  72. // comparing ObjectId
  73. // eslint-disable-next-line eqeqeq
  74. if (cursor && cursor._id == currentRevision._id) {
  75. cursor = revision;
  76. break;
  77. }
  78. cursor = revision;
  79. }
  80. return cursor;
  81. }
  82. onDiffOpenClicked(revision) {
  83. const diffOpened = this.state.diffOpened;
  84. const revisionId = revision._id;
  85. diffOpened[revisionId] = !(diffOpened[revisionId]);
  86. this.setState({
  87. diffOpened,
  88. });
  89. this.fetchPageRevisionBody(revision);
  90. this.fetchPageRevisionBody(this.getPreviousRevision(revision));
  91. }
  92. fetchPageRevisionBody(revision) {
  93. if (revision.body) {
  94. return;
  95. }
  96. this.props.crowi.apiGet('/revisions.get',
  97. { page_id: this.props.pageId, revision_id: revision._id })
  98. .then((res) => {
  99. if (res.ok) {
  100. this.setState({
  101. revisions: this.state.revisions.map((rev) => {
  102. // comparing ObjectId
  103. // eslint-disable-next-line eqeqeq
  104. if (rev._id == res.revision._id) {
  105. return res.revision;
  106. }
  107. return rev;
  108. }),
  109. });
  110. }
  111. })
  112. .catch((err) => {
  113. });
  114. }
  115. render() {
  116. return (
  117. <div className="mt-4">
  118. { this.state.isLoading && (
  119. <div className="my-5 text-center">
  120. <i className="fa fa-lg fa-spinner fa-pulse mx-auto text-muted"></i>
  121. </div>
  122. ) }
  123. { this.state.errorMessage && (
  124. <div className="my-5">
  125. <div className="text-danger">{this.state.errorMessage}</div>
  126. </div>
  127. ) }
  128. { this.state.isLoaded && (
  129. <PageRevisionList
  130. t={this.props.t}
  131. revisions={this.state.revisions}
  132. diffOpened={this.state.diffOpened}
  133. getPreviousRevision={this.getPreviousRevision}
  134. onDiffOpenClicked={this.onDiffOpenClicked}
  135. />
  136. ) }
  137. </div>
  138. );
  139. }
  140. }
  141. PageHistory.propTypes = {
  142. t: PropTypes.func.isRequired, // i18next
  143. pageId: PropTypes.string,
  144. crowi: PropTypes.object.isRequired,
  145. };
  146. export default withTranslation()(PageHistory);