From c40a2a5e614dbc87edfe23df59c499b0591c3e6d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 6 Jun 2020 15:55:46 +0200 Subject: [PATCH] packages/core-api: move router component inside app and configure it with base path --- packages/app/src/App.tsx | 9 ++--- .../default-app/packages/app/src/App.tsx | 5 +-- packages/core-api/src/app/App.tsx | 40 ++++++++++++++++--- packages/core-api/src/app/types.ts | 1 + packages/core/src/api-wrappers/createApp.tsx | 7 ++-- packages/dev-utils/src/devApp/render.tsx | 11 ++--- .../test-utils/src/testUtils/appWrappers.tsx | 7 ++-- 7 files changed, 51 insertions(+), 29 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index b4d01e067b..669838ddd6 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -16,7 +16,6 @@ import { createApp, AlertDisplay, OAuthRequestDialog } from '@backstage/core'; import React, { FC } from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; import Root from './components/Root'; import * as plugins from './plugins'; import apis from './apis'; @@ -33,11 +32,9 @@ const App: FC<{}> = () => ( - - - - - + + + ); diff --git a/packages/cli/templates/default-app/packages/app/src/App.tsx b/packages/cli/templates/default-app/packages/app/src/App.tsx index 84bc1b2e7d..140d1c1660 100644 --- a/packages/cli/templates/default-app/packages/app/src/App.tsx +++ b/packages/cli/templates/default-app/packages/app/src/App.tsx @@ -1,7 +1,6 @@ import { makeStyles } from '@material-ui/core'; import { createApp } from '@backstage/core'; import React, { FC } from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; import * as plugins from './plugins'; const useStyles = makeStyles(theme => ({ @@ -33,9 +32,7 @@ const App: FC<{}> = () => { useStyles(); return ( - - - + ); }; diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index 575dcfc59d..7cc37c2544 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { ComponentType, FC } from 'react'; +import React, { ComponentType, FC, useMemo } from 'react'; import { Route, Switch, Redirect } from 'react-router-dom'; import { AppContextProvider } from './AppContext'; import { BackstageApp, AppComponents, AppConfigLoader } from './types'; @@ -161,30 +161,58 @@ export class PrivateAppImpl implements BackstageApp { getProvider(): ComponentType<{}> { const Provider: FC<{}> = ({ children }) => { + const appThemeApi = useMemo( + () => AppThemeSelector.createWithStorage(this.themes), + [], + ); + // Keeping this synchronous when a config loader isn't set simplifies tests a lot const hasConfig = Boolean(this.configLoader); const config = useAsync(this.configLoader || (() => Promise.resolve([]))); - let childNode = children; + let noConfigNode = undefined; if (hasConfig && config.loading) { const { Progress } = this.components; - childNode = ; + noConfigNode = ; } else if (config.error) { const { BootErrorPage } = this.components; - childNode = ; + noConfigNode = ( + + ); } + // Before the config is loaded we can't use a router, so exit early + if (noConfigNode) { + return ( + + {noConfigNode} + + ); + } + + const configReader = ConfigReader.fromConfigs(config.value ?? []); const appApis = ApiRegistry.from([ [appThemeApiRef, AppThemeSelector.createWithStorage(this.themes)], - [configApiRef, ConfigReader.fromConfigs(config.value ?? [])], + [configApiRef, configReader], ]); const apis = new ApiAggregator(this.apis, appApis); + const { Router } = this.components; + let { pathname } = new URL( + configReader.getString('app.baseUrl') ?? '/', + 'http://dummy.dev', // baseUrl can be specified as just a path + ); + if (pathname.endsWith('/')) { + pathname = pathname.replace(/\/$/, ''); + } + return ( - {childNode} + + {children} + ); diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index 4d685a6312..664c5238bc 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -30,6 +30,7 @@ export type AppComponents = { NotFoundErrorPage: ComponentType<{}>; BootErrorPage: ComponentType; Progress: ComponentType<{}>; + Router: ComponentType<{ basename?: string }>; }; /** diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index 8ed5cddad7..f69451249b 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -22,7 +22,7 @@ import privateExports, { BootErrorPageProps, AppConfigLoader, } from '@backstage/core-api'; -import { BrowserRouter as Router } from 'react-router-dom'; +import { BrowserRouter, MemoryRouter } from 'react-router-dom'; import { ErrorPage } from '../layout/ErrorPage'; import Progress from '../components/Progress'; @@ -87,9 +87,9 @@ export function createApp(options?: AppOptions) { } // TODO: figure out a nicer way to handle routing on the error page, when it can be done. return ( - + - + ); }; @@ -100,6 +100,7 @@ export function createApp(options?: AppOptions) { NotFoundErrorPage: DefaultNotFoundPage, BootErrorPage: DefaultBootErrorPage, Progress: Progress, + Router: BrowserRouter, ...options?.components, }; const themes = options?.themes ?? [ diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index aa952f1ca5..8900ecd54b 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -17,7 +17,6 @@ import { hot } from 'react-hot-loader/root'; import React, { FC, ComponentType, ReactNode } from 'react'; import ReactDOM from 'react-dom'; -import { BrowserRouter } from 'react-router-dom'; import BookmarkIcon from '@material-ui/icons/Bookmark'; import { createApp, @@ -94,12 +93,10 @@ class DevAppBuilder { {this.rootChildren} - - - {sidebar} - - - + + {sidebar} + + ); }; diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 2450604976..6fa6f62d8c 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -55,6 +55,9 @@ export function wrapInTestApp( NotFoundErrorPage, BootErrorPage, Progress, + Router: ({ children }) => ( + + ), }, icons: defaultSystemIcons, plugins: [], @@ -79,9 +82,7 @@ export function wrapInTestApp( return ( - - - + ); }