Просмотр исходного кода

Merge pull request #945 from weseek/imprv/header-copy-button

Imprv/header copy button
Yuki Takei 7 лет назад
Родитель
Сommit
6b8c657754

+ 1 - 2
config/webpack.dev.dll.js

@@ -14,7 +14,6 @@ module.exports = {
       'babel-polyfill',
       'babel-polyfill',
       'browser-bunyan', 'bunyan-format',
       'browser-bunyan', 'bunyan-format',
       'codemirror', 'react-codemirror2',
       'codemirror', 'react-codemirror2',
-      'clipboard',
       'date-fns',
       'date-fns',
       'diff2html',
       'diff2html',
       'debug',
       'debug',
@@ -24,7 +23,7 @@ module.exports = {
       'lodash', 'pako',
       'lodash', 'pako',
       'markdown-it', 'csv-to-markdown-table',
       'markdown-it', 'csv-to-markdown-table',
       'react', 'react-dom',
       'react', 'react-dom',
-      'react-bootstrap', 'react-bootstrap-typeahead', 'react-i18next', 'react-dropzone',
+      'react-bootstrap', 'react-bootstrap-typeahead', 'react-i18next', 'react-dropzone', 'react-copy-to-clipboard',
       'socket.io-client',
       'socket.io-client',
       'toastr',
       'toastr',
       'xss',
       'xss',

+ 1 - 1
package.json

@@ -196,8 +196,8 @@
     "react": "^16.8.3",
     "react": "^16.8.3",
     "react-bootstrap": "^0.32.1",
     "react-bootstrap": "^0.32.1",
     "react-bootstrap-typeahead": "^3.4.2",
     "react-bootstrap-typeahead": "^3.4.2",
-    "react-clipboard.js": "^2.0.0",
     "react-codemirror2": "^6.0.0",
     "react-codemirror2": "^6.0.0",
+    "react-copy-to-clipboard": "^5.0.1",
     "react-dom": "^16.8.3",
     "react-dom": "^16.8.3",
     "react-frame-component": "^4.0.0",
     "react-frame-component": "^4.0.0",
     "react-i18next": "^10.6.1",
     "react-i18next": "^10.6.1",

+ 8 - 0
resource/locales/ja/translation.json

@@ -200,6 +200,14 @@
     }
     }
   },
   },
 
 
