From f6874fbfa8329893880ed4d03caf0b8f3c94022a Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 14 Oct 2024 09:31:12 +0200 Subject: [PATCH] chore: adding some more useful state to the context Signed-off-by: blam --- plugins/scaffolder-react/report.api.md | 4 ---- .../src/next/components/Workflow/Workflow.tsx | 14 ++++++++++---- .../extensions/createScaffolderFormDecorator.ts | 7 ++++++- .../src/secrets/SecretsContext.tsx | 12 ++++++++++++ .../scaffolder/src/alpha/api/FormDecoratorsApi.ts | 8 +++++--- .../src/alpha/hooks/useFormDecorators.test.tsx | 2 ++ plugins/scaffolder/src/plugin.tsx | 7 +++++++ 7 files changed, 42 insertions(+), 12 deletions(-) diff --git a/plugins/scaffolder-react/report.api.md b/plugins/scaffolder-react/report.api.md index 1ac2fd279b..5523b52ad9 100644 --- a/plugins/scaffolder-react/report.api.md +++ b/plugins/scaffolder-react/report.api.md @@ -538,10 +538,6 @@ export type TemplateParameterSchema = { description?: string; schema: JsonObject; }>; - EXPERIMENTAL_formDecorators?: { - id: string; - input?: JsonObject; - }[]; }; // @public diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index 785696436c..83249c0304 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { useCallback, useEffect } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { Content, InfoCard, @@ -28,7 +28,7 @@ import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSche import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider, - useTemplateSecrets, + useInternalTemplateSecrets, } from '../../../secrets/SecretsContext'; import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; @@ -88,11 +88,14 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { const { loading, manifest, error } = useTemplateParameterSchema(templateRef); const sortedManifest = useFilteredSchemaProperties(manifest); const minutesSaved = useTemplateTimeSavedMinutes(templateRef); - const { setSecrets } = useTemplateSecrets(); + const { setSecrets } = useInternalTemplateSecrets(); const formDecorators = useFormDecorators(); + const [formState, setFormState] = useState>({}); const workflowOnCreate = useCallback( - async (formState: Record) => { + async (originalFormState: Record) => { + setFormState(originalFormState); + if (manifest?.EXPERIMENTAL_formDecorators && formDecorators?.size) { // for each of the form decorators, go and call the decorator with the context await Promise.all( @@ -106,6 +109,8 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { await formDecorator.fn({ setSecrets, + setFormState, + formState, input: decorator.input, }); }), @@ -124,6 +129,7 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { manifest?.EXPERIMENTAL_formDecorators, formDecorators, onCreate, + formState, analytics, templateName, minutesSaved, diff --git a/plugins/scaffolder-react/src/next/extensions/createScaffolderFormDecorator.ts b/plugins/scaffolder-react/src/next/extensions/createScaffolderFormDecorator.ts index fc70fc4d52..867435e4c1 100644 --- a/plugins/scaffolder-react/src/next/extensions/createScaffolderFormDecorator.ts +++ b/plugins/scaffolder-react/src/next/extensions/createScaffolderFormDecorator.ts @@ -14,11 +14,16 @@ * limitations under the License. */ import { AnyApiRef } from '@backstage/core-plugin-api'; +import { JsonValue } from '@backstage/types'; +import { Dispatch, SetStateAction } from 'react'; import { z } from 'zod'; export type ScaffolderFormDecoratorContext = { input: TInput; - setSecrets: (input: Record) => void; + formState: Record; + + setFormState: Dispatch>>; + setSecrets: Dispatch>>; }; export type ScaffolderFormDecorator< diff --git a/plugins/scaffolder-react/src/secrets/SecretsContext.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx index 64b25d0e8f..a12722a1fd 100644 --- a/plugins/scaffolder-react/src/secrets/SecretsContext.tsx +++ b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx @@ -94,3 +94,15 @@ export const useTemplateSecrets = (): ScaffolderUseTemplateSecrets => { return { setSecrets, secrets }; }; + +export const useInternalTemplateSecrets = () => { + const value = useContext(SecretsContext)?.atVersion(1); + + if (!value) { + throw new Error( + 'useTemplateSecrets must be used within a SecretsContextProvider', + ); + } + + return value; +}; diff --git a/plugins/scaffolder/src/alpha/api/FormDecoratorsApi.ts b/plugins/scaffolder/src/alpha/api/FormDecoratorsApi.ts index 38170f899a..7638986eab 100644 --- a/plugins/scaffolder/src/alpha/api/FormDecoratorsApi.ts +++ b/plugins/scaffolder/src/alpha/api/FormDecoratorsApi.ts @@ -20,14 +20,16 @@ import { ScaffolderFormDecorator } from '@backstage/plugin-scaffolder-react/alph export class DefaultScaffolderFormDecoratorsApi implements ScaffolderFormDecoratorsApi { - constructor( + private constructor( private readonly options: { decorators: Array; }, ) {} - static create(options: { decorators: ScaffolderFormDecorator[] }) { - return new DefaultScaffolderFormDecoratorsApi(options); + static create(options?: { decorators: ScaffolderFormDecorator[] }) { + return new DefaultScaffolderFormDecoratorsApi( + options ?? { decorators: [] }, + ); } async getFormDecorators(): Promise { diff --git a/plugins/scaffolder/src/alpha/hooks/useFormDecorators.test.tsx b/plugins/scaffolder/src/alpha/hooks/useFormDecorators.test.tsx index cdc3eef918..0198dc3fee 100644 --- a/plugins/scaffolder/src/alpha/hooks/useFormDecorators.test.tsx +++ b/plugins/scaffolder/src/alpha/hooks/useFormDecorators.test.tsx @@ -71,6 +71,8 @@ describe('useFormDecorators', () => { expect(testDecorator).toBeDefined(); await testDecorator.fn({ + formState: {}, + setFormState: () => {}, setSecrets: () => {}, input: { test: 'input value' }, }); diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index 8b24e86069..a6ccdef32c 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -78,6 +78,8 @@ import { } from './components/fields/MyGroupsPicker/MyGroupsPicker'; import { RepoBranchPicker } from './components/fields/RepoBranchPicker/RepoBranchPicker'; import { RepoBranchPickerSchema } from './components/fields/RepoBranchPicker/schema'; +import { formDecoratorsApiRef } from './alpha/api/ref'; +import { DefaultScaffolderFormDecoratorsApi } from './alpha/api/FormDecoratorsApi'; /** * The main plugin export for the scaffolder. @@ -102,6 +104,11 @@ export const scaffolderPlugin = createPlugin({ identityApi, }), }), + createApiFactory({ + api: formDecoratorsApiRef, + deps: {}, + factory: () => DefaultScaffolderFormDecoratorsApi.create(), + }), ], routes: { root: rootRouteRef,