Skip to content

Commit f010b7d

Browse files
committed
ref(layout): move title to page
1 parent 83a01f1 commit f010b7d

File tree

48 files changed

+838
-897
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+838
-897
lines changed

static/app/components/layouts/thirds.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,28 @@ import styled from '@emotion/styled';
44

55
import {Flex} from 'sentry/components/core/layout';
66
import {Tabs} from 'sentry/components/core/tabs';
7-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
7+
import SentryDocumentTitle, {
8+
type DocumentTitleOptions,
9+
} from 'sentry/components/sentryDocumentTitle';
810
import {space} from 'sentry/styles/space';
911

1012
/**
1113
* Main container for a page.
1214
*/
1315
interface PageProps {
1416
children: NonNullable<React.ReactNode>;
15-
title: string | null;
17+
title: string | DocumentTitleOptions | null;
1618
withPadding?: boolean;
1719
}
1820

19-
export function Page(props: PageProps) {
21+
export const Page = styled((props: PageProps) => {
2022
return (
2123
<Fragment>
22-
{props.title ? <SentryDocumentTitle title={props.title} /> : null}
24+
{props.title === null ? null : typeof props.title === 'string' ? (
25+
<SentryDocumentTitle title={props.title} />
26+
) : (
27+
<SentryDocumentTitle {...props.title} />
28+
)}
2329
<Flex
2430
direction="column"
2531
flex={1}
@@ -29,7 +35,7 @@ export function Page(props: PageProps) {
2935
</Flex>
3036
</Fragment>
3137
);
32-
}
38+
})``;
3339

3440
/**
3541
* Header container for header content and header actions.
Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,35 @@
11
import {createContext, useContext, useEffect, useMemo} from 'react';
22

3-
type Props = {
4-
children?: React.ReactNode;
5-
/**
6-
* Should the ` - Sentry` suffix be excluded?
7-
*/
8-
noSuffix?: boolean;
9-
/**
10-
* The organization slug to show in the title
11-
*/
12-
orgSlug?: string;
13-
/**
14-
* The project slug to show in the title.
15-
*/
16-
projectSlug?: string;
17-
18-
/**
19-
* This string will be shown at the very front of the title
20-
*/
21-
title?: string;
22-
};
3+
import type {Organization} from 'sentry/types/organization';
4+
import type {Project} from 'sentry/types/project';
235

246
const DEFAULT_PAGE_TITLE = 'Sentry';
25-
267
const DocumentTitleContext = createContext(DEFAULT_PAGE_TITLE);
278

289
export function useDocumentTitle() {
2910
return useContext(DocumentTitleContext);
3011
}
3112