+  "copy_to_clipboard": {
+    "Copy to clipboard": "クリップボードにコピー",
+    "Page path": "ページ名",
+    "Parmanent link": "パーマリンク",
+    "Page path and parmanent link": "ページ名とパーマリンク",
+    "Markdown link": "マークダウン形式のリンク"
+  },
+
   "search_help": {
   "search_help": {
     "title": "検索のヘルプ",
     "title": "検索のヘルプ",
     "and": {
     "and": {

+ 1 - 1
src/client/js/app.js

@@ -312,7 +312,7 @@ if (pageId) {
 }
 }
 if (pagePath) {
 if (pagePath) {
   componentMappings.page = <Page crowi={crowi} crowiRenderer={crowiRenderer} markdown={markdown} pagePath={pagePath} onSaveWithShortcut={saveWithShortcut} />;
   componentMappings.page = <Page crowi={crowi} crowiRenderer={crowiRenderer} markdown={markdown} pagePath={pagePath} onSaveWithShortcut={saveWithShortcut} />;
-  componentMappings['revision-path'] = <RevisionPath pagePath={pagePath} crowi={crowi} />;
+  componentMappings['revision-path'] = <I18nextProvider i18n={i18n}><RevisionPath pageId={pageId} pagePath={pagePath} crowi={crowi} /></I18nextProvider>;
   componentMappings['tag-label'] = <I18nextProvider i18n={i18n}><TagLabels crowi={crowi} pageId={pageId} sendTagData={setTagData} /></I18nextProvider>;
   componentMappings['tag-label'] = <I18nextProvider i18n={i18n}><TagLabels crowi={crowi} pageId={pageId} sendTagData={setTagData} /></I18nextProvider>;
 }
 }
 
 

+ 0 - 67
src/client/js/components/CopyButton.jsx

@@ -1,67 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import ClipboardButton from 'react-clipboard.js';
-
-export default class CopyButton extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.showToolTip = this.showToolTip.bind(this);
-
-    // retrieve xss library from window
-    this.xss = window.xss;
-  }
-
-  showToolTip() {
-    const buttonId = `#${this.props.buttonId}`;
-    $(buttonId).tooltip('show');
-    setTimeout(() => {
-      $(buttonId).tooltip('hide');
-    }, 1000);
-  }
-
-  render() {
-    const containerStyle = {
-      lineHeight: 0,
-    };
-    const style = Object.assign({
-      padding: '0 2px',
-      verticalAlign: 'text-top',
-    }, this.props.buttonStyle);
-
-    const text = this.xss.process(this.props.text);
-
-    return (
-      <span className="btn-copy-container" style={containerStyle}>
-        <ClipboardButton
-          className={this.props.buttonClassName}
-          button-id={this.props.buttonId}
-          button-data-toggle="tooltip"
-          button-data-container="body"
-          button-title="copied!"
-          button-data-placement="bottom"
-          button-data-trigger="manual"
-          button-style={style}
-          data-clipboard-text={text}
-          onSuccess={this.showToolTip}
-        >
-
-          <i className={this.props.iconClassName} />
-        </ClipboardButton>
-      </span>
-    );
-  }
-
-}
-
-CopyButton.propTypes = {
-  text: PropTypes.string.isRequired,
-  buttonId: PropTypes.string.isRequired,
-  buttonClassName: PropTypes.string.isRequired,
-  buttonStyle: PropTypes.object,
-  iconClassName: PropTypes.string.isRequired,
-};
-CopyButton.defaultProps = {
-  buttonStyle: {},
-};

+ 118 - 0
src/client/js/components/Page/CopyDropdown.jsx

@@ -0,0 +1,118 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import Dropdown from 'react-bootstrap/es/Dropdown';
+import MenuItem from 'react-bootstrap/es/MenuItem';
+
+import { CopyToClipboard } from 'react-copy-to-clipboard';
+
+export default class CopyDropdown extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    // retrieve xss library from window
+    this.xss = window.xss;
+
+    this.generatePageUrl = this.generatePageUrl.bind(this);
+  }
+
+  showToolTip() {
+    const buttonId = '#copyPagePathDropdown';
+    $(buttonId).tooltip('show');
+    setTimeout(() => {
+      $(buttonId).tooltip('hide');
+    }, 1000);
+  }
+
+  generatePageUrl() {
+    return (this.props.pageId == null)
+      ? decodeURIComponent(window.location.pathname + window.location.search)
+      : `${window.location.origin}/${this.props.pageId}`;
+  }
+
+  generateMarkdownLink() {
+    return;
+  }
+
+  render() {
+    const { t } = this.props;
+
+    const safePagePath = this.xss.process(this.props.pagePath);
+    const url = this.generatePageUrl();
+
+    return (
+      <Dropdown id="copyPagePathDropdown">
+
+        <Dropdown.Toggle
+          className="btn-copy"
+          style={this.props.buttonStyle}
+          data-toggle="tooltip"
+          data-placement="bottom"
+          data-trigger="manual"
+          title="copied!"
+        >
+          <i className="ti-clipboard"></i>
+        </Dropdown.Toggle>
+
+        <Dropdown.Menu>
+          <h5 className="ml-3 my-0 text-muted">{ t('copy_to_clipboard.Copy to clipboard') }</h5>
+          <MenuItem divider></MenuItem>
+
+          {/* Page path */}
+          <CopyToClipboard text={this.props.pagePath} onCopy={this.showToolTip}>
+            <MenuItem>
+              <div className="d-inline-flex flex-column">
+                <h6 className="mt-1 mb-2"><strong>{ t('copy_to_clipboard.Page path') }</strong></h6>
+                <span className="small">{safePagePath}</span>
+              </div>
+            </MenuItem>
+          </CopyToClipboard>
+          {/* Parmanent Link */}
+          { this.props.pageId && (
+            <CopyToClipboard text={url} onCopy={this.showToolTip}>
+              <MenuItem>
+                <div className="d-inline-flex flex-column">
+                  <h6 className="mt-1 mb-2"><strong>{ t('copy_to_clipboard.Parmanent link') }</strong></h6>
+                  <span className="small">{url}</span>
+                </div>
+              </MenuItem>
+            </CopyToClipboard>
+          )}
+          {/* Page path + Parmanent Link */}
+          { this.props.pageId && (
+            <CopyToClipboard text={`${this.props.pagePath}\n${url}`} onCopy={this.showToolTip}>
+              <MenuItem>
+                <div className="d-inline-flex flex-column">
+                  <h6 className="mt-1 mb-2"><strong>{ t('copy_to_clipboard.Page path and parmanent link') }</strong></h6>
+                  <span className="small mb-1">{safePagePath}</span><br></br>
+                  <span className="small">{url}</span>
+                </div>
+              </MenuItem>
+            </CopyToClipboard>
+          )}
+          {/* Markdown Link */}
+          { this.props.pageId && (
+            <CopyToClipboard text={`[${this.props.pagePath}](${url})`} onCopy={this.showToolTip}>
+              <MenuItem>
+                <div className="d-inline-flex flex-column">
+                  <h6 className="mt-1 mb-2"><strong>{ t('copy_to_clipboard.Markdown link') }</strong></h6>
+                  <span className="small">{`[${safePagePath}](${url})`}</span>
+                </div>
+              </MenuItem>
+            </CopyToClipboard>
+          )}
+        </Dropdown.Menu>
+
+      </Dropdown>
+    );
+  }
+
+}
+
+CopyDropdown.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  pagePath: PropTypes.string.isRequired,
+  pageId: PropTypes.string,
+  buttonStyle: PropTypes.object,
+};

