]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8992 Fix members add form, show only non members
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Wed, 26 Apr 2017 13:41:47 +0000 (15:41 +0200)
committerGrégoire Aubert <gregaubert@users.noreply.github.com>
Mon, 1 May 2017 14:26:31 +0000 (16:26 +0200)
server/sonar-web/src/main/js/apps/organizations/components/OrganizationMembers.js
server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/MembersListItem-test.js.snap
server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationMembers-test.js.snap
server/sonar-web/src/main/js/apps/organizations/components/forms/AddMemberForm.js
server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js
server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js
server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchOption-test.js.snap
server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchValue-test.js.snap

index 49eac0e3fa7473fa1debccdac9d158768ab5f8fb..c4e3f6bcd25ab8bb97147265772e05229bfdd741 100644 (file)
@@ -84,7 +84,11 @@ export default class OrganizationMembers extends React.PureComponent {
           {organization.canAdmin &&
             <div className="page-actions">
               <div className="button-group">
-                <AddMemberForm memberLogins={this.props.memberLogins} addMember={this.addMember} />
+                <AddMemberForm
+                  addMember={this.addMember}
+                  organization={organization}
+                  memberLogins={this.props.memberLogins}
+                />
               </div>
             </div>}
         </MembersPageHeader>
index 153c98f4d352063c9400289ace6821d4e98c3fac..7d5d1fd90e699c017cfa136d47795e5bef0cfde0 100644 (file)
@@ -1,40 +1,53 @@
-exports[`test should groups at 0 if the groupCount field is not defined (just added user) 1`] = `
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should groups at 0 if the groupCount field is not defined (just added user) 1`] = `
 <tr>
   <td
-    className="thin nowrap">
+    className="thin nowrap"
+  >
     <Connect(Avatar)
       hash="7daf6c79d4802916d83f6266e24850af"
-      size={36} />
+      size={36}
+    />
   </td>
   <td
-    className="nowrap text-middle">
+    className="nowrap text-middle"
+  >
     <strong>
       John Doe
     </strong>
     <span
-      className="note little-spacer-left">
+      className="note little-spacer-left"
+    >
       john
     </span>
   </td>
   <td
-    className="text-right text-middle">
+    className="text-right text-middle"
+  >
     organization.members.x_groups.0
   </td>
   <td
-    className="nowrap text-middle text-right">
+    className="nowrap text-middle text-right"
+  >
     <div
-      className="dropdown">
+      className="dropdown"
+    >
       <button
         className="dropdown-toggle little-spacer-right"
-        data-toggle="dropdown">
+        data-toggle="dropdown"
+      >
         <i
-          className="icon-settings" />
+          className="icon-settings"
+        />
          
         <i
-          className="icon-dropdown" />
+          className="icon-dropdown"
+        />
       </button>
       <ul
-        className="dropdown-menu dropdown-menu-right">
+        className="dropdown-menu dropdown-menu-right"
+      >
         <li>
           <ManageMemberGroupsForm
             member={
@@ -50,11 +63,13 @@ exports[`test should groups at 0 if the groupCount field is not defined (just ad
                 "key": "foo",
                 "name": "Foo",
               }
-            } />
+            }
+          />
         </li>
         <li
           className="divider"
