Use custom UserSettingsTab component to render extra tabs in settings
Signed-off-by: Yousif Al-Raheem <yousifalraheem@gmail.com>
This commit is contained in:
@@ -69,7 +69,10 @@ import {
|
||||
techdocsPlugin,
|
||||
TechDocsReaderPage,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import { UserSettingsPage } from '@backstage/plugin-user-settings';
|
||||
import {
|
||||
UserSettingsPage,
|
||||
UserSettingsTab,
|
||||
} from '@backstage/plugin-user-settings';
|
||||
import { AdvancedSettings } from './components/advancedSettings';
|
||||
import AlarmIcon from '@material-ui/icons/Alarm';
|
||||
import React from 'react';
|
||||
@@ -216,9 +219,9 @@ const routes = (
|
||||
element={<CostInsightsLabelDataflowInstructionsPage />}
|
||||
/>
|
||||
<Route path="/settings" element={<UserSettingsPage />}>
|
||||
<Route path="/advanced" element={<AdvancedSettings />}>
|
||||
Advanced
|
||||
</Route>
|
||||
<UserSettingsTab path="/advanced" title="Advanced">
|
||||
<AdvancedSettings />
|
||||
</UserSettingsTab>
|
||||
</Route>
|
||||
<Route path="/azure-pull-requests" element={<AzurePullRequestsPage />} />
|
||||
<Route path="/apache-airflow" element={<ApacheAirflowPage />} />
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
import React from 'react';
|
||||
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { SettingsPage } from './SettingsPage';
|
||||
import { UserSettingsTab } from './UserSettingsTab';
|
||||
|
||||
jest.mock('react-router', () => ({
|
||||
...jest.requireActual('react-router'),
|
||||
useOutlet: jest.fn().mockReturnValue(undefined),
|
||||
}));
|
||||
|
||||
import { useOutlet, Route } from 'react-router';
|
||||
import { useOutlet } from 'react-router';
|
||||
|
||||
describe('<SettingsPage />', () => {
|
||||
it('should render the settings page with 3 tabs', async () => {
|
||||
@@ -38,9 +39,9 @@ describe('<SettingsPage />', () => {
|
||||
it('should render the settings page with 4 tabs when extra tabs are provided', async () => {
|
||||
const advancedTabRoute = (
|
||||
<>
|
||||
<Route path="/advanced" element={<div>Advanced settings</div>}>
|
||||
Advanced
|
||||
</Route>
|
||||
<UserSettingsTab path="/advanced" title="Advanced">
|
||||
<div>Advanced settings</div>
|
||||
</UserSettingsTab>
|
||||
</>
|
||||
);
|
||||
(useOutlet as jest.Mock).mockReturnValueOnce(advancedTabRoute);
|
||||
@@ -56,9 +57,9 @@ describe('<SettingsPage />', () => {
|
||||
it('should throw error if non compliant route is passed to settings routes', async () => {
|
||||
const advancedTabRoute = (
|
||||
<>
|
||||
<Route path="/advanced" element={<div>Advanced settings</div>}>
|
||||
Advanced
|
||||
</Route>
|
||||
<UserSettingsTab path="/advanced" title="Advanced">
|
||||
<div>Advanced settings</div>
|
||||
</UserSettingsTab>
|
||||
<div>Non compliant element</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -37,11 +37,11 @@ export const SettingsPage = ({ providerSettings }: Props) => {
|
||||
const extraTabs = (React.Children.toArray(outlet?.props?.children) ||
|
||||
[]) as Array<ReactElement>;
|
||||
const notCompliantTab = Array.from(extraTabs).some(
|
||||
child => (child.type as any)?.displayName !== 'Route',
|
||||
child => (child.type as any)?.displayName !== 'UserSettingsTab',
|
||||
);
|
||||
if (notCompliantTab) {
|
||||
throw new Error(
|
||||
'Invalid element passed to SettingsPage Outlet. You may only pass children of type Route.',
|
||||
'Invalid element passed to SettingsPage Outlet. You may only pass children of type UserSettingsTab.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export const SettingsPage = ({ providerSettings }: Props) => {
|
||||
|
||||
{extraTabs.map((child, i) => {
|
||||
const path: string = child.props.path;
|
||||
const title: string = child.props.children;
|
||||
const title: string = child.props.title;
|
||||
|
||||
return (
|
||||
<TabbedLayout.Route key={i} path={path} title={title}>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 from 'react';
|
||||
|
||||
interface Props {
|
||||
path: string;
|
||||
title: React.ReactNode;
|
||||
}
|
||||
|
||||
export const UserSettingsTab: React.FC<Props> = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
UserSettingsTab.displayName = 'UserSettingsTab';
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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';
|
||||
@@ -19,3 +19,4 @@ export * from './AuthProviders';
|
||||
export * from './General';
|
||||
export * from './FeatureFlags';
|
||||
export { useUserProfile } from './useUserProfileInfo';
|
||||
export * from './UserSettingsTab';
|
||||
|
||||
Reference in New Issue
Block a user