From 8be6a7177d288d32a84891c954db3a083554510f Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 27 Feb 2023 17:06:37 +0100 Subject: [PATCH 1/4] chore: split out the uiSchema in the context to align with components Signed-off-by: blam --- .../Stepper/createAsyncValidators.test.ts | 10 +++++-- .../Stepper/createAsyncValidators.ts | 19 +++++++++++--- .../src/next/extensions/types.ts | 26 ++++++++++++++----- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 196bae0255..38543b2148 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -100,10 +100,12 @@ describe('createAsyncValidators', () => { expect.objectContaining({ schema: { type: 'string', + pattern: 'lols', + }, + uiSchema: { 'ui:options': { bob: true, }, - pattern: 'lols', 'ui:field': 'NameField', }, }), @@ -115,7 +117,6 @@ describe('createAsyncValidators', () => { expect.objectContaining({ schema: { type: 'object', - 'ui:field': 'AddressField', properties: { street: { type: 'string', @@ -125,6 +126,11 @@ describe('createAsyncValidators', () => { }, }, }, + uiSchema: { + 'ui:field': 'AddressField', + street: {}, + postcode: {}, + }, }), ); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 111f3a0f1f..31185d1c12 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -18,9 +18,10 @@ import { FieldValidation } from '@rjsf/utils'; import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; -import { createFieldValidation } from '../../lib'; +import { createFieldValidation, extractSchemaFromStep } from '../../lib'; import { NextCustomFieldValidator } from '../../extensions'; import { isObject } from './utils'; +import { NextFieldExtensionUiSchema } from '../../extensions/types'; /** * @internal @@ -31,7 +32,10 @@ export type FormValidation = { export const createAsyncValidators = ( rootSchema: JsonObject, - validators: Record>, + validators: Record< + string, + undefined | NextCustomFieldValidator + >, context: { apiHolder: ApiHolder; }, @@ -49,6 +53,7 @@ export const createAsyncValidators = ( key: string, value: JsonValue | undefined, schema: JsonObject, + uiSchema: NextFieldExtensionUiSchema, ) => { const validator = validators[validatorName]; if (validator) { @@ -58,6 +63,7 @@ export const createAsyncValidators = ( ...context, formData, schema, + uiSchema, }); } catch (ex) { fieldValidation.addError(ex.message); @@ -69,6 +75,7 @@ export const createAsyncValidators = ( for (const [key, value] of Object.entries(current)) { const path = `${pathPrefix}/${key}`; const definitionInSchema = parsedSchema.getSchema(path, formData); + const { schema, uiSchema } = extractSchemaFromStep(definitionInSchema); if (definitionInSchema && 'ui:field' in definitionInSchema) { if ('ui:field' in definitionInSchema) { @@ -76,7 +83,8 @@ export const createAsyncValidators = ( definitionInSchema['ui:field'], key, value, - definitionInSchema, + schema, + uiSchema, ); } } else if ( @@ -85,11 +93,14 @@ export const createAsyncValidators = ( 'ui:field' in definitionInSchema.items ) { if ('ui:field' in definitionInSchema.items) { + const { schema: itemsSchema, uiSchema: itemsUiSchema } = + extractSchemaFromStep(definitionInSchema.items); await validateForm( definitionInSchema.items['ui:field'], key, value, - definitionInSchema.items, + itemsSchema, + itemsUiSchema, ); } } else if (isObject(value)) { diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts index 0917efe85d..803dcb2be6 100644 --- a/plugins/scaffolder-react/src/next/extensions/types.ts +++ b/plugins/scaffolder-react/src/next/extensions/types.ts @@ -33,9 +33,17 @@ export interface NextFieldExtensionComponentProps< TFieldReturnValue, TUiOptions = {}, > extends PropsWithChildren> { - uiSchema?: UiSchemaV5 & { - 'ui:options'?: TUiOptions & UIOptionsType; - }; + uiSchema?: NextFieldExtensionUiSchema; +} + +/** + * Type for Field Extension UiSchema + * + * @alpha + */ +export interface NextFieldExtensionUiSchema + extends UiSchemaV5 { + 'ui:options'?: TUiOptions & UIOptionsType; } /** @@ -43,13 +51,17 @@ export interface NextFieldExtensionComponentProps< * * @alpha */ -export type NextCustomFieldValidator = ( +export type NextCustomFieldValidator< + TFieldReturnValue, + TUiOptions = unknown, +> = ( data: TFieldReturnValue, field: FieldValidationV5, context: { apiHolder: ApiHolder; formData: JsonObject; schema: JsonObject; + uiSchema?: NextFieldExtensionUiSchema; }, ) => void | Promise; @@ -61,12 +73,12 @@ export type NextCustomFieldValidator = ( */ export type NextFieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TUiOptions = unknown, > = { name: string; component: ( - props: NextFieldExtensionComponentProps, + props: NextFieldExtensionComponentProps, ) => JSX.Element | null; - validation?: NextCustomFieldValidator; + validation?: NextCustomFieldValidator; schema?: CustomFieldExtensionSchema; }; From 44941fc97ebf3f74f5fdfa9ef73e18ae126f8181 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 27 Feb 2023 17:07:43 +0100 Subject: [PATCH 2/4] chore: added changeset Signed-off-by: blam --- .changeset/mighty-years-own.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/mighty-years-own.md diff --git a/.changeset/mighty-years-own.md b/.changeset/mighty-years-own.md new file mode 100644 index 0000000000..febee9bf8a --- /dev/null +++ b/.changeset/mighty-years-own.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Move the `uiSchema` to its own property to align with component development and access of `ui:options` From e37af07bda6428da14fb11d9d01b4427140ced42 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 27 Feb 2023 17:11:56 +0100 Subject: [PATCH 3/4] cyhore: fixing api reports Signed-off-by: blam --- plugins/scaffolder-react/alpha-api-report.md | 23 +++++++++++++------ .../src/next/extensions/index.tsx | 2 ++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index ad44cd3707..6633188155 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -64,13 +64,17 @@ export type FormProps = Pick< >; // @alpha -export type NextCustomFieldValidator = ( +export type NextCustomFieldValidator< + TFieldReturnValue, + TUiOptions = unknown, +> = ( data: TFieldReturnValue, field: FieldValidation, context: { apiHolder: ApiHolder; formData: JsonObject; schema: JsonObject; + uiSchema?: NextFieldExtensionUiSchema; }, ) => void | Promise; @@ -80,24 +84,29 @@ export interface NextFieldExtensionComponentProps< TUiOptions = {}, > extends PropsWithChildren> { // (undocumented) - uiSchema?: UiSchema & { - 'ui:options'?: TUiOptions & UIOptionsType; - }; + uiSchema?: NextFieldExtensionUiSchema; } // @alpha export type NextFieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TUiOptions = unknown, > = { name: string; component: ( - props: NextFieldExtensionComponentProps, + props: NextFieldExtensionComponentProps, ) => JSX.Element | null; - validation?: NextCustomFieldValidator; + validation?: NextCustomFieldValidator; schema?: CustomFieldExtensionSchema; }; +// @alpha +export interface NextFieldExtensionUiSchema + extends UiSchema { + // (undocumented) + 'ui:options'?: TUiOptions & UIOptionsType; +} + // @alpha export interface ParsedTemplateSchema { // (undocumented) diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/next/extensions/index.tsx index b2d402c93f..784499bbd9 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/next/extensions/index.tsx @@ -18,6 +18,7 @@ import { NextCustomFieldValidator, NextFieldExtensionOptions, NextFieldExtensionComponentProps, + NextFieldExtensionUiSchema, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; @@ -55,4 +56,5 @@ export type { NextCustomFieldValidator, NextFieldExtensionOptions, NextFieldExtensionComponentProps, + NextFieldExtensionUiSchema, }; From 8c77b4a3873bd1a161637195881a33aaacfd9561 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Tue, 28 Feb 2023 10:40:57 +0100 Subject: [PATCH 4/4] Update mighty-years-own.md Signed-off-by: Ben Lambert --- .changeset/mighty-years-own.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/mighty-years-own.md b/.changeset/mighty-years-own.md index febee9bf8a..b14b974bc4 100644 --- a/.changeset/mighty-years-own.md +++ b/.changeset/mighty-years-own.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-react': patch --- -Move the `uiSchema` to its own property to align with component development and access of `ui:options` +scaffolder/next: Move the `uiSchema` to its own property in the validation `context` to align with component development and access of `ui:options`