2
0

PageRevisionTable.jsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import PageHistroyContainer from '../../services/PageHistoryContainer';
  5. import RevisionComparerContainer from '../../services/RevisionComparerContainer';
  6. import Revision from './Revision';
  7. class PageRevisionTable extends React.Component {
  8. /**
  9. * render a row (Revision component and RevisionDiff component)
  10. * @param {Revison} revision
  11. * @param {Revision} previousRevision
  12. * @param {boolean} hasDiff whether revision has difference to previousRevision
  13. * @param {boolean} isContiguousNodiff true if the current 'hasDiff' and one of previous row is both false
  14. */
  15. renderRow(revision, previousRevision, hasDiff, isContiguousNodiff) {
  16. const { revisionComparerContainer, t } = this.props;
  17. const { latestRevision, oldestRevision } = this.props.pageHistoryContainer.state;
  18. const revisionId = revision._id;
  19. const revisionDiffOpened = this.props.diffOpened[revisionId] || false;
  20. const { sourceRevision, targetRevision } = revisionComparerContainer.state;
  21. const handleCompareLatestRevisionButton = () => {
  22. revisionComparerContainer.setState({ sourceRevision: revision });
  23. revisionComparerContainer.setState({ targetRevision: latestRevision });
  24. };
  25. const handleComparePreviousRevisionButton = () => {
  26. revisionComparerContainer.setState({ sourceRevision: previousRevision });
  27. revisionComparerContainer.setState({ targetRevision: revision });
  28. };
  29. return (
  30. <tr className="d-flex" key={`revision-history-${revisionId}`}>
  31. <td className="col" key={`revision-history-top-${revisionId}`}>
  32. <div className="d-lg-flex">
  33. <Revision
  34. t={this.props.t}
  35. revision={revision}
  36. isLatestRevision={revision === latestRevision}
  37. revisionDiffOpened={revisionDiffOpened}
  38. hasDiff={hasDiff}
  39. key={`revision-history-rev-${revisionId}`}
  40. />
  41. {hasDiff && (
  42. <div className="ml-md-3 mt-auto">
  43. <div className="btn-group">
  44. <button
  45. type="button"
  46. className="btn btn-outline-secondary btn-sm"
  47. onClick={handleCompareLatestRevisionButton}
  48. >
  49. {t('page_history.compare_latest')}
  50. </button>
  51. <button
  52. type="button"
  53. className="btn btn-outline-secondary btn-sm"
  54. onClick={handleComparePreviousRevisionButton}
  55. disabled={revision === oldestRevision}
  56. >
  57. {t('page_history.compare_previous')}
  58. </button>
  59. </div>
  60. </div>
  61. )}
  62. </div>
  63. </td>
  64. <td className="col-1">
  65. {(hasDiff || revision._id === sourceRevision?._id) && (
  66. <div className="custom-control custom-radio custom-control-inline mr-0">
  67. <input
  68. type="radio"
  69. className="custom-control-input"
  70. id={`compareSource-${revision._id}`}
  71. name="compareSource"
  72. value={revision._id}
  73. checked={revision._id === sourceRevision?._id}
  74. onChange={() => revisionComparerContainer.setState({ sourceRevision: revision })}
  75. />
  76. <label className="custom-control-label" htmlFor={`compareSource-${revision._id}`} />
  77. </div>
  78. )}
  79. </td>
  80. <td className="col-2">
  81. {(hasDiff || revision._id === targetRevision?._id) && (
  82. <div className="custom-control custom-radio custom-control-inline mr-0">
  83. <input
  84. type="radio"
  85. className="custom-control-input"
  86. id={`compareTarget-${revision._id}`}
  87. name="compareTarget"
  88. value={revision._id}
  89. checked={revision._id === targetRevision?._id}
  90. onChange={() => revisionComparerContainer.setState({ targetRevision: revision })}
  91. />
  92. <label className="custom-control-label" htmlFor={`compareTarget-${revision._id}`} />
  93. </div>
  94. )}
  95. </td>
  96. </tr>
  97. );
  98. }
  99. render() {
  100. const { t, pageHistoryContainer } = this.props;
  101. const revisions = this.props.revisions;
  102. const revisionCount = this.props.revisions.length;
  103. let hasDiffPrev;
  104. const revisionList = this.props.revisions.map((revision, idx) => {
  105. // Returns null because the last revision is for the bottom diff display
  106. if (idx === pageHistoryContainer.state.pagingLimit) {
  107. return null;
  108. }
  109. let previousRevision;
  110. if (idx + 1 < revisionCount) {
  111. previousRevision = revisions[idx + 1];
  112. }
  113. else {
  114. previousRevision = revision; // if it is the first revision, show full text as diff text
  115. }
  116. const hasDiff = revision.hasDiffToPrev !== false; // set 'true' if undefined for backward compatibility
  117. const isContiguousNodiff = !hasDiff && !hasDiffPrev;
  118. hasDiffPrev = hasDiff;
  119. return this.renderRow(revision, previousRevision, hasDiff, isContiguousNodiff);
  120. });
  121. return (
  122. <table className="table revision-history-table">
  123. <thead>
  124. <tr className="d-flex">
  125. <th className="col">{ t('page_history.revision') }</th>
  126. <th className="col-1">{ t('page_history.comparing_source') }</th>
  127. <th className="col-2">{ t('page_history.comparing_target') }</th>
  128. </tr>
  129. </thead>
  130. <tbody className="overflow-auto d-block">
  131. {revisionList}
  132. </tbody>
  133. </table>
  134. );
  135. }
  136. }
  137. PageRevisionTable.propTypes = {
  138. t: PropTypes.func.isRequired, // i18next
  139. pageHistoryContainer: PropTypes.instanceOf(PageHistroyContainer).isRequired,
  140. revisionComparerContainer: PropTypes.instanceOf(RevisionComparerContainer).isRequired,
  141. revisions: PropTypes.array,
  142. diffOpened: PropTypes.object,
  143. };
  144. export default withTranslation()(PageRevisionTable);