+ 17 - 13
src/client/js/components/Page/RevisionPath.jsx

@@ -1,9 +1,11 @@
 import React from 'react';
 import React from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
 
 
-import CopyButton from '../CopyButton';
+import { withTranslation } from 'react-i18next';
 
 
-export default class RevisionPath extends React.Component {
+import CopyDropdown from './CopyDropdown';
+
+class RevisionPath extends React.Component {
 
 
   constructor(props) {
   constructor(props) {
     super(props);
     super(props);
@@ -49,9 +51,10 @@ export default class RevisionPath extends React.Component {
   }
   }
 
 
   showToolTip() {
   showToolTip() {
-    $('#btnCopy').tooltip('show');
+    const buttonId = '#copyPagePathDropdown';
+    $(buttonId).tooltip('show');
     setTimeout(() => {
     setTimeout(() => {
-      $('#btnCopy').tooltip('hide');
+      $(buttonId).tooltip('hide');
     }, 1000);
     }, 1000);
   }
   }
 
 
@@ -78,7 +81,7 @@ export default class RevisionPath extends React.Component {
       marginLeft: '0.2em',
       marginLeft: '0.2em',
       marginRight: '0.2em',
       marginRight: '0.2em',
     };
     };
-    const editButtonStyle = {
+    const buttonStyle = {
       marginLeft: '0.5em',
       marginLeft: '0.5em',
       padding: '0 2px',
       padding: '0 2px',
     };
     };
@@ -110,13 +113,10 @@ export default class RevisionPath extends React.Component {
           <a href="/">/</a>
           <a href="/">/</a>
         </span>
         </span>
         {afterElements}
         {afterElements}
-        <CopyButton
-          buttonId="btnCopyRevisionPath"
-          text={this.props.pagePath}
-          buttonClassName="btn btn-default btn-copy"
-          iconClassName="ti-clipboard"
-        />
-        <a href="#edit" className="btn btn-default btn-edit" style={editButtonStyle}>
+
+        <CopyDropdown t={this.props.t} pagePath={this.props.pagePath} pageId={this.props.pageId} buttonStyle={buttonStyle}></CopyDropdown>
+
+        <a href="#edit" className="btn btn-default btn-edit" style={buttonStyle}>
           <i className="icon-note" />
           <i className="icon-note" />
         </a>
         </a>
       </span>
       </span>
@@ -126,6 +126,10 @@ export default class RevisionPath extends React.Component {
 }
 }
 
 
 RevisionPath.propTypes = {
 RevisionPath.propTypes = {
-  pagePath: PropTypes.string.isRequired,
+  t: PropTypes.func.isRequired, // i18next
   crowi: PropTypes.object.isRequired,
   crowi: PropTypes.object.isRequired,
+  pagePath: PropTypes.string.isRequired,
+  pageId: PropTypes.string,
 };
 };
+
+export default withTranslation()(RevisionPath);

+ 0 - 46
src/client/js/components/Page/RevisionUrl.js

@@ -1,46 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import CopyButton from '../CopyButton';
-
-export default class RevisionUrl extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    // retrieve xss library from window
-    this.xss = window.xss;
-  }
-
-  render() {
-    const buttonStyle = {
-      fontSize: '1em',
-    };
-
-    const pagePath = this.xss.process(this.props.pagePath);
-
-    const url = (this.props.pageId == null)
-      ? decodeURIComponent(window.location.href)
-      : `${window.location.origin}/${this.props.pageId}`;
-    const copiedText = `${pagePath}\n${url}`;
-
-    return (
-      <span>
-        {url}
-        <CopyButton
-          buttonId="btnCopyRevisionUrl"
-          text={copiedText}
-          buttonClassName="btn btn-default btn-copy-link"
-          buttonStyle={buttonStyle}
-          iconClassName="ti-clipboard"
-        />
-      </span>
-    );
-  }
-
-}
-
-RevisionUrl.propTypes = {
-  pageId: PropTypes.string,
-  pagePath: PropTypes.string.isRequired,
-};

