diff --git a/static/app/components/layouts/thirds.tsx b/static/app/components/layouts/thirds.tsx index 37f9c9190d39a9..3d57eeaf6088c9 100644 --- a/static/app/components/layouts/thirds.tsx +++ b/static/app/components/layouts/thirds.tsx @@ -1,18 +1,41 @@ +import {Fragment} from 'react'; import {css} from '@emotion/react'; import styled from '@emotion/styled'; +import {Flex} from 'sentry/components/core/layout'; import {Tabs} from 'sentry/components/core/tabs'; +import SentryDocumentTitle, { + type DocumentTitleOptions, +} from 'sentry/components/sentryDocumentTitle'; import {space} from 'sentry/styles/space'; /** * Main container for a page. */ -export const Page = styled('main')<{withPadding?: boolean}>` - display: flex; - flex-direction: column; - flex: 1; - ${p => p.withPadding && `padding: ${space(3)} ${space(4)}`}; -`; +interface PageProps { + children: NonNullable; + title: string | DocumentTitleOptions | null; + withPadding?: boolean; +} + +export const Page = styled((props: PageProps) => { + return ( + + {props.title === null ? null : typeof props.title === 'string' ? ( + + ) : ( + + )} + + {props.children} + + + ); +})``; /** * Header container for header content and header actions. diff --git a/static/app/components/noAccess.tsx b/static/app/components/noAccess.tsx index e9a7ba573a5d07..50a97764a530a1 100644 --- a/static/app/components/noAccess.tsx +++ b/static/app/components/noAccess.tsx @@ -4,7 +4,7 @@ import {t} from 'sentry/locale'; export function NoAccess() { return ( - + {t("You don't have access to this feature")} diff --git a/static/app/components/organizations/pageFilters/container.tsx b/static/app/components/organizations/pageFilters/container.tsx index e7f3c28a0ad0a3..8c9e5fbff18c79 100644 --- a/static/app/components/organizations/pageFilters/container.tsx +++ b/static/app/components/organizations/pageFilters/container.tsx @@ -200,7 +200,7 @@ function PageFiltersContainer({ // would speed up orgs with tons of projects if (!isReady || !hasInitialized) { return ( - + ); diff --git a/static/app/components/sentryDocumentTitle.tsx b/static/app/components/sentryDocumentTitle.tsx index 4eac5160916e3e..33e113c807cdfc 100644 --- a/static/app/components/sentryDocumentTitle.tsx +++ b/static/app/components/sentryDocumentTitle.tsx @@ -1,74 +1,35 @@ import {createContext, useContext, useEffect, useMemo} from 'react'; -type Props = { - children?: React.ReactNode; - /** - * Should the ` - Sentry` suffix be excluded? - */ - noSuffix?: boolean; - /** - * The organization slug to show in the title - */ - orgSlug?: string; - /** - * The project slug to show in the title. - */ - projectSlug?: string; - - /** - * This string will be shown at the very front of the title - */ - title?: string; -}; +import type {Organization} from 'sentry/types/organization'; +import type {Project} from 'sentry/types/project'; const DEFAULT_PAGE_TITLE = 'Sentry'; - const DocumentTitleContext = createContext(DEFAULT_PAGE_TITLE); export function useDocumentTitle() { return useContext(DocumentTitleContext); } +interface SentryDocumentTitleProps extends DocumentTitleOptions { + children?: React.ReactNode; +} + /** * Assigns the document title. The deepest nested version of this title will be * the one which is assigned. */ -function SentryDocumentTitle({ - title = '', +export default function SentryDocumentTitle({ + title, orgSlug, projectSlug, noSuffix, children, -}: Props) { +}: SentryDocumentTitleProps) { const parentTitle = useContext(DocumentTitleContext); - - const pageTitle = useMemo(() => { - if (orgSlug && projectSlug) { - return `${title} — ${orgSlug} — ${projectSlug}`; - } - - if (orgSlug) { - return `${title} — ${orgSlug}`; - } - - if (projectSlug) { - return `${title} — ${projectSlug}`; - } - - return title; - }, [orgSlug, projectSlug, title]); - - const documentTitle = useMemo(() => { - if (noSuffix) { - return pageTitle; - } - - if (pageTitle !== '') { - return `${pageTitle} — Sentry`; - } - - return DEFAULT_PAGE_TITLE; - }, [noSuffix, pageTitle]); + const documentTitle = useMemo( + () => makeSentryDocumentTitle(title ?? '', orgSlug, projectSlug, noSuffix), + [orgSlug, projectSlug, title, noSuffix] + ); // NOTE: We do this OUTSIDE of a use effect so that the update order is // correct, otherwsie the inner most SentryDocumentTitle will have its @@ -87,4 +48,30 @@ function SentryDocumentTitle({ return {children}; } -export default SentryDocumentTitle; +export interface DocumentTitleOptions { + title: string; + noSuffix?: boolean; + orgSlug?: Organization['slug']; + projectSlug?: Project['slug']; +} + +export function makeSentryDocumentTitle( + title: string, + orgSlug?: string, + projectSlug?: string, + noSuffix?: boolean +) { + if (orgSlug) { + if (projectSlug) { + return `${title} — ${orgSlug} — ${projectSlug}`; + } + + return `${title} — ${orgSlug}`; + } + + if (projectSlug) { + return `${title} — ${projectSlug}`; + } + + return noSuffix ? title : `${title} — Sentry`; +} diff --git a/static/app/components/workflowEngine/layout/detail.tsx b/static/app/components/workflowEngine/layout/detail.tsx index 0d7b30ebb1082e..ccc51803a1145c 100644 --- a/static/app/components/workflowEngine/layout/detail.tsx +++ b/static/app/components/workflowEngine/layout/detail.tsx @@ -20,7 +20,7 @@ interface WorkflowEngineDetailLayoutProps { * Precomposed 67/33 layout for Automations / Monitors detail pages. */ function DetailLayout({children}: WorkflowEngineDetailLayoutProps) { - return {children}; + return {children as NonNullable}; } const ProjectContainer = styled('div')` diff --git a/static/app/components/workflowEngine/layout/edit.tsx b/static/app/components/workflowEngine/layout/edit.tsx index 347db7b256953a..0ae1066f6feb2f 100644 --- a/static/app/components/workflowEngine/layout/edit.tsx +++ b/static/app/components/workflowEngine/layout/edit.tsx @@ -27,7 +27,7 @@ interface WorkflowEngineEditLayoutProps { function EditLayout({children, formProps}: WorkflowEngineEditLayoutProps) { return ( - {children} + {children as NonNullable} ); } diff --git a/static/app/components/workflowEngine/layout/list.tsx b/static/app/components/workflowEngine/layout/list.tsx index 8b92058643b06f..b18f6a5f356506 100644 --- a/static/app/components/workflowEngine/layout/list.tsx +++ b/static/app/components/workflowEngine/layout/list.tsx @@ -15,7 +15,7 @@ interface WorkflowEngineListLayoutProps { function WorkflowEngineListLayout({children, actions}: WorkflowEngineListLayoutProps) { const title = useDocumentTitle(); return ( - + {title} diff --git a/static/app/views/alerts/rules/crons/details.tsx b/static/app/views/alerts/rules/crons/details.tsx index 722a40304b8028..bc3b3978ce352e 100644 --- a/static/app/views/alerts/rules/crons/details.tsx +++ b/static/app/views/alerts/rules/crons/details.tsx @@ -13,7 +13,6 @@ import LoadingIndicator from 'sentry/components/loadingIndicator'; import {DatePageFilter} from 'sentry/components/organizations/datePageFilter'; import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {TimezoneProvider, useTimezone} from 'sentry/components/timezoneProvider'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -138,7 +137,7 @@ function MonitorDetails({params, location}: Props) { if (!monitor) { return ( - + ); @@ -147,8 +146,7 @@ function MonitorDetails({params, location}: Props) { const envsSortedByLastCheck = sortBy(monitor.environments, e => e.lastCheckIn); return ( - - + diff --git a/static/app/views/alerts/rules/metric/details/index.tsx b/static/app/views/alerts/rules/metric/details/index.tsx index 2422f47619db24..655356ee5ecd6d 100644 --- a/static/app/views/alerts/rules/metric/details/index.tsx +++ b/static/app/views/alerts/rules/metric/details/index.tsx @@ -10,7 +10,6 @@ import {Alert} from 'sentry/components/core/alert'; import {DateTime} from 'sentry/components/dateTime'; import * as Layout from 'sentry/components/layouts/thirds'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; import type {Organization} from 'sentry/types/organization'; @@ -246,7 +245,7 @@ class MetricAlertDetails extends Component { const {error} = this.state; return ( - + {error?.status === 404 @@ -282,22 +281,23 @@ class MetricAlertDetails extends Component { {warning} )} - - - + + + + ); } diff --git a/static/app/views/alerts/rules/uptime/details.tsx b/static/app/views/alerts/rules/uptime/details.tsx index c9cadba8b62e45..33fbe4b1d012b7 100644 --- a/static/app/views/alerts/rules/uptime/details.tsx +++ b/static/app/views/alerts/rules/uptime/details.tsx @@ -14,7 +14,6 @@ import LoadingError from 'sentry/components/loadingError'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import {DatePageFilter} from 'sentry/components/organizations/datePageFilter'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {IconEdit} from 'sentry/icons'; import {t, tct} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -114,8 +113,7 @@ export default function UptimeAlertDetails({params}: UptimeAlertDetailsProps) { ); return ( - - + - - + ; -} - function AutomationBreadcrumbs({automationId}: {automationId: string}) { const title = useFormField('name'); const organization = useOrganization(); @@ -151,8 +145,7 @@ function AutomationEditForm({automation}: {automation: Automation}) { initialData={initialData} onSubmit={handleFormSubmit} > - - + diff --git a/static/app/views/automations/new-settings.tsx b/static/app/views/automations/new-settings.tsx index aee5c23d78d65d..9d960795dadb01 100644 --- a/static/app/views/automations/new-settings.tsx +++ b/static/app/views/automations/new-settings.tsx @@ -8,7 +8,6 @@ import {Flex} from 'sentry/components/core/layout'; import FormModel from 'sentry/components/forms/model'; import type {OnSubmitCallback} from 'sentry/components/forms/types'; import * as Layout from 'sentry/components/layouts/thirds'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {FullHeightForm} from 'sentry/components/workflowEngine/form/fullHeightForm'; import {useFormField} from 'sentry/components/workflowEngine/form/useFormField'; import { @@ -38,15 +37,6 @@ import { makeAutomationDetailsPathname, } from 'sentry/views/automations/pathnames'; -function AutomationDocumentTitle() { - const title = useFormField('name'); - return ( - - ); -} - function AutomationBreadcrumbs() { const title = useFormField('name'); const organization = useOrganization(); @@ -74,6 +64,10 @@ export default function AutomationNewSettings() { const model = useMemo(() => new FormModel(), []); const {state, actions} = useAutomationBuilderReducer(); + const formName = useFormField('name'); + + const formTitle = formName ? t('%s - New Automation', formName) : t('New Automation'); + const [automationBuilderErrors, setAutomationBuilderErrors] = useState< Record >({}); @@ -122,8 +116,7 @@ export default function AutomationNewSettings() { onSubmit={handleSubmit} model={model} > - - + diff --git a/static/app/views/automations/new.tsx b/static/app/views/automations/new.tsx index 4be62afdbe1309..17345c215a755b 100644 --- a/static/app/views/automations/new.tsx +++ b/static/app/views/automations/new.tsx @@ -1,11 +1,10 @@ -import {useState} from 'react'; +import {Fragment, useState} from 'react'; import styled from '@emotion/styled'; import {Breadcrumbs} from 'sentry/components/breadcrumbs'; import {LinkButton} from 'sentry/components/core/button/linkButton'; import {Flex} from 'sentry/components/core/layout'; import * as Layout from 'sentry/components/layouts/thirds'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import { StickyFooter, StickyFooterLabel, @@ -52,8 +51,8 @@ export default function AutomationNew() { }); return ( - - + + @@ -100,7 +99,7 @@ export default function AutomationNew() { - + ); } diff --git a/static/app/views/dashboards/create.tsx b/static/app/views/dashboards/create.tsx index 54e1e06427eec5..0239b6e6a82a28 100644 --- a/static/app/views/dashboards/create.tsx +++ b/static/app/views/dashboards/create.tsx @@ -27,7 +27,7 @@ function CreateDashboard(props: Props) { const [newWidget, setNewWidget] = useState(); function renderDisabled() { return ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/dashboards/detail.tsx b/static/app/views/dashboards/detail.tsx index 25de4fcb890bd7..eb1c49f5897bd0 100644 --- a/static/app/views/dashboards/detail.tsx +++ b/static/app/views/dashboards/detail.tsx @@ -32,7 +32,6 @@ import { } from 'sentry/components/modals/widgetViewerModal/utils'; import NoProjectMessage from 'sentry/components/noProjectMessage'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {USING_CUSTOMER_DOMAIN} from 'sentry/constants'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -1000,7 +999,7 @@ class DashboardDetail extends Component { }, }} > - + @@ -1127,7 +1126,7 @@ class DashboardDetail extends Component { ); return ( - + { @@ -1174,7 +1173,7 @@ class DashboardDetail extends Component { }, }} > - + @@ -1382,7 +1381,7 @@ class DashboardDetail extends Component { - + ); } diff --git a/static/app/views/dashboards/manage/index.tsx b/static/app/views/dashboards/manage/index.tsx index 6ba8c51a5ea876..95f2a2aa827fa9 100644 --- a/static/app/views/dashboards/manage/index.tsx +++ b/static/app/views/dashboards/manage/index.tsx @@ -21,7 +21,6 @@ import NoProjectMessage from 'sentry/components/noProjectMessage'; import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip'; import Pagination from 'sentry/components/pagination'; import SearchBar from 'sentry/components/searchBar'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {IconAdd, IconGrid, IconList} from 'sentry/icons'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -400,7 +399,7 @@ function ManageDashboards() { function renderNoAccess() { return ( - + {t("You don't have access to this feature")} @@ -530,87 +529,85 @@ function ManageDashboards() { features="dashboards-edit" renderDisabled={renderNoAccess} > - - - {isError ? ( - - - - ) : ( - - - - - - {t('All Dashboards')} - + {isError ? ( + + + + ) : ( + + + + + + {t('All Dashboards')} + + + + + + + {t('Show Templates')} + - - - - - - {t('Show Templates')} - - - + + + + - - - - - - - - - {showTemplates && renderTemplates()} - {renderActions()} -
- {renderDashboards()} -
- {!( - organization.features.includes('dashboards-starred-reordering') && - dashboardsLayout === TABLE - ) && renderPagination()} -
-
-
-
- )} -
-
+ + + +
+ + + {showTemplates && renderTemplates()} + {renderActions()} +
+ {renderDashboards()} +
+ {!( + organization.features.includes('dashboards-starred-reordering') && + dashboardsLayout === TABLE + ) && renderPagination()} +
+
+ +
+ )} + ); } diff --git a/static/app/views/dashboards/orgDashboards.tsx b/static/app/views/dashboards/orgDashboards.tsx index f1bc0beea1aa9e..41856fa4c185ed 100644 --- a/static/app/views/dashboards/orgDashboards.tsx +++ b/static/app/views/dashboards/orgDashboards.tsx @@ -152,7 +152,7 @@ function OrgDashboards(props: Props) { if (isDashboardsPending || isSelectedDashboardLoading) { return ( - + ); @@ -168,7 +168,7 @@ function OrgDashboards(props: Props) { // the URL does not contain filters yet. The filters can either match the // saved filters, or can be different (i.e. sharing an unsaved state) return ( - + ); diff --git a/static/app/views/dashboards/view.tsx b/static/app/views/dashboards/view.tsx index 590accf6673eba..996d5dbf2163ad 100644 --- a/static/app/views/dashboards/view.tsx +++ b/static/app/views/dashboards/view.tsx @@ -106,7 +106,7 @@ type FeatureProps = { export function DashboardBasicFeature({organization, children}: FeatureProps) { const renderDisabled = () => ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/dashboards/widgetBuilder/index.tsx b/static/app/views/dashboards/widgetBuilder/index.tsx index 519be4e90f6fef..7d4ee48530f38d 100644 --- a/static/app/views/dashboards/widgetBuilder/index.tsx +++ b/static/app/views/dashboards/widgetBuilder/index.tsx @@ -21,7 +21,7 @@ function WidgetBuilderContainer(props: WidgetBuilderProps) { features="dashboards-edit" organization={organization} renderDisabled={() => ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/detectors/components/forms/error/index.tsx b/static/app/views/detectors/components/forms/error/index.tsx index 6cf9153afa8e85..ea08da7d80968d 100644 --- a/static/app/views/detectors/components/forms/error/index.tsx +++ b/static/app/views/detectors/components/forms/error/index.tsx @@ -98,7 +98,7 @@ function ErrorDetectorForm({detector}: {detector: ErrorDetector}) { export function NewErrorDetectorForm() { return ( - + diff --git a/static/app/views/detectors/components/forms/index.tsx b/static/app/views/detectors/components/forms/index.tsx index 420703460d2703..fab1d907602309 100644 --- a/static/app/views/detectors/components/forms/index.tsx +++ b/static/app/views/detectors/components/forms/index.tsx @@ -22,7 +22,7 @@ import { function PlaceholderForm() { return ( - + diff --git a/static/app/views/detectors/new-settings.tsx b/static/app/views/detectors/new-settings.tsx index 83e32c15be0215..17cdadf7c6a9a4 100644 --- a/static/app/views/detectors/new-settings.tsx +++ b/static/app/views/detectors/new-settings.tsx @@ -24,7 +24,7 @@ export default function DetectorNewSettings() { if (isFetchingProjects) { return ( - + diff --git a/static/app/views/discover/eventDetails/index.tsx b/static/app/views/discover/eventDetails/index.tsx index 833871dae773a3..760553528bcf0a 100644 --- a/static/app/views/discover/eventDetails/index.tsx +++ b/static/app/views/discover/eventDetails/index.tsx @@ -2,7 +2,6 @@ import omit from 'lodash/omit'; import * as Layout from 'sentry/components/layouts/thirds'; import NoProjectMessage from 'sentry/components/noProjectMessage'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; import type {Organization} from 'sentry/types/organization'; @@ -23,33 +22,26 @@ function EventDetails({organization, location, params}: Props) { isHomepage ? {...location, query: omit(location.query, 'id')} : location ); const eventName = eventView.name; + const projectSlug = eventSlug.split(':')[0]; const documentTitle = typeof eventName === 'string' && String(eventName).trim().length > 0 - ? [String(eventName).trim(), t('Discover')] - : [t('Discover')]; - - const projectSlug = eventSlug.split(':')[0]; + ? [String(eventName).trim(), t('Discover'), organization.slug, projectSlug] + : [t('Discover'), organization.slug, projectSlug]; return ( - - - - - - - + + + + + ); } diff --git a/static/app/views/discover/index.tsx b/static/app/views/discover/index.tsx index 130dcb59a0da12..58e64bd0fb67ec 100644 --- a/static/app/views/discover/index.tsx +++ b/static/app/views/discover/index.tsx @@ -25,7 +25,7 @@ function DiscoverContainer({organization, children}: Props) { function renderNoAccess() { return ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/discover/landing.tsx b/static/app/views/discover/landing.tsx index ee6473e24f2cf6..1e0a548aa77bae 100644 --- a/static/app/views/discover/landing.tsx +++ b/static/app/views/discover/landing.tsx @@ -10,7 +10,6 @@ import * as Layout from 'sentry/components/layouts/thirds'; import LoadingError from 'sentry/components/loadingError'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import SearchBar from 'sentry/components/searchBar'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {SelectValue} from 'sentry/types/core'; @@ -44,7 +43,7 @@ const SORT_OPTIONS = [ function NoAccess() { return ( - + {t("You don't have access to this feature")} @@ -182,86 +181,84 @@ function DiscoverLanding() { features="discover-query" renderDisabled={() => } > - - - - - + + + + + + { + trackAnalytics('discover_v2.build_new_query', { + organization, + }); + }} + > + {t('Build a new query')} + + + + + + + - - - { - trackAnalytics('discover_v2.build_new_query', { - organization, - }); - }} - > - {t('Build a new query')} - - - - - - - + Show Prebuilt + setRenderPrebuilt(!renderPrebuilt)} /> - - Show Prebuilt - setRenderPrebuilt(!renderPrebuilt)} - /> - - handleSortChange(opt.value)} - position="bottom-end" - /> - - {status === 'pending' ? ( - - ) : status === 'error' ? ( - - ) : ( - - )} - - - - + + handleSortChange(opt.value)} + position="bottom-end" + /> + + {status === 'pending' ? ( + + ) : status === 'error' ? ( + + ) : ( + + )} + + + ); } diff --git a/static/app/views/explore/logs/content.tsx b/static/app/views/explore/logs/content.tsx index 178d758baefa7b..2db85fcc86875c 100644 --- a/static/app/views/explore/logs/content.tsx +++ b/static/app/views/explore/logs/content.tsx @@ -4,7 +4,6 @@ import {ButtonBar} from 'sentry/components/core/button/buttonBar'; import {LinkButton} from 'sentry/components/core/button/linkButton'; import * as Layout from 'sentry/components/layouts/thirds'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {IconMegaphone, IconOpen} from 'sentry/icons'; import {t} from 'sentry/locale'; import {defined} from 'sentry/utils'; @@ -59,38 +58,36 @@ export default function LogsContent() { logsPickableDays(organization); return ( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + ); } diff --git a/static/app/views/explore/multiQueryMode/index.tsx b/static/app/views/explore/multiQueryMode/index.tsx index 1fdfc035de2330..b3171f8e666574 100644 --- a/static/app/views/explore/multiQueryMode/index.tsx +++ b/static/app/views/explore/multiQueryMode/index.tsx @@ -6,7 +6,6 @@ import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidg import * as Layout from 'sentry/components/layouts/thirds'; import {NoAccess} from 'sentry/components/noAccess'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import {defined} from 'sentry/utils'; import {useLocation} from 'sentry/utils/useLocation'; @@ -36,50 +35,53 @@ export default function MultiQueryMode() { organization={organization} renderDisabled={NoAccess} > - - - - - {title ? title : t('Compare Queries')} - - - - {!prefersStackedNav && ( - - {t('Saved Queries')} - - )} - - {defined(id) && savedQuery?.isPrebuilt === false && } - - - - - - - - - - + + + + {title ? title : t('Compare Queries')} + + + + {!prefersStackedNav && ( + + {t('Saved Queries')} + + )} + + {defined(id) && savedQuery?.isPrebuilt === false && } + + + + + + + + + ); } diff --git a/static/app/views/explore/savedQueries/index.tsx b/static/app/views/explore/savedQueries/index.tsx index f285c6ef1eb7e9..9aed2f1c3bcd78 100644 --- a/static/app/views/explore/savedQueries/index.tsx +++ b/static/app/views/explore/savedQueries/index.tsx @@ -6,7 +6,6 @@ import {LinkButton} from 'sentry/components/core/button/linkButton'; import {DropdownMenu} from 'sentry/components/dropdownMenu'; import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidgetButton'; import * as Layout from 'sentry/components/layouts/thirds'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {IconAdd} from 'sentry/icons/iconAdd'; import {t} from 'sentry/locale'; import useOrganization from 'sentry/utils/useOrganization'; @@ -41,55 +40,53 @@ export default function SavedQueriesView() { ]; return ( - - - - - {t('All Queries')} - - - - - {hasLogsFeature ? ( - ( - - )} - /> - ) : ( - } - size="sm" - to={getExploreUrl({organization, visualize: []})} - > - {t('Create Query')} - - )} - - - - - - - - - - + triggerProps.onClick?.(e); + }} + > + {t('Create Query')} + + )} + /> + ) : ( + } + size="sm" + to={getExploreUrl({organization, visualize: []})} + > + {t('Create Query')} + + )} + + +
+ + + + + +
); } diff --git a/static/app/views/explore/spans/content.tsx b/static/app/views/explore/spans/content.tsx index cca5770e5e50c3..65bb34578663f6 100644 --- a/static/app/views/explore/spans/content.tsx +++ b/static/app/views/explore/spans/content.tsx @@ -8,7 +8,6 @@ import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidg import * as Layout from 'sentry/components/layouts/thirds'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {TourContextProvider} from 'sentry/components/tours/components'; import {useAssistant} from 'sentry/components/tours/useAssistant'; import {t} from 'sentry/locale'; @@ -48,24 +47,22 @@ export function ExploreContent() { const onboardingProject = useOnboardingProject(); return ( - - - - - - {defined(onboardingProject) ? ( - - ) : ( - - )} - - - - + + + + + {defined(onboardingProject) ? ( + + ) : ( + + )} + + + ); } diff --git a/static/app/views/insights/common/components/modulePageProviders.tsx b/static/app/views/insights/common/components/modulePageProviders.tsx index ec4d8dca88720e..aa6582308e70c5 100644 --- a/static/app/views/insights/common/components/modulePageProviders.tsx +++ b/static/app/views/insights/common/components/modulePageProviders.tsx @@ -1,7 +1,6 @@ import * as Layout from 'sentry/components/layouts/thirds'; import NoProjectMessage from 'sentry/components/noProjectMessage'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import type {InsightEventKey} from 'sentry/utils/analytics/insightAnalyticEvents'; import useOrganization from 'sentry/utils/useOrganization'; import {WidgetSyncContextProvider} from 'sentry/views/dashboards/contexts/widgetSyncContext'; @@ -48,13 +47,11 @@ export function ModulePageProviders({ maxPickableDays={hasDateRangeQueryLimit ? QUERY_DATE_RANGE_LIMIT : undefined} storageNamespace={view} > - - - - {children} - - - + + + {children} + + ); } diff --git a/static/app/views/insights/mobile/appStarts/views/screenSummaryPage.tsx b/static/app/views/insights/mobile/appStarts/views/screenSummaryPage.tsx index c77455e11ec8d9..4d5c254a63cb0e 100644 --- a/static/app/views/insights/mobile/appStarts/views/screenSummaryPage.tsx +++ b/static/app/views/insights/mobile/appStarts/views/screenSummaryPage.tsx @@ -48,7 +48,7 @@ export function ScreenSummary() { const {transaction: transactionName} = location.query; return ( - + - - + handleTabChange(tabKey)}> - + + {t("You don't have access to this feature")} diff --git a/static/app/views/issueList/issueViews/issueViewsList/issueViewsList.tsx b/static/app/views/issueList/issueViews/issueViewsList/issueViewsList.tsx index f90fdd6b2d448c..e033c4437df844 100644 --- a/static/app/views/issueList/issueViews/issueViewsList/issueViewsList.tsx +++ b/static/app/views/issueList/issueViews/issueViewsList/issueViewsList.tsx @@ -11,7 +11,6 @@ import * as Layout from 'sentry/components/layouts/thirds'; import Pagination from 'sentry/components/pagination'; import Redirect from 'sentry/components/redirect'; import SearchBar from 'sentry/components/searchBar'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {IconAdd, IconMegaphone, IconSort} from 'sentry/icons'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -367,122 +366,118 @@ export default function IssueViewsList() { }; return ( - - - - - {t('All Views')} - - - - {openFeedbackForm ? ( + + + + {t('All Views')} + + + + {openFeedbackForm ? ( + + ) : null} + + ( + + } + > + {typeof props.children === 'function' + ? props.children(props) + : props.children} + + )} + > + {({hasFeature}) => ( - ) : null} - - ( - - } - > - {typeof props.children === 'function' - ? props.children(props) - : props.children} - - )} - > - {({hasFeature}) => ( - - )} - - - - - - - - { - navigate({ - pathname: location.pathname, - query: {...location.query, query: newQuery}, - }); - trackAnalytics('issue_views.table.search', { + )} + + + + + + + + { + navigate({ + pathname: location.pathname, + query: {...location.query, query: newQuery}, + }); + trackAnalytics('issue_views.table.search', { + organization, + query: newQuery, + }); + }} + placeholder={t('Search views by name or query')} + /> + + + + {t('Created by Me')} + { + trackAnalytics('issue_views.table.banner_create_view_clicked', { organization, - query: newQuery, }); + handleCreateView(); }} - placeholder={t('Search views by name or query')} + isCreatingView={isCreatingView} /> - - - - {t('Created by Me')} - { - trackAnalytics('issue_views.table.banner_create_view_clicked', { - organization, - }); - handleCreateView(); - }} - isCreatingView={isCreatingView} - /> - } - /> - {t('Created by Others')} - - - - - + } + /> + {t('Created by Others')} + + +
+
); } diff --git a/static/app/views/issueList/overview.tsx b/static/app/views/issueList/overview.tsx index e5c51cac22459e..1ba3f0cca626d0 100644 --- a/static/app/views/issueList/overview.tsx +++ b/static/app/views/issueList/overview.tsx @@ -1082,7 +1082,7 @@ function IssueListOverview({ const {numPreviousIssues, numIssuesOnPage} = getPageCounts(); return ( - + {prefersStackedNav ? ( + {t("You don't have access to this feature")} diff --git a/static/app/views/performance/transactionDetails/index.tsx b/static/app/views/performance/transactionDetails/index.tsx index 66650080679dd6..327cfff3298c46 100644 --- a/static/app/views/performance/transactionDetails/index.tsx +++ b/static/app/views/performance/transactionDetails/index.tsx @@ -1,5 +1,4 @@ import * as Layout from 'sentry/components/layouts/thirds'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; import type {Organization} from 'sentry/types/organization'; @@ -21,26 +20,25 @@ function EventDetails(props: Props) { }; const {organization, location, params} = props; - const documentTitle = t('Performance Details'); const eventSlug = getEventSlug(); const projectSlug = eventSlug.split(':')[0]; return ( - - - - - + + ); } diff --git a/static/app/views/performance/transactionSummary/pageLayout.tsx b/static/app/views/performance/transactionSummary/pageLayout.tsx index 6821514521445f..af2ea2a7f38c9f 100644 --- a/static/app/views/performance/transactionSummary/pageLayout.tsx +++ b/static/app/views/performance/transactionSummary/pageLayout.tsx @@ -293,7 +293,13 @@ function PageLayout(props: Props) { specificProjectSlugs={defined(project) ? [project.slug] : []} > - + + {t("You don't have access to this feature")} diff --git a/static/app/views/performance/transactionSummary/transactionSpans/spanDetails/index.tsx b/static/app/views/performance/transactionSummary/transactionSpans/spanDetails/index.tsx index aab88f9ce181a8..2de43c9353e023 100644 --- a/static/app/views/performance/transactionSummary/transactionSpans/spanDetails/index.tsx +++ b/static/app/views/performance/transactionSummary/transactionSpans/spanDetails/index.tsx @@ -1,7 +1,6 @@ import Feature from 'sentry/components/acl/feature'; import * as Layout from 'sentry/components/layouts/thirds'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; import {defined} from 'sentry/utils'; @@ -43,34 +42,34 @@ export default function SpanDetails(props: Props) { }); return ( - - - - - - - - - + + + + ); } diff --git a/static/app/views/performance/vitalDetail/index.tsx b/static/app/views/performance/vitalDetail/index.tsx index 1565e5821a484c..267f96cb95319b 100644 --- a/static/app/views/performance/vitalDetail/index.tsx +++ b/static/app/views/performance/vitalDetail/index.tsx @@ -5,7 +5,6 @@ import {loadOrganizationTags} from 'sentry/actionCreators/tags'; import type {Client} from 'sentry/api'; import * as Layout from 'sentry/components/layouts/thirds'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t} from 'sentry/locale'; import type {PageFilters} from 'sentry/types/core'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; @@ -112,22 +111,25 @@ class VitalDetail extends Component { : undefined; return ( - - - - - - - - - + + + + + + + ); } } diff --git a/static/app/views/permissionDenied.tsx b/static/app/views/permissionDenied.tsx index 35ab46c2147a5e..a26e905a040a0f 100644 --- a/static/app/views/permissionDenied.tsx +++ b/static/app/views/permissionDenied.tsx @@ -4,7 +4,6 @@ import * as Sentry from '@sentry/react'; import {ExternalLink} from 'sentry/components/core/link'; import * as Layout from 'sentry/components/layouts/thirds'; import LoadingError from 'sentry/components/loadingError'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t, tct} from 'sentry/locale'; import getRouteStringFromRoutes from 'sentry/utils/getRouteStringFromRoutes'; import {useRoutes} from 'sentry/utils/useRoutes'; @@ -24,21 +23,19 @@ function PermissionDenied() { }, []); return ( - - - + - ), - } - )} - /> - - + { + link: ( + + ), + } + )} + /> + ); } diff --git a/static/app/views/preprod/buildDetails.tsx b/static/app/views/preprod/buildDetails.tsx index 46a9f81b3795a7..9534d7eda24cf4 100644 --- a/static/app/views/preprod/buildDetails.tsx +++ b/static/app/views/preprod/buildDetails.tsx @@ -1,5 +1,5 @@ import * as Layout from 'sentry/components/layouts/thirds'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; +import {t} from 'sentry/locale'; import {useApiQuery, type UseApiQueryResult} from 'sentry/utils/queryClient'; import type RequestError from 'sentry/utils/requestError/requestError'; import {UrlParamBatchProvider} from 'sentry/utils/url/urlParamBatchContext'; @@ -41,28 +41,26 @@ export default function BuildDetails() { ); return ( - - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + ); } diff --git a/static/app/views/preprod/index.tsx b/static/app/views/preprod/index.tsx index 64188985e74c94..483900b3ac56a6 100644 --- a/static/app/views/preprod/index.tsx +++ b/static/app/views/preprod/index.tsx @@ -17,7 +17,7 @@ function PreprodContainer({children}: Props) { features={['organizations:preprod-frontend-routes']} organization={organization} renderDisabled={() => ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/profiling/content.tsx b/static/app/views/profiling/content.tsx index bf17cc2612f090..53e36cab375da4 100644 --- a/static/app/views/profiling/content.tsx +++ b/static/app/views/profiling/content.tsx @@ -23,7 +23,6 @@ import { } from 'sentry/components/profiling/billing/alerts'; import {ProfileEventsTable} from 'sentry/components/profiling/profileEventsTable'; import QuestionTooltip from 'sentry/components/questionTooltip'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -137,96 +136,92 @@ export default function ProfilingContent({location}: ProfilingContentProps) { ); return ( - - - - - - - - - - - - - - - - - - - {showOnboardingPanel ? ( - - ) : ( - - {organization.features.includes( - 'profiling-global-suspect-functions' - ) && ( - - - - - )} -
- - - - {t('Transactions')} - - - - {t('Aggregate Flamegraph')} - - - - -
- {tab === 'flamegraph' ? ( - - ) : ( - + + + + + + + + + + + + + + + + + {showOnboardingPanel ? ( + + ) : ( + + {organization.features.includes('profiling-global-suspect-functions') && ( + + - )} - - )} - - - -
-
+ + + )} +
+ + + + {t('Transactions')} + + + + {t('Aggregate Flamegraph')} + + + + +
+ {tab === 'flamegraph' ? ( + + ) : ( + + )} + + )} + + +
+ ); } diff --git a/static/app/views/profiling/index.tsx b/static/app/views/profiling/index.tsx index fc5ab4cb08e0b5..57e25c0666ff3a 100644 --- a/static/app/views/profiling/index.tsx +++ b/static/app/views/profiling/index.tsx @@ -31,7 +31,7 @@ function ProfilingContainer({children}: Props) { features={profilingFeature} organization={organization} renderDisabled={() => ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/projectDetail/projectDetail.tsx b/static/app/views/projectDetail/projectDetail.tsx index 4738ed4a04aae9..c1a712634b4816 100644 --- a/static/app/views/projectDetail/projectDetail.tsx +++ b/static/app/views/projectDetail/projectDetail.tsx @@ -18,7 +18,6 @@ import LoadingError from 'sentry/components/loadingError'; import NoProjectMessage from 'sentry/components/noProjectMessage'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import MissingProjectMembership from 'sentry/components/projects/missingProjectMembership'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {DEFAULT_RELATIVE_PERIODS} from 'sentry/constants'; import {IconSettings} from 'sentry/icons'; import {t} from 'sentry/locale'; @@ -127,7 +126,7 @@ export default function ProjectDetail({router, location, organization}: Props) { if (!loadingProjects && !project) { return ( - + + ); } return ( - - - - - - - - - {project ? ( - - ) : null} - {project?.slug} - - - - - - - - {t('View All Issues')} - - + + + + + + + {project ? ( + - } - aria-label={t('Settings')} - to={`/settings/${params.orgId}/projects/${params.projectId}/`} - /> - - - + ) : null} + {project?.slug} + +
- - - - - - - + + + + {t('View All Issues')} + + + } + aria-label={t('Settings')} + to={`/settings/${params.orgId}/projects/${params.projectId}/`} + /> + + +
+ + + + + - {isProjectStabilized && ( - - {visibleCharts.map((id, index) => ( - - - - ))} - - - )} - - - - - + + + {isProjectStabilized && ( + + {visibleCharts.map((id, index) => ( + + + + ))} + - - + )} + + + + + - - - - -
- - + + + + + + +
+ ); } diff --git a/static/app/views/projectEventRedirect.tsx b/static/app/views/projectEventRedirect.tsx index 24bfa3ef59c8da..abe534fe442dba 100644 --- a/static/app/views/projectEventRedirect.tsx +++ b/static/app/views/projectEventRedirect.tsx @@ -70,7 +70,8 @@ function ProjectEventRedirect({router}: Props) { return error ? ( ) : ( - + // @ts-expect-error: Layout.Page should never be used without children + ); } diff --git a/static/app/views/projectInstall/gettingStarted.tsx b/static/app/views/projectInstall/gettingStarted.tsx index 1ebabdeb41a628..1ee14a92adfb27 100644 --- a/static/app/views/projectInstall/gettingStarted.tsx +++ b/static/app/views/projectInstall/gettingStarted.tsx @@ -34,7 +34,7 @@ function GettingStarted({params}: Props) { return ( - + {loadingProjects ? ( ) : project ? ( diff --git a/static/app/views/projects/projectContext.tsx b/static/app/views/projects/projectContext.tsx index 219949219f2c6f..f2e91d0e7c1e50 100644 --- a/static/app/views/projects/projectContext.tsx +++ b/static/app/views/projects/projectContext.tsx @@ -249,7 +249,7 @@ class ProjectContextProvider extends Component { case ErrorTypes.PROJECT_NOT_FOUND: // TODO(chrissy): use scale for margin values return ( - + {t('The project you were looking for was not found.')} diff --git a/static/app/views/projectsDashboard/index.tsx b/static/app/views/projectsDashboard/index.tsx index 44cfe3f99faf3e..050ea3c9f2a48d 100644 --- a/static/app/views/projectsDashboard/index.tsx +++ b/static/app/views/projectsDashboard/index.tsx @@ -281,7 +281,7 @@ function Dashboard() { function OrganizationDashboard() { const organization = useOrganization(); return ( - + diff --git a/static/app/views/releases/detail/index.tsx b/static/app/views/releases/detail/index.tsx index b7ce4b99915a5b..823f1779e134d8 100644 --- a/static/app/views/releases/detail/index.tsx +++ b/static/app/views/releases/detail/index.tsx @@ -10,7 +10,6 @@ import NoProjectMessage from 'sentry/components/noProjectMessage'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse'; import PickProjectToContinue from 'sentry/components/pickProjectToContinue'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {PAGE_URL_PARAM, URL_PARAM} from 'sentry/constants/pageFilters'; import {t} from 'sentry/locale'; import type {SessionApiResponse} from 'sentry/types/organization'; @@ -145,17 +144,15 @@ function ReleasesDetail({ e => e?.status === 404 || e?.status === 403 ); return ( - - - - - {possiblyWrongProject - ? t('This release may not be in your selected project.') - : t('There was an error loading the release details')} - - - - + + + + {possiblyWrongProject + ? t('This release may not be in your selected project.') + : t('There was an error loading the release details')} + + + ); }, [pageTitle] @@ -174,11 +171,9 @@ function ReleasesDetail({ isReleasePending || (isDeploysEnabled && isDeploysPending) || isSessionsPending; if (isPending) { return ( - - - - - + + + ); } @@ -190,34 +185,32 @@ function ReleasesDetail({ } return ( - - - - - 0, - releaseBounds, - }} - > - {children} - - - - + + + + 0, + releaseBounds, + }} + > + {children} + + + ); } @@ -253,7 +246,7 @@ function ReleasesDetailContainer({children}: {children: React.ReactNode}) { if (isPending) { return ( - + ); @@ -262,7 +255,7 @@ function ReleasesDetailContainer({children}: {children: React.ReactNode}) { if (isError && error.status === 404) { // This catches a 404 coming from the release endpoint and displays a custom error message. return ( - + {t('This release could not be found.')} diff --git a/static/app/views/relocation/index.tsx b/static/app/views/relocation/index.tsx index 526f394fa8544a..bacf898b767264 100644 --- a/static/app/views/relocation/index.tsx +++ b/static/app/views/relocation/index.tsx @@ -14,7 +14,7 @@ export default function RelocationOnboardingContainer(props: Props) { features={['relocation:enabled']} organizationAllowNull renderDisabled={() => ( - + {t("You don't have access to this feature")} diff --git a/static/app/views/replays/detail/page.tsx b/static/app/views/replays/detail/page.tsx index ab2331e03e3a6b..df0974acc59b8f 100644 --- a/static/app/views/replays/detail/page.tsx +++ b/static/app/views/replays/detail/page.tsx @@ -17,17 +17,17 @@ export default function ReplayDetailsPage({readerResult}: Props) { ( - + )} renderError={({fetchError, onRetry}) => ( - + )} renderThrottled={({fetchError, onRetry}) => ( - + )} @@ -35,12 +35,12 @@ export default function ReplayDetailsPage({readerResult}: Props) { )} renderMissing={() => ( - + )} renderProcessingError={({replay}) => ( - + diff --git a/static/app/views/routeNotFound.tsx b/static/app/views/routeNotFound.tsx index 3a7009a31db47e..6752da5849878a 100644 --- a/static/app/views/routeNotFound.tsx +++ b/static/app/views/routeNotFound.tsx @@ -4,7 +4,6 @@ import * as Sentry from '@sentry/react'; import NotFound from 'sentry/components/errors/notFound'; import Footer from 'sentry/components/footer'; import * as Layout from 'sentry/components/layouts/thirds'; -import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import Sidebar from 'sentry/components/sidebar'; import {t} from 'sentry/locale'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; @@ -45,26 +44,22 @@ function RouteNotFound({location}: Props) { if (!prefersStackedNav) { return ( - -
- - - - -
-
-
+
+ + + + +
+
); } return ( - - - - - - - + + + + + ); }