From 227c7394ea2b8939464190fb643b058b715b43f5 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 30 Oct 2023 15:18:33 +0100 Subject: [PATCH] feat: create collect legacy components Signed-off-by: Camila Belo --- packages/app-next/src/App.tsx | 13 +++- .../examples/notFoundErrorPageExtension.tsx | 2 +- .../src/collectLegacyComponents.test.tsx | 61 +++++++++++++++++++ .../src/collectLegacyComponents.tsx | 53 ++++++++++++++++ packages/core-compat-api/src/index.ts | 1 + 5 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 packages/core-compat-api/src/collectLegacyComponents.test.tsx create mode 100644 packages/core-compat-api/src/collectLegacyComponents.tsx diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 3fb91bd03e..791d2b38fa 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { pagesPlugin } from './examples/pagesPlugin'; -import customNotFoundErrorPage from './examples/notFoundErrorPageExtension'; +import { CustomNotFoundErrorPage } from './examples/notFoundErrorPageExtension'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; @@ -33,7 +33,10 @@ import { } from '@backstage/frontend-plugin-api'; import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; import { homePage } from './HomePage'; -import { collectLegacyRoutes } from '@backstage/core-compat-api'; +import { + collectLegacyComponents, + collectLegacyRoutes, +} from '@backstage/core-compat-api'; import { FlatRoutes } from '@backstage/core-app-api'; import { Route } from 'react-router'; import { CatalogImportPage } from '@backstage/plugin-catalog-import'; @@ -115,6 +118,10 @@ const collectedLegacyPlugins = collectLegacyRoutes( , ); +const legacyAppComponents = collectLegacyComponents({ + NotFoundErrorPage: CustomNotFoundErrorPage, +}); + const app = createApp({ features: [ graphiqlPlugin, @@ -130,7 +137,7 @@ const app = createApp({ scmAuthExtension, scmIntegrationApi, signInPage, - customNotFoundErrorPage, + ...legacyAppComponents, ], }), ], diff --git a/packages/app-next/src/examples/notFoundErrorPageExtension.tsx b/packages/app-next/src/examples/notFoundErrorPageExtension.tsx index 0e1fbd40f8..c076b059f4 100644 --- a/packages/app-next/src/examples/notFoundErrorPageExtension.tsx +++ b/packages/app-next/src/examples/notFoundErrorPageExtension.tsx @@ -22,7 +22,7 @@ import { import { Box, Typography } from '@material-ui/core'; import { Button } from '@backstage/core-components'; -function CustomNotFoundErrorPage() { +export function CustomNotFoundErrorPage() { return ( { + const components = { + Progress: () =>
Progress
, + BootErrorPage: () =>
BootErrorPage
, + NotFoundErrorPage: () =>
NotFoundErrorPage
, + ErrorBoundaryFallback: () =>
ErrorBoundaryFallback
, + }; + + it('should collect legacy routes', () => { + const collected = collectLegacyComponents(components); + + expect( + collected.map(p => ({ + id: p.id, + attachTo: p.attachTo, + disabled: p.disabled, + })), + ).toEqual([ + { + id: 'core.components.progress', + attachTo: { id: 'core', input: 'components' }, + disabled: false, + }, + { + id: 'core.components.bootErrorPage', + attachTo: { id: 'core', input: 'components' }, + disabled: false, + }, + { + id: 'core.components.notFoundErrorPage', + attachTo: { id: 'core', input: 'components' }, + disabled: false, + }, + { + id: 'core.components.errorBoundaryFallback', + attachTo: { id: 'core', input: 'components' }, + disabled: false, + }, + ]); + }); +}); diff --git a/packages/core-compat-api/src/collectLegacyComponents.tsx b/packages/core-compat-api/src/collectLegacyComponents.tsx new file mode 100644 index 0000000000..97c3ee22ad --- /dev/null +++ b/packages/core-compat-api/src/collectLegacyComponents.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 { + Extension, + ComponentRef, + createComponentExtension, + coreProgressComponentRef, + coreBootErrorPageComponentRef, + coreNotFoundErrorPageComponentRef, + coreErrorBoundaryFallbackComponentRef, +} from '@backstage/frontend-plugin-api'; +import { AppComponents } from '@backstage/core-plugin-api'; + +type ComponentTypes = T[keyof T]; + +const refs: Record> = { + Progress: coreProgressComponentRef, + BootErrorPage: coreBootErrorPageComponentRef, + NotFoundErrorPage: coreNotFoundErrorPageComponentRef, + ErrorBoundaryFallback: coreErrorBoundaryFallbackComponentRef, +}; + +/** @public */ +export function collectLegacyComponents(components: Partial) { + return Object.entries(components).reduce[]>( + (extensions, [componentName, componentFunction]) => { + const ref = refs[componentName]; + return ref + ? extensions.concat( + createComponentExtension({ + ref, + component: async () => componentFunction, + }), + ) + : extensions; + }, + [], + ); +} diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts index 421ced7054..d31513e559 100644 --- a/packages/core-compat-api/src/index.ts +++ b/packages/core-compat-api/src/index.ts @@ -14,5 +14,6 @@ * limitations under the License. */ export { collectLegacyRoutes } from './collectLegacyRoutes'; +export { collectLegacyComponents } from './collectLegacyComponents'; export { convertLegacyApp } from './convertLegacyApp'; export { convertLegacyRouteRef } from './convertLegacyRouteRef';