13+
interface SentryDocumentTitleProps extends DocumentTitleOptions {
14+
children?: React.ReactNode;
15+
}
16+
3217
/**
3318
* Assigns the document title. The deepest nested version of this title will be
3419
* the one which is assigned.
3520
*/
36-
function SentryDocumentTitle({
37-
title = '',
21+
export default function SentryDocumentTitle({
22+
title,
3823
orgSlug,
3924
projectSlug,
4025
noSuffix,
4126
children,
42-
}: Props) {
27+
}: SentryDocumentTitleProps) {
4328
const parentTitle = useContext(DocumentTitleContext);
44-
45-
const pageTitle = useMemo(() => {
46-
if (orgSlug && projectSlug) {
47-
return `${title}${orgSlug}${projectSlug}`;
48-
}
49-
50-
if (orgSlug) {
51-
return `${title}${orgSlug}`;
52-
}
53-
54-
if (projectSlug) {
55-
return `${title}${projectSlug}`;
56-
}
57-
58-
return title;
59-
}, [orgSlug, projectSlug, title]);
60-
61-
const documentTitle = useMemo(() => {
62-
if (noSuffix) {
63-
return pageTitle;
64-
}
65-
66-
if (pageTitle !== '') {
67-
return `${pageTitle} — Sentry`;
68-
}
69-
70-
return DEFAULT_PAGE_TITLE;
71-
}, [noSuffix, pageTitle]);
29+
const documentTitle = useMemo(
30+
() => makeSentryDocumentTitle(title ?? '', orgSlug, projectSlug, noSuffix),
31+
[orgSlug, projectSlug, title, noSuffix]
32+
);
7233

7334
// NOTE: We do this OUTSIDE of a use effect so that the update order is
7435
// correct, otherwsie the inner most SentryDocumentTitle will have its
@@ -87,4 +48,30 @@ function SentryDocumentTitle({
8748
return <DocumentTitleContext value={documentTitle}>{children}</DocumentTitleContext>;
8849
}
8950

90-
export default SentryDocumentTitle;
51+
export interface DocumentTitleOptions {
52+
title: string;
53+
noSuffix?: boolean;
54+
orgSlug?: Organization['slug'];
55+
projectSlug?: Project['slug'];
56+
}
57+
58+
export function makeSentryDocumentTitle(
59+
title: string,
60+
orgSlug?: string,
61+
projectSlug?: string,
62+
noSuffix?: boolean
63+
) {
64+
if (orgSlug) {
65+
if (projectSlug) {
66+
return `${title}${orgSlug}${projectSlug}`;
67+
}
68+
69+
return `${title}${orgSlug}`;
70+
}
71+
72+
if (projectSlug) {
73+
return `${title}${projectSlug}`;
74+
}
75+
76+
return noSuffix ? title : `${title} — Sentry`;
77+
}

static/app/views/alerts/rules/metric/details/index.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {Alert} from 'sentry/components/core/alert';
1010
import {DateTime} from 'sentry/components/dateTime';
1111
import * as Layout from 'sentry/components/layouts/thirds';
1212
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
13-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
1413
import {t} from 'sentry/locale';
1514
import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
1615
import type {Organization} from 'sentry/types/organization';
@@ -246,7 +245,7 @@ class MetricAlertDetails extends Component<Props, State> {
246245
const {error} = this.state;
247246

248247
return (
249-
<Layout.Page withPadding>
248+
<Layout.Page title={t('Alert Rule')} withPadding>
250249
<Alert.Container>
251250
<Alert type="error">
252251
{error?.status === 404
@@ -282,22 +281,23 @@ class MetricAlertDetails extends Component<Props, State> {
282281
<Alert type="warning">{warning}</Alert>
283282
</Alert.Container>
284283
)}
285-
<SentryDocumentTitle title={rule?.name ?? ''} />
286284

287-
<DetailsHeader
288-
hasMetricRuleDetailsError={hasError}
289-
organization={organization}
290-
rule={rule}
291-
project={project}
292-
onSnooze={this.onSnooze}
293-
/>
294-
<MetricDetailsBody
295-
rule={rule}
296-
project={project}
297-
incidents={incidents}
298-
timePeriod={timePeriod}
299-
selectedIncident={selectedIncident}
300-
/>
285+
<Layout.Page title={rule?.name ?? t('Alert Rule')} withPadding>
286+
<DetailsHeader
287+
hasMetricRuleDetailsError={hasError}
288+
organization={organization}
289+
rule={rule}
290+
project={project}
291+
onSnooze={this.onSnooze}
292+
/>
293+
<MetricDetailsBody
294+
rule={rule}
295+
project={project}
296+
incidents={incidents}
297+
timePeriod={timePeriod}
298+
selectedIncident={selectedIncident}
299+
/>
300+
</Layout.Page>
301301
</PageFiltersContainer>
302302
);
303303
}

static/app/views/alerts/rules/uptime/details.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import LoadingError from 'sentry/components/loadingError';
1414
import LoadingIndicator from 'sentry/components/loadingIndicator';
1515
import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
1616
import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
17-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
1817
import {IconEdit} from 'sentry/icons';
1918
import {t, tct} from 'sentry/locale';
2019
import {space} from 'sentry/styles/space';
@@ -114,8 +113,7 @@ export default function UptimeAlertDetails({params}: UptimeAlertDetailsProps) {
114113
);
115114

116115
return (
117-
<Layout.Page>
118-
<SentryDocumentTitle title={`${uptimeRule.name} — Alerts`} />
116+
<Layout.Page title={`${uptimeRule.name} — Alerts`}>
119117
<Layout.Header>
120118
<Layout.HeaderContent>
121119
<Breadcrumbs

static/app/views/alerts/wizard/index.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import ListItem from 'sentry/components/list/listItem';
1212
import Panel from 'sentry/components/panels/panel';
1313
import PanelBody from 'sentry/components/panels/panelBody';
1414
import PanelHeader from 'sentry/components/panels/panelHeader';
15-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
1615
import {t} from 'sentry/locale';
1716
import {space} from 'sentry/styles/space';
1817
import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
@@ -147,9 +146,7 @@ function AlertWizard({organization, params, location, projectId}: AlertWizardPro
147146

148147
const panelContent = AlertWizardPanelContent[alertOption];
149148
return (
150-
<Layout.Page>
151-
<SentryDocumentTitle title={t('Alert Creation Wizard')} projectSlug={projectSlug} />
152-
149+
<Layout.Page title={t('Alert Creation Wizard')}>
153150
<Layout.Header>
154151
<StyledHeaderContent>
155152
<BuilderBreadCrumbs

static/app/views/automations/edit.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import type {OnSubmitCallback} from 'sentry/components/forms/types';
99
import * as Layout from 'sentry/components/layouts/thirds';
1010
import LoadingError from 'sentry/components/loadingError';
1111
import LoadingIndicator from 'sentry/components/loadingIndicator';
12-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
1312
import {FullHeightForm} from 'sentry/components/workflowEngine/form/fullHeightForm';
1413
import {useFormField} from 'sentry/components/workflowEngine/form/useFormField';
1514
import {useWorkflowEngineFeatureGate} from 'sentry/components/workflowEngine/useWorkflowEngineFeatureGate';
@@ -40,11 +39,6 @@ import {
4039
makeAutomationDetailsPathname,
4140
} from 'sentry/views/automations/pathnames';
4241

43-
function AutomationDocumentTitle() {
44-
const title = useFormField('name');
45-
return <SentryDocumentTitle title={title ?? t('Edit Automation')} />;
46-
}
47-
4842
function AutomationBreadcrumbs({automationId}: {automationId: string}) {
4943
const title = useFormField('name');
5044
const organization = useOrganization();
@@ -151,8 +145,7 @@ function AutomationEditForm({automation}: {automation: Automation}) {
151145
initialData={initialData}
152146
onSubmit={handleFormSubmit}
153147
>
154-
<AutomationDocumentTitle />
155-
<Layout.Page>
148+
<Layout.Page title={useFormField('name') ?? t('Edit Automation')}>
156149
<StyledLayoutHeader>
157150
<Layout.HeaderContent>
158151
<AutomationBreadcrumbs automationId={params.automationId} />

static/app/views/automations/new-settings.tsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {Flex} from 'sentry/components/core/layout';
88
import FormModel from 'sentry/components/forms/model';
99
import type {OnSubmitCallback} from 'sentry/components/forms/types';
1010
import * as Layout from 'sentry/components/layouts/thirds';
11-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
1211
import {FullHeightForm} from 'sentry/components/workflowEngine/form/fullHeightForm';
1312
import {useFormField} from 'sentry/components/workflowEngine/form/useFormField';
1413
import {
@@ -38,15 +37,6 @@ import {
3837
makeAutomationDetailsPathname,
3938
} from 'sentry/views/automations/pathnames';
4039

41-
function AutomationDocumentTitle() {
42-
const title = useFormField('name');
43-
return (
44-
<SentryDocumentTitle
45-
title={title ? t('%s - New Automation', title) : t('New Automation')}
46-
/>
47-
);
48-
}
49-
5040
function AutomationBreadcrumbs() {
5141
const title = useFormField('name');
5242
const organization = useOrganization();
@@ -74,6 +64,10 @@ export default function AutomationNewSettings() {
7464
const model = useMemo(() => new FormModel(), []);
7565
const {state, actions} = useAutomationBuilderReducer();
7666

67+
const formName = useFormField('name');
68+
69+
const formTitle = formName ? t('%s - New Automation', formName) : t('New Automation');
70+
7771
const [automationBuilderErrors, setAutomationBuilderErrors] = useState<
7872
Record<string, string>
7973
>({});
@@ -122,8 +116,7 @@ export default function AutomationNewSettings() {
122116
onSubmit={handleSubmit}
123117
model={model}
124118
>
125-
<AutomationDocumentTitle />
126-
<Layout.Page>
119+
<Layout.Page title={{title: formTitle}}>
127120
<StyledLayoutHeader>
128121
<Layout.HeaderContent>
129122
<AutomationBreadcrumbs />

static/app/views/automations/new.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import {useState} from 'react';
1+
import {Fragment, useState} from 'react';
22
import styled from '@emotion/styled';
33

44
import {Breadcrumbs} from 'sentry/components/breadcrumbs';
55
import {LinkButton} from 'sentry/components/core/button/linkButton';
66
import {Flex} from 'sentry/components/core/layout';
77
import * as Layout from 'sentry/components/layouts/thirds';
8-
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
98
import {
109
StickyFooter,
1110
StickyFooterLabel,
@@ -52,8 +51,8 @@ export default function AutomationNew() {
5251
});
5352

5453
return (
55-
<SentryDocumentTitle title={t('New Automation')} noSuffix>
56-
<Layout.Page>
54+
<Fragment>
55+
<Layout.Page title={t('New Automation')}>
5756
<StyledLayoutHeader>
5857
<Layout.HeaderContent>
5958
<AutomationBreadcrumbs />
@@ -100,7 +99,7 @@ export default function AutomationNew() {
10099
</LinkButton>
101100
</Flex>
102101
</StickyFooter>
103-
</SentryDocumentTitle>
102+
</Fragment>
104103
);
105104
}
106105

static/app/views/dashboards/create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function CreateDashboard(props: Props) {
2727
const [newWidget, setNewWidget] = useState<Widget | undefined>();
2828
function renderDisabled() {
2929
return (
30-
<Layout.Page withPadding>
30+
<Layout.Page title={t('Create Dashboard')} withPadding>
3131
<Alert.Container>
3232
<Alert type="warning" showIcon={false}>
3333
{t("You don't have access to this feature")}

0 commit comments

Comments
 (0)