-          role="separator" />
+          role="separator"
+        />
         <li>
           <RemoveMemberForm
             member={
@@ -70,7 +85,8 @@ exports[`test should groups at 0 if the groupCount field is not defined (just ad
                 "key": "foo",
                 "name": "Foo",
               }
-            } />
+            }
+          />
         </li>
       </ul>
     </div>
@@ -78,64 +94,79 @@ exports[`test should groups at 0 if the groupCount field is not defined (just ad
 </tr>
 `;
 
-exports[`test should not render actions and groups for non admin 1`] = `
+exports[`should not render actions and groups for non admin 1`] = `
 <tr>
   <td
-    className="thin nowrap">
+    className="thin nowrap"
+  >
     <Connect(Avatar)
       hash=""
-      size={36} />
+      size={36}
+    />
   </td>
   <td
-    className="nowrap text-middle">
+    className="nowrap text-middle"
+  >
     <strong>
       Admin Istrator
     </strong>
     <span
-      className="note little-spacer-left">
+      className="note little-spacer-left"
+    >
       admin
     </span>
   </td>
 </tr>
 `;
 
-exports[`test should render actions and groups for admin 1`] = `
+exports[`should render actions and groups for admin 1`] = `
 <tr>
   <td
-    className="thin nowrap">
+    className="thin nowrap"
+  >
     <Connect(Avatar)
       hash=""
-      size={36} />
+      size={36}
+    />
   </td>
   <td
-    className="nowrap text-middle">
+    className="nowrap text-middle"
+  >
     <strong>
       Admin Istrator
     </strong>
     <span
-      className="note little-spacer-left">
+      className="note little-spacer-left"
+    >
       admin
     </span>
   </td>
   <td
-    className="text-right text-middle">
+    className="text-right text-middle"
+  >
     organization.members.x_groups.3
   </td>
   <td
-    className="nowrap text-middle text-right">
+    className="nowrap text-middle text-right"
+  >
     <div
-      className="dropdown">
+      className="dropdown"
+    >
       <button
         className="dropdown-toggle little-spacer-right"
-        data-toggle="dropdown">
+        data-toggle="dropdown"
+      >
         <i
-          className="icon-settings" />
+          className="icon-settings"
+        />
          
         <i
-          className="icon-dropdown" />
+          className="icon-dropdown"
+        />
       </button>
       <ul
-        className="dropdown-menu dropdown-menu-right">
+        className="dropdown-menu dropdown-menu-right"
+      >
         <li>
           <ManageMemberGroupsForm
             member={
@@ -152,11 +183,13 @@ exports[`test should render actions and groups for admin 1`] = `
                 "key": "foo",
                 "name": "Foo",
               }
-            } />
+            }
+          />
         </li>
         <li
           className="divider"
-          role="separator" />
+          role="separator"
+        />
         <li>
           <RemoveMemberForm
             member={
@@ -173,7 +206,8 @@ exports[`test should render actions and groups for admin 1`] = `
                 "key": "foo",
                 "name": "Foo",
               }
-            } />
+            }
+          />
         </li>
       </ul>
     </div>
index 4c3bdede556205bfdeca382a0fbf7093c458af9a..f6da626a33f6cf945848d623ebc217bd1e9a7b2a 100644 (file)
@@ -62,6 +62,13 @@ exports[`should render actions for admin 1`] = `
       >
         <AddMemberForm
           addMember={[Function]}
+          organization={
+            Object {
+              "canAdmin": true,
+              "key": "foo",
+              "name": "Foo",
+            }
+          }
         />
       </div>
     </div>
index f1fafe1a2e0cd69d34cd136a0052f5ba1704f34d..4502597be29c67a8be6c62256a75a212eb6950d5 100644 (file)
 import React from 'react';
 import Modal from 'react-modal';
 import UsersSelectSearch from '../../../users/components/UsersSelectSearch';
-import { searchUsers } from '../../../../api/users';
+import { searchMembers } from '../../../../api/organizations';
 import { translate } from '../../../../helpers/l10n';
+import type { Organization } from '../../../../store/organizations/duck';
 import type { Member } from '../../../../store/organizationsMembers/actions';
 
 type Props = {
-  memberLogins: Array<string>,
-  addMember: (member: Member) => void
+  addMember: (member: Member) => void,
+  organization: Organization,
+  memberLogins: Array<string>
 };
 
 type State = {
@@ -50,6 +52,14 @@ export default class AddMemberForm extends React.PureComponent {
     this.setState({ open: false, selectedMember: undefined });
   };
 
+  handleSearch = (query?: string, ps: number): Promise<*> => {
+    const data = { organization: this.props.organization.key, ps, selected: 'deselected' };
+    if (!query) {
+      return searchMembers(data);
+    }
+    return searchMembers({ ...data, q: query });
+  };
+
   handleSubmit = (e: Object) => {
     e.preventDefault();
     if (this.state.selectedMember) {
@@ -81,7 +91,7 @@ export default class AddMemberForm extends React.PureComponent {
                 autoFocus={true}
                 selectedUser={this.state.selectedMember}
                 excludedUsers={this.props.memberLogins}
-                searchUsers={searchUsers}
+                searchUsers={this.handleSearch}
                 handleValueChange={this.selectedMemberChange}
               />
             </div>
index 007a6e05138c44678b23a01fcadc5505bb91c0c1..f6a9b1ad5ee2907ac2ccc8b830fb75376f346b38 100644 (file)
@@ -51,6 +51,7 @@ type State = {
 const LIST_SIZE = 10;
 
 export default class UsersSelectSearch extends React.PureComponent {
+  mounted: boolean;
   props: Props;
   state: State;
 
@@ -59,8 +60,8 @@ export default class UsersSelectSearch extends React.PureComponent {
     this.handleSearch = debounce(this.handleSearch, 250);
     this.state = { searchResult: [], isLoading: false, search: '' };
   }
-
   componentDidMount() {
+    this.mounted = true;
     this.handleSearch(this.state.search);
   }
 
@@ -70,19 +71,33 @@ export default class UsersSelectSearch extends React.PureComponent {
     }
   }
 
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
   filterSearchResult = ({ users }: { users: Array<Option> }) =>
     users.filter(user => !this.props.excludedUsers.includes(user.login)).slice(0, LIST_SIZE);
 
   handleSearch = (search: string) => {
-    this.setState({ isLoading: true, search });
     this.props
       .searchUsers(search, Math.min(this.props.excludedUsers.length + LIST_SIZE, 500))
       .then(this.filterSearchResult)
       .then(searchResult => {
-        this.setState({ isLoading: false, searchResult });
+        if (this.mounted) {
+          this.setState({ isLoading: false, searchResult });
+        }
       });
   };
 
+  handleInputChange = (search: string) => {
+    if (search == null || search.length === 1) {
+      this.setState({ search });
+    } else {
+      this.setState({ isLoading: true, search });
+      this.handleSearch(search);
+    }
+  };
+
   render() {
     const noResult = this.state.search.length === 1
       ? translateWithParameters('select2.tooShort', 2)
@@ -96,7 +111,7 @@ export default class UsersSelectSearch extends React.PureComponent {
         optionComponent={UsersSelectSearchOption}
         valueComponent={UsersSelectSearchValue}
         onChange={this.props.handleValueChange}
-        onInputChange={this.handleSearch}
+        onInputChange={this.handleInputChange}
         value={this.props.selectedUser}
         placeholder=""
         noResultsText={noResult}
index 915817227dd1d8685b21aab920c2bcf258420f15..19ad6ab9029cf47466ff815a4c44ca695beee82d 100644 (file)
@@ -40,8 +40,8 @@ export default class UsersSelectSearchValue extends React.PureComponent {
           user.login &&
           <div className="Select-value-label">
             <Avatar hash={user.avatar} email={user.email} size={AVATAR_SIZE} />
-            <strong className="spacer-left">{user.login}</strong>
-            <span className="note little-spacer-left">{this.props.children}</span>
+            <strong className="spacer-left">{this.props.children}</strong>
+            <span className="note little-spacer-left">{user.login}</span>
           </div>}
       </div>
     );
index 9ee1a0b7206c1e3af852981b6b5f0432916fe71e..45aa90aba39cd4f15d2fa1460cc3b11f80b1162c 100644 (file)
@@ -1,43 +1,55 @@
-exports[`test should render correctly with email instead of hash 1`] = `
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly with email instead of hash 1`] = `
 <div
   onMouseDown={[Function]}
   onMouseEnter={[Function]}
   onMouseMove={[Function]}
-  title="Administrator">
+  title="Administrator"
+>
   <div
-    className="little-spacer-bottom little-spacer-top">
+    className="little-spacer-bottom little-spacer-top"
+  >
     <Connect(Avatar)
       email="admin@admin.ch"
-      size={20} />
+      size={20}
+    />
     <strong
-      className="spacer-left">
+      className="spacer-left"
+    >
       Administrator
     </strong>
     <span
-      className="note little-spacer-left">
+      className="note little-spacer-left"
+    >
       admin
     </span>
   </div>
 </div>
 `;
 
-exports[`test should render correctly without all parameters 1`] = `
+exports[`should render correctly without all parameters 1`] = `
 <div
   onMouseDown={[Function]}
   onMouseEnter={[Function]}
   onMouseMove={[Function]}
-  title="Administrator">
+  title="Administrator"
+>
   <div
-    className="little-spacer-bottom little-spacer-top">
+    className="little-spacer-bottom little-spacer-top"
+  >
     <Connect(Avatar)
       hash="7daf6c79d4802916d83f6266e24850af"
-      size={20} />
+      size={20}
+    />
     <strong
-      className="spacer-left">
+      className="spacer-left"
+    >
       Administrator
     </strong>
     <span
-      className="note little-spacer-left">
+      className="note little-spacer-left"
+    >
       admin
     </span>
   </div>
index c2c7daf824718845c0d2d2114f06ba8768ed6ae4..e6523c5d2e66d6c1a6055ea9f29b9304f15a5de5 100644 (file)
@@ -15,12 +15,12 @@ exports[`should render correctly with a user 1`] = `
     <strong
       className="spacer-left"
     >
-      admin
+      Administrator
     </strong>
     <span
       className="note little-spacer-left"
     >
-      Administrator
+      admin
     </span>
   </div>
 </div>
@@ -41,12 +41,12 @@ exports[`should render correctly with email instead of hash 1`] = `
     <strong
       className="spacer-left"
     >
-      admin
+      Administrator
     </strong>
     <span
       className="note little-spacer-left"
     >
-      Administrator
+      admin
     </span>
   </div>
 </div>