diff --git a/plugins/user-settings/src/alpha.tsx b/plugins/user-settings/src/alpha.tsx index 2d6327f030..235733760b 100644 --- a/plugins/user-settings/src/alpha.tsx +++ b/plugins/user-settings/src/alpha.tsx @@ -19,13 +19,38 @@ import { createFrontendPlugin, PageBlueprint, NavItemBlueprint, + SubPageBlueprint, } from '@backstage/frontend-plugin-api'; +import { Content } from '@backstage/core-components'; import SettingsIcon from '@material-ui/icons/Settings'; import { settingsRouteRef } from './plugin'; export * from './translation'; -const userSettingsPage = PageBlueprint.makeWithOverrides({ +const userSettingsPage = PageBlueprint.make({ + params: { + path: '/settings', + routeRef: settingsRouteRef, + title: 'Settings', + }, +}); + +const generalSettingsPage = SubPageBlueprint.make({ + name: 'general', + params: { + path: 'general', + title: 'General', + loader: () => + import('./components/General').then(m => ( + + + + )), + }, +}); + +const authProvidersSettingsPage = SubPageBlueprint.makeWithOverrides({ + name: 'auth-providers', inputs: { providerSettings: createExtensionInput([coreExtensionData.reactElement], { singleton: true, @@ -34,20 +59,36 @@ const userSettingsPage = PageBlueprint.makeWithOverrides({ }, factory(originalFactory, { inputs }) { return originalFactory({ - path: '/settings', - routeRef: settingsRouteRef, + path: 'auth-providers', + title: 'Authentication Providers', loader: () => - import('./components/SettingsPage/SettingsPage').then(m => ( - + import('./components/AuthProviders').then(m => ( + + + )), }); }, }); +const featureFlagsSettingsPage = SubPageBlueprint.make({ + name: 'feature-flags', + params: { + path: 'feature-flags', + title: 'Feature Flags', + loader: () => + import('./components/FeatureFlags').then(m => ( + + + + )), + }, +}); + /** @alpha */ export const settingsNavItem = NavItemBlueprint.make({ params: { @@ -65,7 +106,13 @@ export default createFrontendPlugin({ title: 'Settings', icon: , info: { packageJson: () => import('../package.json') }, - extensions: [userSettingsPage, settingsNavItem], + extensions: [ + userSettingsPage, + generalSettingsPage, + authProvidersSettingsPage, + featureFlagsSettingsPage, + settingsNavItem, + ], routes: { root: settingsRouteRef, }, diff --git a/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx b/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx index 83f4e28cf3..ea5bc66603 100644 --- a/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx +++ b/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx @@ -19,10 +19,7 @@ import { UserSettingsAuthProviders } from '../AuthProviders'; import { UserSettingsFeatureFlags } from '../FeatureFlags'; import { UserSettingsGeneral } from '../General'; import { SettingsLayoutRouteProps } from '../SettingsLayout'; -import { - NfsSettingsLayout, - SettingsLayout, -} from '../SettingsLayout/SettingsLayout'; +import { SettingsLayout } from '../SettingsLayout/SettingsLayout'; import { useTranslationRef } from '@backstage/frontend-plugin-api'; import { userSettingsTranslationRef } from '../../translation'; @@ -60,35 +57,3 @@ export const DefaultSettingsPage = (props: { ); }; - -export const NfsDefaultSettingsPage = (props: { - tabs?: ReactElement[]; - providerSettings?: JSX.Element; -}) => { - const { providerSettings, tabs } = props; - const { t } = useTranslationRef(userSettingsTranslationRef); - - return ( - - - - - - - - - - - {tabs} - - ); -}; diff --git a/plugins/user-settings/src/components/SettingsLayout/SettingsLayout.tsx b/plugins/user-settings/src/components/SettingsLayout/SettingsLayout.tsx index a059be505c..76ee01e202 100644 --- a/plugins/user-settings/src/components/SettingsLayout/SettingsLayout.tsx +++ b/plugins/user-settings/src/components/SettingsLayout/SettingsLayout.tsx @@ -14,28 +14,19 @@ * limitations under the License. */ -import { ElementType, ReactNode, useMemo } from 'react'; +import { ElementType, ReactNode } from 'react'; import { TabProps } from '@material-ui/core/Tab'; import { - Content, Header, Page, RoutedTabs, useSidebarPinState, } from '@backstage/core-components'; -import { HeaderPage } from '@backstage/ui'; import { attachComponentData, useElementFilter, } from '@backstage/core-plugin-api'; import { useTranslationRef } from '@backstage/frontend-plugin-api'; -import { Helmet } from 'react-helmet'; -import { - matchRoutes, - useLocation, - useParams, - useRoutes, -} from 'react-router-dom'; import { userSettingsTranslationRef } from '../../translation'; /** @public */ @@ -62,78 +53,6 @@ export type SettingsLayoutProps = { children?: ReactNode; }; -const normalizePath = (path: string) => - path !== '/' && path.endsWith('/') ? path.slice(0, -1) : path; - -const getTabsBasePath = ( - pathname: string, - routes: SettingsLayoutRouteProps[], -) => { - const normalizedPathname = normalizePath(pathname); - const relativeRoutePaths = routes - .map(route => route.path.replace(/^\/+|\/+$/g, '')) - .filter(Boolean) - .sort((a, b) => b.length - a.length); - - for (const routePath of relativeRoutePaths) { - const marker = `/${routePath}`; - const matchIndex = normalizedPathname.lastIndexOf(marker); - - if (matchIndex === -1) { - continue; - } - - const matchEndIndex = matchIndex + marker.length; - if ( - matchEndIndex !== normalizedPathname.length && - normalizedPathname[matchEndIndex] !== '/' - ) { - continue; - } - - return normalizedPathname.slice(0, matchIndex) || '/'; - } - - return normalizedPathname || '/'; -}; - -const useSelectedSubRoute = ( - subRoutes: SettingsLayoutRouteProps[], -): { - route?: SettingsLayoutRouteProps; - element?: JSX.Element; -} => { - const params = useParams(); - - const routes = subRoutes.map(({ path, children }) => ({ - caseSensitive: false, - path: `${path}/*`, - element: children, - })); - - const sortedRoutes = routes.sort((a, b) => - b.path.replace(/\/\*$/, '').localeCompare(a.path.replace(/\/\*$/, '')), - ); - - const element = useRoutes(sortedRoutes) ?? subRoutes[0]?.children; - - let currentRoute = params['*'] ?? ''; - if (!currentRoute.startsWith('/')) { - currentRoute = `/${currentRoute}`; - } - - const [matchedRoute] = matchRoutes(sortedRoutes, currentRoute) ?? []; - const foundIndex = matchedRoute - ? subRoutes.findIndex(t => `${t.path}/*` === matchedRoute.route.path) - : 0; - const route = subRoutes[foundIndex === -1 ? 0 : foundIndex] ?? subRoutes[0]; - - return { - route, - element, - }; -}; - /** * @public */ @@ -161,50 +80,6 @@ export const SettingsLayout = (props: SettingsLayoutProps) => { ); }; -export const NfsSettingsLayout = (props: SettingsLayoutProps) => { - const { title, children } = props; - const { isMobile } = useSidebarPinState(); - const { t } = useTranslationRef(userSettingsTranslationRef); - const location = useLocation(); - - const routes = useElementFilter(children, elements => - elements - .selectByComponentData({ - key: LAYOUT_ROUTE_DATA_KEY, - withStrictError: - 'Child of SettingsLayout must be an SettingsLayout.Route', - }) - .getElements() - .map(child => child.props), - ); - const { route, element } = useSelectedSubRoute(routes); - const tabs = useMemo(() => { - const basePath = getTabsBasePath(location.pathname, routes); - - return routes.map(subRoute => ({ - id: subRoute.path, - label: subRoute.title, - href: subRoute.path.startsWith('/') - ? subRoute.path - : `${basePath}/${subRoute.path}`.replace(/\/{2,}/g, '/'), - matchStrategy: 'prefix' as const, - })); - }, [location.pathname, routes]); - - return ( - <> - {!isMobile && } - {isMobile && } - {!isMobile && ( - - - {element} - - )} - - ); -}; - attachComponentData(SettingsLayout, LAYOUT_DATA_KEY, true); SettingsLayout.Route = Route; diff --git a/plugins/user-settings/src/components/SettingsPage/SettingsPage.tsx b/plugins/user-settings/src/components/SettingsPage/SettingsPage.tsx index 14797a3763..b72862e2bc 100644 --- a/plugins/user-settings/src/components/SettingsPage/SettingsPage.tsx +++ b/plugins/user-settings/src/components/SettingsPage/SettingsPage.tsx @@ -15,7 +15,6 @@ */ import { useOutlet } from 'react-router-dom'; import { DefaultSettingsPage } from '../DefaultSettingsPage'; -import { NfsDefaultSettingsPage } from '../DefaultSettingsPage/DefaultSettingsPage'; import { useElementFilter } from '@backstage/core-plugin-api'; import { SettingsLayoutProps, @@ -53,33 +52,3 @@ export const SettingsPage = (props: { providerSettings?: JSX.Element }) => { ); }; - -export const NfsSettingsPage = (props: { providerSettings?: JSX.Element }) => { - const { providerSettings } = props; - const outlet = useOutlet(); - const layout = useElementFilter(outlet, elements => - elements - .selectByComponentData({ - key: LAYOUT_DATA_KEY, - }) - .getElements(), - ); - const tabs = useElementFilter(outlet, elements => - elements - .selectByComponentData({ - key: LAYOUT_ROUTE_DATA_KEY, - }) - .getElements(), - ); - - return ( - <> - {(layout.length !== 0 && layout) || ( - - )} - - ); -}; diff --git a/yarn.lock b/yarn.lock index fbb16ac5c3..8fa3fcd925 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5372,7 +5372,6 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog-unprocessed-entities-common": "workspace:^" - "@backstage/plugin-devtools-react": "workspace:^" "@backstage/ui": "workspace:^" "@material-ui/core": "npm:^4.9.13" "@material-ui/icons": "npm:^4.9.1" @@ -5536,7 +5535,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-devtools-react@workspace:^, @backstage/plugin-devtools-react@workspace:plugins/devtools-react": +"@backstage/plugin-devtools-react@workspace:plugins/devtools-react": version: 0.0.0-use.local resolution: "@backstage/plugin-devtools-react@workspace:plugins/devtools-react" dependencies: @@ -5574,7 +5573,6 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-devtools-common": "workspace:^" - "@backstage/plugin-devtools-react": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/ui": "workspace:^" "@material-ui/core": "npm:^4.9.13"