From 640f05f485117da5f610a0f7b2d48e1c8632604d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 15 Nov 2023 15:24:58 +0100 Subject: [PATCH] frontend-plugin-api: add createSignInPageExtension Co-authored-by: Camila Belo Co-authored-by: Vincenzo Scamporlino Co-authored-by: Philipp Hugenroth Signed-off-by: Patrik Oldsberg --- packages/app-next/src/App.tsx | 66 +++++++--------- .../src/extensions/CoreRouter.tsx | 8 +- packages/frontend-plugin-api/api-report.md | 20 +++++ .../extensions/createSignInPageExtension.tsx | 79 +++++++++++++++++++ .../src/extensions/index.ts | 1 + 5 files changed, 131 insertions(+), 43 deletions(-) create mode 100644 packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 43b93cb14b..987dac8e29 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { ComponentType } from 'react'; +import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { pagesPlugin } from './examples/pagesPlugin'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; @@ -29,7 +29,6 @@ import { createExtension, createApiExtension, createExtensionOverrides, - createExtensionDataRef, } from '@backstage/frontend-plugin-api'; import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; import { homePage } from './HomePage'; @@ -48,6 +47,7 @@ import { scmIntegrationsApiRef, } from '@backstage/integration-react'; import Button from '@material-ui/core/Button'; +import { createSignInPageExtension } from '@backstage/frontend-plugin-api'; /* @@ -90,45 +90,35 @@ const homePageExtension = createExtension({ }, }); -const signInPageComponentDataRef = - createExtensionDataRef>('core.signInPage'); - -const signInPage = createExtension({ +const signInPage = createSignInPageExtension({ id: 'signInPage', - attachTo: { id: 'core.router', input: 'signInPage' }, - output: { - component: signInPageComponentDataRef, - }, - factory() { - return { - component: (props: SignInPageProps) => ( + loader: async () => (props: SignInPageProps) => + ( +
+

Sign in page

-

Sign in page

-
- -
+
- ), - }; - }, +
+ ), }); const scmAuthExtension = createApiExtension({ diff --git a/packages/frontend-app-api/src/extensions/CoreRouter.tsx b/packages/frontend-app-api/src/extensions/CoreRouter.tsx index 712b3d065c..f128a246e6 100644 --- a/packages/frontend-app-api/src/extensions/CoreRouter.tsx +++ b/packages/frontend-app-api/src/extensions/CoreRouter.tsx @@ -18,7 +18,6 @@ import React, { ComponentType, ReactNode, useContext, useState } from 'react'; import { coreExtensionData, createExtension, - createExtensionDataRef, createExtensionInput, } from '@backstage/frontend-plugin-api'; import { @@ -32,6 +31,8 @@ import { InternalAppContext } from '../wiring/InternalAppContext'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; import { BrowserRouter } from 'react-router-dom'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { signInPageComponentDataRef } from '../../../frontend-plugin-api/src/extensions/createSignInPageExtension'; export const CoreRouter = createExtension({ id: 'core.router', @@ -39,10 +40,7 @@ export const CoreRouter = createExtension({ inputs: { signInPage: createExtensionInput( { - component: - createExtensionDataRef>( - 'core.signInPage', - ), + component: signInPageComponentDataRef, }, { singleton: true, optional: true }, ), diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index f1537fd5b7..68aa34dff5 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -68,6 +68,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { SessionApi } from '@backstage/core-plugin-api'; import { SessionState } from '@backstage/core-plugin-api'; +import { SignInPageProps } from '@backstage/core-plugin-api'; import { StorageApi } from '@backstage/core-plugin-api'; import { storageApiRef } from '@backstage/core-plugin-api'; import { StorageValueSnapshot } from '@backstage/core-plugin-api'; @@ -454,6 +455,25 @@ export function createSchemaFromZod( schemaCreator: (zImpl: typeof z) => ZodSchema, ): PortableSchema; +// @public (undocumented) +export function createSignInPageExtension< + TConfig extends {}, + TInputs extends AnyExtensionInputMap, +>(options: { + id: string; + attachTo?: { + id: string; + input: string; + }; + configSchema?: PortableSchema; + disabled?: boolean; + inputs?: TInputs; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise>; +}): Extension; + // @public export function createSubRouteRef< Path extends string, diff --git a/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx new file mode 100644 index 0000000000..048be333b7 --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx @@ -0,0 +1,79 @@ +/* + * 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 React, { ComponentType, lazy } from 'react'; +import { ExtensionBoundary } from '../components'; +import { PortableSchema } from '../schema'; +import { + createExtension, + Extension, + ExtensionInputValues, + AnyExtensionInputMap, + createExtensionDataRef, +} from '../wiring'; +import { Expand } from '../types'; +import { SignInPageProps } from '@backstage/core-plugin-api'; + +/** @internal */ +export const signInPageComponentDataRef = + createExtensionDataRef>('core.signInPage'); + +/** + * + * @public + */ +export function createSignInPageExtension< + TConfig extends {}, + TInputs extends AnyExtensionInputMap, +>(options: { + id: string; + attachTo?: { id: string; input: string }; + configSchema?: PortableSchema; + disabled?: boolean; + inputs?: TInputs; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise>; +}): Extension { + const { id } = options; + + return createExtension({ + id, + attachTo: options.attachTo ?? { id: 'core.router', input: 'signInPage' }, + configSchema: options.configSchema, + inputs: options.inputs, + disabled: options.disabled, + output: { + component: signInPageComponentDataRef, + }, + factory({ config, inputs, source }) { + const ExtensionComponent = lazy(() => + options + .loader({ config, inputs }) + .then(component => ({ default: component })), + ); + + return { + component: props => ( + + + + ), + }; + }, + }); +} diff --git a/packages/frontend-plugin-api/src/extensions/index.ts b/packages/frontend-plugin-api/src/extensions/index.ts index 00cf4f919c..d696774272 100644 --- a/packages/frontend-plugin-api/src/extensions/index.ts +++ b/packages/frontend-plugin-api/src/extensions/index.ts @@ -17,4 +17,5 @@ export { createApiExtension } from './createApiExtension'; export { createPageExtension } from './createPageExtension'; export { createNavItemExtension } from './createNavItemExtension'; +export { createSignInPageExtension } from './createSignInPageExtension'; export { createThemeExtension } from './createThemeExtension';