RevisionCompare.jsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import React, { useMemo, useCallback } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import { withUnstatedContainers } from './UnstatedUtils';
  5. import RevisionCompareContainer from '../services/RevisionCompareContainer';
  6. import RevisionDiff from './PageHistory/RevisionDiff';
  7. import RevisionIdForm from './RevisionCompare/RevisionIdForm';
  8. import { CopyToClipboard } from 'react-copy-to-clipboard';
  9. import {
  10. Dropdown, DropdownToggle, DropdownMenu, DropdownItem
  11. } from 'reactstrap';
  12. const DropdownItemContents = ({ title, contents }) => (
  13. <>
  14. <div className="h6 mt-1 mb-2"><strong>{title}</strong></div>
  15. <div className="card well mb-1 p-2">{contents}</div>
  16. </>
  17. );
  18. function encodeSpaces(str) {
  19. if (str == null) {
  20. return null;
  21. }
  22. // Encode SPACE and IDEOGRAPHIC SPACE
  23. return str.replace(/ /g, '%20').replace(/\u3000/g, '%E3%80%80');
  24. }
  25. class PageCompare extends React.Component {
  26. constructor() {
  27. super();
  28. this.state = {
  29. dropdownOpen: false
  30. }
  31. this.toggleDropdown = this.toggleDropdown.bind(this);
  32. }
  33. componentWillMount() {
  34. const { revisionCompareContainer } = this.props;
  35. revisionCompareContainer.readyRevisions();
  36. }
  37. toggleDropdown() {
  38. this.setState({
  39. dropdownOpen: !this.state.dropdownOpen
  40. });
  41. }
  42. render() {
  43. const { t, revisionCompareContainer } = this.props;
  44. const fromRev = revisionCompareContainer.state.fromRevision;
  45. const toRev = revisionCompareContainer.state.toRevision;
  46. const showDiff = (fromRev && toRev);
  47. const pagePathUrl = () => {
  48. const { origin } = window.location;
  49. const { path } = revisionCompareContainer.pageContainer.state;
  50. const { fromRevision, toRevision } = revisionCompareContainer.state;
  51. const urlParams = (fromRevision && toRevision ? `?compare=${fromRevision._id}...${toRevision._id}` : "");
  52. return encodeSpaces(decodeURI(`${origin}/${path}${urlParams}`));
  53. }
  54. return (
  55. <div id="revision-compare-content">
  56. <div>{ t('page_compare_revision.comparing_changes') }</div>
  57. <RevisionIdForm />
  58. <div className="card card-compare">
  59. <div className="card-body">
  60. <div className="container-fluid px-0">
  61. <div className="row">
  62. <div className="col-sm">
  63. { fromRev && fromRev._id }<i className="icon-arrow-right-circle mx-1"></i>{ toRev && toRev._id }
  64. </div>
  65. <div className="col-sm">
  66. <Dropdown className="grw-copy-dropdown" isOpen={this.state.dropdownOpen} toggle={this.toggleDropdown}>
  67. <DropdownToggle
  68. caret
  69. className={'d-block text-muted bg-transparent btn-copy border-0 py-0'}
  70. >
  71. <i className="ti-clipboard"></i>
  72. </DropdownToggle>
  73. <DropdownMenu positionFixed modifiers={{ preventOverflow: { boundariesElement: null } }}>
  74. {/* Page path URL */}
  75. <CopyToClipboard text={pagePathUrl()}>
  76. <DropdownItem className="px-3">
  77. <DropdownItemContents title={t('copy_to_clipboard.Page URL')} contents={pagePathUrl()} />
  78. </DropdownItem>
  79. </CopyToClipboard>
  80. <DropdownItem divider className="my-0"></DropdownItem>
  81. </DropdownMenu>
  82. </Dropdown>
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. { showDiff &&
  89. <RevisionDiff
  90. revisionDiffOpened={ true }
  91. previousRevision={ fromRev }
  92. currentRevision={ toRev }
  93. />
  94. }
  95. </div>
  96. );
  97. }
  98. }
  99. /**
  100. * Wrapper component for using unstated
  101. */
  102. const PageCompareWrapper = withUnstatedContainers(PageCompare, [RevisionCompareContainer]);
  103. PageCompare.propTypes = {
  104. t: PropTypes.func.isRequired, // i18next
  105. revisionCompareContainer: PropTypes.instanceOf(RevisionCompareContainer).isRequired,
  106. };
  107. export default withTranslation()(PageCompareWrapper);