From 6acaedb962fce171e2528b61df18acb18cd4778d Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 18 Aug 2022 14:51:15 +0200 Subject: [PATCH 01/17] chore: things are working pretty nicely now with the later version and the next version of scaffolder Signed-off-by: blam --- package.json | 3 ++- plugins/scaffolder/package.json | 6 ++++-- .../src/components/MultistepJsonForm/MultistepJsonForm.tsx | 6 ++++-- .../src/next/TemplateWizardPage/Stepper/Stepper.tsx | 2 ++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1013b2a049..267fccc029 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "workspaces": { "packages": [ "packages/*", - "plugins/*" + "plugins/*", + "../react-jsonschema-form/packages/*" ] }, "resolutions": { diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 9b81d6593a..1d9c6013b7 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -54,8 +54,10 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^15.0.0", - "@rjsf/core": "^3.2.1", - "@rjsf/material-ui": "^3.2.1", + "@rjsf/core": "file:../../../react-jsonschema-form/packages/core", + "@rjsf/material-ui": "file:../../../react-jsonschema-form/packages/material-ui", + "@rjsf/utils": "file:../../../react-jsonschema-form/packages/utils", + "@rjsf/validator-ajv6": "file:../../../react-jsonschema-form/packages/validator-ajv6", "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 8c71df67b6..60d242e0a1 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -30,7 +30,8 @@ import { featureFlagsApiRef, } from '@backstage/core-plugin-api'; import { FormProps, IChangeEvent, UiSchema, withTheme } from '@rjsf/core'; -import { Theme as MuiTheme } from '@rjsf/material-ui'; +import { Theme } from '@rjsf/material-ui'; +import validator from '@rjsf/validator-ajv6'; import React, { useState } from 'react'; import { transformSchemaToProps } from './schema'; import { Content, StructuredMetadataTable } from '@backstage/core-components'; @@ -38,7 +39,6 @@ import cloneDeep from 'lodash/cloneDeep'; import * as fieldOverrides from './FieldOverrides'; import { LayoutOptions } from '../../layouts'; -const Form = withTheme(MuiTheme); type Step = { schema: JsonObject; title: string; @@ -123,6 +123,7 @@ export const MultistepJsonForm = (props: Props) => { finishButtonLabel, layouts, } = props; + const Form = withTheme(Theme); const [activeStep, setActiveStep] = useState(0); const [disableButtons, setDisableButtons] = useState(false); const errorApi = useApi(errorApiRef); @@ -206,6 +207,7 @@ export const MultistepJsonForm = (props: Props) => {
({ backButton: { @@ -124,6 +125,7 @@ export const Stepper = (props: StepperProps) => {
{activeStep < steps.length ? ( Date: Tue, 30 Aug 2022 13:43:40 +0200 Subject: [PATCH 02/17] chore: fixing dependencies for the form Signed-off-by: blam --- plugins/scaffolder/package.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 1d9c6013b7..b778f9d31f 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -54,10 +54,9 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^15.0.0", - "@rjsf/core": "file:../../../react-jsonschema-form/packages/core", - "@rjsf/material-ui": "file:../../../react-jsonschema-form/packages/material-ui", - "@rjsf/utils": "file:../../../react-jsonschema-form/packages/utils", - "@rjsf/validator-ajv6": "file:../../../react-jsonschema-form/packages/validator-ajv6", + "@rjsf/core": "^5.0.0-beta.2", + "@rjsf/material-ui": "^5.0.0-beta.2", + "@rjsf/validator-ajv6": "^5.0.0-beta.2", "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", From 618312500827c52eda17fc6b96a6e9f000b204a7 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 30 Aug 2022 14:05:36 +0200 Subject: [PATCH 03/17] chore: fixing up typescript Signed-off-by: blam --- package.json | 3 +-- packages/app/package.json | 1 - .../src/components/scaffolder/customScaffolderExtensions.tsx | 2 +- plugins/scaffolder/package.json | 1 + .../MultistepJsonForm/FieldOverrides/DescriptionField.tsx | 2 +- .../src/components/MultistepJsonForm/MultistepJsonForm.tsx | 5 +++-- .../src/components/TemplatePage/createValidator.test.ts | 2 +- .../src/components/TemplatePage/createValidator.ts | 2 +- .../components/fields/EntityNamePicker/validation.test.ts | 2 +- .../src/components/fields/EntityNamePicker/validation.ts | 2 +- .../src/components/fields/EntityPicker/EntityPicker.test.tsx | 2 +- .../src/components/fields/OwnerPicker/OwnerPicker.test.tsx | 2 +- .../components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx | 5 ++++- .../src/components/fields/RepoUrlPicker/validation.test.ts | 2 +- .../src/components/fields/RepoUrlPicker/validation.ts | 2 +- plugins/scaffolder/src/extensions/types.ts | 2 +- .../src/next/TemplateWizardPage/Stepper/Stepper.tsx | 3 ++- .../next/TemplateWizardPage/Stepper/createAsyncValidators.ts | 2 +- .../scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts | 2 +- .../src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts | 2 +- 20 files changed, 25 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 267fccc029..1013b2a049 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,7 @@ "workspaces": { "packages": [ "packages/*", - "plugins/*", - "../react-jsonschema-form/packages/*" + "plugins/*" ] }, "resolutions": { diff --git a/packages/app/package.json b/packages/app/package.json index 76e099bace..fa8bb5c5ee 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -83,7 +83,6 @@ }, "devDependencies": { "@backstage/test-utils": "workspace:^", - "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index 2a4dedf080..3f6bd33d89 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import type { FieldValidation } from '@rjsf/core'; +import type { FieldValidation } from '@rjsf/utils'; import { createScaffolderFieldExtension, FieldExtensionComponentProps, diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index b778f9d31f..cf28227e8e 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -56,6 +56,7 @@ "@react-hookz/web": "^15.0.0", "@rjsf/core": "^5.0.0-beta.2", "@rjsf/material-ui": "^5.0.0-beta.2", + "@rjsf/utils": "^5.0.0-beta.2", "@rjsf/validator-ajv6": "^5.0.0-beta.2", "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx index 3c592860ef..eded38beee 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { MarkdownContent } from '@backstage/core-components'; -import { FieldProps } from '@rjsf/core'; +import { FieldProps } from '@rjsf/utils'; export const DescriptionField = ({ description }: FieldProps) => description && ; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 60d242e0a1..064299f667 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -29,7 +29,8 @@ import { useApi, featureFlagsApiRef, } from '@backstage/core-plugin-api'; -import { FormProps, IChangeEvent, UiSchema, withTheme } from '@rjsf/core'; +import { UiSchema } from '@rjsf/utils'; +import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; import { Theme } from '@rjsf/material-ui'; import validator from '@rjsf/validator-ajv6'; import React, { useState } from 'react'; @@ -215,7 +216,7 @@ export const MultistepJsonForm = (props: Props) => { formData={formData} formContext={{ formData }} onChange={onChange} - onSubmit={e => { + onSubmit={(e: any) => { if (e.errors.length === 0) handleNext(); }} {...formProps} diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index f549c9e7f2..c17b72148e 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -17,7 +17,7 @@ import { createValidator } from './createValidator'; import { CustomFieldValidator } from '../../extensions'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { FormValidation } from '@rjsf/core'; +import { FormValidation } from '@rjsf/utils'; describe('createValidator', () => { const validators: Record> = diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 9cd1489a02..2769b899df 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -15,7 +15,7 @@ */ import { CustomFieldValidator } from '../../extensions'; -import { FormValidation } from '@rjsf/core'; +import { FormValidation } from '@rjsf/utils'; import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts index 290650387e..7201c9c4b3 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; import { entityNamePickerValidation } from './validation'; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts index 7a40a460ba..1533b0cdc3 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; export const entityNamePickerValidation = ( diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index 942eef9d82..f4eefb26d5 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -17,7 +17,7 @@ import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { FieldProps } from '@rjsf/core'; +import { FieldProps } from '@rjsf/utils'; import { fireEvent } from '@testing-library/react'; import React from 'react'; import { EntityPicker } from './EntityPicker'; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx index b78d3add9e..68c9723974 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx @@ -17,7 +17,7 @@ import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { FieldProps } from '@rjsf/core'; +import { FieldProps } from '@rjsf/utils'; import React from 'react'; import { OwnerPicker } from './OwnerPicker'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 7fac9f7840..be7c05155c 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -15,7 +15,8 @@ */ import React, { useContext } from 'react'; import { RepoUrlPicker } from './RepoUrlPicker'; -import Form from '@rjsf/core'; +import { withTheme } from '@rjsf/core'; +import { Theme } from '@rjsf/material-ui'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { scmIntegrationsApiRef, @@ -50,6 +51,8 @@ describe('RepoUrlPicker', () => { getCredentials: jest.fn().mockResolvedValue({ token: 'abc123' }), }; + const Form = withTheme(Theme); + describe('happy path rendering', () => { it('should render the repo url picker with minimal props', async () => { const onSubmit = jest.fn(); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index 45e44b4072..b9c481957c 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -15,7 +15,7 @@ */ import { repoPickerValidation } from './validation'; -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/core-app-api'; import { ApiHolder } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 99847f9e3b..55ba92abdc 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { ApiHolder } from '@backstage/core-plugin-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index 9b42ba478b..c3d99a6b37 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FieldProps } from '@rjsf/core'; +import { FieldValidation, FieldProps } from '@rjsf/utils'; /** * Field validation type for Custom Field Extensions. diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index 8ae26ebf4a..ccdf32542a 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -22,7 +22,8 @@ import { Button, makeStyles, } from '@material-ui/core'; -import { FieldValidation, withTheme } from '@rjsf/core'; +import { withTheme } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useMemo, useState } from 'react'; import { FieldExtensionOptions } from '../../../extensions'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts index d89f0d4e5f..60eed0f364 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { CustomFieldValidator } from '../../../extensions'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts index e2d5e89932..355bfde45d 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/types'; -import { FieldValidation, UiSchema } from '@rjsf/core'; +import { FieldValidation, UiSchema } from '@rjsf/utils'; function isObject(value: unknown): value is JsonObject { return typeof value === 'object' && value !== null && !Array.isArray(value); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts index d0d8590a7b..6aad6baa96 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts @@ -15,7 +15,7 @@ */ import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; -import { UiSchema } from '@rjsf/core'; +import { UiSchema } from '@rjsf/utils'; import { TemplateParameterSchema } from '../../../types'; import { extractSchemaFromStep } from './schema'; From b9f71b15af19c8ae634d81edffb237a40ebae6fc Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Sep 2022 11:09:45 +0200 Subject: [PATCH 04/17] chore: just the error validation left I think for the `next` scaffolder Signed-off-by: blam --- .../scaffolder/customScaffolderExtensions.tsx | 2 +- .../TemplatePage/createValidator.test.ts | 2 +- .../TemplatePage/createValidator.ts | 2 +- .../EntityNamePicker/EntityNamePicker.tsx | 2 +- .../fields/EntityPicker/EntityPicker.test.tsx | 6 +- .../fields/EntityPicker/EntityPicker.tsx | 13 +- .../EntityTagsPicker/EntityTagsPicker.tsx | 6 +- .../OwnedEntityPicker/OwnedEntityPicker.tsx | 8 +- .../fields/OwnerPicker/OwnerPicker.test.tsx | 2 +- .../fields/OwnerPicker/OwnerPicker.tsx | 8 +- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 7 +- .../fields/RepoUrlPicker/RepoUrlPicker.tsx | 5 +- .../fields/RepoUrlPicker/validation.ts | 2 +- plugins/scaffolder/src/extensions/index.tsx | 3 +- plugins/scaffolder/src/extensions/types.ts | 18 ++- yarn.lock | 115 ++++++++++-------- 16 files changed, 114 insertions(+), 87 deletions(-) diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index 3f6bd33d89..3aadd69c05 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -30,7 +30,7 @@ const TextValuePicker = (props: FieldExtensionComponentProps) => { schema: { title, description }, rawErrors, formData, - uiSchema: { 'ui:autofocus': autoFocus }, + uiSchema: { 'ui:autofocus': autoFocus } = {}, idSchema, placeholder, } = props; diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index c17b72148e..eea5efc296 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -68,6 +68,6 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.p1.addError).toHaveBeenCalledTimes(1); + expect(result.p1?.addError).toHaveBeenCalledTimes(1); }); }); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 2769b899df..d1c55009a9 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -62,7 +62,7 @@ export const createValidator = ( if (fieldName && typeof validators[fieldName] === 'function') { validators[fieldName]!( propData as JsonValue, - propValidation, + propValidation as FormValidation, context, ); } diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx index 802135a863..2b21141edb 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx @@ -29,7 +29,7 @@ export const EntityNamePicker = ( schema: { title = 'Name', description = 'Unique name of the component' }, rawErrors, formData, - uiSchema: { 'ui:autofocus': autoFocus }, + uiSchema: { 'ui:autofocus': autoFocus } = {}, idSchema, placeholder, } = props; diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index f4eefb26d5..ffc447577a 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -39,7 +39,7 @@ describe('', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps; const catalogApi: jest.Mocked = { getLocationById: jest.fn(), @@ -76,7 +76,7 @@ describe('', () => { uiSchema, rawErrors, formData, - } as unknown as FieldProps; + } as any; catalogApi.getEntities.mockResolvedValue({ items: entities }); }); @@ -117,7 +117,7 @@ describe('', () => { uiSchema, rawErrors, formData, - } as unknown as FieldProps; + } as any; catalogApi.getEntities.mockResolvedValue({ items: entities }); }); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index e7883a4721..a040320d79 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -45,7 +45,10 @@ export interface EntityPickerUiOptions { * @public */ export const EntityPicker = ( - props: FieldExtensionComponentProps, + props: FieldExtensionComponentProps< + string | undefined, + EntityPickerUiOptions + >, ) => { const { onChange, @@ -56,9 +59,9 @@ export const EntityPicker = ( formData, idSchema, } = props; - const allowedKinds = uiSchema['ui:options']?.allowedKinds; - const defaultKind = uiSchema['ui:options']?.defaultKind; - const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; + const allowedKinds = uiSchema?.['ui:options']?.allowedKinds; + const defaultKind = uiSchema?.['ui:options']?.defaultKind; + const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace; const catalogApi = useApi(catalogApiRef); @@ -99,7 +102,7 @@ export const EntityPicker = ( onChange={onSelect} options={entityRefs || []} autoSelect - freeSolo={uiSchema['ui:options']?.allowArbitraryValues ?? true} + freeSolo={uiSchema?.['ui:options']?.allowArbitraryValues ?? true} renderInput={params => ( { const facet = 'metadata.tags'; diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index 2446883a86..d15677cfac 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -59,12 +59,12 @@ export const OwnedEntityPicker = ( formData, idSchema, } = props; + const allowedKinds = uiSchema?.['ui:options']?.allowedKinds; + const defaultKind = uiSchema?.['ui:options']?.defaultKind; + const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace; - const allowedKinds = uiSchema['ui:options']?.allowedKinds; - const defaultKind = uiSchema['ui:options']?.defaultKind; - const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; const allowArbitraryValues = - uiSchema['ui:options']?.allowArbitraryValues ?? true; + uiSchema?.['ui:options']?.allowArbitraryValues ?? true; const { ownedEntities, loading } = useOwnedEntities(allowedKinds); const entityRefs = ownedEntities?.items diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx index 68c9723974..a94bdf74d7 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx @@ -36,7 +36,7 @@ describe('', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps; const catalogApi: jest.Mocked = { getLocationById: jest.fn(), diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx index 3de2b12bd0..8ce01fc3ef 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx @@ -36,7 +36,7 @@ export interface OwnerPickerUiOptions { * @public */ export const OwnerPicker = ( - props: FieldExtensionComponentProps, + props: FieldExtensionComponentProps, ) => { const { schema: { title = 'Owner', description = 'The owner of the component' }, @@ -44,18 +44,18 @@ export const OwnerPicker = ( ...restProps } = props; - const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; + const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace; const ownerUiSchema = { ...uiSchema, 'ui:options': { - allowedKinds: (uiSchema['ui:options']?.allowedKinds || [ + allowedKinds: (uiSchema?.['ui:options']?.allowedKinds || [ 'Group', 'User', ]) as string[], defaultKind: 'Group', allowArbitraryValues: - uiSchema['ui:options']?.allowArbitraryValues ?? true, + uiSchema?.['ui:options']?.allowArbitraryValues ?? true, ...(defaultNamespace !== undefined ? { defaultNamespace } : {}), }, }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index be7c05155c..0133c4a29c 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -32,6 +32,7 @@ import { SecretsContext, } from '../../secrets/SecretsContext'; import { act, fireEvent } from '@testing-library/react'; +import { Field } from '@rjsf/utils'; describe('RepoUrlPicker', () => { const mockScaffolderApi: Partial = { @@ -68,7 +69,7 @@ describe('RepoUrlPicker', () => { }} onSubmit={onSubmit} /> @@ -107,7 +108,7 @@ describe('RepoUrlPicker', () => { 'ui:field': 'RepoUrlPicker', 'ui:options': { allowedHosts: ['dev.azure.com'] }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ RepoUrlPicker: RepoUrlPicker as Field }} /> , @@ -145,7 +146,7 @@ describe('RepoUrlPicker', () => { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ RepoUrlPicker: RepoUrlPicker as Field }} /> diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 451df857e5..870ec9dd53 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -62,7 +62,10 @@ export interface RepoUrlPickerUiOptions { * @public */ export const RepoUrlPicker = ( - props: FieldExtensionComponentProps, + props: FieldExtensionComponentProps< + string | undefined, + RepoUrlPickerUiOptions + >, ) => { const { uiSchema, onChange, rawErrors, formData } = props; const [state, setState] = useState( diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 55ba92abdc..ae4f2ec1b9 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -26,7 +26,7 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react'; * @public */ export const repoPickerValidation = ( - value: string, + value: string | undefined, validation: FieldValidation, context: { apiHolder: ApiHolder }, ) => { diff --git a/plugins/scaffolder/src/extensions/index.tsx b/plugins/scaffolder/src/extensions/index.tsx index 60b9022053..21a565bf46 100644 --- a/plugins/scaffolder/src/extensions/index.tsx +++ b/plugins/scaffolder/src/extensions/index.tsx @@ -21,6 +21,7 @@ import { FieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; +import { UIOptionsType } from '@rjsf/utils'; export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; @@ -39,7 +40,7 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; */ export function createScaffolderFieldExtension< TReturnValue = unknown, - TInputProps = unknown, + TInputProps extends UIOptionsType = {}, >( options: FieldExtensionOptions, ): Extension> { diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index c3d99a6b37..85f8f99fd4 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -14,7 +14,13 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FieldProps } from '@rjsf/utils'; +import { + FieldValidation, + FieldProps, + UIOptionsType, + UiSchema, +} from '@rjsf/utils'; +import { PropsWithChildren } from 'react'; /** * Field validation type for Custom Field Extensions. @@ -35,7 +41,7 @@ export type CustomFieldValidator = ( */ export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TInputProps extends UIOptionsType = {}, > = { name: string; component: ( @@ -52,9 +58,9 @@ export type FieldExtensionOptions< */ export interface FieldExtensionComponentProps< TFieldReturnValue, - TUiOptions extends {} = {}, -> extends FieldProps { - uiSchema: FieldProps['uiSchema'] & { - 'ui:options'?: TUiOptions; + TUiOptions = {}, +> extends PropsWithChildren> { + uiSchema?: UiSchema & { + 'ui:options'?: TUiOptions & UIOptionsType; }; } diff --git a/yarn.lock b/yarn.lock index 8be2e5c8a6..441684ce3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6742,8 +6742,10 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@react-hookz/web": ^15.0.0 - "@rjsf/core": ^3.2.1 - "@rjsf/material-ui": ^3.2.1 + "@rjsf/core": ^5.0.0-beta.2 + "@rjsf/material-ui": ^5.0.0-beta.2 + "@rjsf/utils": ^5.0.0-beta.2 + "@rjsf/validator-ajv6": ^5.0.0-beta.2 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 @@ -11940,34 +11942,59 @@ __metadata: languageName: node linkType: hard -"@rjsf/core@npm:^3.2.1": - version: 3.2.1 - resolution: "@rjsf/core@npm:3.2.1" +"@rjsf/core@npm:^5.0.0-beta.2": + version: 5.0.0-beta.5 + resolution: "@rjsf/core@npm:5.0.0-beta.5" dependencies: - "@types/json-schema": ^7.0.7 - ajv: ^6.7.0 - core-js-pure: ^3.6.5 - json-schema-merge-allof: ^0.6.0 - jsonpointer: ^5.0.0 lodash: ^4.17.15 - nanoid: ^3.1.23 + lodash-es: ^4.17.15 + nanoid: ^3.3.4 prop-types: ^15.7.2 - react-is: ^16.9.0 peerDependencies: - react: ">=16" - checksum: 2142d4a31229ea242b79aca4ed93e2fe89e75f15ce93111457c3017d3ab295cae8f53e4dd870c619afa571959d00f46b3c19085c6a336f522c891fc07ecc46f1 + "@rjsf/utils": ^5.0.0-beta.1 + react: ^16.14.0 || >=17 + checksum: bf9538f98e6238b427afb5cccdcbb88dc7cf99d3dc9c25c8336c8cac6b82c6383fa29cb48139d312f737d668b4f836bca9fac4debebc8bd9ee46a3f8178ad37b languageName: node linkType: hard -"@rjsf/material-ui@npm:^3.2.1": - version: 3.2.1 - resolution: "@rjsf/material-ui@npm:3.2.1" +"@rjsf/material-ui@npm:^5.0.0-beta.2": + version: 5.0.0-beta.5 + resolution: "@rjsf/material-ui@npm:5.0.0-beta.5" peerDependencies: - "@material-ui/core": ^4.2.0 - "@material-ui/icons": ^4.2.1 - "@rjsf/core": ^3.0.0 - react: ">=16" - checksum: bd25cd9f2e2d568c653755e7268fe3e53279e1ae675e39bccd85f65557623d2052b706763e017a949f897751e25a16d0f2c8b995508bb56907be6786b09e2b1e + "@material-ui/core": ^4.12.3 + "@material-ui/icons": ^4.11.2 + "@rjsf/core": ^5.0.0-beta.1 + "@rjsf/utils": ^5.0.0-beta.1 + react: ^16.14.0 || >=17 + checksum: 2578ff81c9981ecefab6752a6de6f684cdc4ad0d5a3e4090456a42f811c055437b22ecb662610877598a640d624af9381ef3f15b93bb3a8abfae33770c51d194 + languageName: node + linkType: hard + +"@rjsf/utils@npm:^5.0.0-beta.2": + version: 5.0.0-beta.5 + resolution: "@rjsf/utils@npm:5.0.0-beta.5" + dependencies: + json-schema-merge-allof: ^0.8.1 + jsonpointer: ^5.0.1 + lodash: ^4.17.15 + lodash-es: ^4.17.15 + react-is: ^18.2.0 + peerDependencies: + react: ^16.14.0 || >=17 + checksum: 56549a1b86c068631e19f67c157fbe12e2ec99be2fcbe1b6375f7865b178b874ebce03a129064dcf2c2858b5991067dedac1e4490106269cf81dc4377717dcff + languageName: node + linkType: hard + +"@rjsf/validator-ajv6@npm:^5.0.0-beta.2": + version: 5.0.0-beta.5 + resolution: "@rjsf/validator-ajv6@npm:5.0.0-beta.5" + dependencies: + ajv: ^6.7.0 + lodash: ^4.17.15 + lodash-es: ^4.17.15 + peerDependencies: + "@rjsf/utils": ^5.0.0-beta.1 + checksum: 20e4bf431d8c805e180999c300819b049c52c19cff6f4b5e402edc8eb7757697dc1debb191ccf41bac63de88d067513ba33de958250d6e923f1d34fdaea7283c languageName: node linkType: hard @@ -18550,7 +18577,7 @@ __metadata: languageName: node linkType: hard -"compute-lcm@npm:^1.1.0, compute-lcm@npm:^1.1.2": +"compute-lcm@npm:^1.1.2": version: 1.1.2 resolution: "compute-lcm@npm:1.1.2" dependencies: @@ -18786,7 +18813,7 @@ __metadata: languageName: node linkType: hard -"core-js-pure@npm:^3.20.2, core-js-pure@npm:^3.6.5, core-js-pure@npm:^3.8.1": +"core-js-pure@npm:^3.20.2, core-js-pure@npm:^3.8.1": version: 3.21.1 resolution: "core-js-pure@npm:3.21.1" checksum: 00a5dff599b7fb0b30746a638b9d0edbdc0df24ed1580ca56be595fbe3c78c375d37fc4e1bff23627109229702c9ee8ea2587a66b8280eb33b85160aa4e401e9 @@ -22077,7 +22104,6 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.57 "@octokit/rest": ^19.0.3 "@oriflame/backstage-plugin-score-card": ^0.5.1 - "@rjsf/core": ^3.2.1 "@roadiehq/backstage-plugin-buildkite": ^2.0.8 "@roadiehq/backstage-plugin-github-insights": ^2.0.5 "@roadiehq/backstage-plugin-github-pull-requests": ^2.2.7 @@ -27172,17 +27198,6 @@ __metadata: languageName: node linkType: hard -"json-schema-merge-allof@npm:^0.6.0": - version: 0.6.0 - resolution: "json-schema-merge-allof@npm:0.6.0" - dependencies: - compute-lcm: ^1.1.0 - json-schema-compare: ^0.2.2 - lodash: ^4.17.4 - checksum: 2008aede3f5d05d7870e7d5e554e5c6a5b451cfff1357d34d3d8b34e2ba57468a97c76aa5b967bdb411d91b98c734f19f350de578d25b2a0a27cd4e1ca92bd1d - languageName: node - linkType: hard - "json-schema-merge-allof@npm:^0.8.1": version: 0.8.1 resolution: "json-schema-merge-allof@npm:0.8.1" @@ -27359,10 +27374,10 @@ __metadata: languageName: node linkType: hard -"jsonpointer@npm:^5.0.0": - version: 5.0.0 - resolution: "jsonpointer@npm:5.0.0" - checksum: c7ec0b6bb596b81de687bc12945586bbcdc80dfb54919656d2690d76334f796a936270067ee9f1b5bbc2d9ecc551afb366ac35e6685aa61f07b5b68d1e5e857d +"jsonpointer@npm:^5.0.1": + version: 5.0.1 + resolution: "jsonpointer@npm:5.0.1" + checksum: 0b40f712900ad0c846681ea2db23b6684b9d5eedf55807b4708c656f5894b63507d0e28ae10aa1bddbea551241035afe62b6df0800fc94c2e2806a7f3adecd7c languageName: node linkType: hard @@ -28097,7 +28112,7 @@ __metadata: languageName: node linkType: hard -"lodash-es@npm:^4.17.21": +"lodash-es@npm:^4.17.15, lodash-es@npm:^4.17.21": version: 4.17.21 resolution: "lodash-es@npm:4.17.21" checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2 @@ -30062,15 +30077,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.1.23": - version: 3.3.1 - resolution: "nanoid@npm:3.3.1" - bin: - nanoid: bin/nanoid.cjs - checksum: 4ef0969e1bbe866fc223eb32276cbccb0961900bfe79104fa5abe34361979dead8d0e061410a5c03bc3d47455685adf32c09d6f27790f4a6898fb51f7df7ec86 - languageName: node - linkType: hard - "nanoid@npm:^3.3.4": version: 3.3.4 resolution: "nanoid@npm:3.3.4" @@ -33568,7 +33574,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": +"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f @@ -33589,6 +33595,13 @@ __metadata: languageName: node linkType: hard +"react-is@npm:^18.2.0": + version: 18.2.0 + resolution: "react-is@npm:18.2.0" + checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e + languageName: node + linkType: hard + "react-lifecycles-compat@npm:^3.0.4": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" From adfb075796e5022a16cfaa6311c7fd6cedcbf0e2 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 8 Sep 2022 14:25:09 +0200 Subject: [PATCH 05/17] chore: one last error Signed-off-by: blam --- .../src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx | 5 +---- .../src/next/TemplateWizardPage/Stepper/Stepper.tsx | 6 +++--- .../src/next/TemplateWizardPage/Stepper/schema.ts | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 870ec9dd53..451df857e5 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -62,10 +62,7 @@ export interface RepoUrlPickerUiOptions { * @public */ export const RepoUrlPicker = ( - props: FieldExtensionComponentProps< - string | undefined, - RepoUrlPickerUiOptions - >, + props: FieldExtensionComponentProps, ) => { const { uiSchema, onChange, rawErrors, formData } = props; const [state, setState] = useState( diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index ccdf32542a..ade7c982ff 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -23,7 +23,7 @@ import { makeStyles, } from '@material-ui/core'; import { withTheme } from '@rjsf/core'; -import { FieldValidation } from '@rjsf/utils'; +import { ErrorSchema, FieldValidation } from '@rjsf/utils'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useMemo, useState } from 'react'; import { FieldExtensionOptions } from '../../../extensions'; @@ -95,7 +95,7 @@ export const Stepper = (props: StepperProps) => { const returnedValidation = await validation(formData); const hasErrors = Object.values(returnedValidation).some(i => { - return i.__errors.length > 0; + return i.__errors?.length! > 0 ?? false; }); if (hasErrors) { @@ -127,7 +127,7 @@ export const Stepper = (props: StepperProps) => { {activeStep < steps.length ? ( { const fieldValidation: FieldValidation = { __errors: [] as string[], addError: (message: string) => { - fieldValidation.__errors.push(message); + fieldValidation.__errors?.push(message); }, }; From 7443c37ffc2a07fffe3a9aa2fdde8e682db9b596 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Sep 2022 10:49:14 +0200 Subject: [PATCH 06/17] chore: fixing some typescripty things Signed-off-by: blam --- .../components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx | 5 ++++- .../src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 0133c4a29c..9f126f52a0 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -26,7 +26,7 @@ import { } from '@backstage/integration-react'; import { scaffolderApiRef } from '../../../api'; import { ScaffolderApi } from '../../../types'; - +import validator from '@rjsf/validator-ajv6'; import { SecretsContextProvider, SecretsContext, @@ -67,6 +67,7 @@ describe('RepoUrlPicker', () => { > }} @@ -103,6 +104,7 @@ describe('RepoUrlPicker', () => { > { > , + props: FieldExtensionComponentProps< + string | undefined, + RepoUrlPickerUiOptions + >, ) => { const { uiSchema, onChange, rawErrors, formData } = props; const [state, setState] = useState( From ffe1357499af9b5fb22a8121e877b0c58c4e6360 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 27 Sep 2022 10:40:13 +0200 Subject: [PATCH 07/17] chore: fix Signed-off-by: blam --- plugins/scaffolder/package.json | 10 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 2 - .../RepoUrlPicker/RepoUrlPicker.test.tsx | 2 - plugins/scaffolder/src/extensions/types.ts | 13 +-- yarn.lock | 104 +++++++++++++----- 5 files changed, 88 insertions(+), 43 deletions(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index cf28227e8e..6508ae77e7 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -54,10 +54,12 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^15.0.0", - "@rjsf/core": "^5.0.0-beta.2", - "@rjsf/material-ui": "^5.0.0-beta.2", - "@rjsf/utils": "^5.0.0-beta.2", - "@rjsf/validator-ajv6": "^5.0.0-beta.2", + "@rjsf/core": "^3.2.1", + "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.9", + "@rjsf/material-ui": "^3.2.1", + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.9", + "@rjsf/utils": "^5.0.0-beta.9", + "@rjsf/validator-ajv8": "^5.0.0-beta.9", "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 064299f667..7ab3007e99 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -32,7 +32,6 @@ import { import { UiSchema } from '@rjsf/utils'; import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; import { Theme } from '@rjsf/material-ui'; -import validator from '@rjsf/validator-ajv6'; import React, { useState } from 'react'; import { transformSchemaToProps } from './schema'; import { Content, StructuredMetadataTable } from '@backstage/core-components'; @@ -208,7 +207,6 @@ export const MultistepJsonForm = (props: Props) => { { > }} diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index 85f8f99fd4..4758d96f66 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -14,12 +14,7 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { - FieldValidation, - FieldProps, - UIOptionsType, - UiSchema, -} from '@rjsf/utils'; +import { FieldValidation, FieldProps, UiSchema } from '@rjsf/core'; import { PropsWithChildren } from 'react'; /** @@ -41,7 +36,7 @@ export type CustomFieldValidator = ( */ export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps extends UIOptionsType = {}, + TInputProps extends {} = {}, > = { name: string; component: ( @@ -60,7 +55,7 @@ export interface FieldExtensionComponentProps< TFieldReturnValue, TUiOptions = {}, > extends PropsWithChildren> { - uiSchema?: UiSchema & { - 'ui:options'?: TUiOptions & UIOptionsType; + uiSchema: UiSchema & { + 'ui:options': TUiOptions; }; } diff --git a/yarn.lock b/yarn.lock index 441684ce3d..dcecfe2b9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6742,10 +6742,12 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@react-hookz/web": ^15.0.0 - "@rjsf/core": ^5.0.0-beta.2 - "@rjsf/material-ui": ^5.0.0-beta.2 - "@rjsf/utils": ^5.0.0-beta.2 - "@rjsf/validator-ajv6": ^5.0.0-beta.2 + "@rjsf/core": ^3.2.1 + "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.9" + "@rjsf/material-ui": ^3.2.1 + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.9" + "@rjsf/utils": ^5.0.0-beta.9 + "@rjsf/validator-ajv8": ^5.0.0-beta.9 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 @@ -11942,9 +11944,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/core@npm:^5.0.0-beta.2": - version: 5.0.0-beta.5 - resolution: "@rjsf/core@npm:5.0.0-beta.5" +"@rjsf/core-v5@npm:@rjsf/core@^5.0.0-beta.9": + version: 5.0.0-beta.9 + resolution: "@rjsf/core@npm:5.0.0-beta.9" dependencies: lodash: ^4.17.15 lodash-es: ^4.17.15 @@ -11953,26 +11955,57 @@ __metadata: peerDependencies: "@rjsf/utils": ^5.0.0-beta.1 react: ^16.14.0 || >=17 - checksum: bf9538f98e6238b427afb5cccdcbb88dc7cf99d3dc9c25c8336c8cac6b82c6383fa29cb48139d312f737d668b4f836bca9fac4debebc8bd9ee46a3f8178ad37b + checksum: b55e1a4b3f9f638afdeda1da0abeb145040081201b2f9ed680c93d3dea2ee20e1066da5d2c32c69916d9f2fce422ecb8058f303b9f4df1b20dacf35564f5c7ec languageName: node linkType: hard -"@rjsf/material-ui@npm:^5.0.0-beta.2": - version: 5.0.0-beta.5 - resolution: "@rjsf/material-ui@npm:5.0.0-beta.5" +"@rjsf/core@npm:^3.2.1": + version: 3.2.1 + resolution: "@rjsf/core@npm:3.2.1" + dependencies: + "@types/json-schema": ^7.0.7 + ajv: ^6.7.0 + core-js-pure: ^3.6.5 + json-schema-merge-allof: ^0.6.0 + jsonpointer: ^5.0.0 + lodash: ^4.17.15 + nanoid: ^3.1.23 + prop-types: ^15.7.2 + react-is: ^16.9.0 + peerDependencies: + react: ">=16" + checksum: 2142d4a31229ea242b79aca4ed93e2fe89e75f15ce93111457c3017d3ab295cae8f53e4dd870c619afa571959d00f46b3c19085c6a336f522c891fc07ecc46f1 + languageName: node + linkType: hard + +"@rjsf/material-ui-v5@npm:@rjsf/material-ui@^5.0.0-beta.9": + version: 5.0.0-beta.9 + resolution: "@rjsf/material-ui@npm:5.0.0-beta.9" peerDependencies: "@material-ui/core": ^4.12.3 "@material-ui/icons": ^4.11.2 "@rjsf/core": ^5.0.0-beta.1 "@rjsf/utils": ^5.0.0-beta.1 react: ^16.14.0 || >=17 - checksum: 2578ff81c9981ecefab6752a6de6f684cdc4ad0d5a3e4090456a42f811c055437b22ecb662610877598a640d624af9381ef3f15b93bb3a8abfae33770c51d194 + checksum: 44624d1aff0f30963d7ae2ab529713d9fcf6e6df809264d6bdee7ef5e71934ab031dbba9dcc9c10be05cb7b0fd679f6fbb1eb27ce7081940b56034a5f2564093 languageName: node linkType: hard -"@rjsf/utils@npm:^5.0.0-beta.2": - version: 5.0.0-beta.5 - resolution: "@rjsf/utils@npm:5.0.0-beta.5" +"@rjsf/material-ui@npm:^3.2.1": + version: 3.2.1 + resolution: "@rjsf/material-ui@npm:3.2.1" + peerDependencies: + "@material-ui/core": ^4.2.0 + "@material-ui/icons": ^4.2.1 + "@rjsf/core": ^3.0.0 + react: ">=16" + checksum: bd25cd9f2e2d568c653755e7268fe3e53279e1ae675e39bccd85f65557623d2052b706763e017a949f897751e25a16d0f2c8b995508bb56907be6786b09e2b1e + languageName: node + linkType: hard + +"@rjsf/utils@npm:^5.0.0-beta.9": + version: 5.0.0-beta.9 + resolution: "@rjsf/utils@npm:5.0.0-beta.9" dependencies: json-schema-merge-allof: ^0.8.1 jsonpointer: ^5.0.1 @@ -11981,20 +12014,21 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^16.14.0 || >=17 - checksum: 56549a1b86c068631e19f67c157fbe12e2ec99be2fcbe1b6375f7865b178b874ebce03a129064dcf2c2858b5991067dedac1e4490106269cf81dc4377717dcff + checksum: ac5b99cf7860c838e5b509a523b19824f4966ec8d44284a026bf81de7c7733bac40432af4c67ab538bd400f529dc55d9001e07618a514cac365cd604ff786b11 languageName: node linkType: hard -"@rjsf/validator-ajv6@npm:^5.0.0-beta.2": - version: 5.0.0-beta.5 - resolution: "@rjsf/validator-ajv6@npm:5.0.0-beta.5" +"@rjsf/validator-ajv8@npm:^5.0.0-beta.9": + version: 5.0.0-beta.9 + resolution: "@rjsf/validator-ajv8@npm:5.0.0-beta.9" dependencies: - ajv: ^6.7.0 + ajv: ^8.11.0 + ajv-formats: ^2.1.1 lodash: ^4.17.15 lodash-es: ^4.17.15 peerDependencies: "@rjsf/utils": ^5.0.0-beta.1 - checksum: 20e4bf431d8c805e180999c300819b049c52c19cff6f4b5e402edc8eb7757697dc1debb191ccf41bac63de88d067513ba33de958250d6e923f1d34fdaea7283c + checksum: 64ca81f1f440b08f959d61e1f97b25d890cd8f03582287004961d0ba0ec7d6719748b00d821ef009d330816ca2e4e030d46fa695a3c12c338518e469242694cd languageName: node linkType: hard @@ -15653,7 +15687,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.6.3, ajv@npm:^8.8.0": +"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0, ajv@npm:^8.6.3, ajv@npm:^8.8.0": version: 8.11.0 resolution: "ajv@npm:8.11.0" dependencies: @@ -18577,7 +18611,7 @@ __metadata: languageName: node linkType: hard -"compute-lcm@npm:^1.1.2": +"compute-lcm@npm:^1.1.0, compute-lcm@npm:^1.1.2": version: 1.1.2 resolution: "compute-lcm@npm:1.1.2" dependencies: @@ -18820,6 +18854,13 @@ __metadata: languageName: node linkType: hard +"core-js-pure@npm:^3.6.5": + version: 3.25.3 + resolution: "core-js-pure@npm:3.25.3" + checksum: be3097b8e2b541977a08004e433b68adb4951cc7694229e695ae407f296d370c1f360e5fd70fc6910c4427e46e48e087ac455d68cebdf4314370907d2e03eef1 + languageName: node + linkType: hard + "core-js@npm:^2.4.0, core-js@npm:^2.5.0, core-js@npm:^2.6.10": version: 2.6.12 resolution: "core-js@npm:2.6.12" @@ -27198,6 +27239,17 @@ __metadata: languageName: node linkType: hard +"json-schema-merge-allof@npm:^0.6.0": + version: 0.6.0 + resolution: "json-schema-merge-allof@npm:0.6.0" + dependencies: + compute-lcm: ^1.1.0 + json-schema-compare: ^0.2.2 + lodash: ^4.17.4 + checksum: 2008aede3f5d05d7870e7d5e554e5c6a5b451cfff1357d34d3d8b34e2ba57468a97c76aa5b967bdb411d91b98c734f19f350de578d25b2a0a27cd4e1ca92bd1d + languageName: node + linkType: hard + "json-schema-merge-allof@npm:^0.8.1": version: 0.8.1 resolution: "json-schema-merge-allof@npm:0.8.1" @@ -27374,7 +27426,7 @@ __metadata: languageName: node linkType: hard -"jsonpointer@npm:^5.0.1": +"jsonpointer@npm:^5.0.0, jsonpointer@npm:^5.0.1": version: 5.0.1 resolution: "jsonpointer@npm:5.0.1" checksum: 0b40f712900ad0c846681ea2db23b6684b9d5eedf55807b4708c656f5894b63507d0e28ae10aa1bddbea551241035afe62b6df0800fc94c2e2806a7f3adecd7c @@ -30077,7 +30129,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.4": +"nanoid@npm:^3.1.23, nanoid@npm:^3.3.4": version: 3.3.4 resolution: "nanoid@npm:3.3.4" bin: @@ -33574,7 +33626,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6": +"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f From d362737143a2a9be3c17a2b79d67a9b29a408b7a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 27 Sep 2022 14:24:52 +0200 Subject: [PATCH 08/17] chore: reset some things so we can run it in paralell Signed-off-by: blam --- .../FieldOverrides/DescriptionField.tsx | 2 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 9 ++- .../TemplatePage/createValidator.test.ts | 4 +- .../TemplatePage/createValidator.ts | 4 +- .../fields/EntityPicker/EntityPicker.test.tsx | 8 +-- .../fields/EntityPicker/EntityPicker.tsx | 13 ++-- .../fields/OwnerPicker/OwnerPicker.test.tsx | 4 +- .../fields/OwnerPicker/OwnerPicker.tsx | 8 +-- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 15 ++--- .../fields/RepoUrlPicker/RepoUrlPicker.tsx | 5 +- .../fields/RepoUrlPicker/validation.test.ts | 2 +- .../fields/RepoUrlPicker/validation.ts | 4 +- plugins/scaffolder/src/extensions/index.tsx | 34 ++++++++++- plugins/scaffolder/src/extensions/types.ts | 61 +++++++++++++++++-- .../TemplateWizardPage/Stepper/Stepper.tsx | 6 +- .../Stepper/createAsyncValidators.test.ts | 13 ++-- .../Stepper/createAsyncValidators.ts | 4 +- 17 files changed, 134 insertions(+), 62 deletions(-) diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx index eded38beee..3c592860ef 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { MarkdownContent } from '@backstage/core-components'; -import { FieldProps } from '@rjsf/utils'; +import { FieldProps } from '@rjsf/core'; export const DescriptionField = ({ description }: FieldProps) => description && ; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 7ab3007e99..8c71df67b6 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -29,9 +29,8 @@ import { useApi, featureFlagsApiRef, } from '@backstage/core-plugin-api'; -import { UiSchema } from '@rjsf/utils'; -import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; -import { Theme } from '@rjsf/material-ui'; +import { FormProps, IChangeEvent, UiSchema, withTheme } from '@rjsf/core'; +import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useState } from 'react'; import { transformSchemaToProps } from './schema'; import { Content, StructuredMetadataTable } from '@backstage/core-components'; @@ -39,6 +38,7 @@ import cloneDeep from 'lodash/cloneDeep'; import * as fieldOverrides from './FieldOverrides'; import { LayoutOptions } from '../../layouts'; +const Form = withTheme(MuiTheme); type Step = { schema: JsonObject; title: string; @@ -123,7 +123,6 @@ export const MultistepJsonForm = (props: Props) => { finishButtonLabel, layouts, } = props; - const Form = withTheme(Theme); const [activeStep, setActiveStep] = useState(0); const [disableButtons, setDisableButtons] = useState(false); const errorApi = useApi(errorApiRef); @@ -214,7 +213,7 @@ export const MultistepJsonForm = (props: Props) => { formData={formData} formContext={{ formData }} onChange={onChange} - onSubmit={(e: any) => { + onSubmit={e => { if (e.errors.length === 0) handleNext(); }} {...formProps} diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index eea5efc296..f549c9e7f2 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -17,7 +17,7 @@ import { createValidator } from './createValidator'; import { CustomFieldValidator } from '../../extensions'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { FormValidation } from '@rjsf/utils'; +import { FormValidation } from '@rjsf/core'; describe('createValidator', () => { const validators: Record> = @@ -68,6 +68,6 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.p1?.addError).toHaveBeenCalledTimes(1); + expect(result.p1.addError).toHaveBeenCalledTimes(1); }); }); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index d1c55009a9..9cd1489a02 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -15,7 +15,7 @@ */ import { CustomFieldValidator } from '../../extensions'; -import { FormValidation } from '@rjsf/utils'; +import { FormValidation } from '@rjsf/core'; import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; @@ -62,7 +62,7 @@ export const createValidator = ( if (fieldName && typeof validators[fieldName] === 'function') { validators[fieldName]!( propData as JsonValue, - propValidation as FormValidation, + propValidation, context, ); } diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index ffc447577a..942eef9d82 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -17,7 +17,7 @@ import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { FieldProps } from '@rjsf/utils'; +import { FieldProps } from '@rjsf/core'; import { fireEvent } from '@testing-library/react'; import React from 'react'; import { EntityPicker } from './EntityPicker'; @@ -39,7 +39,7 @@ describe('', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps; const catalogApi: jest.Mocked = { getLocationById: jest.fn(), @@ -76,7 +76,7 @@ describe('', () => { uiSchema, rawErrors, formData, - } as any; + } as unknown as FieldProps; catalogApi.getEntities.mockResolvedValue({ items: entities }); }); @@ -117,7 +117,7 @@ describe('', () => { uiSchema, rawErrors, formData, - } as any; + } as unknown as FieldProps; catalogApi.getEntities.mockResolvedValue({ items: entities }); }); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index a040320d79..e7883a4721 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -45,10 +45,7 @@ export interface EntityPickerUiOptions { * @public */ export const EntityPicker = ( - props: FieldExtensionComponentProps< - string | undefined, - EntityPickerUiOptions - >, + props: FieldExtensionComponentProps, ) => { const { onChange, @@ -59,9 +56,9 @@ export const EntityPicker = ( formData, idSchema, } = props; - const allowedKinds = uiSchema?.['ui:options']?.allowedKinds; - const defaultKind = uiSchema?.['ui:options']?.defaultKind; - const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace; + const allowedKinds = uiSchema['ui:options']?.allowedKinds; + const defaultKind = uiSchema['ui:options']?.defaultKind; + const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; const catalogApi = useApi(catalogApiRef); @@ -102,7 +99,7 @@ export const EntityPicker = ( onChange={onSelect} options={entityRefs || []} autoSelect - freeSolo={uiSchema?.['ui:options']?.allowArbitraryValues ?? true} + freeSolo={uiSchema['ui:options']?.allowArbitraryValues ?? true} renderInput={params => ( ', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps; const catalogApi: jest.Mocked = { getLocationById: jest.fn(), diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx index 8ce01fc3ef..3de2b12bd0 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx @@ -36,7 +36,7 @@ export interface OwnerPickerUiOptions { * @public */ export const OwnerPicker = ( - props: FieldExtensionComponentProps, + props: FieldExtensionComponentProps, ) => { const { schema: { title = 'Owner', description = 'The owner of the component' }, @@ -44,18 +44,18 @@ export const OwnerPicker = ( ...restProps } = props; - const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace; + const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; const ownerUiSchema = { ...uiSchema, 'ui:options': { - allowedKinds: (uiSchema?.['ui:options']?.allowedKinds || [ + allowedKinds: (uiSchema['ui:options']?.allowedKinds || [ 'Group', 'User', ]) as string[], defaultKind: 'Group', allowArbitraryValues: - uiSchema?.['ui:options']?.allowArbitraryValues ?? true, + uiSchema['ui:options']?.allowArbitraryValues ?? true, ...(defaultNamespace !== undefined ? { defaultNamespace } : {}), }, }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index f28b4bc816..7fac9f7840 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -15,8 +15,7 @@ */ import React, { useContext } from 'react'; import { RepoUrlPicker } from './RepoUrlPicker'; -import { withTheme } from '@rjsf/core'; -import { Theme } from '@rjsf/material-ui'; +import Form from '@rjsf/core'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { scmIntegrationsApiRef, @@ -26,12 +25,12 @@ import { } from '@backstage/integration-react'; import { scaffolderApiRef } from '../../../api'; import { ScaffolderApi } from '../../../types'; + import { SecretsContextProvider, SecretsContext, } from '../../secrets/SecretsContext'; import { act, fireEvent } from '@testing-library/react'; -import { Field } from '@rjsf/utils'; describe('RepoUrlPicker', () => { const mockScaffolderApi: Partial = { @@ -51,8 +50,6 @@ describe('RepoUrlPicker', () => { getCredentials: jest.fn().mockResolvedValue({ token: 'abc123' }), }; - const Form = withTheme(Theme); - describe('happy path rendering', () => { it('should render the repo url picker with minimal props', async () => { const onSubmit = jest.fn(); @@ -68,7 +65,7 @@ describe('RepoUrlPicker', () => { }} + fields={{ RepoUrlPicker: RepoUrlPicker }} onSubmit={onSubmit} /> @@ -102,13 +99,12 @@ describe('RepoUrlPicker', () => { > }} + fields={{ RepoUrlPicker: RepoUrlPicker }} /> , @@ -136,7 +132,6 @@ describe('RepoUrlPicker', () => { > { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker as Field }} + fields={{ RepoUrlPicker: RepoUrlPicker }} /> diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 870ec9dd53..451df857e5 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -62,10 +62,7 @@ export interface RepoUrlPickerUiOptions { * @public */ export const RepoUrlPicker = ( - props: FieldExtensionComponentProps< - string | undefined, - RepoUrlPickerUiOptions - >, + props: FieldExtensionComponentProps, ) => { const { uiSchema, onChange, rawErrors, formData } = props; const [state, setState] = useState( diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index b9c481957c..45e44b4072 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -15,7 +15,7 @@ */ import { repoPickerValidation } from './validation'; -import { FieldValidation } from '@rjsf/utils'; +import { FieldValidation } from '@rjsf/core'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/core-app-api'; import { ApiHolder } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index ae4f2ec1b9..99847f9e3b 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/utils'; +import { FieldValidation } from '@rjsf/core'; import { ApiHolder } from '@backstage/core-plugin-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; @@ -26,7 +26,7 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react'; * @public */ export const repoPickerValidation = ( - value: string | undefined, + value: string, validation: FieldValidation, context: { apiHolder: ApiHolder }, ) => { diff --git a/plugins/scaffolder/src/extensions/index.tsx b/plugins/scaffolder/src/extensions/index.tsx index 21a565bf46..38cabd5511 100644 --- a/plugins/scaffolder/src/extensions/index.tsx +++ b/plugins/scaffolder/src/extensions/index.tsx @@ -19,6 +19,9 @@ import { CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, + NextCustomFieldValidator, + NextFieldExtensionOptions, + NextFieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; @@ -40,7 +43,7 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; */ export function createScaffolderFieldExtension< TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, + TInputProps = unknown, >( options: FieldExtensionOptions, ): Extension> { @@ -59,6 +62,32 @@ export function createScaffolderFieldExtension< }; } +/** + * Method for creating field extensions that can be used in the scaffolder + * frontend form. + * @alpha + */ +export function createNextScaffolderFieldExtension< + TReturnValue = unknown, + TInputProps extends UIOptionsType = {}, +>( + options: FieldExtensionOptions, +): Extension> { + return { + expose() { + const FieldExtensionDataHolder: any = () => null; + + attachComponentData( + FieldExtensionDataHolder, + FIELD_EXTENSION_KEY, + options, + ); + + return FieldExtensionDataHolder; + }, + }; +} + /** * The Wrapping component for defining fields extensions inside * @@ -77,6 +106,9 @@ export type { CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, + NextCustomFieldValidator, + NextFieldExtensionOptions, + NextFieldExtensionComponentProps, }; export { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default'; diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index 4758d96f66..627587bba6 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -14,9 +14,16 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FieldProps, UiSchema } from '@rjsf/core'; +import { FieldValidation, FieldProps } from '@rjsf/core'; import { PropsWithChildren } from 'react'; +import { + UIOptionsType, + FieldProps as FieldPropsV5, + UiSchema as UiSchemaV5, + FieldValidation as FieldValidationV5, +} from '@rjsf/utils'; + /** * Field validation type for Custom Field Extensions. * @@ -36,7 +43,7 @@ export type CustomFieldValidator = ( */ export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps extends {} = {}, + TInputProps = unknown, > = { name: string; component: ( @@ -53,9 +60,51 @@ export type FieldExtensionOptions< */ export interface FieldExtensionComponentProps< TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren> { - uiSchema: UiSchema & { - 'ui:options': TUiOptions; + TUiOptions extends {} = {}, +> extends FieldProps { + uiSchema: FieldProps['uiSchema'] & { + 'ui:options'?: TUiOptions; }; } + +/** + * Type for Field Extension Props for RJSF v5 + * + * @alpha + */ +export interface NextFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren> { + uiSchema?: UiSchemaV5 & { + 'ui:options'?: TUiOptions & UIOptionsType; + }; +} + +/** + * Field validation type for Custom Field Extensions. + * + * @alpha + */ +export type NextCustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidationV5, + context: { apiHolder: ApiHolder }, +) => void | Promise; + +/** + * Type for the Custom Field Extension with the + * name and components and validation function. + * + * @alpha + */ +export type NextFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: FieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: NextCustomFieldValidator; +}; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index ade7c982ff..aa3a384738 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -26,12 +26,12 @@ import { withTheme } from '@rjsf/core'; import { ErrorSchema, FieldValidation } from '@rjsf/utils'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useMemo, useState } from 'react'; -import { FieldExtensionOptions } from '../../../extensions'; +import { NextFieldExtensionOptions } from '../../../extensions'; import { TemplateParameterSchema } from '../../../types'; import { createAsyncValidators } from './createAsyncValidators'; import { useTemplateSchema } from './useTemplateSchema'; import { ReviewState } from './ReviewState'; -import validator from '@rjsf/validator-ajv6'; +import validator from '@rjsf/validator-ajv8'; const useStyles = makeStyles(theme => ({ backButton: { @@ -50,7 +50,7 @@ const useStyles = makeStyles(theme => ({ export interface StepperProps { manifest: TemplateParameterSchema; - extensions: FieldExtensionOptions[]; + extensions: NextFieldExtensionOptions[]; } const Form = withTheme(MuiTheme); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.test.ts index ed887fb56d..a4a937e6fe 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/types'; -import { CustomFieldValidator } from '../../../extensions'; +import { NextCustomFieldValidator } from '../../../extensions'; import { createAsyncValidators } from './createAsyncValidators'; describe('createAsyncValidators', () => { @@ -79,13 +79,16 @@ describe('createAsyncValidators', () => { }, }; - const NameField: CustomFieldValidator = (value, { addError }) => { + const NameField: NextCustomFieldValidator = ( + value, + { addError }, + ) => { if (!value) { addError('something is broken here!'); } }; - const AddressField: CustomFieldValidator<{ + const AddressField: NextCustomFieldValidator<{ street?: string; postcode?: string; }> = (value, { addError }) => { @@ -101,8 +104,8 @@ describe('createAsyncValidators', () => { const validate = createAsyncValidators( schema, { - NameField: NameField as CustomFieldValidator, - AddressField: AddressField as CustomFieldValidator, + NameField: NameField as NextCustomFieldValidator, + AddressField: AddressField as NextCustomFieldValidator, }, { apiHolder: { get: jest.fn() }, diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts index 60eed0f364..1355387eda 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts @@ -17,13 +17,13 @@ import { FieldValidation } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { CustomFieldValidator } from '../../../extensions'; +import { NextCustomFieldValidator } from '../../../extensions'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation } from './schema'; export const createAsyncValidators = ( rootSchema: JsonObject, - validators: Record>, + validators: Record>, context: { apiHolder: ApiHolder; }, From 2548b5a5909ecf95e97eb0138806fcb9000a1e77 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 28 Sep 2022 18:57:46 +0200 Subject: [PATCH 09/17] chore: typescript is happy. ring the police. Signed-off-by: blam Signed-off-by: blam --- plugins/scaffolder/src/extensions/types.ts | 2 +- plugins/scaffolder/src/next/Router/Router.tsx | 6 +++--- .../src/next/TemplateWizardPage/Stepper/Stepper.tsx | 7 ++++--- .../src/next/TemplateWizardPage/TemplateWizardPage.tsx | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index 627587bba6..62f17dff15 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -104,7 +104,7 @@ export type NextFieldExtensionOptions< > = { name: string; component: ( - props: FieldExtensionComponentProps, + props: NextFieldExtensionComponentProps, ) => JSX.Element | null; validation?: NextCustomFieldValidator; }; diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 758e268cb3..f0e5823f84 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -18,10 +18,10 @@ import { Routes, Route, useOutlet } from 'react-router'; import { TemplateListPage } from '../TemplateListPage'; import { TemplateWizardPage } from '../TemplateWizardPage'; import { - FieldExtensionOptions, FIELD_EXTENSION_WRAPPER_KEY, FIELD_EXTENSION_KEY, DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS, + NextFieldExtensionOptions, } from '../../extensions'; import { useElementFilter } from '@backstage/core-plugin-api'; @@ -60,7 +60,7 @@ export const Router = (props: PropsWithChildren) => { .selectByComponentData({ key: FIELD_EXTENSION_WRAPPER_KEY, }) - .findComponentData({ + .findComponentData({ key: FIELD_EXTENSION_KEY, }), ); @@ -73,7 +73,7 @@ export const Router = (props: PropsWithChildren) => { customFieldExtension => customFieldExtension.name === name, ), ), - ]; + ] as NextFieldExtensionOptions[]; // here just to coerce the default extensions to the correct type return ( diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index aa3a384738..2735ea7e61 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -22,9 +22,9 @@ import { Button, makeStyles, } from '@material-ui/core'; -import { withTheme } from '@rjsf/core'; +import { withTheme } from '@rjsf/core-v5'; import { ErrorSchema, FieldValidation } from '@rjsf/utils'; -import { Theme as MuiTheme } from '@rjsf/material-ui'; +import { Theme as MuiTheme } from '@rjsf/material-ui-v5'; import React, { useMemo, useState } from 'react'; import { NextFieldExtensionOptions } from '../../../extensions'; import { TemplateParameterSchema } from '../../../types'; @@ -53,7 +53,8 @@ export interface StepperProps { extensions: NextFieldExtensionOptions[]; } -const Form = withTheme(MuiTheme); +// This needs an any for some reason, think it coul +const Form = withTheme(MuiTheme as any); export const Stepper = (props: StepperProps) => { const { steps } = useTemplateSchema(props.manifest); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 468db438d5..f6739e6389 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -22,7 +22,7 @@ import { InfoCard, MarkdownContent, } from '@backstage/core-components'; -import { FieldExtensionOptions } from '../../extensions'; +import { NextFieldExtensionOptions } from '../../extensions'; import { Navigate } from 'react-router'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { @@ -39,7 +39,7 @@ import { BackstageTheme } from '@backstage/theme'; import { nextRouteRef, selectedTemplateRouteRef } from '../../routes'; export interface TemplateWizardPageProps { - customFieldExtensions: FieldExtensionOptions[]; + customFieldExtensions: NextFieldExtensionOptions[]; } const useStyles = makeStyles(() => ({ From 2d58be910dc63b5fba08bc2f58bea2782b1b4a2c Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 29 Sep 2022 10:15:48 +0200 Subject: [PATCH 10/17] chore: resetting the fields Signed-off-by: blam --- .../components/scaffolder/customScaffolderExtensions.tsx | 4 ++-- .../fields/EntityNamePicker/EntityNamePicker.tsx | 2 +- .../components/fields/EntityNamePicker/validation.test.ts | 2 +- .../src/components/fields/EntityNamePicker/validation.ts | 2 +- .../fields/EntityTagsPicker/EntityTagsPicker.tsx | 6 +++--- .../fields/OwnedEntityPicker/OwnedEntityPicker.tsx | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index 3aadd69c05..2a4dedf080 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import type { FieldValidation } from '@rjsf/utils'; +import type { FieldValidation } from '@rjsf/core'; import { createScaffolderFieldExtension, FieldExtensionComponentProps, @@ -30,7 +30,7 @@ const TextValuePicker = (props: FieldExtensionComponentProps) => { schema: { title, description }, rawErrors, formData, - uiSchema: { 'ui:autofocus': autoFocus } = {}, + uiSchema: { 'ui:autofocus': autoFocus }, idSchema, placeholder, } = props; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx index 2b21141edb..802135a863 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx @@ -29,7 +29,7 @@ export const EntityNamePicker = ( schema: { title = 'Name', description = 'Unique name of the component' }, rawErrors, formData, - uiSchema: { 'ui:autofocus': autoFocus } = {}, + uiSchema: { 'ui:autofocus': autoFocus }, idSchema, placeholder, } = props; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts index 7201c9c4b3..290650387e 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/utils'; +import { FieldValidation } from '@rjsf/core'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; import { entityNamePickerValidation } from './validation'; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts index 1533b0cdc3..7a40a460ba 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/utils'; +import { FieldValidation } from '@rjsf/core'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; export const entityNamePickerValidation = ( diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx index fcbf7a7c80..c0e3aab436 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx @@ -51,9 +51,9 @@ export const EntityTagsPicker = ( const [inputValue, setInputValue] = useState(''); const [inputError, setInputError] = useState(false); const tagValidator = makeValidator().isValidTag; - const kinds = uiSchema?.['ui:options']?.kinds; - const showCounts = uiSchema?.['ui:options']?.showCounts; - const helperText = uiSchema?.['ui:options']?.helperText; + const kinds = uiSchema['ui:options']?.kinds; + const showCounts = uiSchema['ui:options']?.showCounts; + const helperText = uiSchema['ui:options']?.helperText; const { loading, value: existingTags } = useAsync(async () => { const facet = 'metadata.tags'; diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index d15677cfac..2446883a86 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -59,12 +59,12 @@ export const OwnedEntityPicker = ( formData, idSchema, } = props; - const allowedKinds = uiSchema?.['ui:options']?.allowedKinds; - const defaultKind = uiSchema?.['ui:options']?.defaultKind; - const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace; + const allowedKinds = uiSchema['ui:options']?.allowedKinds; + const defaultKind = uiSchema['ui:options']?.defaultKind; + const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; const allowArbitraryValues = - uiSchema?.['ui:options']?.allowArbitraryValues ?? true; + uiSchema['ui:options']?.allowArbitraryValues ?? true; const { ownedEntities, loading } = useOwnedEntities(allowedKinds); const entityRefs = ownedEntities?.items From bc6b470825915a73f6dc155ede802afb9ee29082 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 29 Sep 2022 23:32:18 +0200 Subject: [PATCH 11/17] chore: finally make typescript full happy too Signed-off-by: blam --- .../src/next/TemplateWizardPage/Stepper/Stepper.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index 2735ea7e61..f668205573 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -24,7 +24,6 @@ import { } from '@material-ui/core'; import { withTheme } from '@rjsf/core-v5'; import { ErrorSchema, FieldValidation } from '@rjsf/utils'; -import { Theme as MuiTheme } from '@rjsf/material-ui-v5'; import React, { useMemo, useState } from 'react'; import { NextFieldExtensionOptions } from '../../../extensions'; import { TemplateParameterSchema } from '../../../types'; @@ -53,8 +52,10 @@ export interface StepperProps { extensions: NextFieldExtensionOptions[]; } -// This needs an any for some reason, think it coul -const Form = withTheme(MuiTheme as any); +// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly +// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because +// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. +const Form = withTheme(require('@rjsf/material-ui-v5').Theme); export const Stepper = (props: StepperProps) => { const { steps } = useTemplateSchema(props.manifest); From 2b825ff357077f5210523ec4505c94d0b381c004 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 29 Sep 2022 23:34:29 +0200 Subject: [PATCH 12/17] chore: bump to latest beta Signed-off-by: blam --- plugins/scaffolder/package.json | 8 +++---- yarn.lock | 40 ++++++++++++++++----------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 6508ae77e7..4508a4b49d 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -55,11 +55,11 @@ "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^15.0.0", "@rjsf/core": "^3.2.1", - "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.9", + "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.10", "@rjsf/material-ui": "^3.2.1", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.9", - "@rjsf/utils": "^5.0.0-beta.9", - "@rjsf/validator-ajv8": "^5.0.0-beta.9", + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.10", + "@rjsf/utils": "^5.0.0-beta.10", + "@rjsf/validator-ajv8": "^5.0.0-beta.10", "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", diff --git a/yarn.lock b/yarn.lock index dcecfe2b9f..9af65cfa61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6743,11 +6743,11 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.57 "@react-hookz/web": ^15.0.0 "@rjsf/core": ^3.2.1 - "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.9" + "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.10" "@rjsf/material-ui": ^3.2.1 - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.9" - "@rjsf/utils": ^5.0.0-beta.9 - "@rjsf/validator-ajv8": ^5.0.0-beta.9 + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.10" + "@rjsf/utils": ^5.0.0-beta.10 + "@rjsf/validator-ajv8": ^5.0.0-beta.10 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 @@ -11944,9 +11944,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/core-v5@npm:@rjsf/core@^5.0.0-beta.9": - version: 5.0.0-beta.9 - resolution: "@rjsf/core@npm:5.0.0-beta.9" +"@rjsf/core-v5@npm:@rjsf/core@^5.0.0-beta.10": + version: 5.0.0-beta.10 + resolution: "@rjsf/core@npm:5.0.0-beta.10" dependencies: lodash: ^4.17.15 lodash-es: ^4.17.15 @@ -11955,7 +11955,7 @@ __metadata: peerDependencies: "@rjsf/utils": ^5.0.0-beta.1 react: ^16.14.0 || >=17 - checksum: b55e1a4b3f9f638afdeda1da0abeb145040081201b2f9ed680c93d3dea2ee20e1066da5d2c32c69916d9f2fce422ecb8058f303b9f4df1b20dacf35564f5c7ec + checksum: c3e8852c8fedc6ae23da610033e0bded1bd198cebf7f54a5cdcf3b42d22a3b3864da9c735300cadc7d756f26055a7e62408d51a5ebdb906be9b1bf85bf3712ed languageName: node linkType: hard @@ -11978,16 +11978,16 @@ __metadata: languageName: node linkType: hard -"@rjsf/material-ui-v5@npm:@rjsf/material-ui@^5.0.0-beta.9": - version: 5.0.0-beta.9 - resolution: "@rjsf/material-ui@npm:5.0.0-beta.9" +"@rjsf/material-ui-v5@npm:@rjsf/material-ui@^5.0.0-beta.10": + version: 5.0.0-beta.10 + resolution: "@rjsf/material-ui@npm:5.0.0-beta.10" peerDependencies: "@material-ui/core": ^4.12.3 "@material-ui/icons": ^4.11.2 "@rjsf/core": ^5.0.0-beta.1 "@rjsf/utils": ^5.0.0-beta.1 react: ^16.14.0 || >=17 - checksum: 44624d1aff0f30963d7ae2ab529713d9fcf6e6df809264d6bdee7ef5e71934ab031dbba9dcc9c10be05cb7b0fd679f6fbb1eb27ce7081940b56034a5f2564093 + checksum: c6e602fc331ec37524837123f42e605389c8ea1a9207ed3e9052de380b91fb90365aa962b0020197f0fb2bcbd87baac34bef7dbbb31ea4b57b6587d0fcd81a09 languageName: node linkType: hard @@ -12003,9 +12003,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/utils@npm:^5.0.0-beta.9": - version: 5.0.0-beta.9 - resolution: "@rjsf/utils@npm:5.0.0-beta.9" +"@rjsf/utils@npm:^5.0.0-beta.10": + version: 5.0.0-beta.10 + resolution: "@rjsf/utils@npm:5.0.0-beta.10" dependencies: json-schema-merge-allof: ^0.8.1 jsonpointer: ^5.0.1 @@ -12014,13 +12014,13 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^16.14.0 || >=17 - checksum: ac5b99cf7860c838e5b509a523b19824f4966ec8d44284a026bf81de7c7733bac40432af4c67ab538bd400f529dc55d9001e07618a514cac365cd604ff786b11 + checksum: df5dda5a17ce11df2342ceff8d6ad2b3dad3a1f98d44aa7da378e6cd48387e4af023964b6143836e1ad16ff68f6592c0dcf24ff9f3fc859480b42b2c879406bc languageName: node linkType: hard -"@rjsf/validator-ajv8@npm:^5.0.0-beta.9": - version: 5.0.0-beta.9 - resolution: "@rjsf/validator-ajv8@npm:5.0.0-beta.9" +"@rjsf/validator-ajv8@npm:^5.0.0-beta.10": + version: 5.0.0-beta.10 + resolution: "@rjsf/validator-ajv8@npm:5.0.0-beta.10" dependencies: ajv: ^8.11.0 ajv-formats: ^2.1.1 @@ -12028,7 +12028,7 @@ __metadata: lodash-es: ^4.17.15 peerDependencies: "@rjsf/utils": ^5.0.0-beta.1 - checksum: 64ca81f1f440b08f959d61e1f97b25d890cd8f03582287004961d0ba0ec7d6719748b00d821ef009d330816ca2e4e030d46fa695a3c12c338518e469242694cd + checksum: faa359c9ec58cf0fff35932d4e08a5c42f8449120cae606ebff108814f974e8db8a62df85e90e1fec7b0345388df09b83359ae1cc09103d41e73f298472b846a languageName: node linkType: hard From 1047baa92657a2d29c763924355bbfa522df8f1b Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 5 Oct 2022 15:01:20 +0200 Subject: [PATCH 13/17] chore: added changeset for the scaffolder package Signed-off-by: blam --- .changeset/lucky-beans-bathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lucky-beans-bathe.md diff --git a/.changeset/lucky-beans-bathe.md b/.changeset/lucky-beans-bathe.md new file mode 100644 index 0000000000..b425a29599 --- /dev/null +++ b/.changeset/lucky-beans-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Bump to `react-jsonschema-form@v5-beta` for the `NextRouter` under `@alpha` exports From 8020d8e8e938873c9cb22aad0139a800e92d6109 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 5 Oct 2022 15:07:10 +0200 Subject: [PATCH 14/17] chore: export some more things out of the alpha exports Signed-off-by: blam --- plugins/scaffolder/api-report.md | 44 ++++++++++++++++++++++++++++++++ plugins/scaffolder/src/index.ts | 8 +++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 23b374541b..824b56daf0 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -15,7 +15,9 @@ import { Extension } from '@backstage/core-plugin-api'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FetchApi } 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 } from '@rjsf/core'; import { IdentityApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; @@ -29,6 +31,16 @@ import { ScmIntegrationRegistry } from '@backstage/integration'; 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'; + +// @alpha +export function createNextScaffolderFieldExtension< + TReturnValue = unknown, + TInputProps extends UIOptionsType = {}, +>( + options: FieldExtensionOptions, +): Extension>; // @public export function createScaffolderFieldExtension< @@ -155,6 +167,38 @@ export type LogEvent = { taskId: string; }; +// @alpha +export type NextCustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidation_2, + context: { + apiHolder: ApiHolder; + }, +) => void | Promise; + +// @alpha +export interface NextFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren> { + // (undocumented) + uiSchema?: UiSchema & { + 'ui:options'?: TUiOptions & UIOptionsType; + }; +} + +// @alpha +export type NextFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: NextFieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: NextCustomFieldValidator; +}; + // @alpha export type NextRouterProps = { components?: { diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index c16e12beb5..e68eece8e5 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -59,11 +59,17 @@ export { RepoUrlPickerFieldExtension, ScaffolderPage, scaffolderPlugin, - NextScaffolderPage, } from './plugin'; export * from './components'; export type { TaskPageProps } from './components/TaskPage'; /** next exports */ +export { NextScaffolderPage } from './plugin'; export type { NextRouterProps } from './next'; export type { TemplateGroupFilter } from './next'; +export { + createNextScaffolderFieldExtension, + type NextCustomFieldValidator, + type NextFieldExtensionOptions, + type NextFieldExtensionComponentProps, +} from './extensions'; From 42a8b0c3f3648d3e75e7fe81558bf2f021124e70 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 5 Oct 2022 15:12:31 +0200 Subject: [PATCH 15/17] chore: fix the typings Signed-off-by: blam Signed-off-by: blam --- plugins/scaffolder/src/extensions/index.tsx | 2 +- plugins/scaffolder/src/next/Router/Router.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder/src/extensions/index.tsx b/plugins/scaffolder/src/extensions/index.tsx index 38cabd5511..08075b5b9d 100644 --- a/plugins/scaffolder/src/extensions/index.tsx +++ b/plugins/scaffolder/src/extensions/index.tsx @@ -71,7 +71,7 @@ export function createNextScaffolderFieldExtension< TReturnValue = unknown, TInputProps extends UIOptionsType = {}, >( - options: FieldExtensionOptions, + options: NextFieldExtensionOptions, ): Extension> { return { expose() { diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index f0e5823f84..608709b05c 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -73,7 +73,7 @@ export const Router = (props: PropsWithChildren) => { customFieldExtension => customFieldExtension.name === name, ), ), - ] as NextFieldExtensionOptions[]; // here just to coerce the default extensions to the correct type + ] as NextFieldExtensionOptions[]; return ( From 2d76e6f6c473721ad00c0dfb29aa479d7c0fce0f Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 5 Oct 2022 17:36:41 +0200 Subject: [PATCH 16/17] chore: fixing api-reports Signed-off-by: blam --- plugins/scaffolder/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 824b56daf0..cf69736bd4 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -39,7 +39,7 @@ export function createNextScaffolderFieldExtension< TReturnValue = unknown, TInputProps extends UIOptionsType = {}, >( - options: FieldExtensionOptions, + options: NextFieldExtensionOptions, ): Extension>; // @public From 6edbf33499bfef87b0bfcd7c410bb1a0c85148f2 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 11 Oct 2022 11:26:35 +0100 Subject: [PATCH 17/17] chore: code reviews Signed-off-by: blam --- plugins/scaffolder/src/next/Router/Router.tsx | 3 ++- .../src/next/TemplateWizardPage/Stepper/Stepper.tsx | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 608709b05c..125a0bbbf6 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -22,6 +22,7 @@ import { FIELD_EXTENSION_KEY, DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS, NextFieldExtensionOptions, + FieldExtensionOptions, } from '../../extensions'; import { useElementFilter } from '@backstage/core-plugin-api'; @@ -60,7 +61,7 @@ export const Router = (props: PropsWithChildren) => { .selectByComponentData({ key: FIELD_EXTENSION_WRAPPER_KEY, }) - .findComponentData({ + .findComponentData({ key: FIELD_EXTENSION_KEY, }), ); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index f668205573..97f21111d3 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -96,9 +96,9 @@ export const Stepper = (props: StepperProps) => { const returnedValidation = await validation(formData); - const hasErrors = Object.values(returnedValidation).some(i => { - return i.__errors?.length! > 0 ?? false; - }); + const hasErrors = Object.values(returnedValidation).some( + i => i.__errors?.length, + ); if (hasErrors) { setErrors(returnedValidation);