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

Merge pull request #1434 from weseek/feat/view-user-suggestions

Feat/view user suggestions
Yuki Takei 6 лет назад
Родитель
Сommit
fd6acaaf4e

+ 94 - 17
src/client/js/components/Admin/UserGroupDetail/UserGroupUserFormByInput.jsx

@@ -2,6 +2,8 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
+import { AsyncTypeahead } from 'react-bootstrap-typeahead';
+import { debounce } from 'throttle-debounce';
 import { createSubscribedElement } from '../../UnstatedUtils';
 import AppContainer from '../../../services/AppContainer';
 import UserGroupDetailContainer from '../../../services/UserGroupDetailContainer';
@@ -13,51 +15,126 @@ class UserGroupUserFormByInput extends React.Component {
     super(props);
 
     this.state = {
-      username: '',
+      input: '',
+      // TDOO GW-665 fetch users
+      applicableUsers: ['hoge', 'huga'],
+      isLoading: false,
+      searchError: null,
     };
 
     this.xss = window.xss;
 
-    this.changeUsername = this.changeUsername.bind(this);
+    this.onInputChange = this.onInputChange.bind(this);
     this.addUserBySubmit = this.addUserBySubmit.bind(this);
     this.validateForm = this.validateForm.bind(this);
+    this.handleChange = this.handleChange.bind(this);
+    this.handleSearch = this.handleSearch.bind(this);
+    this.onKeyDown = this.onKeyDown.bind(this);
+    this.renderMenuItemChildren = this.renderMenuItemChildren.bind(this);
+
+    this.searchUserDebounce = debounce(1000, this.searchUser);
   }
 
-  changeUsername(e) {
-    this.setState({ username: e.target.value });
+  /**
+   * input user name to add to the group
+   * @param {string} input
+   */
+  onInputChange(input) {
+    this.setState({ input });
+    // this.props.onInputChange(text);
+    if (input === '') {
+      this.setState({ applicableUsers: [] });
+    }
   }
 
+
   async addUserBySubmit(e) {
     e.preventDefault();
-    const { username } = this.state;
+    const { input } = this.state;
 
     try {
-      await this.props.userGroupDetailContainer.addUserByUsername(username);
-      toastSuccess(`Added "${this.xss.process(username)}" to "${this.xss.process(this.props.userGroupDetailContainer.state.userGroup.name)}"`);
-      this.setState({ username: '' });
+      await this.props.userGroupDetailContainer.addUserByUsername(input);
+      toastSuccess(`Added "${this.xss.process(input)}" to "${this.xss.process(this.props.userGroupDetailContainer.state.userGroup.name)}"`);
+      this.setState({ input: '' });
     }
     catch (err) {
-      toastError(new Error(`Unable to add "${this.xss.process(username)}" to "${this.xss.process(this.props.userGroupDetailContainer.state.userGroup.name)}"`));
+      toastError(new Error(`Unable to add "${this.xss.process(input)}" to "${this.xss.process(this.props.userGroupDetailContainer.state.userGroup.name)}"`));
     }
   }
 
   validateForm() {
-    return this.state.username !== '';
+    return this.state.input !== '';
+  }
+
+  searchUser() {
+    // TODO GW-665 fetch users
+    this.setState({ isLoading: false });
+  }
+
+  /**
+   * Reflect when forecast is clicked
+   * @param {string} input
+   */
+  handleChange(input) {
+    this.setState({ input });
+  }
+
+  handleSearch(keyword) {
+
+    if (keyword === '') {
+      return;
+    }
+
+    this.setState({ isLoading: true });
+    this.searchUserDebounce();
+  }
+
+  onKeyDown(event) {
+    // 13 is Enter key
+    if (event.keyCode === 13) {
+      this.addUserBySubmit();
+    }
+  }
+
+  getEmptyLabel() {
+    return (this.state.searchError !== null) && 'Error on searching.';
+  }
+
+  renderMenuItemChildren(option, props, index) {
+    const user = option;
+    return (
+      <span>
+        {user}
+      </span>
+    );
   }
 
   render() {
     const { t } = this.props;
 
+    const inputProps = { autoComplete: 'off' };
+
     return (
       <form className="form-inline" onSubmit={this.addUserBySubmit}>
         <div className="form-group">
-          <input
-            type="text"
-            name="username"
-            className="form-control input-sm"
-            placeholder={t('username')}
-            value={this.state.username}
-            onChange={this.changeUsername}
+          <AsyncTypeahead
+            {...this.props}
+            id="name-typeahead-asynctypeahead"
+            ref={(c) => { this.typeahead = c }}
+            inputProps={inputProps}
+            isLoading={this.state.isLoading}
+            labelKey="name"
+            minLength={0}
+            options={this.state.applicableUsers} // Search result (Some page names)
+            emptyLabel={this.getEmptyLabel()}
+            searchText={(this.state.isLoading ? 'Searching...' : this.getEmptyLabel())}
+            align="left"
+            onChange={this.handleChange}
+            onSearch={this.handleSearch}
+            onInputChange={this.onInputChange}
+            onKeyDown={this.onKeyDown}
+            renderMenuItemChildren={this.renderMenuItemChildren}
+            caseSensitive={false}
           />
         </div>
         <button type="submit" className="btn btn-sm btn-success" disabled={!this.validateForm()}>{ t('add') }</button>