From 52d6ad7c0f9dec78386d6be939f1b85bd38f3eed Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 5 Jan 2023 10:01:48 +0100 Subject: [PATCH] chore: moving some more re-usable logic to the `-react` package Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 91 ++++++------------- .../src/hooks/useCustomFieldExtensions.ts | 9 +- .../src/next/extensions/index.tsx | 3 +- plugins/scaffolder/src/components/Router.tsx | 3 +- plugins/scaffolder/src/next/Router/Router.tsx | 3 +- 5 files changed, 39 insertions(+), 70 deletions(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 79e461a2ec..1091f68d17 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -9,31 +9,25 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; -import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; import { FieldProps as FieldProps_2 } from '@rjsf/utils'; import { FieldValidation } from '@rjsf/core'; import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { Observable } from '@backstage/types'; -import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; -import { RouteRef } from '@backstage/core-plugin-api'; import { SetStateAction } from 'react'; -import { SubRouteRef } from '@backstage/core-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { UIOptionsType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; -// @public (undocumented) -export const actionsRouteRef: SubRouteRef; - // @alpha export const createFieldValidation: () => FieldValidation_2; @@ -68,21 +62,12 @@ export type CustomFieldValidator = ( }, ) => void | Promise; -// @public (undocumented) -export const editRouteRef: SubRouteRef; - // @alpha export const extractSchemaFromStep: (inputStep: JsonObject) => { uiSchema: UiSchema; schema: JsonObject; }; -// @public -export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; - -// @public -export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; - // @public export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; @@ -116,11 +101,6 @@ export type FormProps = Pick< 'transformErrors' | 'noHtml5Validate' >; -// @public @deprecated (undocumented) -export const legacySelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:templateName'> ->; - // @public export type ListActionsResponse = Array<{ id: string; @@ -178,19 +158,6 @@ export type NextFieldExtensionOptions< schema?: CustomFieldExtensionSchema; }; -// @alpha (undocumented) -export const nextRouteRef: RouteRef; - -// @alpha (undocumented) -export const nextScaffolderTaskRouteRef: SubRouteRef< - PathParams<'/tasks/:taskId'> ->; - -// @alpha (undocumented) -export const nextSelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @alpha export interface ParsedTemplateSchema { // (undocumented) @@ -205,9 +172,6 @@ export interface ParsedTemplateSchema { uiSchema: UiSchema; } -// @public (undocumented) -export const registerComponentRouteRef: ExternalRouteRef; - // @alpha export const ReviewState: (props: ReviewStateProps) => JSX.Element; @@ -217,9 +181,6 @@ export type ReviewStateProps = { formState: JsonObject; }; -// @public (undocumented) -export const rootRouteRef: RouteRef; - // @public export interface ScaffolderApi { // (undocumented) @@ -299,9 +260,6 @@ export interface ScaffolderGetIntegrationsListResponse { }[]; } -// @public (undocumented) -export const scaffolderListTaskRouteRef: SubRouteRef; - // @public (undocumented) export type ScaffolderOutputLink = { title?: string; @@ -350,9 +308,6 @@ export type ScaffolderTaskOutput = { [key: string]: unknown; }; -// @public (undocumented) -export const scaffolderTaskRouteRef: SubRouteRef>; - // @public export type ScaffolderTaskStatus = | 'open' @@ -383,11 +338,6 @@ export const SecretsContextProvider: ({ children, }: PropsWithChildren<{}>) => JSX.Element; -// @public (undocumented) -export const selectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @alpha export const Stepper: (props: StepperProps) => JSX.Element; @@ -395,8 +345,9 @@ export const Stepper: (props: StepperProps) => JSX.Element; export type StepperProps = { manifest: TemplateParameterSchema; extensions: NextFieldExtensionOptions[]; - onComplete: (values: Record) => Promise; + templateName?: string; FormProps?: FormProps; + onComplete: (values: Record) => Promise; }; // @alpha @@ -405,7 +356,13 @@ export const TemplateCard: (props: TemplateCardProps) => JSX.Element; // @alpha export interface TemplateCardProps { // (undocumented) - deprecated?: boolean; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + // (undocumented) + onSelected?: (template: TemplateEntityV1beta3) => void; // (undocumented) template: TemplateEntityV1beta3; } @@ -420,7 +377,16 @@ export interface TemplateGroupProps { CardComponent?: React_2.ComponentType; }; // (undocumented) - templates: TemplateEntityV1beta3[]; + onSelected: (template: TemplateEntityV1beta3) => void; + // (undocumented) + templates: { + template: TemplateEntityV1beta3; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + }[]; // (undocumented) title: React_2.ReactNode; } @@ -436,6 +402,13 @@ export type TemplateParameterSchema = { }>; }; +// @public +export const useCustomFieldExtensions: < + TComponentDataType = FieldExtensionOptions, +>( + outlet: React.ReactNode, +) => TComponentDataType[]; + // @alpha export const useFormData: () => [ Record, @@ -450,15 +423,5 @@ export const useTemplateSchema: (manifest: TemplateParameterSchema) => { // @public export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets; -// @public (undocumented) -export const viewTechDocRouteRef: ExternalRouteRef< - { - name: string; - kind: string; - namespace: string; - }, - true ->; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts b/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts index 15300956c6..7e0aafd53f 100644 --- a/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts +++ b/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts @@ -19,19 +19,22 @@ import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY, } from '../extensions/keys'; -import { NextFieldExtensionOptions } from '../next'; /** * Hook that returns all custom field extensions from the current outlet. * @public */ -export const useCustomFieldExtensions = (outlet: React.ReactNode) => { +export const useCustomFieldExtensions = < + TComponentDataType = FieldExtensionOptions, +>( + outlet: React.ReactNode, +) => { return useElementFilter(outlet, elements => elements .selectByComponentData({ key: FIELD_EXTENSION_WRAPPER_KEY, }) - .findComponentData({ + .findComponentData({ key: FIELD_EXTENSION_KEY, }), ); diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/next/extensions/index.tsx index d4161867e4..ee9b1cd326 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/next/extensions/index.tsx @@ -21,7 +21,8 @@ import { } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; -import { FieldExtensionComponent, FIELD_EXTENSION_KEY } from '../../extensions'; +import { FieldExtensionComponent } from '../../extensions'; +import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; /** * Method for creating field extensions that can be used in the scaffolder diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 564e12bcae..6a2da406e0 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -30,6 +30,7 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { + FieldExtensionOptions, SecretsContextProvider, useCustomFieldExtensions, } from '@backstage/plugin-scaffolder-react'; @@ -101,7 +102,7 @@ export const Router = (props: RouterProps) => { customFieldExtension => customFieldExtension.name === name, ), ), - ]; + ] as FieldExtensionOptions[]; // todo(blam): this should also be moved to a hook in -react const customLayouts = useElementFilter(outlet, elements => diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 33c2b40f01..784e17dd55 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -53,7 +53,8 @@ export type NextRouterProps = { export const Router = (props: PropsWithChildren) => { const { components: { TemplateCardComponent } = {} } = props; const outlet = useOutlet() || props.children; - const customFieldExtensions = useCustomFieldExtensions(outlet); + const customFieldExtensions = + useCustomFieldExtensions(outlet); const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(