chore: reset some things so we can run it in paralell

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2022-09-27 14:24:52 +02:00
parent ffe1357499
commit d362737143
17 changed files with 134 additions and 62 deletions
@@ -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 && <MarkdownContent content={description} linkTarget="_blank" />;
@@ -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}
@@ -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<string, undefined | CustomFieldValidator<unknown>> =
@@ -68,6 +68,6 @@ describe('createValidator', () => {
/* THEN */
expect(result).not.toBeNull();
expect(result.p1?.addError).toHaveBeenCalledTimes(1);
expect(result.p1.addError).toHaveBeenCalledTimes(1);
});
});
@@ -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,
);
}
@@ -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('<EntityPicker />', () => {
const rawErrors: string[] = [];
const formData = undefined;
let props: FieldProps<string | undefined>;
let props: FieldProps;
const catalogApi: jest.Mocked<CatalogApi> = {
getLocationById: jest.fn(),
@@ -76,7 +76,7 @@ describe('<EntityPicker />', () => {
uiSchema,
rawErrors,
formData,
} as any;
} as unknown as FieldProps<any>;
catalogApi.getEntities.mockResolvedValue({ items: entities });
});
@@ -117,7 +117,7 @@ describe('<EntityPicker />', () => {
uiSchema,
rawErrors,
formData,
} as any;
} as unknown as FieldProps<any>;
catalogApi.getEntities.mockResolvedValue({ items: entities });
});
@@ -45,10 +45,7 @@ export interface EntityPickerUiOptions {
* @public
*/
export const EntityPicker = (
props: FieldExtensionComponentProps<
string | undefined,
EntityPickerUiOptions
>,
props: FieldExtensionComponentProps<string, EntityPickerUiOptions>,
) => {
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 => (
<TextField
{...params}
@@ -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 React from 'react';
import { OwnerPicker } from './OwnerPicker';
@@ -36,7 +36,7 @@ describe('<OwnerPicker />', () => {
const rawErrors: string[] = [];
const formData = undefined;
let props: FieldProps<string | undefined>;
let props: FieldProps;
const catalogApi: jest.Mocked<CatalogApi> = {
getLocationById: jest.fn(),
@@ -36,7 +36,7 @@ export interface OwnerPickerUiOptions {
* @public
*/
export const OwnerPicker = (
props: FieldExtensionComponentProps<string | undefined, OwnerPickerUiOptions>,
props: FieldExtensionComponentProps<string, OwnerPickerUiOptions>,
) => {
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 } : {}),
},
};
@@ -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<ScaffolderApi> = {
@@ -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', () => {
<Form
schema={{ type: 'string' }}
uiSchema={{ 'ui:field': 'RepoUrlPicker' }}
fields={{ RepoUrlPicker: RepoUrlPicker as Field<unknown> }}
fields={{ RepoUrlPicker: RepoUrlPicker }}
onSubmit={onSubmit}
/>
</SecretsContextProvider>
@@ -102,13 +99,12 @@ describe('RepoUrlPicker', () => {
>
<SecretsContextProvider>
<Form
validator={validator}
schema={{ type: 'string' }}
uiSchema={{
'ui:field': 'RepoUrlPicker',
'ui:options': { allowedHosts: ['dev.azure.com'] },
}}
fields={{ RepoUrlPicker: RepoUrlPicker as Field<unknown> }}
fields={{ RepoUrlPicker: RepoUrlPicker }}
/>
</SecretsContextProvider>
</TestApiProvider>,
@@ -136,7 +132,6 @@ describe('RepoUrlPicker', () => {
>
<SecretsContextProvider>
<Form
validator={validator}
schema={{ type: 'string' }}
uiSchema={{
'ui:field': 'RepoUrlPicker',
@@ -147,7 +142,7 @@ describe('RepoUrlPicker', () => {
},
},
}}
fields={{ RepoUrlPicker: RepoUrlPicker as Field<unknown> }}
fields={{ RepoUrlPicker: RepoUrlPicker }}
/>
<SecretsComponent />
</SecretsContextProvider>
@@ -62,10 +62,7 @@ export interface RepoUrlPickerUiOptions {
* @public
*/
export const RepoUrlPicker = (
props: FieldExtensionComponentProps<
string | undefined,
RepoUrlPickerUiOptions
>,
props: FieldExtensionComponentProps<string, RepoUrlPickerUiOptions>,
) => {
const { uiSchema, onChange, rawErrors, formData } = props;
const [state, setState] = useState<RepoUrlPickerState>(
@@ -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';
@@ -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 },
) => {
+33 -1
View File
@@ -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<TReturnValue, TInputProps>,
): Extension<FieldExtensionComponent<TReturnValue, TInputProps>> {
@@ -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<TReturnValue, TInputProps>,
): Extension<NextFieldExtensionComponentProps<TReturnValue, TInputProps>> {
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';
+55 -6
View File
@@ -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<TFieldReturnValue> = (
*/
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<FieldProps<TFieldReturnValue>> {
uiSchema: UiSchema & {
'ui:options': TUiOptions;
TUiOptions extends {} = {},
> extends FieldProps<TFieldReturnValue> {
uiSchema: FieldProps['uiSchema'] & {
'ui:options'?: TUiOptions;
};
}
/**
* Type for Field Extension Props for RJSF v5
*
* @alpha
*/
export interface NextFieldExtensionComponentProps<
TFieldReturnValue,
TUiOptions = {},
> extends PropsWithChildren<FieldPropsV5<TFieldReturnValue>> {
uiSchema?: UiSchemaV5<TFieldReturnValue> & {
'ui:options'?: TUiOptions & UIOptionsType;
};
}
/**
* Field validation type for Custom Field Extensions.
*
* @alpha
*/
export type NextCustomFieldValidator<TFieldReturnValue> = (
data: TFieldReturnValue,
field: FieldValidationV5,
context: { apiHolder: ApiHolder },
) => void | Promise<void>;
/**
* 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<TFieldReturnValue, TInputProps>,
) => JSX.Element | null;
validation?: NextCustomFieldValidator<TFieldReturnValue>;
};
@@ -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<any, any>[];
extensions: NextFieldExtensionOptions<any, any>[];
}
const Form = withTheme(MuiTheme);
@@ -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<string> = (value, { addError }) => {
const NameField: NextCustomFieldValidator<string> = (
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<unknown>,
AddressField: AddressField as CustomFieldValidator<unknown>,
NameField: NameField as NextCustomFieldValidator<unknown>,
AddressField: AddressField as NextCustomFieldValidator<unknown>,
},
{
apiHolder: { get: jest.fn() },
@@ -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<string, undefined | CustomFieldValidator<unknown>>,
validators: Record<string, undefined | NextCustomFieldValidator<unknown>>,
context: {
apiHolder: ApiHolder;
},