diff --git a/static/app/router/routes.tsx b/static/app/router/routes.tsx index 757f4e320448c0..76f3c08ab11e75 100644 --- a/static/app/router/routes.tsx +++ b/static/app/router/routes.tsx @@ -12,6 +12,10 @@ import {ProvideAriaRouter} from 'sentry/utils/provideAriaRouter'; import {translateSentryRoute} from 'sentry/utils/reactRouter6Compat/router'; import withDomainRedirect from 'sentry/utils/withDomainRedirect'; import withDomainRequired from 'sentry/utils/withDomainRequired'; +import { + WorkflowEngineRedirectToAutomationDetails, + WorkflowEngineRedirectToAutomationEdit, +} from 'sentry/views/alerts/workflowEngineRedirects'; import App from 'sentry/views/app'; import {AppBodyContent} from 'sentry/views/app/appBodyContent'; import AuthLayout from 'sentry/views/auth/layout'; @@ -1487,13 +1491,22 @@ function buildRoutes(): RouteObject[] { }, { path: ':ruleId/', - component: make(() => import('sentry/views/alerts/edit')), + component: WorkflowEngineRedirectToAutomationEdit, deprecatedRouteProps: true, + children: [ + { + index: true, + component: make(() => import('sentry/views/alerts/edit')), + deprecatedRouteProps: true, + }, + ], }, ], }, { path: ':projectId/:ruleId/details/', + component: WorkflowEngineRedirectToAutomationDetails, + deprecatedRouteProps: true, children: [ { index: true, diff --git a/static/app/views/alerts/workflowEngineRedirects.tsx b/static/app/views/alerts/workflowEngineRedirects.tsx new file mode 100644 index 00000000000000..370caad107e92d --- /dev/null +++ b/static/app/views/alerts/workflowEngineRedirects.tsx @@ -0,0 +1,109 @@ +import {cloneElement, isValidElement} from 'react'; + +import LoadingIndicator from 'sentry/components/loadingIndicator'; +import Redirect from 'sentry/components/redirect'; +import {useApiQuery} from 'sentry/utils/queryClient'; +import useOrganization from 'sentry/utils/useOrganization'; +import {useParams} from 'sentry/utils/useParams'; +import {useUser} from 'sentry/utils/useUser'; +import { + makeAutomationDetailsPathname, + makeAutomationEditPathname, +} from 'sentry/views/automations/pathnames'; + +interface AlertRuleWorkflow { + alertRuleId: string | null; + ruleId: string | null; + workflowId: string; +} + +/** + * Base component for workflow engine redirects that require fetching + * workflow data from a rule before redirecting. + */ +function WorkflowEngineRedirectWithData({ + children, + makeRedirectPath, + ...props +}: { + children: React.ReactNode; + makeRedirectPath: (workflowId: string, orgSlug: string) => string; +}) { + const user = useUser(); + const organization = useOrganization(); + const params = useParams<{projectId: string; ruleId: string}>(); + const {ruleId} = params; + + const shouldRedirect = + !user.isStaff && organization.features.includes('workflow-engine-ui'); + + const {data: alertRuleWorkflow, isPending} = useApiQuery( + [ + `/organizations/${organization.slug}/alert-rule-workflow/`, + {query: {rule_id: ruleId}}, + ], + { + staleTime: 0, + enabled: shouldRedirect, + retry: false, + } + ); + + if (shouldRedirect) { + if (isPending) { + return ; + } + if (alertRuleWorkflow) { + return ( + + ); + } + } + + // Pass through all props to children + if (isValidElement(children)) { + return cloneElement(children, props); + } + + return children; +} + +// Data-dependent redirects + +export function WorkflowEngineRedirectToAutomationDetails({ + children, + ...props +}: { + children: React.ReactNode; +}) { + return ( + + makeAutomationDetailsPathname(orgSlug, workflowId) + } + {...props} + > + {children} + + ); +} + +export function WorkflowEngineRedirectToAutomationEdit({ + children, + ...props +}: { + children: React.ReactNode; +}) { + return ( + + makeAutomationEditPathname(orgSlug, workflowId) + } + {...props} + > + {children} + + ); +} diff --git a/tests/acceptance/test_organization_alert_rule_details.py b/tests/acceptance/test_organization_alert_rule_details.py index 8640c13bf00fa8..bd7aeb8d5a6e7a 100644 --- a/tests/acceptance/test_organization_alert_rule_details.py +++ b/tests/acceptance/test_organization_alert_rule_details.py @@ -5,17 +5,19 @@ from sentry.models.rule import Rule from sentry.models.rulefirehistory import RuleFireHistory from sentry.testutils.cases import AcceptanceTestCase, SnubaTestCase +from sentry.testutils.helpers import with_feature from sentry.testutils.silo import no_silo_test @no_silo_test +@with_feature({"organizations:workflow-engine-ui": False}) class OrganizationAlertRuleDetailsTest(AcceptanceTestCase, SnubaTestCase): def setUp(self) -> None: super().setUp() self.login_as(self.user) self.project = self.create_project(fire_project_created=True) self.rule = Rule.objects.get(project=self.project) - self.path = f"/organizations/{self.organization.slug}/alerts/rules/{self.project.slug}/{self.rule.id}/details/" + self.path = f"/organizations/{self.organization.slug}/issues/alerts/rules/{self.project.slug}/{self.rule.id}/details/" def test_empty_alert_rule_details(self) -> None: self.browser.get(self.path)