From ac7470591edc05bb49c4cc27387be2bd0ad32a64 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 4 Jul 2022 09:55:23 +0200 Subject: [PATCH] refactor: apply review suggestions Signed-off-by: Camila Belo --- .changeset/ninety-coats-learn.md | 2 +- packages/core-app-api/api-report.md | 3 -- packages/core-app-api/src/app/AppManager.tsx | 3 +- packages/core-app-api/src/app/index.ts | 1 - packages/core-components/package.json | 1 - .../src/components/Link/Link.tsx | 39 +++++++++++++++---- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/.changeset/ninety-coats-learn.md b/.changeset/ninety-coats-learn.md index 19d56aa128..9d6945e9c0 100644 --- a/.changeset/ninety-coats-learn.md +++ b/.changeset/ninety-coats-learn.md @@ -2,4 +2,4 @@ '@backstage/core-components': patch --- -Fix the relative `sub-paths` by concatenating the app's base URL with them. +Fix relative `sub-paths` by concatenating the app's base path with them. diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 6cbff05709..116b33c598 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -372,9 +372,6 @@ export type FlatRoutesProps = { children: ReactNode; }; -// @public -export function getBasePath(configApi: Config): string; - // @public export class GithubAuth { // (undocumented) diff --git a/packages/core-app-api/src/app/AppManager.tsx b/packages/core-app-api/src/app/AppManager.tsx index 25aa606e4e..f47ddf676a 100644 --- a/packages/core-app-api/src/app/AppManager.tsx +++ b/packages/core-app-api/src/app/AppManager.tsx @@ -95,9 +95,8 @@ const InternalAppContext = createContext<{ * Get the app base path from the configured app baseUrl. * * The returned path does not have a trailing slash. - * @public */ -export function getBasePath(configApi: Config) { +function getBasePath(configApi: Config) { let { pathname } = new URL( configApi.getOptionalString('app.baseUrl') ?? '/', 'http://dummy.dev', // baseUrl can be specified as just a path diff --git a/packages/core-app-api/src/app/index.ts b/packages/core-app-api/src/app/index.ts index 4d4ddf7e8b..7843b36339 100644 --- a/packages/core-app-api/src/app/index.ts +++ b/packages/core-app-api/src/app/index.ts @@ -16,5 +16,4 @@ export { createSpecializedApp } from './createSpecializedApp'; export { defaultConfigLoader } from './defaultConfigLoader'; -export { getBasePath } from './AppManager'; export * from './types'; diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 0202904448..51cbc37a1b 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -34,7 +34,6 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/core-app-api": "^1.0.4-next.0", "@backstage/core-plugin-api": "^1.0.3", "@backstage/errors": "^1.1.0-next.0", "@backstage/theme": "^0.2.16-next.0", diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index d404755b54..22b203d157 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -25,7 +25,7 @@ import { Link as RouterLink, LinkProps as RouterLinkProps, } from 'react-router-dom'; -import { getBasePath } from '@backstage/core-app-api'; +import { trimEnd } from 'lodash'; const useStyles = makeStyles( { @@ -53,14 +53,39 @@ export type LinkProps = MaterialLinkProps & noTrack?: boolean; }; +/** + * Returns the app base url that could be empty if the Config API is not properly implemented. + * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior. + */ +const useBaseUrl = () => { + try { + const config = useApi(configApiRef); + return config.getOptionalString('app.baseUrl'); + } catch { + return undefined; + } +}; + +/** + * Get the app base path from the configured app baseUrl. + * The returned path does not have a trailing slash. + */ +const useBasePath = () => { + // baseUrl can be specified as just a path + const base = 'http://dummy.dev'; + const url = useBaseUrl() ?? '/'; + const { pathname } = new URL(url, base); + return trimEnd(pathname, '/'); +}; + export const useResolvedPath = (uri: LinkProps['to']) => { - const configApi = useApi(configApiRef); - const basePath = getBasePath(configApi); - let resolvedPath = String(uri); - const external = isExternalUri(resolvedPath); - if (!external && !resolvedPath.startsWith(basePath)) { + const basePath = useBasePath(); + const external = isExternalUri(resolvedPath); + const startsWithBasePath = resolvedPath.startsWith(basePath); + + if (!external && !startsWithBasePath) { resolvedPath = basePath.concat(resolvedPath); } @@ -130,8 +155,8 @@ export const Link = React.forwardRef( {...props} ref={ref} component={RouterLink} - onClick={handleClick} to={to} + onClick={handleClick} /> ); },