deprecate UserSettingsTab in favour of SettingsLayout.Route

Signed-off-by: Nikita Karpukhin <nikita.karpukhin@scout24.com>
This commit is contained in:
Nikita Karpukhin
2022-11-15 12:46:46 +01:00
parent 931eb6d3bc
commit 29bdda5442
12 changed files with 43 additions and 103 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-user-settings': minor
---
Deprecated UserSettingsTab in favour of SettingsLayout.Route
+3 -3
View File
@@ -80,8 +80,8 @@ import {
TextSize,
} from '@backstage/plugin-techdocs-module-addons-contrib';
import {
SettingsLayout,
UserSettingsPage,
UserSettingsTab,
} from '@backstage/plugin-user-settings';
import { AdvancedSettings } from './components/advancedSettings';
import AlarmIcon from '@material-ui/icons/Alarm';
@@ -267,9 +267,9 @@ const routes = (
element={<CostInsightsLabelDataflowInstructionsPage />}
/>
<Route path="/settings" element={<UserSettingsPage />}>
<UserSettingsTab path="/advanced" title="Advanced">
<SettingsLayout.Route path="/advanced" title="Advanced">
<AdvancedSettings />
</UserSettingsTab>
</SettingsLayout.Route>
</Route>
<Route path="/azure-pull-requests" element={<AzurePullRequestsPage />} />
<Route path="/apache-airflow" element={<ApacheAirflowPage />} />
+4 -4
View File
@@ -71,20 +71,20 @@ const AppRoutes = () => (
By default, the plugin renders 3 tabs of settings; GENERAL, AUTHENTICATION PROVIDERS, and FEATURE FLAGS.
If you want to add more options for your users,
just pass the extra tabs using `UserSettingsTab` components as children of the `UserSettingsPage` route.
just pass the extra tabs using `SettingsLayout.Route` components as children of the `UserSettingsPage` route.
The path is in this case a child of the settings path,
in the example below it would be `/settings/advanced` so that you can easily link to it.
```tsx
import {
SettingsLayout,
UserSettingsPage,
UserSettingsTab,
} from '@backstage/plugin-user-settings';
<Route path="/settings" element={<UserSettingsPage />}>
<UserSettingsTab path="/advanced" title="Advanced">
<SettingsLayout.Route path="/advanced" title="Advanced">
<AdvancedSettings />
</UserSettingsTab>
</SettingsLayout.Route>
</Route>;
```
-13
View File
@@ -17,7 +17,6 @@ import { JsonValue } from '@backstage/types';
import { Observable } from '@backstage/types';
import { ProfileInfo } from '@backstage/core-plugin-api';
import { ProfileInfoApi } from '@backstage/core-plugin-api';
import { PropsWithChildren } from 'react';
import { default as React_2 } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';
import { SessionApi } from '@backstage/core-plugin-api';
@@ -70,9 +69,6 @@ export type SettingsLayoutRouteProps = {
>;
};
// @public (undocumented)
export const USER_SETTINGS_TAB_KEY = 'user-settings.tab';
// @public (undocumented)
export const UserSettingsAppearanceCard: () => JSX.Element;
@@ -144,15 +140,6 @@ export class UserSettingsStorage implements StorageApi {
snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T>;
}
// @public
export const UserSettingsTab: (props: UserSettingsTabProps) => JSX.Element;
// @public (undocumented)
export type UserSettingsTabProps = PropsWithChildren<{
path: string;
title: string;
}>;
// @public (undocumented)
export const UserSettingsThemeToggle: () => JSX.Element;
@@ -17,8 +17,8 @@
import React from 'react';
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
import { DefaultSettingsPage } from './DefaultSettingsPage';
import { UserSettingsTab } from '../UserSettingsTab';
import { useOutlet } from 'react-router';
import { SettingsLayout } from '../SettingsLayout';
jest.mock('react-router', () => ({
...jest.requireActual('react-router'),
@@ -41,9 +41,9 @@ describe('<DefaultSettingsPage />', () => {
it('should render the settings page with 4 tabs when extra tabs are provided', async () => {
const advancedTabRoute = (
<UserSettingsTab path="/advanced" title="Advanced">
<SettingsLayout.Route path="/advanced" title="Advanced">
<div>Advanced settings</div>
</UserSettingsTab>
</SettingsLayout.Route>
);
const { container } = await renderWithEffects(
wrapInTestApp(<DefaultSettingsPage tabs={[advancedTabRoute]} />),
@@ -18,14 +18,13 @@ import React from 'react';
import { UserSettingsAuthProviders } from '../AuthProviders';
import { UserSettingsFeatureFlags } from '../FeatureFlags';
import { UserSettingsGeneral } from '../General';
import { SettingsLayout } from '../SettingsLayout';
import { UserSettingsTabProps } from '../UserSettingsTab';
import { SettingsLayout, SettingsLayoutRouteProps } from '../SettingsLayout';
/**
* @public
*/
export const DefaultSettingsPage = (props: {
tabs?: React.ReactElement<UserSettingsTabProps>[];
tabs?: React.ReactElement<SettingsLayoutRouteProps>[];
providerSettings?: JSX.Element;
}) => {
const { providerSettings, tabs } = props;
@@ -44,11 +43,7 @@ export const DefaultSettingsPage = (props: {
<SettingsLayout.Route path="feature-flags" title="Feature Flags">
<UserSettingsFeatureFlags />
</SettingsLayout.Route>
{tabs?.map((child, i) => (
<SettingsLayout.Route key={i} {...child.props}>
{child}
</SettingsLayout.Route>
))}
{tabs}
</SettingsLayout>
);
};
@@ -35,10 +35,11 @@ export type SettingsLayoutRouteProps = {
tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;
};
const dataKey = 'plugin.user-settings.settingsLayoutRoute';
export const LAYOUT_ROUTE_DATA_KEY = 'plugin.user-settings.settingsLayoutRoute';
export const LAYOUT_DATA_KEY = 'plugin.user-settings.settingsLayout';
const Route: (props: SettingsLayoutRouteProps) => null = () => null;
attachComponentData(Route, dataKey, true);
attachComponentData(Route, LAYOUT_ROUTE_DATA_KEY, true);
// This causes all mount points that are discovered within this route to use the path of the route itself
attachComponentData(Route, 'core.gatherMountPoints', true);
@@ -60,7 +61,7 @@ export const SettingsLayout = (props: SettingsLayoutProps) => {
const routes = useElementFilter(children, elements =>
elements
.selectByComponentData({
key: dataKey,
key: LAYOUT_ROUTE_DATA_KEY,
withStrictError:
'Child of SettingsLayout must be an SettingsLayout.Route',
})
@@ -76,4 +77,6 @@ export const SettingsLayout = (props: SettingsLayoutProps) => {
);
};
attachComponentData(SettingsLayout, LAYOUT_DATA_KEY, true);
SettingsLayout.Route = Route;
@@ -17,7 +17,6 @@
import React from 'react';
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
import { SettingsPage } from './SettingsPage';
import { UserSettingsTab } from '../UserSettingsTab';
import { useOutlet } from 'react-router';
import { SettingsLayout } from '../SettingsLayout';
@@ -42,9 +41,9 @@ describe('<SettingsPage />', () => {
it('should render the default settings page with 4 tabs when extra tabs are provided', async () => {
const advancedTabRoute = (
<UserSettingsTab path="/advanced" title="Advanced">
<SettingsLayout.Route path="/advanced" title="Advanced">
<div>Advanced settings</div>
</UserSettingsTab>
</SettingsLayout.Route>
);
(useOutlet as jest.Mock).mockReturnValue(advancedTabRoute);
const { container } = await renderWithEffects(
@@ -18,25 +18,36 @@ import React from 'react';
import { DefaultSettingsPage } from '../DefaultSettingsPage';
import { useElementFilter } from '@backstage/core-plugin-api';
import {
USER_SETTINGS_TAB_KEY,
UserSettingsTabProps,
} from '../UserSettingsTab';
SettingsLayoutProps,
SettingsLayoutRouteProps,
} from '../SettingsLayout';
import {
LAYOUT_DATA_KEY,
LAYOUT_ROUTE_DATA_KEY,
} from '../SettingsLayout/SettingsLayout';
/** @public */
export const SettingsPage = (props: { providerSettings?: JSX.Element }) => {
const { providerSettings } = props;
const outlet = useOutlet();
const layout = useElementFilter(outlet, elements =>
elements
.selectByComponentData({
key: LAYOUT_DATA_KEY,
})
.getElements<SettingsLayoutProps>(),
);
const tabs = useElementFilter(outlet, elements =>
elements
.selectByComponentData({
key: USER_SETTINGS_TAB_KEY,
key: LAYOUT_ROUTE_DATA_KEY,
})
.getElements<UserSettingsTabProps>(),
.getElements<SettingsLayoutRouteProps>(),
);
return (
<>
{(tabs.length === 0 && outlet) || (
{(layout.length !== 0 && layout) || (
<DefaultSettingsPage tabs={tabs} providerSettings={providerSettings} />
)}
</>
@@ -1,42 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import { attachComponentData } from '@backstage/core-plugin-api';
/** @public */
export const USER_SETTINGS_TAB_KEY = 'user-settings.tab';
/** @public */
export type UserSettingsTabProps = PropsWithChildren<{
/**
* The path to the tab in the settings route
* @example `/settings/advanced`
*/
path: string;
/** The title of the tab. It will also reflect in the document title when the tab is active */
title: string;
}>;
/**
* Renders a tab inside the settings page
* @param props - Component props
* @public
*/
export const UserSettingsTab = (props: UserSettingsTabProps) => {
return <>{props.children}</>;
};
attachComponentData(UserSettingsTab, USER_SETTINGS_TAB_KEY, 'UserSettingsTab');
@@ -1,17 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './UserSettingsTab';
@@ -20,5 +20,4 @@ export * from './AuthProviders';
export * from './General';
export * from './FeatureFlags';
export { useUserProfile } from './useUserProfileInfo';
export * from './UserSettingsTab';
export * from './SettingsLayout';