From 1fa5041091aa0dafb4f56835e1cab2ca642c45e9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 18 Jan 2024 14:20:38 +0100 Subject: [PATCH] core-compat-api: make compatWrapper use ComponentsApi and IconsApi Signed-off-by: Patrik Oldsberg --- .changeset/chilly-seahorses-bake.md | 5 ++ .../compatWrapper/BackwardsCompatProvider.tsx | 62 ++++++++++++++----- .../src/compatWrapper/compatWrapper.test.tsx | 2 +- 3 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 .changeset/chilly-seahorses-bake.md diff --git a/.changeset/chilly-seahorses-bake.md b/.changeset/chilly-seahorses-bake.md new file mode 100644 index 0000000000..8ab80cf93e --- /dev/null +++ b/.changeset/chilly-seahorses-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +The backwards compatibility provider will now use the new `ComponentsApi` and `IconsApi` when implementing the old `AppContext`. diff --git a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx index 099993a392..1dd64efb89 100644 --- a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx +++ b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx @@ -18,14 +18,13 @@ import React, { useMemo } from 'react'; import { ReactNode } from 'react'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppContextProvider } from '../../../core-app-api/src/app/AppContext'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { - components as defaultComponents, - icons as defaultIcons, -} from '../../../app-defaults/src/defaults'; import { + createPlugin as createNewPlugin, BackstagePlugin as NewBackstagePlugin, appTreeApiRef, + componentsApiRef, + coreComponentRefs, + iconsApiRef, useApi, } from '@backstage/frontend-plugin-api'; import { @@ -71,15 +70,35 @@ function toLegacyPlugin(plugin: NewBackstagePlugin): LegacyBackstagePlugin { return legacy; } +// TODO: Currently a very naive implementation, may need some more work +function toNewPlugin(plugin: LegacyBackstagePlugin): NewBackstagePlugin { + return createNewPlugin({ + id: plugin.getId(), + }); +} + // Recreates the old AppContext APIs using the various new APIs that replaced it function LegacyAppContextProvider(props: { children: ReactNode }) { const appTreeApi = useApi(appTreeApiRef); + const componentsApi = useApi(componentsApiRef); + const iconsApi = useApi(iconsApiRef); const appContext = useMemo(() => { const { tree } = appTreeApi.getTree(); let gatheredPlugins: LegacyBackstagePlugin[] | undefined = undefined; + const ErrorBoundaryFallback = componentsApi.getComponent( + coreComponentRefs.errorBoundaryFallback, + ); + const ErrorBoundaryFallbackWrapper: AppComponents['ErrorBoundaryFallback'] = + ({ plugin, ...rest }) => ( + + ); + return { getPlugins(): LegacyBackstagePlugin[] { if (gatheredPlugins) { @@ -98,24 +117,39 @@ function LegacyAppContextProvider(props: { children: ReactNode }) { return gatheredPlugins; }, - // TODO: Grab these from new API once it exists getSystemIcon(key: string): IconComponent | undefined { - return key in defaultIcons - ? defaultIcons[key as keyof typeof defaultIcons] - : undefined; + return iconsApi.getIcon(key); }, - // TODO: Grab these from new API once it exists getSystemIcons(): Record { - return defaultIcons; + const { keys } = iconsApi.listIconKeys(); + + return Object.fromEntries( + Array.from(keys).map(key => [key, iconsApi.getIcon(key)!]), + ); }, - // TODO: Grab these from new API once it exists getComponents(): AppComponents { - return defaultComponents; + return { + NotFoundErrorPage: componentsApi.getComponent( + coreComponentRefs.notFoundErrorPage, + ), + BootErrorPage() { + throw new Error( + 'The BootErrorPage app component should not be accessed by plugins', + ); + }, + Progress: componentsApi.getComponent(coreComponentRefs.progress), + Router() { + throw new Error( + 'The Router app component should not be accessed by plugins', + ); + }, + ErrorBoundaryFallback: ErrorBoundaryFallbackWrapper, + }; }, }; - }, [appTreeApi]); + }, [appTreeApi, componentsApi, iconsApi]); return ( diff --git a/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx b/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx index b2ad7f3d0c..2e7dbd9d37 100644 --- a/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx +++ b/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx @@ -60,7 +60,7 @@ describe('BackwardsCompatProvider', () => { expect(screen.getByTestId('ctx').textContent).toMatchInlineSnapshot(` "plugins: - components: Progress, Router, NotFoundErrorPage, BootErrorPage, ErrorBoundaryFallback + components: NotFoundErrorPage, BootErrorPage, Progress, Router, ErrorBoundaryFallback icons: brokenImage, catalog, scaffolder, techdocs, search, chat, dashboard, docs, email, github, group, help, kind:api, kind:component, kind:domain, kind:group, kind:location, kind:system, kind:user, kind:resource, kind:template, user, warning" `); });