diff --git a/static/app/components/createAlertButton.tsx b/static/app/components/createAlertButton.tsx
index d413120e694c86..e811880ea22278 100644
--- a/static/app/components/createAlertButton.tsx
+++ b/static/app/components/createAlertButton.tsx
@@ -18,6 +18,7 @@ import type EventView from 'sentry/utils/discover/eventView';
import useApi from 'sentry/utils/useApi';
import useProjects from 'sentry/utils/useProjects';
import useRouter from 'sentry/utils/useRouter';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {AlertType, AlertWizardAlertNames} from 'sentry/views/alerts/wizard/options';
import {
AlertWizardRuleTemplates,
@@ -75,7 +76,10 @@ function CreateAlertFromViewButton({
: DEFAULT_WIZARD_TEMPLATE;
const to = {
- pathname: `/organizations/${organization.slug}/alerts/new/metric/`,
+ pathname: makeAlertsPathname({
+ path: '/new/metric/',
+ organization,
+ }),
query: {
...queryParams,
createFromDiscover: true,
@@ -143,7 +147,12 @@ export default function CreateAlertButton({
if (alertOption) {
params.append('alert_option', alertOption);
}
- return `/organizations/${organization.slug}/alerts/wizard/?${params.toString()}`;
+ return (
+ makeAlertsPathname({
+ path: '/wizard/',
+ organization,
+ }) + `?${params.toString()}`
+ );
};
function handleClickWithoutProject(event: React.MouseEvent) {
diff --git a/static/app/components/events/interfaces/crons/cronTimelineSection.tsx b/static/app/components/events/interfaces/crons/cronTimelineSection.tsx
index c9ea45e6b49257..76416400e23ab1 100644
--- a/static/app/components/events/interfaces/crons/cronTimelineSection.tsx
+++ b/static/app/components/events/interfaces/crons/cronTimelineSection.tsx
@@ -23,6 +23,7 @@ import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {useDimensions} from 'sentry/utils/useDimensions';
import {useLocation} from 'sentry/utils/useLocation';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {SectionKey} from 'sentry/views/issueDetails/streamline/context';
import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection';
import {ResolutionSelector} from 'sentry/views/monitors/components/overviewTimeline/resolutionSelector';
@@ -77,7 +78,10 @@ export function CronTimelineSection({event, organization, project}: Props) {
size="xs"
icon={}
to={{
- pathname: `/organizations/${organization.slug}/alerts/rules/crons/${project.slug}/${monitorSlug}/details/`,
+ pathname: makeAlertsPathname({
+ path: `/rules/crons/${project.slug}/${monitorSlug}/details/`,
+ organization,
+ }),
query: {environment},
}}
>
diff --git a/static/app/components/events/interfaces/uptime/uptimeDataSection.tsx b/static/app/components/events/interfaces/uptime/uptimeDataSection.tsx
index 67bdded595cec2..a3a275cb305114 100644
--- a/static/app/components/events/interfaces/uptime/uptimeDataSection.tsx
+++ b/static/app/components/events/interfaces/uptime/uptimeDataSection.tsx
@@ -25,11 +25,11 @@ import type {Event} from 'sentry/types/event';
import {type Group, GroupActivityType, GroupStatus} from 'sentry/types/group';
import type {Project} from 'sentry/types/project';
import {defined} from 'sentry/utils';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import {useDebouncedValue} from 'sentry/utils/useDebouncedValue';
import {useDimensions} from 'sentry/utils/useDimensions';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {
checkStatusPrecedent,
statusToText,
@@ -133,9 +133,10 @@ export function UptimeDataSection({group, event, project}: Props) {
}
size="xs"
- to={normalizeUrl(
- `/organizations/${organization.slug}/alerts/rules/uptime/${project.slug}/${alertRuleId}/details/`
- )}
+ to={makeAlertsPathname({
+ path: `/rules/uptime/${project.slug}/${alertRuleId}/details/`,
+ organization,
+ })}
>
{t('Uptime Alert Rule')}
diff --git a/static/app/components/onboardingWizard/taskConfig.tsx b/static/app/components/onboardingWizard/taskConfig.tsx
index d616b765529dee..5336c654581c1c 100644
--- a/static/app/components/onboardingWizard/taskConfig.tsx
+++ b/static/app/components/onboardingWizard/taskConfig.tsx
@@ -22,6 +22,7 @@ import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {isDemoModeEnabled} from 'sentry/utils/demoMode';
import {getDemoWalkthroughTasks} from 'sentry/utils/demoMode/guides';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {getPerformanceBaseUrl} from 'sentry/views/performance/utils';
import {makeReplaysPathname} from 'sentry/views/replays/pathnames';
@@ -47,12 +48,18 @@ type Options = {
function getIssueAlertUrl({projects, organization}: Options) {
if (!projects || !projects.length) {
- return `/organizations/${organization.slug}/alerts/rules/`;
+ return makeAlertsPathname({
+ path: '/rules/',
+ organization,
+ });
}
// pick the first project with events if we have that, otherwise just pick the first project
const firstProjectWithEvents = projects.find(project => !!project.firstEvent);
const project = firstProjectWithEvents ?? projects[0]!;
- return `/organizations/${organization.slug}/alerts/${project.slug}/wizard/`;
+ return makeAlertsPathname({
+ path: `/${project.slug}/wizard/`,
+ organization,
+ });
}
function getOnboardingInstructionsUrl({projects, organization}: Options) {
diff --git a/static/app/components/sidebar/index.tsx b/static/app/components/sidebar/index.tsx
index 7b9d40d23be03a..abd41b0041ec29 100644
--- a/static/app/components/sidebar/index.tsx
+++ b/static/app/components/sidebar/index.tsx
@@ -55,6 +55,7 @@ import useMedia from 'sentry/utils/useMedia';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import useProjects from 'sentry/utils/useProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
import {
AI_LANDING_SUB_PATH,
@@ -328,7 +329,10 @@ function Sidebar() {
{...sidebarItemProps}
icon={}
label={t('Alerts')}
- to={`/organizations/${organization.slug}/alerts/rules/`}
+ to={makeAlertsPathname({
+ path: '/rules/',
+ organization,
+ })}
id="alerts"
/>
);
diff --git a/static/app/views/alerts/builder/builderBreadCrumbs.tsx b/static/app/views/alerts/builder/builderBreadCrumbs.tsx
index 2461fb20f08ce3..a50cbd5aa7353f 100644
--- a/static/app/views/alerts/builder/builderBreadCrumbs.tsx
+++ b/static/app/views/alerts/builder/builderBreadCrumbs.tsx
@@ -2,6 +2,7 @@ import type {Crumb, CrumbDropdown} from 'sentry/components/breadcrumbs';
import Breadcrumbs from 'sentry/components/breadcrumbs';
import {t} from 'sentry/locale';
import type {Organization} from 'sentry/types/organization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
interface Props {
organization: Organization;
@@ -13,7 +14,10 @@ interface Props {
function BuilderBreadCrumbs({title, alertName, projectSlug, organization}: Props) {
const crumbs: Array = [
{
- to: `/organizations/${organization.slug}/alerts/rules/`,
+ to: makeAlertsPathname({
+ path: '/rules/',
+ organization,
+ }),
label: t('Alerts'),
preservePageFilters: true,
},
@@ -21,7 +25,10 @@ function BuilderBreadCrumbs({title, alertName, projectSlug, organization}: Props
label: title,
...(alertName
? {
- to: `/organizations/${organization.slug}/alerts/${projectSlug}/wizard`,
+ to: makeAlertsPathname({
+ path: `/${projectSlug}/wizard/`,
+ organization,
+ }),
preservePageFilters: true,
}
: {}),
diff --git a/static/app/views/alerts/builder/projectProvider.tsx b/static/app/views/alerts/builder/projectProvider.tsx
index 8edbefa0e75c9b..73cd9d5cba8168 100644
--- a/static/app/views/alerts/builder/projectProvider.tsx
+++ b/static/app/views/alerts/builder/projectProvider.tsx
@@ -11,6 +11,7 @@ import useApi from 'sentry/utils/useApi';
import {useIsMountedRef} from 'sentry/utils/useIsMountedRef';
import useProjects from 'sentry/utils/useProjects';
import useScrollToTop from 'sentry/utils/useScrollToTop';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
type Props = RouteComponentProps & {
hasMetricAlerts: boolean;
@@ -57,7 +58,10 @@ function AlertBuilderProjectProvider(props: Props) {
// If there's no project show the project selector modal
if (!project && !fetchError) {
navigateTo(
- `/organizations/${organization.slug}/alerts/wizard/?referrer=${props.location.query.referrer}&project=:projectId`,
+ makeAlertsPathname({
+ path: '/wizard/',
+ organization,
+ }) + `?referrer=${props.location.query.referrer}&project=:projectId`,
props.router
);
}
diff --git a/static/app/views/alerts/create.spec.tsx b/static/app/views/alerts/create.spec.tsx
index fab6553ec22a68..b8df8fe270cbde 100644
--- a/static/app/views/alerts/create.spec.tsx
+++ b/static/app/views/alerts/create.spec.tsx
@@ -136,7 +136,7 @@ describe('ProjectAlertsCreate', function () {
await waitFor(() => {
expect(wrapper.router.replace).toHaveBeenCalledWith(
expect.objectContaining({
- pathname: '/organizations/org-slug/alerts/new/metric',
+ pathname: '/organizations/org-slug/alerts/new/metric/',
query: {
aggregate: 'count()',
dataset: 'events',
@@ -360,9 +360,9 @@ describe('ProjectAlertsCreate', function () {
expect(metric.startSpan).toHaveBeenCalledWith({name: 'saveAlertRule'});
await waitFor(() => {
- expect(wrapper.router.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/alerts/rules/project-slug/1/details/',
- });
+ expect(wrapper.router.push).toHaveBeenCalledWith(
+ '/organizations/org-slug/alerts/rules/project-slug/1/details/'
+ );
});
});
@@ -415,9 +415,9 @@ describe('ProjectAlertsCreate', function () {
expect(metric.startSpan).toHaveBeenCalledWith({name: 'saveAlertRule'});
await waitFor(() => {
- expect(wrapper.router.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/alerts/rules/project-slug/1/details/',
- });
+ expect(wrapper.router.push).toHaveBeenCalledWith(
+ '/organizations/org-slug/alerts/rules/project-slug/1/details/'
+ );
});
});
@@ -464,9 +464,9 @@ describe('ProjectAlertsCreate', function () {
expect(metric.startSpan).toHaveBeenCalledWith({name: 'saveAlertRule'});
await waitFor(() => {
- expect(wrapper.router.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/alerts/rules/project-slug/1/details/',
- });
+ expect(wrapper.router.push).toHaveBeenCalledWith(
+ '/organizations/org-slug/alerts/rules/project-slug/1/details/'
+ );
});
});
@@ -510,9 +510,9 @@ describe('ProjectAlertsCreate', function () {
expect(metric.startSpan).toHaveBeenCalledWith({name: 'saveAlertRule'});
await waitFor(() => {
- expect(wrapper.router.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/alerts/rules/project-slug/1/details/',
- });
+ expect(wrapper.router.push).toHaveBeenCalledWith(
+ '/organizations/org-slug/alerts/rules/project-slug/1/details/'
+ );
});
});
});
diff --git a/static/app/views/alerts/create.tsx b/static/app/views/alerts/create.tsx
index 675bb1b58e964f..914d824c8eb09e 100644
--- a/static/app/views/alerts/create.tsx
+++ b/static/app/views/alerts/create.tsx
@@ -15,6 +15,7 @@ import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import {useNavigate} from 'sentry/utils/useNavigate';
import {useUserTeams} from 'sentry/utils/useUserTeams';
import BuilderBreadCrumbs from 'sentry/views/alerts/builder/builderBreadCrumbs';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import IssueRuleEditor from 'sentry/views/alerts/rules/issue';
import MetricRulesCreate from 'sentry/views/alerts/rules/metric/create';
import MetricRuleDuplicate from 'sentry/views/alerts/rules/metric/duplicate';
@@ -74,7 +75,10 @@ function Create(props: Props) {
router.replace(
normalizeUrl({
...location,
- pathname: `/organizations/${organization.slug}/alerts/new/${alertType}`,
+ pathname: makeAlertsPathname({
+ path: `/new/${alertType}/`,
+ organization,
+ }),
query: {
...location.query,
...DEFAULT_WIZARD_TEMPLATE,
@@ -93,6 +97,7 @@ function Create(props: Props) {
location,
organization.slug,
project.slug,
+ organization,
]);
const {teams, isLoading} = useUserTeams();
@@ -154,9 +159,10 @@ function Create(props: Props) {
apiEndpoint={`/organizations/${organization.slug}/monitors/`}
onSubmitSuccess={(data: Monitor) =>
navigate(
- normalizeUrl(
- `/organizations/${organization.slug}/alerts/rules/crons/${data.project.slug}/${data.slug}/details/`
- )
+ makeAlertsPathname({
+ path: `/rules/crons/${data.project.slug}/${data.slug}/details/`,
+ organization,
+ })
)
}
submitLabel={t('Create')}
diff --git a/static/app/views/alerts/list/header.tsx b/static/app/views/alerts/list/header.tsx
index 68ecb9431dcc6c..ff649f903b4442 100644
--- a/static/app/views/alerts/list/header.tsx
+++ b/static/app/views/alerts/list/header.tsx
@@ -9,10 +9,10 @@ import {TabList} from 'sentry/components/tabs';
import {IconSettings} from 'sentry/icons';
import {t} from 'sentry/locale';
import ProjectsStore from 'sentry/stores/projectsStore';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import useRouter from 'sentry/utils/useRouter';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
type Props = {
activeTab: 'stream' | 'rules';
@@ -34,7 +34,10 @@ function AlertHeader({activeTab}: Props) {
const alertRulesLink = (
{t('Alert Rules')}
@@ -85,7 +88,10 @@ function AlertHeader({activeTab}: Props) {
{alertRulesLink}
{t('History')}
diff --git a/static/app/views/alerts/list/rules/alertRulesList.tsx b/static/app/views/alerts/list/rules/alertRulesList.tsx
index b008c8dd688c1e..29a11a22a11d8a 100644
--- a/static/app/views/alerts/list/rules/alertRulesList.tsx
+++ b/static/app/views/alerts/list/rules/alertRulesList.tsx
@@ -284,7 +284,7 @@ function AlertRulesList() {
projectsLoaded={initiallyLoaded}
projects={projects as Project[]}
rule={rule}
- orgId={organization.slug}
+ organization={organization}
onOwnerChange={handleOwnerChange}
onDelete={handleDeleteRule}
hasEditAccess={hasEditAccess}
diff --git a/static/app/views/alerts/list/rules/row.tsx b/static/app/views/alerts/list/rules/row.tsx
index 71e4fbf73c1ca0..dbc9eddb871a1c 100644
--- a/static/app/views/alerts/list/rules/row.tsx
+++ b/static/app/views/alerts/list/rules/row.tsx
@@ -22,12 +22,14 @@ import {IconChevron, IconEllipsis, IconUser} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Actor} from 'sentry/types/core';
+import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {useUserTeams} from 'sentry/utils/useUserTeams';
import AlertLastIncidentActivationInfo from 'sentry/views/alerts/list/rules/alertLastIncidentActivationInfo';
import AlertRuleStatus from 'sentry/views/alerts/list/rules/alertRuleStatus';
import CombinedAlertBadge from 'sentry/views/alerts/list/rules/combinedAlertBadge';
import {getActor} from 'sentry/views/alerts/list/rules/utils';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {UptimeMonitorMode} from 'sentry/views/alerts/rules/uptime/types';
import type {CombinedAlerts} from '../../types';
@@ -38,7 +40,7 @@ type Props = {
hasEditAccess: boolean;
onDelete: (projectId: string, rule: CombinedAlerts) => void;
onOwnerChange: (projectId: string, rule: CombinedAlerts, ownerValue: string) => void;
- orgId: string;
+ organization: Organization;
projects: Project[];
projectsLoaded: boolean;
rule: CombinedAlerts;
@@ -48,7 +50,7 @@ function RuleListRow({
rule,
projectsLoaded,
projects,
- orgId,
+ organization,
onDelete,
onOwnerChange,
hasEditAccess,
@@ -72,7 +74,10 @@ function RuleListRow({
[CombinedAlertType.CRONS]: 'crons-rules',
} satisfies Record;
- const editLink = `/organizations/${orgId}/alerts/${editKey[rule.type]}/${slug}/${rule.id}/`;
+ const editLink = makeAlertsPathname({
+ path: `/${editKey[rule.type]}/${slug}/${rule.id}/`,
+ organization,
+ });
const mutateKey = {
[CombinedAlertType.ISSUE]: 'issue',
@@ -82,7 +87,10 @@ function RuleListRow({
} satisfies Record;
const duplicateLink = {
- pathname: `/organizations/${orgId}/alerts/new/${mutateKey[rule.type]}/`,
+ pathname: makeAlertsPathname({
+ path: `/new/${mutateKey[rule.type]}/`,
+ organization,
+ }),
query: {
project: slug,
duplicateRuleId: rule.id,
@@ -222,13 +230,25 @@ function RuleListRow({
function ruleUrl() {
switch (rule.type) {
case CombinedAlertType.METRIC:
- return `/organizations/${orgId}/alerts/rules/details/${rule.id}/`;
+ return makeAlertsPathname({
+ path: `/rules/details/${rule.id}/`,
+ organization,
+ });
case CombinedAlertType.CRONS:
- return `/organizations/${orgId}/alerts/rules/crons/${rule.project.slug}/${rule.id}/details/`;
+ return makeAlertsPathname({
+ path: `/rules/crons/${rule.project.slug}/${rule.id}/details/`,
+ organization,
+ });
case CombinedAlertType.UPTIME:
- return `/organizations/${orgId}/alerts/rules/uptime/${rule.projectSlug}/${rule.id}/details/`;
+ return makeAlertsPathname({
+ path: `/rules/uptime/${rule.projectSlug}/${rule.id}/details/`,
+ organization,
+ });
default:
- return `/organizations/${orgId}/alerts/rules/${rule.projects[0]}/${rule.id}/details/`;
+ return makeAlertsPathname({
+ path: `/rules/${rule.projects[0]}/${rule.id}/details/`,
+ organization,
+ });
}
}
diff --git a/static/app/views/alerts/pathnames.tsx b/static/app/views/alerts/pathnames.tsx
new file mode 100644
index 00000000000000..e5aa7afd3d50dd
--- /dev/null
+++ b/static/app/views/alerts/pathnames.tsx
@@ -0,0 +1,19 @@
+import type {Organization} from 'sentry/types/organization';
+import normalizeUrl from 'sentry/utils/url/normalizeUrl';
+
+const LEGACY_ALERTS_BASE_PATHNAME = 'alerts';
+const ALERTS_BASE_PATHNAME = 'issues/alerts';
+
+export function makeAlertsPathname({
+ path,
+ organization,
+}: {
+ organization: Organization;
+ path: '/' | `/${string}/`;
+}) {
+ return normalizeUrl(
+ organization.features.includes('navigation-sidebar-v2')
+ ? `/organizations/${organization.slug}/${ALERTS_BASE_PATHNAME}${path}`
+ : `/organizations/${organization.slug}/${LEGACY_ALERTS_BASE_PATHNAME}${path}`
+ );
+}
diff --git a/static/app/views/alerts/rules/crons/edit.tsx b/static/app/views/alerts/rules/crons/edit.tsx
index 3fbfd2506c8d31..c4aa4a69e7d03d 100644
--- a/static/app/views/alerts/rules/crons/edit.tsx
+++ b/static/app/views/alerts/rules/crons/edit.tsx
@@ -11,6 +11,7 @@ import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import {useNavigate} from 'sentry/utils/useNavigate';
import usePageFilters from 'sentry/utils/usePageFilters';
import {useParams} from 'sentry/utils/useParams';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import MonitorForm from 'sentry/views/monitors/components/monitorForm';
import type {Monitor} from 'sentry/views/monitors/types';
import {makeMonitorDetailsQueryKey} from 'sentry/views/monitors/utils';
@@ -54,7 +55,10 @@ export function CronRulesEdit({onChangeTitle, project, organization}: Props) {
setApiQueryData(queryClient, queryKey, data);
navigate(
normalizeUrl({
- pathname: `/organizations/${organization.slug}/alerts/rules/crons/${data.project.slug}/${data.slug}/details/`,
+ pathname: makeAlertsPathname({
+ path: `/rules/crons/${data.project.slug}/${data.slug}/details/`,
+ organization,
+ }),
query: {
environment: selection.environments,
project: selection.projects,
diff --git a/static/app/views/alerts/rules/issue/details/ruleDetails.tsx b/static/app/views/alerts/rules/issue/details/ruleDetails.tsx
index d8eda44c247cb2..1ce579b100b9b8 100644
--- a/static/app/views/alerts/rules/issue/details/ruleDetails.tsx
+++ b/static/app/views/alerts/rules/issue/details/ruleDetails.tsx
@@ -38,6 +38,7 @@ import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyti
import useApi from 'sentry/utils/useApi';
import useOrganization from 'sentry/utils/useOrganization';
import useProjects from 'sentry/utils/useProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {findIncompatibleRules} from 'sentry/views/alerts/rules/issue';
import {ALERT_DEFAULT_CHART_PERIOD} from 'sentry/views/alerts/rules/metric/details/constants';
import {getRuleActionCategory} from 'sentry/views/alerts/rules/utils';
@@ -270,7 +271,10 @@ function AlertRuleDetails({params, location, router}: AlertRuleDetailsProps) {
const ruleActionCategory = getRuleActionCategory(rule);
const duplicateLink = {
- pathname: `/organizations/${organization.slug}/alerts/new/issue/`,
+ pathname: makeAlertsPathname({
+ path: `/new/issue/`,
+ organization,
+ }),
query: {
project: project.slug,
duplicateRuleId: rule.id,
@@ -288,7 +292,10 @@ function AlertRuleDetails({params, location, router}: AlertRuleDetailsProps) {
{
link: (
),
}
@@ -379,7 +386,10 @@ function AlertRuleDetails({params, location, router}: AlertRuleDetailsProps) {
crumbs={[
{
label: t('Alerts'),
- to: `/organizations/${organization.slug}/alerts/rules/`,
+ to: makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ }),
},
{
label: t('Issue Alert'),
@@ -423,7 +433,10 @@ function AlertRuleDetails({params, location, router}: AlertRuleDetailsProps) {
}
- to={`/organizations/${organization.slug}/alerts/rules/${projectSlug}/${ruleId}/`}
+ to={makeAlertsPathname({
+ path: `/rules/${projectSlug}/${ruleId}/`,
+ organization,
+ })}
onClick={() =>
trackAnalytics('issue_alert_rule_details.edit_clicked', {
organization,
diff --git a/static/app/views/alerts/rules/issue/index.spec.tsx b/static/app/views/alerts/rules/issue/index.spec.tsx
index dd029efaba962d..ba5b4a66bd4948 100644
--- a/static/app/views/alerts/rules/issue/index.spec.tsx
+++ b/static/app/views/alerts/rules/issue/index.spec.tsx
@@ -459,9 +459,9 @@ describe('IssueRuleEditor', function () {
await waitFor(() => expect(addLoadingMessage).toHaveBeenCalledTimes(2));
await waitFor(() => expect(addSuccessMessage).toHaveBeenCalledTimes(1));
await waitFor(() => expect(mockSuccess).toHaveBeenCalledTimes(1));
- expect(router.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/alerts/rules/project-slug/1/details/',
- });
+ expect(router.push).toHaveBeenCalledWith(
+ '/organizations/org-slug/alerts/rules/project-slug/1/details/'
+ );
});
it('pending status keeps loading true', async function () {
diff --git a/static/app/views/alerts/rules/issue/index.tsx b/static/app/views/alerts/rules/issue/index.tsx
index dda7619457ef53..6689f2eeec9a20 100644
--- a/static/app/views/alerts/rules/issue/index.tsx
+++ b/static/app/views/alerts/rules/issue/index.tsx
@@ -67,9 +67,9 @@ import {browserHistory} from 'sentry/utils/browserHistory';
import {getDisplayName} from 'sentry/utils/environment';
import {isActiveSuperuser} from 'sentry/utils/isActiveSuperuser';
import recreateRoute from 'sentry/utils/recreateRoute';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import withOrganization from 'sentry/utils/withOrganization';
import withProjects from 'sentry/utils/withProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import FeedbackAlertBanner from 'sentry/views/alerts/rules/issue/feedbackAlertBanner';
import {PreviewIssues} from 'sentry/views/alerts/rules/issue/previewIssues';
import SetupMessagingIntegrationButton, {
@@ -468,8 +468,9 @@ class IssueRuleEditor extends DeprecatedAsyncComponent {
metric.endSpan({name: 'saveAlertRule'});
router.push(
- normalizeUrl({
- pathname: `/organizations/${organization.slug}/alerts/rules/${project.slug}/${rule.id}/details/`,
+ makeAlertsPathname({
+ path: `/rules/${project.slug}/${rule.id}/details/`,
+ organization,
})
);
addSuccessMessage(isNew ? t('Created alert rule') : t('Updated alert rule'));
@@ -601,7 +602,12 @@ class IssueRuleEditor extends DeprecatedAsyncComponent {
handleCancel = () => {
const {organization, router} = this.props;
- router.push(normalizeUrl(`/organizations/${organization.slug}/alerts/rules/`));
+ router.push(
+ makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ })
+ );
};
hasError = (field: string) => {
@@ -909,9 +915,10 @@ class IssueRuleEditor extends DeprecatedAsyncComponent {
openInNewTab
priority="error"
icon={}
- href={normalizeUrl(
- `/organizations/${organization.slug}/alerts/rules/${project.slug}/${duplicateRuleId}/details/`
- )}
+ href={makeAlertsPathname({
+ path: `/rules/${project.slug}/${duplicateRuleId}/details/`,
+ organization,
+ })}
>
{tct(
'This rule fully duplicates "[alertName]" in the project [projectName] and cannot be saved.',
diff --git a/static/app/views/alerts/rules/metric/create.tsx b/static/app/views/alerts/rules/metric/create.tsx
index d00e42e322a1e3..482ead45fabe2b 100644
--- a/static/app/views/alerts/rules/metric/create.tsx
+++ b/static/app/views/alerts/rules/metric/create.tsx
@@ -5,6 +5,7 @@ import {metric} from 'sentry/utils/analytics';
import type EventView from 'sentry/utils/discover/eventView';
import {decodeScalar} from 'sentry/utils/queryString';
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {
createDefaultRule,
createRuleFromEventView,
@@ -42,10 +43,16 @@ function MetricRulesCreate(props: Props) {
metric.endSpan({name: 'saveAlertRule'});
const target = alertRuleId
? {
- pathname: `/organizations/${organization.slug}/alerts/rules/details/${alertRuleId}/`,
+ pathname: makeAlertsPathname({
+ path: `/rules/details/${alertRuleId}/`,
+ organization,
+ }),
}
: {
- pathname: `/organizations/${organization.slug}/alerts/rules/`,
+ pathname: makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ }),
query: {project: project.id},
};
router.push(normalizeUrl(target));
diff --git a/static/app/views/alerts/rules/metric/details/header.tsx b/static/app/views/alerts/rules/metric/details/header.tsx
index f017411476a891..8dd671cd4ac85c 100644
--- a/static/app/views/alerts/rules/metric/details/header.tsx
+++ b/static/app/views/alerts/rules/metric/details/header.tsx
@@ -12,6 +12,7 @@ import {IconCopy, IconEdit} from 'sentry/icons';
import {t} from 'sentry/locale';
import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
import {getAlertRuleActionCategory} from 'sentry/views/alerts/rules/utils';
import {AlertWizardAlertNames} from 'sentry/views/alerts/wizard/options';
@@ -39,11 +40,17 @@ function DetailsHeader({
const isRuleReady = !!rule && !hasMetricRuleDetailsError;
const ruleTitle = rule && !hasMetricRuleDetailsError ? rule.name : '';
const settingsLink = rule
- ? `/organizations/${organization.slug}/alerts/metric-rules/${project?.slug ?? rule?.projects?.[0]}/${rule.id}/`
+ ? makeAlertsPathname({
+ path: `/metric-rules/${project?.slug ?? rule?.projects?.[0]}/${rule.id}/`,
+ organization,
+ })
: '#';
const duplicateLink = {
- pathname: `/organizations/${organization.slug}/alerts/new/metric/`,
+ pathname: makeAlertsPathname({
+ path: `/new/metric/`,
+ organization,
+ }),
query: {
project: project?.slug,
duplicateRuleId: rule?.id,
@@ -66,7 +73,13 @@ function DetailsHeader({
;
diff --git a/static/app/views/alerts/rules/metric/ruleForm.tsx b/static/app/views/alerts/rules/metric/ruleForm.tsx
index b2c15986673812..781781aad50cfe 100644
--- a/static/app/views/alerts/rules/metric/ruleForm.tsx
+++ b/static/app/views/alerts/rules/metric/ruleForm.tsx
@@ -43,8 +43,8 @@ import {
hasOnDemandMetricAlertFeature,
shouldShowOnDemandMetricAlertUI,
} from 'sentry/utils/onDemandMetrics/features';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import withProjects from 'sentry/utils/withProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {IncompatibleAlertQuery} from 'sentry/views/alerts/rules/metric/incompatibleAlertQuery';
import RuleNameOwnerForm from 'sentry/views/alerts/rules/metric/ruleNameOwnerForm';
import ThresholdTypeForm from 'sentry/views/alerts/rules/metric/thresholdTypeForm';
@@ -271,7 +271,12 @@ class RuleFormContainer extends DeprecatedAsyncComponent {
const {router} = this.props;
const {organization} = this.props;
- router.push(normalizeUrl(`/organizations/${organization.slug}/alerts/rules/`));
+ router.push(
+ makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ })
+ );
}
resetPollingState = (loadingSlackIndicator: Indicator) => {
diff --git a/static/app/views/alerts/rules/uptime/details.tsx b/static/app/views/alerts/rules/uptime/details.tsx
index 1f6017374ada01..9e1c69bbfd7c6c 100644
--- a/static/app/views/alerts/rules/uptime/details.tsx
+++ b/static/app/views/alerts/rules/uptime/details.tsx
@@ -34,6 +34,7 @@ import {
import useApi from 'sentry/utils/useApi';
import useOrganization from 'sentry/utils/useOrganization';
import useProjects from 'sentry/utils/useProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {CheckIndicator} from 'sentry/views/alerts/rules/uptime/checkIndicator';
import {
CheckStatus,
@@ -120,7 +121,10 @@ export default function UptimeAlertDetails({params}: UptimeAlertDetailsProps) {
crumbs={[
{
label: t('Alerts'),
- to: `/organizations/${organization.slug}/alerts/rules/`,
+ to: makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ }),
},
{
label: t('Uptime Monitor'),
@@ -147,7 +151,10 @@ export default function UptimeAlertDetails({params}: UptimeAlertDetailsProps) {
}
- to={`/organizations/${organization.slug}/alerts/uptime-rules/${project.slug}/${uptimeRuleId}/`}
+ to={makeAlertsPathname({
+ path: `/uptime-rules/${project.slug}/${uptimeRuleId}/`,
+ organization,
+ })}
>
{t('Edit Rule')}
diff --git a/static/app/views/alerts/rules/uptime/edit.tsx b/static/app/views/alerts/rules/uptime/edit.tsx
index 64527827cdf22b..bc1d472eac2350 100644
--- a/static/app/views/alerts/rules/uptime/edit.tsx
+++ b/static/app/views/alerts/rules/uptime/edit.tsx
@@ -11,9 +11,9 @@ import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {useApiQuery} from 'sentry/utils/queryClient';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useApi from 'sentry/utils/useApi';
import {useNavigate} from 'sentry/utils/useNavigate';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {UptimeAlertForm} from 'sentry/views/alerts/rules/uptime/uptimeAlertForm';
import type {UptimeAlert} from 'sentry/views/alerts/types';
@@ -71,7 +71,12 @@ export function UptimeRulesEdit({params, onChangeTitle, organization, project}:
const handleDelete = async () => {
try {
await api.requestPromise(apiUrl, {method: 'DELETE'});
- navigate(normalizeUrl(`/organizations/${organization.slug}/alerts/rules/`));
+ navigate(
+ makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ })
+ );
} catch (_err) {
addErrorMessage(t('Error deleting rule'));
}
diff --git a/static/app/views/alerts/rules/uptime/existingOrCreate.tsx b/static/app/views/alerts/rules/uptime/existingOrCreate.tsx
index bb76442005ed6e..a52a267a15ecf6 100644
--- a/static/app/views/alerts/rules/uptime/existingOrCreate.tsx
+++ b/static/app/views/alerts/rules/uptime/existingOrCreate.tsx
@@ -2,9 +2,9 @@ import {useEffect} from 'react';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {useApiQuery} from 'sentry/utils/queryClient';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import {useNavigate} from 'sentry/utils/useNavigate';
import useOrganization from 'sentry/utils/useOrganization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {CombinedAlertType, type UptimeAlert} from '../../types';
@@ -34,26 +34,39 @@ export default function ExistingOrCreate() {
// Has one single alert rule
if (existingRules.length === 1) {
- const url = normalizeUrl(
- `/organizations/${organization.slug}/alerts/uptime-rules/${existingRules[0]?.projectSlug}/${existingRules[0]?.id}/`
- );
+ const url = makeAlertsPathname({
+ path: `/uptime-rules/${existingRules[0]?.projectSlug}/${existingRules[0]?.id}/`,
+ organization,
+ });
navigate(url, {replace: true});
return;
}
// Has multiple existing alert rules
if (existingRules.length > 1) {
- const url = normalizeUrl(
- `/organizations/${organization.slug}/alerts/rules/?alertType=uptime`
+ const url = makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ });
+ navigate(
+ {
+ pathname: url,
+ query: {
+ alertType: CombinedAlertType.UPTIME,
+ },
+ },
+ {replace: true}
);
- navigate(url, {replace: true});
return;
}
// No alert rules, create a new one
- const url = normalizeUrl(`/organizations/${organization.slug}/alerts/new/uptime/`);
+ const url = makeAlertsPathname({
+ path: `/new/uptime/`,
+ organization,
+ });
navigate(url, {replace: true});
- }, [existingRules, isPending, navigate, organization.slug]);
+ }, [existingRules, isPending, navigate, organization]);
return ;
}
diff --git a/static/app/views/alerts/rules/uptime/uptimeAlertForm.tsx b/static/app/views/alerts/rules/uptime/uptimeAlertForm.tsx
index 9d263d7c70ca98..b33b411d7bfc1b 100644
--- a/static/app/views/alerts/rules/uptime/uptimeAlertForm.tsx
+++ b/static/app/views/alerts/rules/uptime/uptimeAlertForm.tsx
@@ -27,10 +27,10 @@ import {space} from 'sentry/styles/space';
import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import getDuration from 'sentry/utils/duration/getDuration';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import {useNavigate} from 'sentry/utils/useNavigate';
import useOrganization from 'sentry/utils/useOrganization';
import useProjects from 'sentry/utils/useProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {UptimeRule} from 'sentry/views/alerts/rules/uptime/types';
import {HTTPSnippet} from './httpSnippet';
@@ -103,9 +103,10 @@ export function UptimeAlertForm({project, handleDelete, rule}: Props) {
function onSubmitSuccess(response: any) {
navigate(
- normalizeUrl(
- `/organizations/${organization.slug}/alerts/rules/uptime/${projectSlug}/${response.id}/details/`
- )
+ makeAlertsPathname({
+ path: `/rules/uptime/${projectSlug}/${response.id}/details/`,
+ organization,
+ })
);
}
formModel.setFormOptions({apiEndpoint, onSubmitSuccess});
@@ -114,7 +115,7 @@ export function UptimeAlertForm({project, handleDelete, rule}: Props) {
setEnvironments(selectedProject.environments);
}
}),
- [formModel, navigate, organization.slug, projects, rule]
+ [formModel, navigate, organization, projects, rule]
);
return (
diff --git a/static/app/views/explore/components/chartContextMenu.tsx b/static/app/views/explore/components/chartContextMenu.tsx
index cf0bed967efa98..078dcf7b21005e 100644
--- a/static/app/views/explore/components/chartContextMenu.tsx
+++ b/static/app/views/explore/components/chartContextMenu.tsx
@@ -42,7 +42,7 @@ function ChartContextMenu({
query,
pageFilters: pageFilters.selection,
aggregate: yAxis,
- orgSlug: organization.slug,
+ organization,
dataset: Dataset.EVENTS_ANALYTICS_PLATFORM,
interval,
}),
diff --git a/static/app/views/explore/toolbar/toolbarSaveAs.tsx b/static/app/views/explore/toolbar/toolbarSaveAs.tsx
index d1626f0399ddc5..b158fc0699cb2f 100644
--- a/static/app/views/explore/toolbar/toolbarSaveAs.tsx
+++ b/static/app/views/explore/toolbar/toolbarSaveAs.tsx
@@ -46,7 +46,7 @@ export function ToolbarSaveAs() {
query,
pageFilters: pageFilters.selection,
aggregate: yAxis,
- orgSlug: organization.slug,
+ organization,
dataset: Dataset.EVENTS_ANALYTICS_PLATFORM,
interval,
}),
diff --git a/static/app/views/insights/common/utils/getAlertsUrl.spec.tsx b/static/app/views/insights/common/utils/getAlertsUrl.spec.tsx
index ec3c44464c3d22..16243408d04e1f 100644
--- a/static/app/views/insights/common/utils/getAlertsUrl.spec.tsx
+++ b/static/app/views/insights/common/utils/getAlertsUrl.spec.tsx
@@ -1,3 +1,4 @@
+import {OrganizationFixture} from 'sentry-fixture/organization';
import {PageFiltersFixture} from 'sentry-fixture/pageFilters';
import {initializeOrg} from 'sentry-test/initializeOrg';
@@ -16,7 +17,7 @@ describe('getAlertsUrl', function () {
project,
aggregate,
query,
- orgSlug,
+ organization: OrganizationFixture({slug: orgSlug}),
pageFilters,
});
expect(url).toBe(
@@ -31,7 +32,7 @@ describe('getAlertsUrl', function () {
project,
aggregate,
query,
- orgSlug,
+ organization: OrganizationFixture({slug: orgSlug}),
pageFilters,
dataset: Dataset.EVENTS_ANALYTICS_PLATFORM,
});
diff --git a/static/app/views/insights/common/utils/getAlertsUrl.tsx b/static/app/views/insights/common/utils/getAlertsUrl.tsx
index 3a6defb9e1ccfe..7051071a232479 100644
--- a/static/app/views/insights/common/utils/getAlertsUrl.tsx
+++ b/static/app/views/insights/common/utils/getAlertsUrl.tsx
@@ -1,22 +1,23 @@
import * as qs from 'query-string';
import type {PageFilters} from 'sentry/types/core';
+import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
-import normalizeUrl from 'sentry/utils/url/normalizeUrl';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {Dataset} from 'sentry/views/alerts/rules/metric/types';
export function getAlertsUrl({
project,
query,
aggregate,
- orgSlug,
+ organization,
pageFilters,
name,
interval,
dataset = Dataset.GENERIC_METRICS,
}: {
aggregate: string;
- orgSlug: string;
+ organization: Organization;
pageFilters: PageFilters;
dataset?: Dataset;
interval?: string;
@@ -38,8 +39,12 @@ export function getAlertsUrl({
name,
interval: supportedInterval,
};
- return normalizeUrl(
- `/organizations/${orgSlug}/alerts/new/metric/?${qs.stringify(queryParams)}`
+
+ return (
+ makeAlertsPathname({
+ path: `/new/metric/`,
+ organization,
+ }) + `?${qs.stringify(queryParams)}`
);
}
diff --git a/static/app/views/insights/uptime/components/overviewTimeline/overviewRow.tsx b/static/app/views/insights/uptime/components/overviewTimeline/overviewRow.tsx
index dfe3b0b962b604..b92f86bec0f7ec 100644
--- a/static/app/views/insights/uptime/components/overviewTimeline/overviewRow.tsx
+++ b/static/app/views/insights/uptime/components/overviewTimeline/overviewRow.tsx
@@ -16,6 +16,7 @@ import getDuration from 'sentry/utils/duration/getDuration';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import useProjectFromSlug from 'sentry/utils/useProjectFromSlug';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {UptimeRule} from 'sentry/views/alerts/rules/uptime/types';
import {checkStatusPrecedent, statusToText, tickStyle} from '../../timelineConfig';
@@ -51,7 +52,10 @@ export function OverviewRow({uptimeRule, timeWindowConfig, singleRuleView}: Prop
diff --git a/static/app/views/insights/uptime/views/overview.tsx b/static/app/views/insights/uptime/views/overview.tsx
index 4bbb9443128d88..9e959408caf7b5 100644
--- a/static/app/views/insights/uptime/views/overview.tsx
+++ b/static/app/views/insights/uptime/views/overview.tsx
@@ -26,6 +26,7 @@ import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyti
import {useLocation} from 'sentry/utils/useLocation';
import {useNavigate} from 'sentry/utils/useNavigate';
import useOrganization from 'sentry/utils/useOrganization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {UptimeRule} from 'sentry/views/alerts/rules/uptime/types';
import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders';
import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader';
@@ -108,7 +109,10 @@ export default function UptimeOverview() {
}
size="sm"
priority="primary"
- to={`/organizations/${organization.slug}/alerts/new/uptime/`}
+ to={makeAlertsPathname({
+ path: `/new/uptime/`,
+ organization,
+ })}
icon={}
>
{t('Add Uptime Monitor')}
@@ -157,7 +161,10 @@ export default function UptimeOverview() {
}
>
{t('Add Uptime Monitor')}
diff --git a/static/app/views/issueDetails/streamline/sidebar/detectorSection.tsx b/static/app/views/issueDetails/streamline/sidebar/detectorSection.tsx
index 5976441a014c16..f6e57e60197242 100644
--- a/static/app/views/issueDetails/streamline/sidebar/detectorSection.tsx
+++ b/static/app/views/issueDetails/streamline/sidebar/detectorSection.tsx
@@ -8,6 +8,7 @@ import type {Group} from 'sentry/types/group';
import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {useIssueDetails} from 'sentry/views/issueDetails/streamline/context';
import {SidebarSectionTitle} from 'sentry/views/issueDetails/streamline/sidebar/sidebar';
@@ -38,7 +39,10 @@ export function getDetectorDetails({
return {
detectorType: 'metric_alert',
detectorId: metricAlertRuleId,
- detectorPath: `/organizations/${organization.slug}/alerts/rules/details/${metricAlertRuleId}/`,
+ detectorPath: makeAlertsPathname({
+ path: `/rules/details/${metricAlertRuleId}/`,
+ organization,
+ }),
// TODO(issues): We can probably enrich this description with details from the alert itself.
description: t(
'This issue was created by a metric alert detector. View the detector details to learn more.'
@@ -53,7 +57,10 @@ export function getDetectorDetails({
detectorType: 'cron_monitor',
detectorId: cronId,
detectorSlug: cronSlug,
- detectorPath: `/organizations/${organization.slug}/alerts/rules/crons/${project.slug}/${cronSlug}/details/`,
+ detectorPath: makeAlertsPathname({
+ path: `/rules/crons/${project.slug}/${cronSlug}/details/`,
+ organization,
+ }),
description: t(
'This issue was created by a cron monitor. View the monitor details to learn more.'
),
@@ -65,7 +72,10 @@ export function getDetectorDetails({
return {
detectorType: 'uptime_monitor',
detectorId: uptimeAlertRuleId,
- detectorPath: `/organizations/${organization.slug}/alerts/rules/uptime/${project.slug}/${uptimeAlertRuleId}/details/`,
+ detectorPath: makeAlertsPathname({
+ path: `/rules/uptime/${project.slug}/${uptimeAlertRuleId}/details/`,
+ organization,
+ }),
// TODO(issues): Update this to mention detectors when that language is user-facing
description: t(
'This issue was created by an uptime monitoring alert rule after detecting 3 consecutive failed checks.'
diff --git a/static/app/views/monitors/components/monitorForm.tsx b/static/app/views/monitors/components/monitorForm.tsx
index e1e49b27fb94eb..29bde4e6f9bae0 100644
--- a/static/app/views/monitors/components/monitorForm.tsx
+++ b/static/app/views/monitors/components/monitorForm.tsx
@@ -30,6 +30,7 @@ import commonTheme from 'sentry/utils/theme';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import useProjects from 'sentry/utils/useProjects';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {getScheduleIntervals} from 'sentry/views/monitors/utils';
import {crontabAsText} from 'sentry/views/monitors/utils/crontabAsText';
@@ -494,7 +495,10 @@ function MonitorForm({
{monitor?.config.alert_rule_id && (
{t('Customize this monitors notification configuration in Alerts')}
diff --git a/static/app/views/monitors/components/monitorHeader.tsx b/static/app/views/monitors/components/monitorHeader.tsx
index 1d8aebf8ac280d..16d8811185c744 100644
--- a/static/app/views/monitors/components/monitorHeader.tsx
+++ b/static/app/views/monitors/components/monitorHeader.tsx
@@ -2,6 +2,8 @@ import {Breadcrumbs} from 'sentry/components/breadcrumbs';
import IdBadge from 'sentry/components/idBadge';
import * as Layout from 'sentry/components/layouts/thirds';
import {t} from 'sentry/locale';
+import useOrganization from 'sentry/utils/useOrganization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {Monitor} from '../types';
@@ -18,11 +20,15 @@ interface Props {
}
export function MonitorHeader({monitor, orgSlug, onUpdate, linkToAlerts}: Props) {
+ const organization = useOrganization();
const crumbs = [
{
label: linkToAlerts ? t('Alerts') : t('Crons'),
to: linkToAlerts
- ? `/organizations/${orgSlug}/alerts/rules/`
+ ? makeAlertsPathname({
+ path: `/rules/`,
+ organization,
+ })
: `/organizations/${orgSlug}/crons/`,
preservePageFilters: true,
},
diff --git a/static/app/views/monitors/components/monitorHeaderActions.tsx b/static/app/views/monitors/components/monitorHeaderActions.tsx
index 0d251fa8b76b24..1ac40c4e60139c 100644
--- a/static/app/views/monitors/components/monitorHeaderActions.tsx
+++ b/static/app/views/monitors/components/monitorHeaderActions.tsx
@@ -8,7 +8,9 @@ import {t} from 'sentry/locale';
import {browserHistory} from 'sentry/utils/browserHistory';
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useApi from 'sentry/utils/useApi';
+import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {Monitor} from '../types';
@@ -26,6 +28,7 @@ type Props = {
function MonitorHeaderActions({monitor, orgSlug, onUpdate, linkToAlerts}: Props) {
const api = useApi();
+ const organization = useOrganization();
const {selection} = usePageFilters();
const endpointOptions = {
@@ -81,7 +84,10 @@ function MonitorHeaderActions({monitor, orgSlug, onUpdate, linkToAlerts}: Props)
icon={}
to={{
pathname: linkToAlerts
- ? `/organizations/${orgSlug}/alerts/crons-rules/${monitor.project.slug}/${monitor.slug}/`
+ ? makeAlertsPathname({
+ path: `/crons-rules/${monitor.project.slug}/${monitor.slug}/`,
+ organization,
+ })
: `/organizations/${orgSlug}/crons/${monitor.project.slug}/${monitor.slug}/edit/`,
// TODO(davidenwang): Right now we have to pass the environment
// through the URL so that when we save the monitor and are
diff --git a/static/app/views/monitors/components/newMonitorButton.tsx b/static/app/views/monitors/components/newMonitorButton.tsx
index c16ac76edc0cb0..0807b52e430ca7 100644
--- a/static/app/views/monitors/components/newMonitorButton.tsx
+++ b/static/app/views/monitors/components/newMonitorButton.tsx
@@ -2,6 +2,7 @@ import type {LinkButtonProps} from 'sentry/components/button';
import {LinkButton} from 'sentry/components/button';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
interface Props extends Omit {
/**
@@ -18,7 +19,10 @@ export function NewMonitorButton({linkToAlerts, ...props}: Props) {
{t('Create Alert')}
@@ -182,7 +186,10 @@ function TeamAlertsTriggered({
{rule.name}
diff --git a/static/app/views/projectDetail/projectLatestAlerts.tsx b/static/app/views/projectDetail/projectLatestAlerts.tsx
index 3788fe369660bd..dcd15a2c1d7c10 100644
--- a/static/app/views/projectDetail/projectLatestAlerts.tsx
+++ b/static/app/views/projectDetail/projectLatestAlerts.tsx
@@ -15,6 +15,8 @@ import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Organization} from 'sentry/types/organization';
import {useApiQuery} from 'sentry/utils/queryClient';
+import useOrganization from 'sentry/utils/useOrganization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import type {Incident} from 'sentry/views/alerts/types';
import {IncidentStatus} from 'sentry/views/alerts/types';
@@ -25,10 +27,10 @@ const PLACEHOLDER_AND_EMPTY_HEIGHT = '172px';
interface AlertRowProps {
alert: Incident;
- orgSlug: string;
}
-function AlertRow({alert, orgSlug}: AlertRowProps) {
+function AlertRow({alert}: AlertRowProps) {
+ const organization = useOrganization();
const {status, identifier, title, dateClosed, dateStarted} = alert;
const isResolved = status === IncidentStatus.CLOSED;
const isWarning = status === IncidentStatus.WARNING;
@@ -40,7 +42,10 @@ function AlertRow({alert, orgSlug}: AlertRowProps) {
return (
@@ -154,9 +159,7 @@ function ProjectLatestAlerts({
return alertsUnresolvedAndResolved
.slice(0, 3)
- .map(alert => (
-
- ));
+ .map(alert => );
}
return (
@@ -166,7 +169,10 @@ function ProjectLatestAlerts({
{/* as this is a link to latest alerts, we want to only preserve project and environment */}
{t('Add Alert Rule')}
diff --git a/static/app/views/settings/projectAlerts/settings.tsx b/static/app/views/settings/projectAlerts/settings.tsx
index af02e095ed8e44..6a5080d4e65ac7 100644
--- a/static/app/views/settings/projectAlerts/settings.tsx
+++ b/static/app/views/settings/projectAlerts/settings.tsx
@@ -19,6 +19,7 @@ import type {ApiQueryKey} from 'sentry/utils/queryClient';
import {setApiQueryData, useApiQuery, useQueryClient} from 'sentry/utils/queryClient';
import routeTitleGen from 'sentry/utils/routeTitle';
import useOrganization from 'sentry/utils/useOrganization';
+import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
import {ProjectPermissionAlert} from 'sentry/views/settings/project/projectPermissionAlert';
@@ -107,7 +108,10 @@ function ProjectAlertSettings({canEditRule, params}: ProjectAlertSettingsProps)
action={