Browse Source

feat(insights): update routing for backend, mobile, and ai domain views (#78127)

Work for https://github.com/getsentry/sentry/issues/77572
Pretty much exactly the same as
https://github.com/getsentry/sentry/pull/78027 except for ai, mobile and
backend modules.

Some additional changes
1. Removed some unused code directly related to this change
2. Update names to `frontendOverviewPage` from `frontendLandingPage` for
consistency

There's a couple things we can share between each domain view quite
easily, this will be done in follow up PRs
Dominik Buszowiecki 5 months ago
parent
commit
fe96e0e2ff

+ 3 - 3
static/app/components/sidebar/index.tsx

@@ -56,11 +56,11 @@ import {MODULE_SIDEBAR_TITLE as HTTP_MODULE_SIDEBAR_TITLE} from 'sentry/views/in
 import {
   AI_LANDING_SUB_PATH,
   AI_LANDING_TITLE,
-} from 'sentry/views/insights/pages/aiLandingPage';
+} from 'sentry/views/insights/pages/ai/settings';
 import {
   BACKEND_LANDING_SUB_PATH,
   BACKEND_LANDING_TITLE,
-} from 'sentry/views/insights/pages/backendLandingPage';
+} from 'sentry/views/insights/pages/backend/settings';
 import {
   FRONTEND_LANDING_SUB_PATH,
   FRONTEND_LANDING_TITLE,
@@ -68,7 +68,7 @@ import {
 import {
   MOBILE_LANDING_SUB_PATH,
   MOBILE_LANDING_TITLE,
-} from 'sentry/views/insights/pages/mobileLandingPage';
+} from 'sentry/views/insights/pages/mobile/settings';
 import {MODULE_TITLES} from 'sentry/views/insights/settings';
 import MetricsOnboardingSidebar from 'sentry/views/metrics/ddmOnboarding/sidebar';
 

+ 102 - 16
static/app/routes.tsx

@@ -15,10 +15,10 @@ import withDomainRequired from 'sentry/utils/withDomainRequired';
 import App from 'sentry/views/app';
 import AuthLayout from 'sentry/views/auth/layout';
 import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
-import {AI_LANDING_SUB_PATH} from 'sentry/views/insights/pages/aiLandingPage';
-import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backendLandingPage';
+import {AI_LANDING_SUB_PATH} from 'sentry/views/insights/pages/ai/settings';
+import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
 import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
-import {MOBILE_LANDING_SUB_PATH} from 'sentry/views/insights/pages/mobileLandingPage';
+import {MOBILE_LANDING_SUB_PATH} from 'sentry/views/insights/pages/mobile/settings';
 import {INSIGHTS_BASE_URL} from 'sentry/views/insights/settings';
 import {ModuleName} from 'sentry/views/insights/types';
 import {Tab, TabPaths} from 'sentry/views/issueDetails/types';
@@ -1644,7 +1644,7 @@ function buildRoutes() {
       <Route path={`${FRONTEND_LANDING_SUB_PATH}/`}>
         <IndexRoute
           component={make(
-            () => import('sentry/views/insights/pages/frontend/frontendLandingPage')
+            () => import('sentry/views/insights/pages/frontend/frontendOverviewPage')
           )}
         />
         <Route path={`${MODULE_BASE_URLS[ModuleName.HTTP]}/`}>
@@ -1696,18 +1696,104 @@ function buildRoutes() {
           />
         </Route>
       </Route>
-      <Route
-        path={`${BACKEND_LANDING_SUB_PATH}/`}
-        component={make(() => import('sentry/views/insights/pages/backendLandingPage'))}
-      />
-      <Route
-        path={`${MOBILE_LANDING_SUB_PATH}/`}
-        component={make(() => import('sentry/views/insights/pages/mobileLandingPage'))}
-      />
-      <Route
-        path={`${AI_LANDING_SUB_PATH}/`}
-        component={make(() => import('sentry/views/insights/pages/aiLandingPage'))}
-      />
+      <Route path={`${BACKEND_LANDING_SUB_PATH}/`}>
+        <IndexRoute
+          component={make(
+            () => import('sentry/views/insights/pages/backend/backendOverviewPage')
+          )}
+        />
+        <Route path={`${MODULE_BASE_URLS[ModuleName.DB]}/`}>
+          <IndexRoute
+            component={make(
+              () => import('sentry/views/insights/database/views/databaseLandingPage')
+            )}
+          />
+          <Route
+            path="spans/span/:groupId/"
+            component={make(
+              () => import('sentry/views/insights/database/views/databaseSpanSummaryPage')
+            )}
+          />
+        </Route>
+        <Route path={`${MODULE_BASE_URLS[ModuleName.HTTP]}/`}>
+          <IndexRoute
+            component={make(
+              () => import('sentry/views/insights/http/views/httpLandingPage')
+            )}
+          />
+          <Route
+            path="domains/"
+            component={make(
+              () => import('sentry/views/insights/http/views/httpDomainSummaryPage')
+            )}
+          />
+        </Route>
+        <Route path={`${MODULE_BASE_URLS[ModuleName.CACHE]}/`}>
+          <IndexRoute
+            component={make(
+              () => import('sentry/views/insights/cache/views/cacheLandingPage')
+            )}
+          />
+        </Route>
+        <Route path={`${MODULE_BASE_URLS[ModuleName.QUEUE]}/`}>
+          <IndexRoute
+            component={make(
+              () => import('sentry/views/insights/queues/views/queuesLandingPage')
+            )}
+          />
+          <Route
+            path="destination/"
+            component={make(
+              () => import('sentry/views/insights/queues/views/destinationSummaryPage')
+            )}
+          />
+        </Route>
+      </Route>
+      <Route path={`${MOBILE_LANDING_SUB_PATH}/`}>
+        <IndexRoute
+          component={make(
+            () => import('sentry/views/insights/pages/mobile/mobileOverviewPage')
+          )}
+        />
+        <Route path={`${MODULE_BASE_URLS[ModuleName.MOBILE_SCREENS]}/`}>
+          <IndexRoute
+            component={make(
+              () =>
+                import('sentry/views/insights/mobile/screens/views/screensLandingPage')
+            )}
+          />
+          <Route
+            path="details/"
+            component={make(
+              () => import('sentry/views/insights/mobile/screens/views/screenDetailsPage')
+            )}
+          />
+        </Route>
+      </Route>
+      <Route path={`${AI_LANDING_SUB_PATH}/`}>
+        <IndexRoute
+          component={make(() => import('sentry/views/insights/pages/ai/aiOverviewPage'))}
+        />
+        <Route path={`${MODULE_BASE_URLS[ModuleName.AI]}/`}>
+          <IndexRoute
+            component={make(
+              () =>
+                import(
+                  'sentry/views/insights/llmMonitoring/views/llmMonitoringLandingPage'
+                )
+            )}
+          />
+          <Route
+            path="pipeline-type/:groupId/"
+            component={make(
+              () =>
+                import(
+                  'sentry/views/insights/llmMonitoring/views/llmMonitoringDetailsPage'
+                )
+            )}
+          />
+        </Route>
+      </Route>
       <Route path="summary/">
         <IndexRoute
           component={make(

+ 14 - 10
static/app/views/insights/cache/views/cacheLandingPage.tsx

@@ -46,12 +46,9 @@ import {useOnboardingProject} from 'sentry/views/insights/common/queries/useOnbo
 import {useModuleBreadcrumbs} from 'sentry/views/insights/common/utils/useModuleBreadcrumbs';
 import {QueryParameterNames} from 'sentry/views/insights/common/views/queryParameters';
 import {DataTitles} from 'sentry/views/insights/common/views/spans/types';
-import {
-  type InsightLandingProps,
-  ModuleName,
-  SpanFunction,
-  SpanMetricsField,
-} from 'sentry/views/insights/types';
+import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader';
+import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
+import {ModuleName, SpanFunction, SpanMetricsField} from 'sentry/views/insights/types';
 
 const {CACHE_MISS_RATE} = SpanFunction;
 const {CACHE_ITEM_SIZE} = SpanMetricsField;
@@ -69,7 +66,8 @@ const SDK_UPDATE_ALERT = (
 
 const CACHE_ERROR_MESSAGE = 'Column cache.hit was not found in metrics indexer';
 
-export function CacheLandingPage({disableHeader}: InsightLandingProps) {
+export function CacheLandingPage() {
+  const {isInDomainView} = useDomainViewFilters();
   const location = useLocation();
   const {setPageInfo, pageAlert} = usePageAlert();
 
@@ -186,7 +184,7 @@ export function CacheLandingPage({disableHeader}: InsightLandingProps) {
 
   return (
     <React.Fragment>
-      {!disableHeader && (
+      {!isInDomainView && (
         <Layout.Header>
           <Layout.HeaderContent>
             <Breadcrumbs crumbs={crumbs} />
@@ -207,6 +205,12 @@ export function CacheLandingPage({disableHeader}: InsightLandingProps) {
         </Layout.Header>
       )}
 
+      {isInDomainView && (
+        <Layout.Header>
+          <BackendHeader module={ModuleName.CACHE} />
+        </Layout.Header>
+      )}
+
       <Layout.Body>
         <Layout.Main fullWidth>
           <PageAlert />
@@ -251,7 +255,7 @@ export function CacheLandingPage({disableHeader}: InsightLandingProps) {
   );
 }
 
-function PageWithProviders(props: InsightLandingProps) {
+function PageWithProviders() {
   return (
     <ModulePageProviders
       moduleName="cache"
@@ -259,7 +263,7 @@ function PageWithProviders(props: InsightLandingProps) {
       analyticEventName="insight.page_loads.cache"
     >
       <PageAlertProvider>
-        <CacheLandingPage {...props} />
+        <CacheLandingPage />
       </PageAlertProvider>
     </ModulePageProviders>
   );

+ 14 - 9
static/app/views/insights/database/views/databaseLandingPage.tsx

@@ -40,13 +40,12 @@ import {
   MODULE_DOC_LINK,
   MODULE_TITLE,
 } from 'sentry/views/insights/database/settings';
-import {
-  type InsightLandingProps,
-  ModuleName,
-  SpanMetricsField,
-} from 'sentry/views/insights/types';
+import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader';
+import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
+import {ModuleName, SpanMetricsField} from 'sentry/views/insights/types';
 
-export function DatabaseLandingPage({disableHeader}: InsightLandingProps) {
+export function DatabaseLandingPage() {
+  const {isInDomainView} = useDomainViewFilters();
   const organization = useOrganization();
   const moduleName = ModuleName.DB;
   const location = useLocation();
@@ -164,7 +163,7 @@ export function DatabaseLandingPage({disableHeader}: InsightLandingProps) {
 
   return (
     <React.Fragment>
-      {!disableHeader && (
+      {!isInDomainView && (
         <Layout.Header>
           <Layout.HeaderContent>
             <Breadcrumbs crumbs={crumbs} />
@@ -185,6 +184,12 @@ export function DatabaseLandingPage({disableHeader}: InsightLandingProps) {
         </Layout.Header>
       )}
 
+      {isInDomainView && (
+        <Layout.Header>
+          <BackendHeader module={ModuleName.DB} />
+        </Layout.Header>
+      )}
+
       <Layout.Body>
         <Layout.Main fullWidth>
           <ModuleLayout.Layout>
@@ -255,14 +260,14 @@ function AlertBanner(props) {
 
 const LIMIT: number = 25;
 
-function PageWithProviders(props: InsightLandingProps) {
+function PageWithProviders() {
   return (
     <ModulePageProviders
       moduleName="db"
       features="insights-initial-modules"
       analyticEventName="insight.page_loads.db"
     >
-      <DatabaseLandingPage {...props} />
+      <DatabaseLandingPage />
     </ModulePageProviders>
   );
 }

+ 29 - 18
static/app/views/insights/database/views/databaseSpanSummaryPage.tsx

@@ -42,6 +42,8 @@ import {ThroughputChart} from 'sentry/views/insights/database/components/charts/
 import {isAValidSort} from 'sentry/views/insights/database/components/tables/queriesTable';
 import {QueryTransactionsTable} from 'sentry/views/insights/database/components/tables/queryTransactionsTable';
 import {DEFAULT_DURATION_AGGREGATE} from 'sentry/views/insights/database/settings';
+import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader';
+import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
 import type {SpanMetricsQueryFilters} from 'sentry/views/insights/types';
 import {
   ModuleName,
@@ -61,6 +63,7 @@ type Query = {
 type Props = RouteComponentProps<Query, {groupId: string}>;
 
 export function DatabaseSpanSummaryPage({params}: Props) {
+  const {isInDomainView} = useDomainViewFilters();
   const location = useLocation<Query>();
 
   const selectedAggregate = DEFAULT_DURATION_AGGREGATE;
@@ -183,24 +186,32 @@ export function DatabaseSpanSummaryPage({params}: Props) {
 
   return (
     <Fragment>
-      <Layout.Header>
-        <Layout.HeaderContent>
-          <Breadcrumbs
-            crumbs={[
-              ...crumbs,
-              {
-                label: 'Query Summary',
-              },
-            ]}
-          />
-          <Layout.Title>{t('Query Summary')}</Layout.Title>
-        </Layout.HeaderContent>
-        <Layout.HeaderActions>
-          <ButtonBar gap={1}>
-            <FeedbackWidgetButton />
-          </ButtonBar>
-        </Layout.HeaderActions>
-      </Layout.Header>
+      {!isInDomainView && (
+        <Layout.Header>
+          <Layout.HeaderContent>
+            <Breadcrumbs
+              crumbs={[
+                ...crumbs,
+                {
+                  label: 'Query Summary',
+                },
+              ]}
+            />
+            <Layout.Title>{t('Query Summary')}</Layout.Title>
+          </Layout.HeaderContent>
+          <Layout.HeaderActions>
+            <ButtonBar gap={1}>
+              <FeedbackWidgetButton />
+            </ButtonBar>
+          </Layout.HeaderActions>
+        </Layout.Header>
+      )}
+
+      {isInDomainView && (
+        <Layout.Header>
+          <BackendHeader module={ModuleName.DB} />
+        </Layout.Header>
+      )}
 
       <Layout.Body>
         <Layout.Main fullWidth>

+ 11 - 2
static/app/views/insights/http/views/httpDomainSummaryPage.tsx

@@ -52,7 +52,10 @@ import {
   MODULE_DOC_LINK,
   NULL_DOMAIN_DESCRIPTION,
 } from 'sentry/views/insights/http/settings';
+import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader';
+import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
 import {FrontendHeader} from 'sentry/views/insights/pages/frontend/frontendPageHeader';
+import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
 import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
 import type {SpanMetricsQueryFilters} from 'sentry/views/insights/types';
 import {ModuleName, SpanFunction, SpanMetricsField} from 'sentry/views/insights/types';
@@ -65,7 +68,7 @@ type Query = {
 export function HTTPDomainSummaryPage() {
   const location = useLocation<Query>();
   const {projects} = useProjects();
-  const {isInDomainView} = useDomainViewFilters();
+  const {isInDomainView, view} = useDomainViewFilters();
 
   // TODO: Fetch sort information using `useLocationQuery`
   const sortField = decodeScalar(location.query?.[QueryParameterNames.TRANSACTIONS_SORT]);
@@ -208,12 +211,18 @@ export function HTTPDomainSummaryPage() {
         </Layout.Header>
       )}
 
-      {isInDomainView && (
+      {isInDomainView && view === FRONTEND_LANDING_SUB_PATH && (
         <Layout.Header>
           <FrontendHeader module={ModuleName.HTTP} />
         </Layout.Header>
       )}
 
+      {isInDomainView && view === BACKEND_LANDING_SUB_PATH && (
+        <Layout.Header>
+          <BackendHeader module={ModuleName.HTTP} />
+        </Layout.Header>
+      )}
+
       <Layout.Body>
         <Layout.Main fullWidth>
           {domain === '' && (

+ 11 - 2
static/app/views/insights/http/views/httpLandingPage.tsx

@@ -39,14 +39,17 @@ import {
   MODULE_DOC_LINK,
   MODULE_TITLE,
 } from 'sentry/views/insights/http/settings';
+import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader';
+import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
 import {FrontendHeader} from 'sentry/views/insights/pages/frontend/frontendPageHeader';
+import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
 import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
 import {ModuleName, SpanMetricsField} from 'sentry/views/insights/types';
 
 export function HTTPLandingPage() {
   const organization = useOrganization();
   const location = useLocation();
-  const {isInDomainView} = useDomainViewFilters();
+  const {isInDomainView, view} = useDomainViewFilters();
 
   const sortField = decodeScalar(location.query?.[QueryParameterNames.DOMAINS_SORT]);
 
@@ -181,12 +184,18 @@ export function HTTPLandingPage() {
         </Layout.Header>
       )}
 
-      {isInDomainView && (
+      {isInDomainView && view === FRONTEND_LANDING_SUB_PATH && (
         <Layout.Header>
           <FrontendHeader module={ModuleName.HTTP} />
         </Layout.Header>
       )}
 
+      {isInDomainView && view === BACKEND_LANDING_SUB_PATH && (
+        <Layout.Header>
+          <BackendHeader module={ModuleName.HTTP} />
+        </Layout.Header>
+      )}
+
       <Layout.Body>
         <Layout.Main fullWidth>
           <ModuleLayout.Layout>

+ 28 - 16
static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx

@@ -32,7 +32,10 @@ import {
 } from 'sentry/views/insights/llmMonitoring/components/charts/llmMonitoringCharts';
 import {PipelineSpansTable} from 'sentry/views/insights/llmMonitoring/components/tables/pipelineSpansTable';
 import {RELEASE_LEVEL} from 'sentry/views/insights/llmMonitoring/settings';
+import {AiHeader} from 'sentry/views/insights/pages/ai/aiPageHeader';
+import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
 import {
+  ModuleName,
   SpanFunction,
   SpanMetricsField,
   type SpanMetricsQueryFilters,
@@ -49,6 +52,7 @@ type Query = {
 };
 
 export function LLMMonitoringPage({params}: Props) {
+  const {isInDomainView} = useDomainViewFilters();
   const location = useLocation<Query>();
 
   const organization = useOrganization();
@@ -121,22 +125,30 @@ export function LLMMonitoringPage({params}: Props) {
   return (
     <Layout.Page>
       <NoProjectMessage organization={organization}>
-        <Layout.Header>
-          <Layout.HeaderContent>
-            <Breadcrumbs
-              crumbs={[
-                ...crumbs,
-                {
-                  label: t('Pipeline Summary'),
-                },
-              ]}
-            />
-            <Layout.Title>
-              {spanDescription}
-              <FeatureBadge type={RELEASE_LEVEL} />
-            </Layout.Title>
-          </Layout.HeaderContent>
-        </Layout.Header>
+        {!isInDomainView && (
+          <Layout.Header>
+            <Layout.HeaderContent>
+              <Breadcrumbs
+                crumbs={[
+                  ...crumbs,
+                  {
+                    label: t('Pipeline Summary'),
+                  },
+                ]}
+              />
+              <Layout.Title>
+                {spanDescription}
+                <FeatureBadge type={RELEASE_LEVEL} />
+              </Layout.Title>
+            </Layout.HeaderContent>
+          </Layout.Header>
+        )}
+
+        {isInDomainView && (
+          <Layout.Header>
+            <AiHeader module={ModuleName.AI} />
+          </Layout.Header>
+        )}
         <Layout.Body>
           <Layout.Main fullWidth>
             <ModuleLayout.Layout>

+ 13 - 5
static/app/views/insights/llmMonitoring/views/llmMonitoringLandingPage.tsx

@@ -29,9 +29,12 @@ import {
   MODULE_TITLE,
   RELEASE_LEVEL,
 } from 'sentry/views/insights/llmMonitoring/settings';
-import {type InsightLandingProps, ModuleName} from 'sentry/views/insights/types';
+import {AiHeader} from 'sentry/views/insights/pages/ai/aiPageHeader';
+import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
+import {ModuleName} from 'sentry/views/insights/types';
 
-export function LLMMonitoringPage({disableHeader}: InsightLandingProps) {
+export function LLMMonitoringPage() {
+  const {isInDomainView} = useDomainViewFilters();
   const organization = useOrganization();
 
   const crumbs = useModuleBreadcrumbs('ai');
@@ -40,7 +43,7 @@ export function LLMMonitoringPage({disableHeader}: InsightLandingProps) {
   return (
     <Layout.Page>
       <NoProjectMessage organization={organization}>
-        {!disableHeader && (
+        {!isInDomainView && (
           <Layout.Header>
             <Layout.HeaderContent>
               <Breadcrumbs crumbs={crumbs} />
@@ -60,6 +63,11 @@ export function LLMMonitoringPage({disableHeader}: InsightLandingProps) {
             </Layout.HeaderActions>
           </Layout.Header>
         )}
+        {isInDomainView && (
+          <Layout.Header>
+            <AiHeader module={ModuleName.AI} />
+          </Layout.Header>
+        )}
         <Layout.Body>
           <Layout.Main fullWidth>
             <ModuleLayout.Layout>
@@ -88,14 +96,14 @@ export function LLMMonitoringPage({disableHeader}: InsightLandingProps) {
   );
 }
 
-function PageWithProviders(props: InsightLandingProps) {
+function PageWithProviders() {
   return (
     <ModulePageProviders
       moduleName="ai"
       features="insights-addon-modules"
       analyticEventName="insight.page_loads.ai"
     >
-      <LLMMonitoringPage {...props} />
+      <LLMMonitoringPage />
     </ModulePageProviders>
   );
 }

+ 56 - 25
static/app/views/insights/mobile/screens/views/screenDetailsPage.tsx

@@ -21,6 +21,8 @@ import useCrossPlatformProject from 'sentry/views/insights/mobile/common/queries
 import {PlatformSelector} from 'sentry/views/insights/mobile/screenload/components/platformSelector';
 import {ScreenLoadSpansContent as ScreenLoadPage} from 'sentry/views/insights/mobile/screenload/views/screenLoadSpansPage';
 import {ScreenSummaryContent as UiPage} from 'sentry/views/insights/mobile/ui/views/screenSummaryPage';
+import {MobileHeader} from 'sentry/views/insights/pages/mobile/mobilePageHeader';
+import {useDomainViewFilters} from 'sentry/views/insights/pages/useFilters';
 import {ModuleName} from 'sentry/views/insights/types';
 
 type Query = {
@@ -38,6 +40,7 @@ type Tab = {
 };
 
 export function ScreenDetailsPage() {
+  const {isInDomainView} = useDomainViewFilters();
   const location: Location = useLocation<Query>();
   const organization = useOrganization();
   const {isProjectCrossPlatform} = useCrossPlatformProject();
@@ -102,31 +105,59 @@ export function ScreenDetailsPage() {
       <Layout.Page>
         <PageAlertProvider>
           <Tabs value={selectedTabKey} onChange={tabKey => handleTabChange(tabKey)}>
-            <Layout.Header>
-              <Layout.HeaderContent style={{margin: 0}}>
-                <Breadcrumbs crumbs={crumbs} />
-                <Layout.Title>{transactionName}</Layout.Title>
-              </Layout.HeaderContent>
-              <Layout.HeaderActions>
-                <ButtonBar gap={1}>
-                  {isProjectCrossPlatform && <PlatformSelector />}
-                </ButtonBar>
-              </Layout.HeaderActions>
-
-              <TabList hideBorder>
-                {tabs.map(tab => {
-                  const visible =
-                    tab.feature === undefined ||
-                    organization.features?.includes(tab.feature);
-                  return (
-                    <TabList.Item key={tab.key} hidden={!visible} textValue={tab.label}>
-                      {tab.label}
-                      {tab.alpha && <FeatureBadge type="alpha" variant={'badge'} />}
-                    </TabList.Item>
-                  );
-                })}
-              </TabList>
-            </Layout.Header>
+            {!isInDomainView && (
+              <Layout.Header>
+                <Layout.HeaderContent style={{margin: 0}}>
+                  <Breadcrumbs crumbs={crumbs} />
+                  <Layout.Title>{transactionName}</Layout.Title>
+                </Layout.HeaderContent>
+                <Layout.HeaderActions>
+                  <ButtonBar gap={1}>
+                    {isProjectCrossPlatform && <PlatformSelector />}
+                  </ButtonBar>
+                </Layout.HeaderActions>
+
+                <TabList hideBorder>
+                  {tabs.map(tab => {
+                    const visible =
+                      tab.feature === undefined ||
+                      organization.features?.includes(tab.feature);
+                    return (
+                      <TabList.Item key={tab.key} hidden={!visible} textValue={tab.label}>
+                        {tab.label}
+                        {tab.alpha && <FeatureBadge type="alpha" variant={'badge'} />}
+                      </TabList.Item>
+                    );
+                  })}
+                </TabList>
+              </Layout.Header>
+            )}
+
+            {isInDomainView && (
+              <Layout.Header>
+                <MobileHeader module={ModuleName.MOBILE_SCREENS} hideTabs />
+                <Layout.HeaderActions>
+                  <ButtonBar gap={1}>
+                    {isProjectCrossPlatform && <PlatformSelector />}
+                  </ButtonBar>
+                </Layout.HeaderActions>
+
+                {/* TODO - There's two sets of tabs here, we'll have to do some UI work here */}
+                <TabList hideBorder>
+                  {tabs.map(tab => {
+                    const visible =
+                      tab.feature === undefined ||
+                      organization.features?.includes(tab.feature);
+                    return (
+                      <TabList.Item key={tab.key} hidden={!visible} textValue={tab.label}>
+                        {tab.label}
+                        {tab.alpha && <FeatureBadge type="alpha" variant={'badge'} />}
+                      </TabList.Item>
+                    );
+                  })}
+                </TabList>
+              </Layout.Header>
+            )}
             <Layout.Body>
               <Layout.Main fullWidth>
                 <PageAlert />

Some files were not shown because too many files changed in this diff