PageRevisionTable.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import React from 'react';
  2. import { IRevisionHasId } from '@growi/core';
  3. import { useTranslation } from 'next-i18next';
  4. import { Revision } from './Revision';
  5. import styles from './PageRevisionTable.module.scss';
  6. type PageRevisionTAble = {
  7. revisions: IRevisionHasId[],
  8. pagingLimit: number,
  9. sourceRevision: IRevisionHasId,
  10. targetRevision: IRevisionHasId,
  11. onChangeSourceInvoked: React.Dispatch<React.SetStateAction<IRevisionHasId | undefined>>,
  12. onChangeTargetInvoked: React.Dispatch<React.SetStateAction<IRevisionHasId | undefined>>,
  13. }
  14. export const PageRevisionTable = (props: PageRevisionTAble): JSX.Element => {
  15. const { t } = useTranslation();
  16. const {
  17. revisions, pagingLimit, sourceRevision, targetRevision, onChangeSourceInvoked, onChangeTargetInvoked,
  18. } = props;
  19. const revisionCount = revisions.length;
  20. const latestRevision = revisions[0];
  21. const oldestRevision = revisions[revisions.length - 1];
  22. const renderRow = (revision: IRevisionHasId, previousRevision: IRevisionHasId, latestRevision: IRevisionHasId,
  23. isOldestRevision: boolean, hasDiff: boolean) => {
  24. const revisionId = revision._id;
  25. const handleCompareLatestRevisionButton = () => {
  26. onChangeSourceInvoked(revision);
  27. onChangeTargetInvoked(latestRevision);
  28. };
  29. const handleComparePreviousRevisionButton = () => {
  30. onChangeSourceInvoked(previousRevision);
  31. onChangeTargetInvoked(revision);
  32. };
  33. return (
  34. <tr className="d-flex" key={`revision-history-${revisionId}`}>
  35. <td className="col" key={`revision-history-top-${revisionId}`}>
  36. <div className="d-lg-flex">
  37. <Revision
  38. revision={revision}
  39. isLatestRevision={revision === latestRevision}
  40. hasDiff={hasDiff}
  41. key={`revision-history-rev-${revisionId}`}
  42. />
  43. {hasDiff && (
  44. <div className="ml-md-3 mt-auto">
  45. <div className="btn-group">
  46. <button
  47. type="button"
  48. className="btn btn-outline-secondary btn-sm"
  49. onClick={handleCompareLatestRevisionButton}
  50. >
  51. {t('page_history.compare_latest')}
  52. </button>
  53. <button
  54. type="button"
  55. className="btn btn-outline-secondary btn-sm"
  56. onClick={handleComparePreviousRevisionButton}
  57. disabled={isOldestRevision}
  58. >
  59. {t('page_history.compare_previous')}
  60. </button>
  61. </div>
  62. </div>
  63. )}
  64. </div>
  65. </td>
  66. <td className="col-1">
  67. {(hasDiff || revisionId === sourceRevision?._id) && (
  68. <div className="custom-control custom-radio custom-control-inline mr-0">
  69. <input
  70. type="radio"
  71. className="custom-control-input"
  72. id={`compareSource-${revisionId}`}
  73. name="compareSource"
  74. value={revisionId}
  75. checked={revisionId === sourceRevision?._id}
  76. onChange={() => onChangeSourceInvoked(revision)}
  77. />
  78. <label className="custom-control-label" htmlFor={`compareSource-${revisionId}`} />
  79. </div>
  80. )}
  81. </td>
  82. <td className="col-2">
  83. {(hasDiff || revisionId === targetRevision?._id) && (
  84. <div className="custom-control custom-radio custom-control-inline mr-0">
  85. <input
  86. type="radio"
  87. className="custom-control-input"
  88. id={`compareTarget-${revisionId}`}
  89. name="compareTarget"
  90. value={revisionId}
  91. checked={revisionId === targetRevision?._id}
  92. onChange={() => onChangeTargetInvoked(revision)}
  93. />
  94. <label className="custom-control-label" htmlFor={`compareTarget-${revisionId}`} />
  95. </div>
  96. )}
  97. </td>
  98. </tr>
  99. );
  100. };
  101. const revisionList = revisions.map((revision, idx) => {
  102. // Returns null because the last revision is for the bottom diff display
  103. if (idx === pagingLimit) {
  104. return null;
  105. }
  106. // if it is the first revision, show full text as diff text
  107. const previousRevision = (idx + 1 < revisionCount) ? revisions[idx + 1] : revision;
  108. const isOldestRevision = revision === oldestRevision;
  109. // set 'true' if undefined for backward compatibility
  110. const hasDiff = revision.hasDiffToPrev !== false;
  111. return renderRow(revision, previousRevision, latestRevision, isOldestRevision, hasDiff);
  112. });
  113. return (
  114. <table className={`${styles['revision-history-table']} table revision-history-table`}>
  115. <thead>
  116. <tr className="d-flex">
  117. <th className="col">{ t('page_history.revision') }</th>
  118. <th className="col-1">{ t('page_history.comparing_source') }</th>
  119. <th className="col-2">{ t('page_history.comparing_target') }</th>
  120. </tr>
  121. </thead>
  122. <tbody className="overflow-auto d-block">
  123. {revisionList}
  124. </tbody>
  125. </table>
  126. );
  127. };