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={