Przeglądaj źródła

migrate Dropdowns

Yuki Takei 6 lat temu
rodzic
commit
b8e7aa2815

+ 19 - 16
src/client/js/components/HeaderSearchBox.jsx

@@ -2,14 +2,10 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import { withTranslation } from 'react-i18next';
 
 
-// TODO: GW-333
-// import FormGroup from 'react-bootstrap/es/FormGroup';
-// import DropdownButton from 'react-bootstrap/es/DropdownButton';
-// import MenuItem from 'react-bootstrap/es/MenuItem';
-// import InputGroup from 'react-bootstrap/es/InputGroup';
-
 import {
 import {
   Button,
   Button,
+  InputGroup, InputGroupButtonDropdown, InputGroupAddon,
+  DropdownToggle, DropdownMenu, DropdownItem,
 } from 'reactstrap';
 } from 'reactstrap';
 
 
 import SearchForm from './SearchForm';
 import SearchForm from './SearchForm';
@@ -21,10 +17,12 @@ class HeaderSearchBox extends React.Component {
     super(props);
     super(props);
 
 
     this.state = {
     this.state = {
+      dropdownOpen: false,
       text: '',
       text: '',
       isScopeChildren: false,
       isScopeChildren: false,
     };
     };
 
 
+    this.toggle = this.toggle.bind(this);
     this.onInputChange = this.onInputChange.bind(this);
     this.onInputChange = this.onInputChange.bind(this);
     this.onClickAllPages = this.onClickAllPages.bind(this);
     this.onClickAllPages = this.onClickAllPages.bind(this);
     this.onClickChildren = this.onClickChildren.bind(this);
     this.onClickChildren = this.onClickChildren.bind(this);
@@ -37,6 +35,10 @@ class HeaderSearchBox extends React.Component {
   componentWillUnmount() {
   componentWillUnmount() {
   }
   }
 
 
+  toggle() {
+    this.setState({ dropdownOpen: !this.state.dropdownOpen });
+  }
+
   onInputChange(text) {
   onInputChange(text) {
     this.setState({ text });
     this.setState({ text });
   }
   }
@@ -70,14 +72,15 @@ class HeaderSearchBox extends React.Component {
       : 'All pages';
       : 'All pages';
 
 
     return (
     return (
-      <FormGroup>
+      <>
         <InputGroup className="flex-nowrap">
         <InputGroup className="flex-nowrap">
-          <InputGroup.Button className="btn-group-dropdown-scope" data-toggle="dropdown">
-            <DropdownButton id="dbScope" className="pl-3 py-0" title={scopeLabel}>
-              <MenuItem onClick={this.onClickAllPages}>All pages</MenuItem>
-              <MenuItem onClick={this.onClickChildren}>{ t('header_search_box.item_label.This tree') }</MenuItem>
-            </DropdownButton>
-          </InputGroup.Button>
+          <InputGroupButtonDropdown addonType="append" isOpen={this.state.dropdownOpen} toggle={this.toggle} className="btn-group-dropdown-scope">
+            <DropdownToggle caret>{scopeLabel}</DropdownToggle>
+            <DropdownMenu className="pl-3 py-0" title={scopeLabel}>
+              <DropdownItem onClick={this.onClickAllPages}>All pages</DropdownItem>
+              <DropdownItem onClick={this.onClickChildren}>{ t('header_search_box.item_label.This tree') }</DropdownItem>
+            </DropdownMenu>
+          </InputGroupButtonDropdown>
           <SearchForm
           <SearchForm
             t={this.props.t}
             t={this.props.t}
             crowi={this.props.crowi}
             crowi={this.props.crowi}
@@ -85,13 +88,13 @@ class HeaderSearchBox extends React.Component {
             onSubmit={this.search}
             onSubmit={this.search}
             placeholder="Search ..."
             placeholder="Search ..."
           />
           />
-          <InputGroup.Button className="btn-group-submit-search">
+          <InputGroupAddon addonType="append" className="btn-group-submit-search">
             <Button color="link" onClick={this.search}>
             <Button color="link" onClick={this.search}>
               <i className="icon-magnifier"></i>
               <i className="icon-magnifier"></i>
             </Button>
             </Button>
-          </InputGroup.Button>
+          </InputGroupAddon>
         </InputGroup>
         </InputGroup>
-      </FormGroup>
+      </>
     );
     );
   }
   }
 
 

+ 80 - 66
src/client/js/components/Page/CopyDropdown.jsx

@@ -1,9 +1,10 @@
 import React from 'react';
 import React from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
 
 
-// TODO: GW-333
-// import Dropdown from 'react-bootstrap/es/Dropdown';
-// import MenuItem from 'react-bootstrap/es/MenuItem';
+import {
+  Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
+  Tooltip,
+} from 'reactstrap';
 
 
 import { CopyToClipboard } from 'react-copy-to-clipboard';
 import { CopyToClipboard } from 'react-copy-to-clipboard';
 
 
@@ -15,14 +16,24 @@ export default class CopyDropdown extends React.Component {
     // retrieve xss library from window
     // retrieve xss library from window
     this.xss = window.xss;
     this.xss = window.xss;
 
 
+    this.state = {
+      dropdownOpen: false,
+      tooltipOpen: false,
+    };
+
+    this.toggle = this.toggle.bind(this);
+    this.showToolTip = this.showToolTip.bind(this);
     this.generatePageUrl = this.generatePageUrl.bind(this);
     this.generatePageUrl = this.generatePageUrl.bind(this);
   }
   }
 
 
+  toggle() {
+    this.setState({ dropdownOpen: !this.state.dropdownOpen });
+  }
+
   showToolTip() {
   showToolTip() {
-    const buttonId = '#copyPagePathDropdown';
-    $(buttonId).tooltip('show');
+    this.setState({ tooltipOpen: true });
     setTimeout(() => {
     setTimeout(() => {
-      $(buttonId).tooltip('hide');
+      this.setState({ tooltipOpen: false });
     }, 1000);
     }, 1000);
   }
   }
 
 
@@ -43,69 +54,72 @@ export default class CopyDropdown extends React.Component {
     const url = this.generatePageUrl();
     const url = this.generatePageUrl();
 
 
     return (
     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>
+      <>
+        <Dropdown id="copyPagePathDropdown" isOpen={this.state.dropdownOpen} toggle={this.toggle}>
+
+          <DropdownToggle
+            caret
+            className="btn-copy"
+            style={this.props.buttonStyle}
+          >
+            <i className="ti-clipboard"></i>
+          </DropdownToggle>
+
+          <DropdownMenu>
+            <h5 className="ml-3 my-0 text-muted">{ t('copy_to_clipboard.Copy to clipboard') }</h5>
+            <DropdownItem divider></DropdownItem>
+
+            {/* Page path */}
+            <CopyToClipboard text={this.props.pagePath} onCopy={this.showToolTip}>
+              <DropdownItem>
                 <div className="d-inline-flex flex-column">
                 <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>
+                  <h6 className="mt-1 mb-2"><strong>{ t('copy_to_clipboard.Page path') }</strong></h6>
+                  <span className="small">{safePagePath}</span>
                 </div>
                 </div>
-              </MenuItem>
+              </DropdownItem>
             </CopyToClipboard>
             </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>
+            {/* Parmanent Link */}
+            { this.props.pageId && (
+              <CopyToClipboard text={url} onCopy={this.showToolTip}>
+                <DropdownItem>
+                  <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>
+                </DropdownItem>
+              </CopyToClipboard>
+            )}
+            {/* Page path + Parmanent Link */}
+            { this.props.pageId && (
+              <CopyToClipboard text={`${this.props.pagePath}\n${url}`} onCopy={this.showToolTip}>
+                <DropdownItem>
+                  <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>
+                </DropdownItem>
+              </CopyToClipboard>
+            )}
+            {/* Markdown Link */}
+            { this.props.pageId && (
+              <CopyToClipboard text={`[${this.props.pagePath}](${url})`} onCopy={this.showToolTip}>
+                <DropdownItem>
+                  <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>
+                </DropdownItem>
+              </CopyToClipboard>
+            )}
+          </DropdownMenu>
+
+        </Dropdown>
+
+        <Tooltip placement="bottom" isOpen={this.state.tooltipOpen} target="copyPagePathDropdown" fade={false}>
+          copied!
+        </Tooltip>
+      </>
     );
     );
   }
   }
 
 

