Skip to content

Commit

Permalink
fix(dashboards): team rendering for Edit Access selector (getsentry#8…
Browse files Browse the repository at this point in the history
…1059)

Problem:
The `useTeamsById()` hook only renders teams from the `TeamStore` which
causes the dashboard to error out when the Edit Access selector uses an
unavailable team.

Fix:
- Query the selected team by `teamId` to ensure it isn't undefined
- This PR also fixes the Search functionality by being able to search
for any team irrespective of `TeamStore`

---------

Co-authored-by: harshithadurai <[email protected]>
  • Loading branch information
harshithadurai and harshithadurai authored Nov 21, 2024
1 parent 5b42c1e commit ebae966
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
10 changes: 10 additions & 0 deletions static/app/views/dashboards/editAccessSelector.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {DashboardFixture} from 'sentry-fixture/dashboard';
import {OrganizationFixture} from 'sentry-fixture/organization';
import {TeamFixture} from 'sentry-fixture/team';
import {UserFixture} from 'sentry-fixture/user';

import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';

import OrganizationStore from 'sentry/stores/organizationStore';
import TeamStore from 'sentry/stores/teamStore';
import EditAccessSelector from 'sentry/views/dashboards/editAccessSelector';

Expand Down Expand Up @@ -224,7 +226,15 @@ describe('When EditAccessSelector is rendered with Teams', function () {
});

it('searches teams', async function () {
const org = OrganizationFixture();
OrganizationStore.onUpdate(org, {replace: true});
MockApiClient.addMockResponse({
url: `/organizations/org-slug/teams/`,
method: 'GET',
body: teams,
});
renderTestComponent();

await userEvent.click(await screen.findByText('Edit Access:'));
await userEvent.type(screen.getByPlaceholderText('Search Teams'), 'team2');

Expand Down
17 changes: 13 additions & 4 deletions static/app/views/dashboards/editAccessSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {useState} from 'react';
import styled from '@emotion/styled';
import debounce from 'lodash/debounce';
import isEqual from 'lodash/isEqual';

import AvatarList from 'sentry/components/avatar/avatarList';
Expand All @@ -13,11 +14,13 @@ import {CheckWrap} from 'sentry/components/compactSelect/styles';
import UserBadge from 'sentry/components/idBadge/userBadge';
import {InnerWrap, LeadingItems} from 'sentry/components/menuListItem';
import {Tooltip} from 'sentry/components/tooltip';
import {DEFAULT_DEBOUNCE_DURATION} from 'sentry/constants';
import {t, tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Team} from 'sentry/types/organization';
import type {User} from 'sentry/types/user';
import {defined} from 'sentry/utils';
import {useTeams} from 'sentry/utils/useTeams';
import {useTeamsById} from 'sentry/utils/useTeamsById';
import {useUser} from 'sentry/utils/useUser';
import type {DashboardDetails, DashboardPermissions} from 'sentry/views/dashboards/types';
Expand All @@ -35,10 +38,15 @@ function EditAccessSelector({dashboard, onChangeEditAccess}: EditAccessSelectorP
const currentUser: User = useUser();
const dashboardCreator: User | undefined = dashboard.createdBy;
const isCurrentUserDashboardOwner = dashboardCreator?.id === currentUser.id;
const {teams} = useTeamsById();
const teamIds: string[] = Object.values(teams).map(team => team.id);

// Retrieves teams from the team store, which may contain only a subset of all teams
const {teams: teamsToRender} = useTeamsById();
const {onSearch} = useTeams();
const teamIds: string[] = Object.values(teamsToRender).map(team => team.id);

const [selectedOptions, setSelectedOptions] = useState<string[]>(getSelectedOptions());
const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
const {teams: selectedTeam} = useTeamsById({ids: [selectedOptions[1]]});

// Handles state change when dropdown options are selected
const onSelectOptions = newSelectedOptions => {
Expand Down Expand Up @@ -131,7 +139,7 @@ function EditAccessSelector({dashboard, onChangeEditAccess}: EditAccessSelectorP
key="avatar-list-2-badges"
typeAvatars="users"
users={[dashboardCreator]}
teams={[teams.find(team => team.id === selectedOptions[1])!]}
teams={selectedTeam ? selectedTeam : []}
maxVisibleAvatars={1}
avatarSize={25}
renderUsersFirst
Expand Down Expand Up @@ -162,7 +170,7 @@ function EditAccessSelector({dashboard, onChangeEditAccess}: EditAccessSelectorP
{
value: '_teams',
label: t('Teams'),
options: teams.map(makeTeamOption),
options: teamsToRender.map(makeTeamOption),
showToggleAllButton: isCurrentUserDashboardOwner,
disabled: !isCurrentUserDashboardOwner,
},
Expand Down Expand Up @@ -236,6 +244,7 @@ function EditAccessSelector({dashboard, onChangeEditAccess}: EditAccessSelectorP
}
}}
menuFooter={dropdownFooterButtons}
onSearch={debounce(val => void onSearch(val), DEFAULT_DEBOUNCE_DURATION)}
/>
);

Expand Down

0 comments on commit ebae966

Please sign in to comment.