Skip to content

Commit cd5d346

Browse files
author
davidenwang
committed
feat(crons): Disallow teams not part of project to be selected for alerts
commit-id:3863ee1e
1 parent 6cb8a73 commit cd5d346

File tree

2 files changed

+54
-12
lines changed

2 files changed

+54
-12
lines changed

static/app/components/forms/fields/sentryMemberTeamSelectorField.tsx

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import {useContext, useEffect, useMemo} from 'react';
22

33
import Avatar from 'sentry/components/avatar';
4+
import {Tooltip} from 'sentry/components/tooltip';
45
import {t} from 'sentry/locale';
6+
import type {DetailedTeam} from 'sentry/types';
7+
import {defined} from 'sentry/utils';
58
import {useMembers} from 'sentry/utils/useMembers';
69
import {useTeams} from 'sentry/utils/useTeams';
710
import {useTeamsById} from 'sentry/utils/useTeamsById';
@@ -15,6 +18,10 @@ import SelectField from './selectField';
1518
// projects can be passed as a direct prop as well
1619
export interface RenderFieldProps extends SelectFieldProps<any> {
1720
avatarSize?: number;
21+
/**
22+
* Ensures the only selectable teams and members are members of the given project
23+
*/
24+
memberOfProjectSlug?: string;
1825
/**
1926
* Use the slug as the select field value. Without setting this the numeric id
2027
* of the project will be used.
@@ -25,6 +32,7 @@ export interface RenderFieldProps extends SelectFieldProps<any> {
2532
function SentryMemberTeamSelectorField({
2633
avatarSize = 20,
2734
placeholder = t('Choose Teams and Members'),
35+
memberOfProjectSlug,
2836
...props
2937
}: RenderFieldProps) {
3038
const {form} = useContext(FormContext);
@@ -77,11 +85,36 @@ function SentryMemberTeamSelectorField({
7785
loadMore: loadMoreTeams,
7886
} = useTeams({provideUserTeams: true});
7987

80-
const teamOptions = teams?.map(team => ({
81-
value: `team:${team.id}`,
82-
label: `#${team.slug}`,
83-
leadingItems: <Avatar team={team} size={avatarSize} />,
84-
}));
88+
// TODO(davidenwang): Fix the team type here to avoid this type cast
89+
const teamOptions = (teams as DetailedTeam[])
90+
.map(team => {
91+
const isDisabledTeam =
92+
memberOfProjectSlug &&
93+
!defined(team.projects.find(({slug}) => memberOfProjectSlug === slug));
94+
return {
95+
value: `team:${team.id}`,
96+
leadingItems: <Avatar team={team} size={avatarSize} />,
97+
...(isDisabledTeam
98+
? {
99+
disabled: true,
100+
label: (
101+
<Tooltip
102+
position="left"
103+
title={t('%s is not a member of the selected project', `#${team.slug}`)}
104+
>
105+
#{team.slug}
106+
</Tooltip>
107+
),
108+
}
109+
: {
110+
disabled: false,
111+
label: `#${team.slug}`,
112+
}),
113+
};
114+
})
115+
.sort(({disabled: teamADisabled}, {disabled: teamBDisabled}) =>
116+
teamADisabled === teamBDisabled ? 0 : teamADisabled ? 1 : -1
117+
);
85118

86119
// TODO(epurkhiser): This is an unfortunate hack right now since we don't
87120
// actually load members anywhere and the useMembers and useTeams hook don't

static/app/views/monitors/components/monitorForm.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -504,13 +504,22 @@ function MonitorForm({
504504
{t('Customize this monitors notification configuration in Alerts')}
505505
</AlertLink>
506506
)}
507-
<SentryMemberTeamSelectorField
508-
label={t('Notify')}
509-
help={t('Send notifications to a member or team.')}
510-
name="alertRule.targets"
511-
multiple
512-
menuPlacement="auto"
513-
/>
507+
<Observer>
508+
{() => {
509+
const projectSlug = form.current.getValue('project')?.toString();
510+
511+
return (
512+
<SentryMemberTeamSelectorField
513+
label={t('Notify')}
514+
help={t('Send notifications to a member or team.')}
515+
name="alertRule.targets"
516+
memberOfProjectSlug={projectSlug}
517+
multiple
518+
menuPlacement="auto"
519+
/>
520+
);
521+
}}
522+
</Observer>
514523
<Observer>
515524
{() => {
516525
const selectedAssignee = form.current.getValue('alertRule.targets');

0 commit comments

Comments
 (0)