+ 36 - 53
src/client/js/components/PageEditor/OptionsSelector.jsx

@@ -3,12 +3,10 @@ import PropTypes from 'prop-types';
 
 
 import { withTranslation } from 'react-i18next';
 import { withTranslation } from 'react-i18next';
 
 
-// TODO: GW-333
-// import FormGroup from 'react-bootstrap/es/FormGroup';
-// import FormControl from 'react-bootstrap/es/FormControl';
-// import ControlLabel from 'react-bootstrap/es/ControlLabel';
-// import Dropdown from 'react-bootstrap/es/Dropdown';
-// import MenuItem from 'react-bootstrap/es/MenuItem';
+import {
+  FormGroup, Label, Input,
+  Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
+} from 'reactstrap';
 
 
 import { createSubscribedElement } from '../UnstatedUtils';
 import { createSubscribedElement } from '../UnstatedUtils';
 import EditorContainer from '../../services/EditorContainer';
 import EditorContainer from '../../services/EditorContainer';
@@ -104,9 +102,6 @@ class OptionsSelector extends React.Component {
   onClickRenderMathJaxInRealtime(event) {
   onClickRenderMathJaxInRealtime(event) {
     const { editorContainer } = this.props;
     const { editorContainer } = this.props;
 
 
-    // keep dropdown opened
-    this._cddForceOpen = true;
-
     const newValue = !editorContainer.state.previewOptions.renderMathJaxInRealtime;
     const newValue = !editorContainer.state.previewOptions.renderMathJaxInRealtime;
     const newOpts = Object.assign(editorContainer.state.previewOptions, { renderMathJaxInRealtime: newValue });
     const newOpts = Object.assign(editorContainer.state.previewOptions, { renderMathJaxInRealtime: newValue });
     editorContainer.setState({ previewOptions: newOpts });
     editorContainer.setState({ previewOptions: newOpts });
@@ -115,17 +110,8 @@ class OptionsSelector extends React.Component {
     editorContainer.saveOptsToLocalStorage();
     editorContainer.saveOptsToLocalStorage();
   }
   }
 
 
-  /*
-   * see: https://github.com/react-bootstrap/react-bootstrap/issues/1490#issuecomment-207445759
-   */
   onToggleConfigurationDropdown(newValue) {
   onToggleConfigurationDropdown(newValue) {
-    if (this._cddForceOpen) {
-      this.setState({ isCddMenuOpened: true });
-      this._cddForceOpen = false;
-    }
-    else {
-      this.setState({ isCddMenuOpened: newValue });
-    }
+    this.setState({ isCddMenuOpened: !this.state.isCddMenuOpened });
   }
   }
 
 
   renderThemeSelector() {
   renderThemeSelector() {
@@ -133,24 +119,23 @@ class OptionsSelector extends React.Component {
       return <option key={theme} value={theme}>{theme}</option>;
       return <option key={theme} value={theme}>{theme}</option>;
     });
     });
 
 
-    const bsClassName = 'form-control-dummy'; // set form-control* to shrink width
-
     return (
     return (
-      <FormGroup controlId="formControlsSelect" className="my-0">
-        <ControlLabel>Theme:</ControlLabel>
-        <FormControl
-          componentClass="select"
+      <FormGroup className="my-0">
+        <Label>Theme:</Label>
+        <Input
+          type="select"
+          bsSize="sm"
           placeholder="select"
           placeholder="select"
-          bsClass={bsClassName}
-          className="btn-group-sm selectpicker"
+          className="selectpicker"
+          cssModule={{ width: 'unset' }}
           onChange={this.onChangeTheme}
           onChange={this.onChangeTheme}
           // eslint-disable-next-line no-return-assign
           // eslint-disable-next-line no-return-assign
-          inputRef={(el) => { return this.themeSelectorInputEl = el }}
+          innerRef={(el) => { return this.themeSelectorInputEl = el }}
         >
         >
 
 
           {optionElems}
           {optionElems}
 
 
-        </FormControl>
+        </Input>
       </FormGroup>
       </FormGroup>
     );
     );
   }
   }
