diff --git a/static/app/views/detectors/components/details/common/actions.tsx b/static/app/views/detectors/components/details/common/actions.tsx
index 9afc02efb5ac2f..8c259191f38347 100644
--- a/static/app/views/detectors/components/details/common/actions.tsx
+++ b/static/app/views/detectors/components/details/common/actions.tsx
@@ -16,6 +16,7 @@ import {
makeMonitorBasePathname,
makeMonitorDetailsPathname,
} from 'sentry/views/detectors/pathnames';
+import {detectorTypeIsUserCreateable} from 'sentry/views/detectors/utils/detectorTypeConfig';
import {useCanEditDetector} from 'sentry/views/detectors/utils/useCanEditDetector';
export function DisableDetectorAction({detector}: {detector: Detector}) {
@@ -59,19 +60,23 @@ export function EditDetectorAction({detector}: {detector: Detector}) {
projectId: detector.projectId,
});
- const permissionTooltipText = tct(
- 'You do not have permission to edit this monitor. Ask your organization owner or manager to [settingsLink:enable monitor access] for you.',
- {
- settingsLink: (
-
- ),
- }
- );
+ const permissionTooltipText = detectorTypeIsUserCreateable(detector.type)
+ ? tct(
+ 'You do not have permission to edit this monitor. Ask your organization owner or manager to [settingsLink:enable monitor access] for you.',
+ {
+ settingsLink: (
+
+ ),
+ }
+ )
+ : t(
+ 'This monitor is managed by Sentry. Only organization owners and managers can edit it.'
+ );
return (
}
+ actions={}
title={TITLE}
description={DESCRIPTION}
docsUrl={DOCS_URL}
diff --git a/static/app/views/detectors/list/common/detectorListActions.tsx b/static/app/views/detectors/list/common/detectorListActions.tsx
index 68e6becc922ba7..da3e37c644f165 100644
--- a/static/app/views/detectors/list/common/detectorListActions.tsx
+++ b/static/app/views/detectors/list/common/detectorListActions.tsx
@@ -1,20 +1,50 @@
+import {Link} from '@sentry/scraps/link';
+
import {LinkButton} from 'sentry/components/core/button/linkButton';
import {Flex} from 'sentry/components/core/layout';
import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters';
import {IconAdd} from 'sentry/icons';
-import {t} from 'sentry/locale';
+import {t, tct} from 'sentry/locale';
+import type {Organization} from 'sentry/types/organization';
import type {DetectorType} from 'sentry/types/workflowEngine/detectors';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import {MonitorFeedbackButton} from 'sentry/views/detectors/components/monitorFeedbackButton';
import {makeMonitorCreatePathname} from 'sentry/views/detectors/pathnames';
+import {detectorTypeIsUserCreateable} from 'sentry/views/detectors/utils/detectorTypeConfig';
+import {useCanCreateDetector} from 'sentry/views/detectors/utils/useCanCreateDetector';
interface DetectorListActionsProps {
+ detectorType: DetectorType | null;
children?: React.ReactNode;
- /**
- * Pass a detector type to skip type selection on the create monitor page
- */
- detectorType?: DetectorType;
+}
+
+function getPermissionTooltipText({
+ organization,
+ detectorType,
+}: {
+ detectorType: DetectorType | null;
+ organization: Organization;
+}) {
+ const noPermissionText = tct(
+ 'You do not have permission to create monitors. Ask your organization owner or manager to [settingsLink:enable monitor access] for you.',
+ {
+ settingsLink: (
+
+ ),
+ }
+ );
+
+ if (!detectorType || detectorTypeIsUserCreateable(detectorType)) {
+ return noPermissionText;
+ }
+
+ return t('This monitor type is managed by Sentry.');
}
export function DetectorListActions({detectorType, children}: DetectorListActionsProps) {
@@ -24,6 +54,7 @@ export function DetectorListActions({detectorType, children}: DetectorListAction
const createPath = makeMonitorCreatePathname(organization.slug);
const project = selection.projects.find(pid => pid !== ALL_ACCESS_PROJECTS);
const createQuery = detectorType ? {project, detectorType} : {project};
+ const canCreateDetector = useCanCreateDetector(detectorType);
return (
@@ -37,6 +68,15 @@ export function DetectorListActions({detectorType, children}: DetectorListAction
priority="primary"
icon={}
size="sm"
+ disabled={!canCreateDetector}
+ title={
+ canCreateDetector
+ ? undefined
+ : getPermissionTooltipText({
+ organization,
+ detectorType,
+ })
+ }
>
{t('Create Monitor')}
diff --git a/static/app/views/detectors/list/myMonitors.tsx b/static/app/views/detectors/list/myMonitors.tsx
index af56e6d160b57c..072026629cccef 100644
--- a/static/app/views/detectors/list/myMonitors.tsx
+++ b/static/app/views/detectors/list/myMonitors.tsx
@@ -18,7 +18,7 @@ export default function MyMonitorsList() {
return (
}
+ actions={}
title={TITLE}
description={DESCRIPTION}
docsUrl={DOCS_URL}
diff --git a/static/app/views/detectors/utils/useCanCreateDetector.tsx b/static/app/views/detectors/utils/useCanCreateDetector.tsx
new file mode 100644
index 00000000000000..ae5d1b50d09dc5
--- /dev/null
+++ b/static/app/views/detectors/utils/useCanCreateDetector.tsx
@@ -0,0 +1,15 @@
+import {hasEveryAccess} from 'sentry/components/acl/access';
+import type {DetectorType} from 'sentry/types/workflowEngine/detectors';
+import useOrganization from 'sentry/utils/useOrganization';
+
+import {detectorTypeIsUserCreateable} from './detectorTypeConfig';
+
+export function useCanCreateDetector(detectorType: DetectorType | null) {
+ const organization = useOrganization();
+
+ if (!detectorType) {
+ return hasEveryAccess(['alerts:write'], {organization});
+ }
+
+ return detectorTypeIsUserCreateable(detectorType);
+}