CopyDropdown.jsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import {
  5. UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem,
  6. Tooltip,
  7. } from 'reactstrap';
  8. import { CopyToClipboard } from 'react-copy-to-clipboard';
  9. class CopyDropdown extends React.Component {
  10. constructor(props) {
  11. super(props);
  12. this.state = {
  13. dropdownOpen: false,
  14. tooltipOpen: false,
  15. isParamsAppended: true,
  16. };
  17. this.toggle = this.toggle.bind(this);
  18. this.showToolTip = this.showToolTip.bind(this);
  19. this.generatePagePathWithParams = this.generatePagePathWithParams.bind(this);
  20. this.generatePagePathUrl = this.generatePagePathUrl.bind(this);
  21. this.generatePermalink = this.generatePermalink.bind(this);
  22. this.generateMarkdownLink = this.generateMarkdownLink.bind(this);
  23. }
  24. toggle() {
  25. this.setState({ dropdownOpen: !this.state.dropdownOpen });
  26. }
  27. showToolTip() {
  28. this.setState({ tooltipOpen: true });
  29. setTimeout(() => {
  30. this.setState({ tooltipOpen: false });
  31. }, 1000);
  32. }
  33. get uriParams() {
  34. const { isParamsAppended } = this.state;
  35. if (!isParamsAppended) {
  36. return '';
  37. }
  38. const {
  39. search, hash,
  40. } = window.location;
  41. return `${search}${hash}`;
  42. }
  43. generatePagePathWithParams() {
  44. const { pagePath } = this.props;
  45. return decodeURI(`${pagePath}${this.uriParams}`);
  46. }
  47. generatePagePathUrl() {
  48. const { origin } = window.location;
  49. return `${origin}${this.generatePagePathWithParams()}`;
  50. }
  51. generatePermalink() {
  52. const { pageId, pagePath, isShareLinkMode } = this.props;
  53. if (isShareLinkMode) {
  54. return decodeURI(`${origin}/share/${pagePath}`);
  55. }
  56. if (pageId == null) {
  57. return null;
  58. }
  59. return decodeURI(`${origin}/${pageId}${this.uriParams}`);
  60. }
  61. generateMarkdownLink() {
  62. const { pagePath } = this.props;
  63. const label = decodeURI(`${pagePath}${this.uriParams}`);
  64. const permalink = this.generatePermalink();
  65. return `[${label}](${permalink})`;
  66. }
  67. DropdownItemContents = ({ title, contents }) => (
  68. <>
  69. <div className="h6 mt-1 mb-2"><strong>{title}</strong></div>
  70. <div className="card well mb-1 p-2">{contents}</div>
  71. </>
  72. );
  73. render() {
  74. const {
  75. t, pageId, pagePath, isShareLinkMode,
  76. } = this.props;
  77. const { isParamsAppended } = this.state;
  78. const pagePathWithParams = this.generatePagePathWithParams();
  79. const pagePathUrl = this.generatePagePathUrl();
  80. const permalink = this.generatePermalink();
  81. const { DropdownItemContents } = this;
  82. const copyTarget = isShareLinkMode ? `copyShareLink${pagePath}` : 'copyPagePathDropdown';
  83. return (
  84. <>
  85. <UncontrolledDropdown id={copyTarget} className="grw-copy-dropdown">
  86. <DropdownToggle
  87. caret
  88. className="d-block text-muted bg-transparent btn-copy border-0"
  89. style={this.props.buttonStyle}
  90. >
  91. { isShareLinkMode ? (
  92. <>Copy Link</>
  93. ) : (<i className="ti-clipboard"></i>)}
  94. </DropdownToggle>
  95. <DropdownMenu>
  96. <div className="d-flex align-items-center justify-content-between">
  97. <DropdownItem header className="px-3">
  98. { t('copy_to_clipboard.Copy to clipboard') }
  99. </DropdownItem>
  100. <div className="px-3 custom-control custom-switch custom-switch-sm">
  101. <input
  102. type="checkbox"
  103. id="customSwitchForParams"
  104. className="custom-control-input"
  105. checked={isParamsAppended}
  106. onChange={e => this.setState({ isParamsAppended: !isParamsAppended })}
  107. />
  108. <label className="custom-control-label small" htmlFor="customSwitchForParams">Append params</label>
  109. </div>
  110. </div>
  111. <DropdownItem divider className="my-0"></DropdownItem>
  112. {/* Page path */}
  113. { pageId && (
  114. <>
  115. <CopyToClipboard text={pagePathWithParams} onCopy={this.showToolTip}>
  116. <DropdownItem className="px-3">
  117. <DropdownItemContents title={t('copy_to_clipboard.Page path')} contents={pagePathWithParams} />
  118. </DropdownItem>
  119. </CopyToClipboard>
  120. <DropdownItem divider className="my-0"></DropdownItem>
  121. </>
  122. )}
  123. {/* Page path URL */}
  124. <CopyToClipboard text={pagePathUrl} onCopy={this.showToolTip}>
  125. <DropdownItem className="px-3">
  126. <DropdownItemContents title={t('copy_to_clipboard.Page URL')} contents={pagePathUrl} />
  127. </DropdownItem>
  128. </CopyToClipboard>
  129. <DropdownItem divider className="my-0"></DropdownItem>
  130. {/* Parmanent Link */}
  131. { pageId && (
  132. <CopyToClipboard text={permalink} onCopy={this.showToolTip}>
  133. <DropdownItem className="px-3">
  134. <DropdownItemContents title={t('copy_to_clipboard.Parmanent link')} contents={permalink} />
  135. </DropdownItem>
  136. </CopyToClipboard>
  137. )}
  138. <DropdownItem divider className="my-0"></DropdownItem>
  139. {/* Page path + Parmanent Link */}
  140. { pageId && (
  141. <CopyToClipboard text={`${pagePathWithParams}\n${permalink}`} onCopy={this.showToolTip}>
  142. <DropdownItem className="px-3">
  143. <DropdownItemContents title={t('copy_to_clipboard.Page path and parmanent link')} contents={<>{pagePathWithParams}<br />{permalink}</>} />
  144. </DropdownItem>
  145. </CopyToClipboard>
  146. )}
  147. <DropdownItem divider className="my-0"></DropdownItem>
  148. {/* Markdown Link */}
  149. { (pageId || pagePath) && (
  150. <CopyToClipboard text={this.generateMarkdownLink()} onCopy={this.showToolTip}>
  151. <DropdownItem className="px-3 text-wrap">
  152. <DropdownItemContents title={t('copy_to_clipboard.Markdown link')} contents={this.generateMarkdownLink()} isContentsWrap />
  153. </DropdownItem>
  154. </CopyToClipboard>
  155. )}
  156. </DropdownMenu>
  157. </UncontrolledDropdown>
  158. <Tooltip placement="bottom" isOpen={this.state.tooltipOpen} target={copyTarget} fade={false}>
  159. copied!
  160. </Tooltip>
  161. </>
  162. );
  163. }
  164. }
  165. CopyDropdown.propTypes = {
  166. t: PropTypes.func.isRequired, // i18next
  167. pagePath: PropTypes.string.isRequired,
  168. pageId: PropTypes.string,
  169. buttonStyle: PropTypes.object,
  170. isShareLinkMode: PropTypes.bool,
  171. };
  172. export default withTranslation()(CopyDropdown);