From 50d43662b4388ae8a512364fd1ac3f206cf3066f Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Tue, 25 Nov 2025 10:18:57 -0800 Subject: [PATCH 1/2] chore(seer): Setup new, blank, page for Seer settings to live This is all behind a feature flag called "seer-settings-gtm". I tested things by enabling the flag with the toolbar and I can see that urls like /settings/seer/ and /settings/seer/projects/ and /settings/seer/repositories/ show the basic html that is defined. When I toggle the flag off (again, via the toolbar) I can see the "You dont have access to this feature " message as expected. By setting up the flag and the blank pages like this it should be easier to do work in parallel against all three pages, and the original settings page is not affected. --- src/sentry/features/temporary.py | 2 + static/app/router/routes.tsx | 13 +++- .../seerAutomationDefault.tsx | 0 .../seerAutomationProjectList.tsx | 0 .../gsApp/views/seerAutomation/index.spec.tsx | 2 +- static/gsApp/views/seerAutomation/index.tsx | 59 +++---------------- .../gsApp/views/seerAutomation/projects.tsx | 17 ++++++ .../views/seerAutomation/repositories.tsx | 17 ++++++ .../views/seerAutomation/seerAutomation.tsx | 58 ++++++++++++++++++ .../gsApp/views/seerAutomation/settings.tsx | 17 ++++++ 10 files changed, 132 insertions(+), 53 deletions(-) rename static/gsApp/views/seerAutomation/{ => components}/seerAutomationDefault.tsx (100%) rename static/gsApp/views/seerAutomation/{ => components}/seerAutomationProjectList.tsx (100%) create mode 100644 static/gsApp/views/seerAutomation/projects.tsx create mode 100644 static/gsApp/views/seerAutomation/repositories.tsx create mode 100644 static/gsApp/views/seerAutomation/seerAutomation.tsx create mode 100644 static/gsApp/views/seerAutomation/settings.tsx diff --git a/src/sentry/features/temporary.py b/src/sentry/features/temporary.py index d6a982282683ad..3a9c8684f703a2 100644 --- a/src/sentry/features/temporary.py +++ b/src/sentry/features/temporary.py @@ -380,6 +380,8 @@ def register_temporary_features(manager: FeatureManager) -> None: manager.add("organizations:seer-coding-agent-integrations", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) # Enable Seer Explorer panel for AI-powered data exploration manager.add("organizations:seer-explorer", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) + # Enable Seer GTM Settings page designs + manager.add("organizations:seer-settings-gtm", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) # Enable search query builder boolean operator select feature manager.add("organizations:search-query-builder-add-boolean-operator-select", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) # Enable search query builder case insensitivity features diff --git a/static/app/router/routes.tsx b/static/app/router/routes.tsx index 764fb3dc187168..ddc7f24f0f32f2 100644 --- a/static/app/router/routes.tsx +++ b/static/app/router/routes.tsx @@ -1214,10 +1214,21 @@ function buildRoutes(): RouteObject[] { { path: 'seer/', name: t('Seer Automation'), + component: make(() => import('getsentry/views/seerAutomation/index')), children: [ { index: true, - component: make(() => import('getsentry/views/seerAutomation')), + component: make(() => import('getsentry/views/seerAutomation/seerAutomation')), + }, + { + path: 'projects/', + name: t('Seer'), + component: make(() => import('getsentry/views/seerAutomation/projects')), + }, + { + path: 'repositories/', + name: t('Seer'), + component: make(() => import('getsentry/views/seerAutomation/repositories')), }, { path: 'onboarding/', diff --git a/static/gsApp/views/seerAutomation/seerAutomationDefault.tsx b/static/gsApp/views/seerAutomation/components/seerAutomationDefault.tsx similarity index 100% rename from static/gsApp/views/seerAutomation/seerAutomationDefault.tsx rename to static/gsApp/views/seerAutomation/components/seerAutomationDefault.tsx diff --git a/static/gsApp/views/seerAutomation/seerAutomationProjectList.tsx b/static/gsApp/views/seerAutomation/components/seerAutomationProjectList.tsx similarity index 100% rename from static/gsApp/views/seerAutomation/seerAutomationProjectList.tsx rename to static/gsApp/views/seerAutomation/components/seerAutomationProjectList.tsx diff --git a/static/gsApp/views/seerAutomation/index.spec.tsx b/static/gsApp/views/seerAutomation/index.spec.tsx index f23bff7947b986..f503d4dec553bd 100644 --- a/static/gsApp/views/seerAutomation/index.spec.tsx +++ b/static/gsApp/views/seerAutomation/index.spec.tsx @@ -5,7 +5,7 @@ import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingL import ProjectsStore from 'sentry/stores/projectsStore'; -import SeerAutomationRoot from './index'; +import SeerAutomationRoot from 'getsentry/views/seerAutomation'; describe('SeerAutomation', () => { beforeEach(() => { diff --git a/static/gsApp/views/seerAutomation/index.tsx b/static/gsApp/views/seerAutomation/index.tsx index ddc698563da609..11c395a17f9b24 100644 --- a/static/gsApp/views/seerAutomation/index.tsx +++ b/static/gsApp/views/seerAutomation/index.tsx @@ -1,24 +1,18 @@ import {Fragment} from 'react'; +import {Outlet} from 'react-router-dom'; + +import {Stack} from '@sentry/scraps/layout/stack'; -import {LinkButton} from 'sentry/components/core/button/linkButton'; import {useOrganizationSeerSetup} from 'sentry/components/events/autofix/useOrganizationSeerSetup'; -import ExternalLink from 'sentry/components/links/externalLink'; import {NoAccess} from 'sentry/components/noAccess'; -import NoProjectMessage from 'sentry/components/noProjectMessage'; import Placeholder from 'sentry/components/placeholder'; import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; -import {t, tct} from 'sentry/locale'; -import {DataCategoryExact} from 'sentry/types/core'; +import {t} from 'sentry/locale'; import useOrganization from 'sentry/utils/useOrganization'; -import {getPricingDocsLinkForEventType} from 'sentry/views/settings/account/notifications/utils'; -import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader'; import AiSetupDataConsent from 'getsentry/components/ai/AiSetupDataConsent'; -import {SeerAutomationDefault} from './seerAutomationDefault'; -import {SeerAutomationProjectList} from './seerAutomationProjectList'; - -function SeerAutomationRoot() { +export default function SeerAutomationRoot() { const organization = useOrganization(); const {isLoading, billing, setupAcknowledgement} = useOrganizationSeerSetup(); @@ -29,14 +23,12 @@ function SeerAutomationRoot() { // Show loading placeholders while checking setup if (isLoading) { return ( - + -
-
-
+ ); } @@ -57,40 +49,5 @@ function SeerAutomationRoot() { ); } - // Show the regular settings page - return ( - - - , - spendlink: ( - - ), - } - )} - action={ - - {t('Read the docs')} - - } - /> - - - -
- -
-
- ); + return ; } - -export default SeerAutomationRoot; diff --git a/static/gsApp/views/seerAutomation/projects.tsx b/static/gsApp/views/seerAutomation/projects.tsx new file mode 100644 index 00000000000000..3b41bea4fb04e3 --- /dev/null +++ b/static/gsApp/views/seerAutomation/projects.tsx @@ -0,0 +1,17 @@ +import Feature from 'sentry/components/acl/feature'; +import {NoAccess} from 'sentry/components/noAccess'; +import useOrganization from 'sentry/utils/useOrganization'; + +export default function SeerAutomationProjects() { + const organization = useOrganization(); + + return ( + +
SeerAutomationProjects
+
+ ); +} diff --git a/static/gsApp/views/seerAutomation/repositories.tsx b/static/gsApp/views/seerAutomation/repositories.tsx new file mode 100644 index 00000000000000..2d9787655abb30 --- /dev/null +++ b/static/gsApp/views/seerAutomation/repositories.tsx @@ -0,0 +1,17 @@ +import Feature from 'sentry/components/acl/feature'; +import {NoAccess} from 'sentry/components/noAccess'; +import useOrganization from 'sentry/utils/useOrganization'; + +export default function SeerAutomationRepositories() { + const organization = useOrganization(); + + return ( + +
SeerAutomationRepositories
+
+ ); +} diff --git a/static/gsApp/views/seerAutomation/seerAutomation.tsx b/static/gsApp/views/seerAutomation/seerAutomation.tsx new file mode 100644 index 00000000000000..128d34cfc3f19c --- /dev/null +++ b/static/gsApp/views/seerAutomation/seerAutomation.tsx @@ -0,0 +1,58 @@ +import {Fragment} from 'react'; + +import {LinkButton} from 'sentry/components/core/button/linkButton'; +import ExternalLink from 'sentry/components/links/externalLink'; +import NoProjectMessage from 'sentry/components/noProjectMessage'; +import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; +import {t, tct} from 'sentry/locale'; +import {DataCategoryExact} from 'sentry/types/core'; +import useOrganization from 'sentry/utils/useOrganization'; +import {getPricingDocsLinkForEventType} from 'sentry/views/settings/account/notifications/utils'; +import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader'; + +import {SeerAutomationDefault} from 'getsentry/views/seerAutomation/components/seerAutomationDefault'; +import {SeerAutomationProjectList} from 'getsentry/views/seerAutomation/components/seerAutomationProjectList'; +import Settings from 'getsentry/views/seerAutomation/settings'; + +export default function SeerAutomation() { + const organization = useOrganization(); + + if (organization.features.includes('seer-settings-gtm')) { + return ; + } + + // Show the regular settings page + return ( + + + , + spendlink: ( + + ), + } + )} + action={ + + {t('Read the docs')} + + } + /> + + + +
+ +
+
+ ); +} diff --git a/static/gsApp/views/seerAutomation/settings.tsx b/static/gsApp/views/seerAutomation/settings.tsx new file mode 100644 index 00000000000000..6da46507869010 --- /dev/null +++ b/static/gsApp/views/seerAutomation/settings.tsx @@ -0,0 +1,17 @@ +import Feature from 'sentry/components/acl/feature'; +import {NoAccess} from 'sentry/components/noAccess'; +import useOrganization from 'sentry/utils/useOrganization'; + +export default function SeerAutomationSettings() { + const organization = useOrganization(); + + return ( + +
SeerAutomationSettings
+
+ ); +} From 56e1658af669f7ccc25d263815dbd224c8dcc9ac Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Tue, 25 Nov 2025 13:55:48 -0800 Subject: [PATCH 2/2] test only the page contents --- static/gsApp/views/seerAutomation/index.spec.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/gsApp/views/seerAutomation/index.spec.tsx b/static/gsApp/views/seerAutomation/index.spec.tsx index f503d4dec553bd..5af94c7b7ddfdd 100644 --- a/static/gsApp/views/seerAutomation/index.spec.tsx +++ b/static/gsApp/views/seerAutomation/index.spec.tsx @@ -5,7 +5,7 @@ import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingL import ProjectsStore from 'sentry/stores/projectsStore'; -import SeerAutomationRoot from 'getsentry/views/seerAutomation'; +import SeerAutomation from 'getsentry/views/seerAutomation/seerAutomation'; describe('SeerAutomation', () => { beforeEach(() => { @@ -61,7 +61,7 @@ describe('SeerAutomation', () => { }, }); - render(, {organization}); + render(, {organization}); // Project details populate the project list const projectItem = await screen.findByText(project.slug); @@ -124,7 +124,7 @@ describe('SeerAutomation', () => { }, }); - render(, {organization}); + render(, {organization}); // Find the toggle for Default for Issue Scans const toggle = await screen.findByRole('checkbox', {