+ 1 - 4
src/client/styles/scss/_on-edit.scss

@@ -92,6 +92,7 @@ body.on-edit {
     left: $left-margin;
     left: $left-margin;
     z-index: 1;
     z-index: 1;
     width: calc(100% - #{$left-margin} - #{$right-margin});
     width: calc(100% - #{$left-margin} - #{$right-margin});
+    padding-top: 3px;
     pointer-events: none; // disable pointer-events because it becomes an obstacle
     pointer-events: none; // disable pointer-events because it becomes an obstacle
 
 
     background: none;
     background: none;
@@ -102,10 +103,6 @@ body.on-edit {
       pointer-events: initial; // enable pointer-events
       pointer-events: initial; // enable pointer-events
     }
     }
 
 
-    .header-wrap {
-      overflow-x: hidden;
-    }
-
     h1#revision-path {
     h1#revision-path {
       @include variable-font-size(20px);
       @include variable-font-size(20px);
       line-height: 1em;
       line-height: 1em;

+ 21 - 34
yarn.lock

@@ -2214,14 +2214,6 @@ cli@~1.0.1:
     exit "0.1.2"
     exit "0.1.2"
     glob "^7.1.1"
     glob "^7.1.1"
 
 
-clipboard@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.1.tgz#a12481e1c13d8a50f5f036b0560fe5d16d74e46a"
-  dependencies:
-    good-listener "^1.2.2"
-    select "^1.1.2"
-    tiny-emitter "^2.0.0"
-
 cliui@^2.1.0:
 cliui@^2.1.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
@@ -2554,6 +2546,13 @@ copy-descriptor@^0.1.0:
   version "0.1.1"
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
 
 
+copy-to-clipboard@^3:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz#d2724a3ccbfed89706fac8a894872c979ac74467"
+  integrity sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==
+  dependencies:
+    toggle-selection "^1.0.6"
+
 core-js@^1.0.0:
 core-js@^1.0.0:
   version "1.2.7"
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@@ -3018,10 +3017,6 @@ delayed-stream@~1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
 
 
-delegate@^3.1.2:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
-
 delegates@^1.0.0:
 delegates@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
@@ -4632,12 +4627,6 @@ gonzales-pe@^4.0.3:
   dependencies:
   dependencies:
     minimist "1.1.x"
     minimist "1.1.x"
 
 
-good-listener@^1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
-  dependencies:
-    delegate "^3.1.2"
-
 google-auth-library@^3.0.0:
 google-auth-library@^3.0.0:
   version "3.1.0"
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-3.1.0.tgz#6378ea3e56067312209eee58223e5a00adaec639"
   resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-3.1.0.tgz#6378ea3e56067312209eee58223e5a00adaec639"
@@ -8357,7 +8346,7 @@ prop-types@^15.0.0, prop-types@^15.6.2:
     loose-envify "^1.3.1"
     loose-envify "^1.3.1"
     object-assign "^4.1.1"
     object-assign "^4.1.1"
 
 
-prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.8:
+prop-types@^15.5.10, prop-types@^15.5.8:
   version "15.6.0"
   version "15.6.0"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
   dependencies:
   dependencies:
@@ -8593,18 +8582,19 @@ react-bootstrap@^0.32.1:
     uncontrollable "^4.1.0"
     uncontrollable "^4.1.0"
     warning "^3.0.0"
     warning "^3.0.0"
 
 
-react-clipboard.js@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/react-clipboard.js/-/react-clipboard.js-2.0.0.tgz#8ab3c49093e73ea146eb3bbc054889b7a60bf2b4"
-  dependencies:
-    clipboard "^2.0.0"
-    prop-types "^15.5.0"
-
 react-codemirror2@^6.0.0:
 react-codemirror2@^6.0.0:
   version "6.0.0"
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
   resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
   integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
   integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
 
 
+react-copy-to-clipboard@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz#8eae107bb400be73132ed3b6a7b4fb156090208e"
+  integrity sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA==
+  dependencies:
+    copy-to-clipboard "^3"
+    prop-types "^15.5.8"
+
 react-dom@^16.8.3:
 react-dom@^16.8.3:
   version "16.8.3"
   version "16.8.3"
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.3.tgz#ae236029e66210783ac81999d3015dfc475b9c32"
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.3.tgz#ae236029e66210783ac81999d3015dfc475b9c32"
@@ -9388,10 +9378,6 @@ scss-tokenizer@^0.2.3:
     js-base64 "^2.1.8"
     js-base64 "^2.1.8"
     source-map "^0.4.2"
     source-map "^0.4.2"
 
 
-select@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
-
 semver-diff@^2.0.0:
 semver-diff@^2.0.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
   resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
@@ -10479,10 +10465,6 @@ timsort@^0.3.0:
   version "0.3.0"
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
   resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
 
 
-tiny-emitter@^2.0.0:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
-
 tmp@0.0.x, tmp@^0.0.33:
 tmp@0.0.x, tmp@^0.0.33:
   version "0.0.33"
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -10533,6 +10515,11 @@ toastr@^2.1.2:
   dependencies:
   dependencies:
     jquery ">=1.12.0"
     jquery ">=1.12.0"
 
 
+toggle-selection@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
+  integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
+
 tough-cookie@~2.3.3:
 tough-cookie@~2.3.3:
   version "2.3.3"
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"