Used Layout pattern in SettingsPage, analogous to Explore Plugin
Signed-off-by: Nikita Karpukhin <nikita.karpukhin@scout24.com>
This commit is contained in:
+5
-6
@@ -16,16 +16,15 @@
|
||||
|
||||
import React from 'react';
|
||||
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { SettingsPage } from './SettingsPage';
|
||||
import { UserSettingsTab } from './UserSettingsTab';
|
||||
import { DefaultSettingsPage } from './DefaultSettingsPage';
|
||||
import { UserSettingsTab } from '../UserSettingsTab';
|
||||
import { useOutlet } from 'react-router';
|
||||
|
||||
jest.mock('react-router', () => ({
|
||||
...jest.requireActual('react-router'),
|
||||
useOutlet: jest.fn().mockReturnValue(undefined),
|
||||
}));
|
||||
|
||||
import { useOutlet } from 'react-router';
|
||||
|
||||
describe('<SettingsPage />', () => {
|
||||
beforeEach(() => {
|
||||
(useOutlet as jest.Mock).mockReset();
|
||||
@@ -33,7 +32,7 @@ describe('<SettingsPage />', () => {
|
||||
|
||||
it('should render the settings page with 3 tabs', async () => {
|
||||
const { container } = await renderWithEffects(
|
||||
wrapInTestApp(<SettingsPage />),
|
||||
wrapInTestApp(<DefaultSettingsPage />),
|
||||
);
|
||||
|
||||
const tabs = container.querySelectorAll('[class*=MuiTabs-root] button');
|
||||
@@ -48,7 +47,7 @@ describe('<SettingsPage />', () => {
|
||||
);
|
||||
(useOutlet as jest.Mock).mockReturnValue(advancedTabRoute);
|
||||
const { container } = await renderWithEffects(
|
||||
wrapInTestApp(<SettingsPage />),
|
||||
wrapInTestApp(<DefaultSettingsPage />),
|
||||
);
|
||||
|
||||
const tabs = container.querySelectorAll('[class*=MuiTabs-root] button');
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2022 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';
|
||||
import { UserSettingsAuthProviders } from '../AuthProviders';
|
||||
import { UserSettingsFeatureFlags } from '../FeatureFlags';
|
||||
import { UserSettingsGeneral } from '../General';
|
||||
import { SettingsLayout } from '../SettingsLayout';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const DefaultSettingsPage = (props: {
|
||||
providerSettings?: JSX.Element;
|
||||
}) => {
|
||||
const { providerSettings } = props;
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<SettingsLayout.Route path="general" title="General">
|
||||
<UserSettingsGeneral />
|
||||
</SettingsLayout.Route>
|
||||
<SettingsLayout.Route
|
||||
path="auth-providers"
|
||||
title="Authentication Providers"
|
||||
>
|
||||
<UserSettingsAuthProviders providerSettings={providerSettings} />
|
||||
</SettingsLayout.Route>
|
||||
<SettingsLayout.Route path="feature-flags" title="Feature Flags">
|
||||
<UserSettingsFeatureFlags />
|
||||
</SettingsLayout.Route>
|
||||
</SettingsLayout>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2022 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 { DefaultSettingsPage } from './DefaultSettingsPage';
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2022 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';
|
||||
import { TabProps } from '@material-ui/core';
|
||||
import {
|
||||
Header,
|
||||
Page,
|
||||
RoutedTabs,
|
||||
useSidebarPinState,
|
||||
} from '@backstage/core-components';
|
||||
import {
|
||||
attachComponentData,
|
||||
useElementFilter,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
/** @public */
|
||||
export type SubRoute = {
|
||||
path: string;
|
||||
title: string;
|
||||
children: JSX.Element;
|
||||
tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;
|
||||
};
|
||||
|
||||
const dataKey = 'plugin.explore.settingsLayoutRoute';
|
||||
|
||||
const Route: (props: SubRoute) => null = () => null;
|
||||
attachComponentData(Route, dataKey, 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);
|
||||
|
||||
/** @public */
|
||||
export type SettingsLayoutProps = {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const SettingsLayout = (props: SettingsLayoutProps) => {
|
||||
const { title, children } = props;
|
||||
const { isMobile } = useSidebarPinState();
|
||||
|
||||
const routes = useElementFilter(children, elements =>
|
||||
elements
|
||||
.selectByComponentData({
|
||||
key: dataKey,
|
||||
withStrictError:
|
||||
'Child of SettingsLayout must be an SettingsLayout.Route',
|
||||
})
|
||||
.getElements<SubRoute>()
|
||||
.map(child => child.props),
|
||||
);
|
||||
|
||||
return (
|
||||
<Page themeId="home">
|
||||
{!isMobile && <Header title={title ?? 'Settings'} />}
|
||||
<RoutedTabs routes={routes} />
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
SettingsLayout.Route = Route;
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2022 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 type { SettingsLayoutProps, SubRoute } from './SettingsLayout';
|
||||
export { SettingsLayout } from './SettingsLayout';
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
* Copyright 2022 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.
|
||||
@@ -13,60 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Header,
|
||||
Page,
|
||||
TabbedLayout,
|
||||
useSidebarPinState,
|
||||
} from '@backstage/core-components';
|
||||
import React from 'react';
|
||||
import { useOutlet } from 'react-router';
|
||||
import { useElementFilter } from '@backstage/core-plugin-api';
|
||||
import { UserSettingsAuthProviders } from './AuthProviders';
|
||||
import { UserSettingsFeatureFlags } from './FeatureFlags';
|
||||
import { UserSettingsGeneral } from './General';
|
||||
import { USER_SETTINGS_TAB_KEY, UserSettingsTabProps } from './UserSettingsTab';
|
||||
import React from 'react';
|
||||
import { DefaultSettingsPage } from './DefaultSettingsPage';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const SettingsPage = (props: { providerSettings?: JSX.Element }) => {
|
||||
const { providerSettings } = props;
|
||||
const { isMobile } = useSidebarPinState();
|
||||
export const SettingsPage = () => {
|
||||
const outlet = useOutlet();
|
||||
|
||||
const tabs = useElementFilter(outlet, elements =>
|
||||
elements
|
||||
.selectByComponentData({
|
||||
key: USER_SETTINGS_TAB_KEY,
|
||||
})
|
||||
.getElements<UserSettingsTabProps>(),
|
||||
);
|
||||
|
||||
return (
|
||||
<Page themeId="home">
|
||||
{!isMobile && <Header title="Settings" />}
|
||||
<TabbedLayout>
|
||||
<TabbedLayout.Route path="general" title="General">
|
||||
<UserSettingsGeneral />
|
||||
</TabbedLayout.Route>
|
||||
<TabbedLayout.Route
|
||||
path="auth-providers"
|
||||
title="Authentication Providers"
|
||||
>
|
||||
<UserSettingsAuthProviders providerSettings={providerSettings} />
|
||||
</TabbedLayout.Route>
|
||||
<TabbedLayout.Route path="feature-flags" title="Feature Flags">
|
||||
<UserSettingsFeatureFlags />
|
||||
</TabbedLayout.Route>
|
||||
|
||||
{tabs.map((child, i) => (
|
||||
<TabbedLayout.Route key={i} {...child.props}>
|
||||
{child}
|
||||
</TabbedLayout.Route>
|
||||
))}
|
||||
</TabbedLayout>
|
||||
</Page>
|
||||
);
|
||||
return <>{outlet || <DefaultSettingsPage />}</>;
|
||||
};
|
||||
|
||||
@@ -21,3 +21,4 @@ export * from './General';
|
||||
export * from './FeatureFlags';
|
||||
export { useUserProfile } from './useUserProfileInfo';
|
||||
export * from './UserSettingsTab';
|
||||
export * from './SettingsLayout';
|
||||
|
||||
Reference in New Issue
Block a user