Browse Source

ref(ui): Use TeamSelector component for organization invite requests (#29864)

Change to the team selector here so we don't need to use withTeams here which technically doesn't provide all teams.
David Wang 3 years ago
parent
commit
b65989e8f6

+ 1 - 1
static/app/components/forms/teamSelector.tsx

@@ -240,7 +240,7 @@ function TeamSelector(props: Props) {
       isOptionDisabled={option => !!option.disabled}
       styles={{
         ...(includeUnassigned ? unassignedSelectStyles : {}),
-        ...placeholderSelectStyles,
+        ...(multiple ? {} : placeholderSelectStyles),
         ...(styles ?? {}),
       }}
       isLoading={fetching}

+ 5 - 11
static/app/views/settings/organizationMembers/inviteRequestRow.tsx

@@ -3,9 +3,8 @@ import styled from '@emotion/styled';
 
 import Button from 'app/components/button';
 import Confirm from 'app/components/confirm';
-import MultiSelectControl, {
-  MultiControlProps,
-} from 'app/components/forms/multiSelectControl';
+import {MultiControlProps} from 'app/components/forms/multiSelectControl';
+import TeamSelector from 'app/components/forms/teamSelector';
 import HookOrDefault from 'app/components/hookOrDefault';
 import {PanelItem} from 'app/components/panels';
 import RoleSelectControl from 'app/components/roleSelectControl';
@@ -14,7 +13,7 @@ import Tooltip from 'app/components/tooltip';
 import {IconCheckmark, IconClose} from 'app/icons';
 import {t, tct} from 'app/locale';
 import space from 'app/styles/space';
-import {Member, MemberRole, Organization, Team} from 'app/types';
+import {Member, MemberRole, Organization} from 'app/types';
 
 type Props = {
   inviteRequest: Member;
@@ -23,7 +22,6 @@ type Props = {
   onApprove: (inviteRequest: Member) => void;
   onDeny: (inviteRequest: Member) => void;
   onUpdate: (data: Partial<Member>) => void;
-  allTeams: Team[];
   allRoles: MemberRole[];
 };
 
@@ -43,7 +41,6 @@ const InviteRequestRow = ({
   onApprove,
   onDeny,
   onUpdate,
-  allTeams,
   allRoles,
 }: Props) => {
   const role = allRoles.find(r => r.id === inviteRequest.role);
@@ -100,11 +97,8 @@ const InviteRequestRow = ({
             onUpdate({teams: (teams || []).map(team => team.value)})
           }
           value={inviteRequest.teams}
-          options={allTeams.map(({slug}) => ({
-            value: slug,
-            label: `#${slug}`,
-          }))}
           clearable
+          multiple
         />
       ) : (
         <div>{inviteRequest.teams.join(', ')}</div>
@@ -201,7 +195,7 @@ const StyledRoleSelectControl = styled(RoleSelectControl)`
   max-width: 140px;
 `;
 
-const TeamSelectControl = styled(MultiSelectControl)`
+const TeamSelectControl = styled(TeamSelector)`
   max-width: 220px;
   .Select-value-label {
     max-width: 150px;

+ 3 - 6
static/app/views/settings/organizationMembers/organizationMembersList.tsx

@@ -16,12 +16,11 @@ import {IconSliders} from 'app/icons';
 import {t, tct} from 'app/locale';
 import ConfigStore from 'app/stores/configStore';
 import space from 'app/styles/space';
-import {Member, MemberRole, Organization, Team} from 'app/types';
+import {Member, MemberRole, Organization} from 'app/types';
 import trackAdvancedAnalyticsEvent from 'app/utils/analytics/trackAdvancedAnalyticsEvent';
 import routeTitleGen from 'app/utils/routeTitle';
 import theme from 'app/utils/theme';
 import withOrganization from 'app/utils/withOrganization';
-import withTeams from 'app/utils/withTeams';
 import AsyncView from 'app/views/asyncView';
 import {
   RenderSearch,
@@ -35,7 +34,6 @@ import OrganizationMemberRow from './organizationMemberRow';
 
 type Props = {
   organization: Organization;
-  teams: Team[];
 } & RouteComponentProps<{orgId: string}, {}>;
 
 type State = AsyncView['state'] & {
@@ -233,7 +231,7 @@ class OrganizationMembersList extends AsyncView<Props, State> {
   };
 
   renderBody() {
-    const {params, organization, routes, teams} = this.props;
+    const {params, organization, routes} = this.props;
     const {membersPageLinks, members, member: currentMember, inviteRequests} = this.state;
     const {name: orgName, access} = organization;
 
@@ -303,7 +301,6 @@ class OrganizationMembersList extends AsyncView<Props, State> {
                   organization={organization}
                   inviteRequest={inviteRequest}
                   inviteRequestBusy={{}}
-                  allTeams={teams}
                   allRoles={currentMember?.roles ?? MEMBER_ROLES}
                   onApprove={this.handleInviteRequestApprove}
                   onDeny={this.handleInviteRequestDeny}
@@ -388,4 +385,4 @@ const StyledPanelItem = styled('div')`
   width: 100%;
 `;
 
-export default withTeams(withOrganization(OrganizationMembersList));
+export default withOrganization(OrganizationMembersList);

+ 5 - 7
tests/js/spec/views/settings/organizationMembers/inviteRequestRow.spec.jsx

@@ -1,7 +1,9 @@
 import {mountWithTheme} from 'sentry-test/enzyme';
 import {mountGlobalModal} from 'sentry-test/modal';
+import {act} from 'sentry-test/reactTestingLibrary';
 import {selectByValue} from 'sentry-test/select-new';
 
+import TeamStore from 'app/stores/teamStore';
 import InviteRequestRow from 'app/views/settings/organizationMembers/inviteRequestRow';
 
 const roles = [
@@ -58,7 +60,6 @@ describe('InviteRequestRow', function () {
         organization={orgWithoutAdminAccess}
         inviteRequest={inviteRequest}
         inviteRequestBusy={inviteRequestBusy}
-        allTeams={[]}
         allRoles={roles}
       />
     );
@@ -76,7 +77,6 @@ describe('InviteRequestRow', function () {
         organization={orgWithoutAdminAccess}
         inviteRequest={joinRequest}
         inviteRequestBusy={inviteRequestBusy}
-        allTeams={[]}
         allRoles={roles}
       />
     );
@@ -97,7 +97,6 @@ describe('InviteRequestRow', function () {
         inviteRequestBusy={inviteRequestBusy}
         onApprove={mockApprove}
         onDeny={mockDeny}
-        allTeams={[]}
         allRoles={roles}
       />
     );
@@ -123,7 +122,6 @@ describe('InviteRequestRow', function () {
         inviteRequestBusy={inviteRequestBusy}
         onApprove={mockApprove}
         onDeny={mockDeny}
-        allTeams={[]}
         allRoles={roles}
       />
     );
@@ -142,7 +140,6 @@ describe('InviteRequestRow', function () {
         inviteRequestBusy={inviteRequestBusy}
         onApprove={() => {}}
         onDeny={() => {}}
-        allTeams={[]}
         allRoles={roles}
       />
     );
@@ -161,6 +158,7 @@ describe('InviteRequestRow', function () {
       teams: ['myteam'],
     });
 
+    act(() => void TeamStore.loadInitialData([{slug: 'one'}, {slug: 'two'}]));
     const mockUpdate = jest.fn();
 
     const wrapper = mountWithTheme(
@@ -169,7 +167,6 @@ describe('InviteRequestRow', function () {
         organization={orgWithAdminAccess}
         inviteRequest={adminInviteRequest}
         inviteRequestBusy={inviteRequestBusy}
-        allTeams={[{slug: 'one'}, {slug: 'two'}]}
         allRoles={roles}
         onUpdate={mockUpdate}
       />
@@ -180,6 +177,8 @@ describe('InviteRequestRow', function () {
 
     selectByValue(wrapper, 'one', {name: 'teams', control: true});
     expect(mockUpdate).toHaveBeenCalledWith({teams: ['one']});
+
+    TeamStore.reset();
   });
 
   it('cannot be approved when invitee role is not allowed', function () {
@@ -200,7 +199,6 @@ describe('InviteRequestRow', function () {
         organization={orgWithoutAdminAccess}
         inviteRequest={ownerInviteRequest}
         inviteRequestBusy={inviteRequestBusy}
-        allTeams={[{slug: 'one'}, {slug: 'two'}]}
         allRoles={roles}
         onUpdate={mockUpdate}
       />