@@ -168,49 +153,47 @@ class OptionsSelector extends React.Component {
       );
       );
     }
     }
 
 
-    const bsClassName = 'form-control-dummy'; // set form-control* to shrink width
-
     return (
     return (
-      <FormGroup controlId="formControlsSelect" className="my-0">
-        <ControlLabel>Keymap:</ControlLabel>
-        <FormControl
-          componentClass="select"
+      <FormGroup className="my-0">
+        <Label>Keymap:</Label>
+        <Input
+          type="select"
+          bsSize="sm"
           placeholder="select"
           placeholder="select"
-          bsClass={bsClassName}
-          className="btn-group-sm selectpicker"
+          className="selectpicker"
           onChange={this.onChangeKeymapMode}
           onChange={this.onChangeKeymapMode}
           // eslint-disable-next-line no-return-assign
           // eslint-disable-next-line no-return-assign
-          inputRef={(el) => { return this.keymapModeSelectorInputEl = el }}
+          innerRef={(el) => { return this.keymapModeSelectorInputEl = el }}
         >
         >
 
 
           {optionElems}
           {optionElems}
 
 
-        </FormControl>
+        </Input>
       </FormGroup>
       </FormGroup>
     );
     );
   }
   }
 
 
   renderConfigurationDropdown() {
   renderConfigurationDropdown() {
     return (
     return (
-      <FormGroup controlId="formControlsSelect" className="my-0">
+      <FormGroup className="my-0">
 
 
         <Dropdown
         <Dropdown
-          dropup
-          id="configurationDropdown"
+          direction="up"
+          bsSize="sm"
           className="configuration-dropdown"
           className="configuration-dropdown"
-          open={this.state.isCddMenuOpened}
-          onToggle={this.onToggleConfigurationDropdown}
+          isOpen={this.state.isCddMenuOpened}
+          toggle={this.onToggleConfigurationDropdown}
         >
         >
 
 
-          <Dropdown.Toggle bsSize="sm">
+          <DropdownToggle caret>
             <i className="icon-settings"></i>
             <i className="icon-settings"></i>
-          </Dropdown.Toggle>
+          </DropdownToggle>
 
 
-          <Dropdown.Menu>
+          <DropdownMenu>
             {this.renderActiveLineMenuItem()}
             {this.renderActiveLineMenuItem()}
             {this.renderRealtimeMathJaxMenuItem()}
             {this.renderRealtimeMathJaxMenuItem()}
-            {/* <MenuItem divider /> */}
-          </Dropdown.Menu>
+            {/* <DropdownItem divider /> */}
+          </DropdownMenu>
 
 
         </Dropdown>
         </Dropdown>
 
 
@@ -229,11 +212,11 @@ class OptionsSelector extends React.Component {
     const iconClassName = iconClasses.join(' ');
     const iconClassName = iconClasses.join(' ');
 
 
     return (
     return (
-      <MenuItem onClick={this.onClickStyleActiveLine}>
+      <DropdownItem toggle={false} onClick={this.onClickStyleActiveLine}>
         <span className="icon-container"></span>
         <span className="icon-container"></span>
         <span className="menuitem-label">{ t('page_edit.Show active line') }</span>
         <span className="menuitem-label">{ t('page_edit.Show active line') }</span>
         <span className="icon-container"><i className={iconClassName}></i></span>
         <span className="icon-container"><i className={iconClassName}></i></span>
-      </MenuItem>
+      </DropdownItem>
     );
     );
   }
   }
 
 
@@ -254,11 +237,11 @@ class OptionsSelector extends React.Component {
     const iconClassName = iconClasses.join(' ');
     const iconClassName = iconClasses.join(' ');
 
 
     return (
     return (
-      <MenuItem onClick={this.onClickRenderMathJaxInRealtime}>
+      <DropdownItem toggle={false} onClick={this.onClickRenderMathJaxInRealtime}>
         <span className="icon-container"><img src="/images/icons/fx.svg" width="14px" alt="fx"></img></span>
         <span className="icon-container"><img src="/images/icons/fx.svg" width="14px" alt="fx"></img></span>
         <span className="menuitem-label">MathJax Rendering</span>
         <span className="menuitem-label">MathJax Rendering</span>
         <i className={iconClassName}></i>
         <i className={iconClassName}></i>
-      </MenuItem>
+      </DropdownItem>
     );
     );
   }
   }