Browse Source

fix(team-members): team member dropdown should not close after selection (#48896)

When adding new team member from organization settings the drop down
closes every time. Expected behavior is that it stays open because
usually people add multiple team members in one attempt. This fixes the
issue by keeping the dropdown open and only close on click.




https://github.com/getsentry/sentry/assets/132939361/89735f54-2c93-4525-918c-05599afda23f

Fixes: ER-1212

---------

Co-authored-by: Athena K Moghaddam <athena1@WYDJCF9NHC.local>
Athena Moghaddam 1 year ago
parent
commit
2b840455aa

+ 21 - 0
static/app/views/settings/organizationTeams/teamMembers.spec.jsx

@@ -75,6 +75,27 @@ describe('TeamMembers', function () {
     expect(createMock).toHaveBeenCalled();
   });
 
+  it('can add multiple members with one click on dropdown', async function () {
+    const org = TestStubs.Organization({access: [], openMembership: true});
+    render(
+      <TeamMembers
+        params={{orgId: org.slug, teamId: team.slug}}
+        organization={org}
+        team={team}
+      />
+    );
+
+    await userEvent.click(
+      (
+        await screen.findAllByRole('button', {name: 'Add Member'})
+      )[0]
+    );
+
+    await userEvent.click(screen.getAllByTestId('letter_avatar-avatar')[0]);
+    expect(createMock).toHaveBeenCalled();
+    expect(screen.getAllByTestId('add-member-menu')[0]).toBeVisible();
+  });
+
   it('can add member to team with team:admin permission', async function () {
     const org = TestStubs.Organization({access: ['team:admin'], openMembership: false});
     render(

+ 2 - 11
static/app/views/settings/organizationTeams/teamMembers.tsx

@@ -18,7 +18,6 @@ import DropdownButton from 'sentry/components/dropdownButton';
 import EmptyMessage from 'sentry/components/emptyMessage';
 import Link from 'sentry/components/links/link';
 import LoadingError from 'sentry/components/loadingError';
-import LoadingIndicator from 'sentry/components/loadingIndicator';
 import Pagination from 'sentry/components/pagination';
 import {Panel, PanelHeader} from 'sentry/components/panels';
 import {IconUser} from 'sentry/icons';
@@ -49,7 +48,6 @@ type Props = {
 type State = {
   dropdownBusy: boolean;
   error: boolean;
-  loading: boolean;
   orgMembers: Member[];
   teamMembers: TeamMember[];
 } & AsyncView['state'];
@@ -58,7 +56,6 @@ class TeamMembers extends AsyncView<Props, State> {
   getDefaultState() {
     return {
       ...super.getDefaultState(),
-      loading: true,
       error: false,
       dropdownBusy: false,
       teamMembers: [],
@@ -119,8 +116,6 @@ class TeamMembers extends AsyncView<Props, State> {
     const {organization, params} = this.props;
     const {orgMembers, teamMembers} = this.state;
 
-    this.setState({loading: true});
-
     // Reset members list after adding member to team
     this.debouncedFetchMembersRequest('');
 
@@ -138,14 +133,12 @@ class TeamMembers extends AsyncView<Props, State> {
             return;
           }
           this.setState({
-            loading: false,
             error: false,
             teamMembers: teamMembers.concat([orgMember as TeamMember]),
           });
           addSuccessMessage(t('Successfully added member to team.'));
         },
         error: () => {
-          this.setState({loading: false});
           addErrorMessage(t('Unable to add team member.'));
         },
       }
@@ -253,6 +246,7 @@ class TeamMembers extends AsyncView<Props, State> {
 
     return (
       <DropdownAutoComplete
+        closeOnSelect={false}
         items={items}
         alignMenu="right"
         onSelect={
@@ -271,6 +265,7 @@ class TeamMembers extends AsyncView<Props, State> {
         busy={this.state.dropdownBusy}
         onClose={() => this.debouncedFetchMembersRequest('')}
         disabled={isDropdownDisabled}
+        data-test-id="add-member-menu"
       >
         {({isOpen}) => (
           <DropdownButton
@@ -305,10 +300,6 @@ class TeamMembers extends AsyncView<Props, State> {
   }
 
   render() {
-    if (this.state.loading) {
-      return <LoadingIndicator />;
-    }
-
     if (this.state.error) {
       return <LoadingError onRetry={this.fetchData} />;
     }