Skip to content

Commit ef82c67

Browse files
authored
feat(aci): add issue stream detectors to Connect Monitors drawer (#103197)
adds issue stream detectors to the connected monitors table. these rows can not be clicked (the details views for these are not very useful), but there is still a tooltip on hover. <img width="692" height="76" alt="Screenshot 2025-11-11 at 3 29 05 PM" src="https://github.com/user-attachments/assets/a2f70032-a2c3-4a48-89dc-974bf168e7cc" /> <img width="305" height="102" alt="Screenshot 2025-11-11 at 3 30 32 PM" src="https://github.com/user-attachments/assets/8f0e10dd-cb1b-4e95-8949-068f440c3d78" />
1 parent efb475d commit ef82c67

File tree

9 files changed

+71
-10
lines changed

9 files changed

+71
-10
lines changed

static/app/components/workflowEngine/gridCell/titleCell.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {StatusWarning} from 'sentry/types/workflowEngine/automations';
1111
import {defined} from 'sentry/utils';
1212

1313
export type TitleCellProps = {
14-
link: string;
14+
link: string | null;
1515
name: string;
1616
className?: string;
1717
details?: React.ReactNode;
@@ -57,6 +57,14 @@ export function TitleCell({
5757
</Fragment>
5858
);
5959

60+
if (!link) {
61+
return (
62+
<TitleBase className={className} noHover>
63+
{content}
64+
</TitleBase>
65+
);
66+
}
67+
6068
if (openInNewTab) {
6169
return (
6270
<TitleWrapperAnchor
@@ -98,19 +106,23 @@ const CreatedBySentryIcon = styled(IconSentry)`
98106
flex-shrink: 0;
99107
`;
100108

101-
const TitleBase = styled('div')`
109+
const TitleBase = styled('div')<{noHover?: boolean}>`
102110
display: flex;
103111
flex-direction: column;
104112
gap: ${space(0.5)};
105113
flex: 1;
106114
overflow: hidden;
107115
min-height: 20px;
108116
109-
&:hover {
110-
${NameText} {
111-
text-decoration: underline;
117+
${p =>
118+
!p.noHover &&
119+
`
120+
&:hover {
121+
${NameText} {
122+
text-decoration: underline;
123+
}
112124
}
113-
}
125+
`}
114126
`;
115127

116128
const TitleWrapper = TitleBase.withComponent(Link);

static/app/types/workflowEngine/detectors.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,17 @@ export interface ErrorDetector extends BaseDetector {
154154
readonly type: 'error';
155155
}
156156

157-
export type Detector = MetricDetector | UptimeDetector | CronDetector | ErrorDetector;
157+
interface IssueStreamDetector extends BaseDetector {
158+
// TODO: Add issue stream detector type fields
159+
readonly type: 'issue_stream';
160+
}
161+
162+
export type Detector =
163+
| MetricDetector
164+
| UptimeDetector
165+
| CronDetector
166+
| ErrorDetector
167+
| IssueStreamDetector;
158168

159169
interface UpdateConditionGroupPayload {
160170
conditions: Array<Omit<MetricCondition, 'id'>>;

static/app/views/automations/components/connectedMonitorsList.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ export default function ConnectedMonitorsList({
8686
isSuccess,
8787
getResponseHeader,
8888
} = useDetectorsQuery(
89-
{ids: detectorIds ?? undefined, limit: limit ?? undefined, cursor, query},
89+
{
90+
ids: detectorIds ?? undefined,
91+
limit: limit ?? undefined,
92+
cursor,
93+
query,
94+
includeIssueStreamDetectors: true,
95+
},
9096
{enabled: detectorIds === null || detectorIds.length > 0}
9197
);
9298

@@ -143,6 +149,7 @@ export default function ConnectedMonitorsList({
143149
<SimpleTable.Empty>{emptyMessage}</SimpleTable.Empty>
144150
)}
145151
{isSuccess &&
152+
(detectorIds === null || detectorIds.length > 0) &&
146153
detectors.map(detector => (
147154
<SimpleTable.Row key={detector.id}>
148155
<SimpleTable.RowCell>

static/app/views/automations/components/editConnectedMonitors.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ function ConnectMonitorsDrawer({
110110
makeDetectorListQueryKey({
111111
orgSlug: organization.slug,
112112
ids: localDetectorIds,
113+
includeIssueStreamDetectors: true,
113114
})
114115
) ?? [];
115116

@@ -126,6 +127,7 @@ function ConnectMonitorsDrawer({
126127
makeDetectorListQueryKey({
127128
orgSlug: organization.slug,
128129
ids: newDetectorIds,
130+
includeIssueStreamDetectors: true,
129131
}),
130132
newDetectors
131133
);

static/app/views/detectors/components/details/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import {Alert} from 'sentry/components/core/alert';
12
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
3+
import {t} from 'sentry/locale';
24
import type {Project} from 'sentry/types/project';
35
import type {Detector} from 'sentry/types/workflowEngine/detectors';
46
import {unreachable} from 'sentry/utils/unreachable';
@@ -37,6 +39,14 @@ export function DetectorDetailsContent({detector, project}: DetectorDetailsConte
3739
<CronDetectorDetails detector={detector} project={project} />
3840
</PageFiltersContainer>
3941
);
42+
case 'issue_stream':
43+
return (
44+
<Alert.Container>
45+
<Alert type="error">
46+
{t('Issue stream monitors do not support detail views.')}
47+
</Alert>
48+
</Alert.Container>
49+
);
4050
default:
4151
unreachable(detectorType);
4252
return (

static/app/views/detectors/components/detectorLink.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ function Details({detector}: {detector: Detector}) {
197197
case 'monitor_check_in_failure':
198198
return <CronDetectorDetails detector={detector} />;
199199
case 'error':
200+
case 'issue_stream':
200201
return null;
201202
default:
202203
unreachable(detectorType);
@@ -208,11 +209,21 @@ export function DetectorLink({detector, className, openInNewTab}: DetectorLinkPr
208209
const org = useOrganization();
209210
const project = useProjectFromId({project_id: detector.projectId});
210211

212+
const detectorName =
213+
detector.type === 'issue_stream'
214+
? t('All Issues in %s', project?.name || 'project')
215+
: detector.name;
216+
217+
const detectorLink =
218+
detector.type === 'issue_stream'
219+
? null
220+
: makeMonitorDetailsPathname(org.slug, detector.id);
221+
211222
return (
212223
<TitleCell
213224
className={className}
214-
name={detector.name}
215-
link={makeMonitorDetailsPathname(org.slug, detector.id)}
225+
name={detectorName}
226+
link={detectorLink}
216227
systemCreated={getDetectorSystemCreatedNotice(detector)}
217228
disabled={!detector.enabled}
218229
openInNewTab={openInNewTab}

static/app/views/detectors/components/forms/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {Alert} from 'sentry/components/core/alert';
12
import * as Layout from 'sentry/components/layouts/thirds';
23
import LoadingError from 'sentry/components/loadingError';
34
import {t} from 'sentry/locale';
@@ -61,6 +62,12 @@ export function EditExistingDetectorForm({detector}: {detector: Detector}) {
6162
return <EditExistingErrorDetectorForm detector={detector} />;
6263
case 'monitor_check_in_failure':
6364
return <EditExistingCronDetectorForm detector={detector} />;
65+
case 'issue_stream':
66+
return (
67+
<Alert.Container>
68+
<Alert type="error">{t('Issue stream monitors can not be edited.')}</Alert>
69+
</Alert.Container>
70+
);
6471
default:
6572
unreachable(detectorType);
6673
return <PlaceholderForm />;

static/app/views/detectors/utils/detectorTypeConfig.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const DETECTOR_TYPE_CONFIG: Record<DetectorType, DetectorTypeConfig> = {
3434
issue_stream: {
3535
userCreateable: false,
3636
label: t('Issue Stream'),
37+
systemCreatedNotice: () => t('This monitor is managed by Sentry'),
3738
},
3839
};
3940

static/app/views/detectors/utils/getDetectorEnvironment.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export function getDetectorEnvironment(detector: Detector): string | null {
1515
// Crons can have multiple environments
1616
return null;
1717
case 'error':
18+
case 'issue_stream':
1819
return null;
1920
default:
2021
unreachable(detectorType);

0 commit comments

Comments
 (0)