frontend-plugin-api: add createSignInPageExtension

Co-authored-by: Camila Belo <camilaibs@gmail.com>
Co-authored-by: Vincenzo Scamporlino <vincenzos@spotify.com>
Co-authored-by: Philipp Hugenroth <philipph@spotify.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-11-15 15:24:58 +01:00
parent 07afe68561
commit 640f05f485
5 changed files with 131 additions and 43 deletions
+28 -38
View File
@@ -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<ComponentType<SignInPageProps>>('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) =>
(
<div>
<h1>Sign in page</h1>
<div>
<h1>Sign in page</h1>
<div>
<Button
onClick={() =>
props.onSignInSuccess({
getProfileInfo: async () => ({
email: 'guest@example.com',
displayName: 'Guest',
}),
getBackstageIdentity: async () => ({
type: 'user',
userEntityRef: 'user:default/guest',
ownershipEntityRefs: ['user:default/guest'],
}),
getCredentials: async () => ({}),
signOut: async () => {},
})
}
>
Sign in
</Button>
</div>
<Button
onClick={() =>
props.onSignInSuccess({
getProfileInfo: async () => ({
email: 'guest@example.com',
displayName: 'Guest',
}),
getBackstageIdentity: async () => ({
type: 'user',
userEntityRef: 'user:default/guest',
ownershipEntityRefs: ['user:default/guest'],
}),
getCredentials: async () => ({}),
signOut: async () => {},
})
}
>
Sign in
</Button>
</div>
),
};
},
</div>
),
});
const scmAuthExtension = createApiExtension({
@@ -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<ComponentType<SignInPageProps>>(
'core.signInPage',
),
component: signInPageComponentDataRef,
},
{ singleton: true, optional: true },
),
@@ -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<TOutput, TInput>(
schemaCreator: (zImpl: typeof z) => ZodSchema<TOutput, ZodTypeDef, TInput>,
): PortableSchema<TOutput>;
// @public (undocumented)
export function createSignInPageExtension<
TConfig extends {},
TInputs extends AnyExtensionInputMap,
>(options: {
id: string;
attachTo?: {
id: string;
input: string;
};
configSchema?: PortableSchema<TConfig>;
disabled?: boolean;
inputs?: TInputs;
loader: (options: {
config: TConfig;
inputs: Expand<ExtensionInputValues<TInputs>>;
}) => Promise<ComponentType<SignInPageProps>>;
}): Extension<TConfig>;
// @public
export function createSubRouteRef<
Path extends string,
@@ -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<ComponentType<SignInPageProps>>('core.signInPage');
/**
*
* @public
*/
export function createSignInPageExtension<
TConfig extends {},
TInputs extends AnyExtensionInputMap,
>(options: {
id: string;
attachTo?: { id: string; input: string };
configSchema?: PortableSchema<TConfig>;
disabled?: boolean;
inputs?: TInputs;
loader: (options: {
config: TConfig;
inputs: Expand<ExtensionInputValues<TInputs>>;
}) => Promise<ComponentType<SignInPageProps>>;
}): Extension<TConfig> {
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 => (
<ExtensionBoundary id={id} source={source} routable>
<ExtensionComponent {...props} />
</ExtensionBoundary>
),
};
},
});
}
@@ -17,4 +17,5 @@
export { createApiExtension } from './createApiExtension';
export { createPageExtension } from './createPageExtension';
export { createNavItemExtension } from './createNavItemExtension';
export { createSignInPageExtension } from './createSignInPageExtension';
export { createThemeExtension } from './createThemeExtension';