Incorporated a feedback

Signed-off-by: bnechyporenko <bogdannechiporenko@gmail.com>
Signed-off-by: bogdannechyporenko <bogdannechiporenko@gmail.com>
This commit is contained in:
bogdannechyporenko
2022-10-26 22:00:32 +02:00
parent 577d7ad3ad
commit 16cd6d442a
7 changed files with 68 additions and 59 deletions
+18 -15
View File
@@ -34,7 +34,8 @@ 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';
import { UiSchema } from '@rjsf/core';
import { UiSchema as UiSchema_2 } from '@rjsf/utils';
// @alpha
export function createNextScaffolderFieldExtension<
@@ -132,18 +133,6 @@ export type FieldExtensionOptions<
validation?: CustomFieldValidator<TFieldReturnValue>;
};
// @public
export type LastStepFormProps = {
disableButtons: boolean;
finishButtonLabel?: string;
formData: Record<string, any>;
handleBack: () => void;
handleCreate: () => void;
handleReset: () => void;
onFinish?: () => Promise<void>;
steps: Step[];
};
// @public
export type LayoutComponent<_TInputProps> = () => null;
@@ -196,7 +185,7 @@ export interface NextFieldExtensionComponentProps<
TUiOptions = {},
> extends PropsWithChildren<FieldProps_2<TFieldReturnValue>> {
// (undocumented)
uiSchema?: UiSchema<TFieldReturnValue> & {
uiSchema?: UiSchema_2<TFieldReturnValue> & {
'ui:options'?: TUiOptions & UIOptionsType;
};
}
@@ -309,13 +298,27 @@ export interface RepoUrlPickerUiOptions {
};
}
// @public
export type ReviewStepProps = {
disableButtons: boolean;
formData: JsonObject;
handleBack: () => void;
handleReset: () => void;
handleCreate: () => void;
steps: {
uiSchema: UiSchema;
mergedSchema: JsonObject;
schema: JsonObject;
}[];
};
// @public (undocumented)
export const rootRouteRef: RouteRef<undefined>;
// @public
export type RouterProps = {
components?: {
LastStepFormComponent?: ComponentType<LastStepFormProps>;
ReviewStepComponent?: ComponentType<ReviewStepProps>;
TemplateCardComponent?:
| ComponentType<{
template: TemplateEntityV1beta3;
@@ -21,6 +21,7 @@ import {
Stepper,
Typography,
} from '@material-ui/core';
import { JsonObject } from '@backstage/types';
import {
errorApiRef,
featureFlagsApiRef,
@@ -28,16 +29,17 @@ import {
useRouteRefParams,
useApi,
} from '@backstage/core-plugin-api';
import { FormProps, IChangeEvent, withTheme } from '@rjsf/core';
import { FormProps, IChangeEvent, UiSchema, withTheme } from '@rjsf/core';
import { Theme as MuiTheme } from '@rjsf/material-ui';
import React, { ComponentType, useState } from 'react';
import { transformSchemaToProps } from './schema';
import cloneDeep from 'lodash/cloneDeep';
import * as fieldOverrides from './FieldOverrides';
import { LayoutOptions } from '../../layouts';
import { ReviewStepComponentProps, Step } from '../types';
import { ReviewStepProps, Step } from '../types';
import { ReviewStep } from './ReviewStep';
import { selectedTemplateRouteRef } from '../../routes';
import { extractSchemaFromStep } from '../../next/TemplateWizardPage/Stepper/schema';
const Form = withTheme(MuiTheme);
@@ -57,9 +59,26 @@ export type MultistepJsonFormProps = {
fields?: FormProps<any>['fields'];
finishButtonLabel?: string;
layouts: LayoutOptions[];
ReviewStepComponent?: ComponentType<ReviewStepComponentProps>;
ReviewStepComponent?: ComponentType<ReviewStepProps>;
};
function getUiSchemasFromSteps(steps: Step[]): {
uiSchema: UiSchema;
mergedSchema: JsonObject;
schema: JsonObject;
}[] {
const res = steps.map(({ schema }) => ({
mergedSchema: schema,
...extractSchemaFromStep(schema),
}));
return res as unknown as {
uiSchema: UiSchema;
mergedSchema: JsonObject;
schema: JsonObject;
}[];
}
/**
* Creates the dynamic form for a scaffolder template.
*/
@@ -71,7 +90,6 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => {
onFinish,
fields,
widgets,
finishButtonLabel,
layouts,
ReviewStepComponent,
} = props;
@@ -196,10 +214,8 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => {
handleBack={handleBack}
handleCreate={handleCreate}
handleReset={handleReset}
finishButtonLabel={finishButtonLabel}
formData={formData}
onFinish={onFinish}
steps={steps}
steps={getUiSchemasFromSteps(steps)}
/>
)}
</>
@@ -18,29 +18,16 @@ import React from 'react';
import { Content, StructuredMetadataTable } from '@backstage/core-components';
import { UiSchema } from '@rjsf/core';
import { JsonObject } from '@backstage/types';
import { ReviewStepComponentProps, Step } from '../types';
import { ReviewStepProps } from '../types';
export function getUiSchemasFromSteps(steps: Step[]): UiSchema[] {
const uiSchemas: Array<UiSchema> = [];
steps.forEach(step => {
const schemaProps = step.schema.properties as JsonObject;
for (const key in schemaProps) {
if (schemaProps.hasOwnProperty(key)) {
const uiSchema = schemaProps[key] as UiSchema;
uiSchema.name = key;
uiSchemas.push(uiSchema);
}
}
});
return uiSchemas;
}
export function getReviewData(formData: Record<string, any>, steps: Step[]) {
const uiSchemas = getUiSchemasFromSteps(steps);
export function getReviewData(
formData: Record<string, any>,
steps: UiSchema[],
) {
const reviewData: Record<string, any> = {};
for (const key in formData) {
if (formData.hasOwnProperty(key)) {
const uiSchema = uiSchemas.find(us => us.name === key);
const uiSchema = steps.find(us => us.name === key);
if (!uiSchema) {
reviewData[key] = formData[key];
@@ -77,15 +64,13 @@ export function getReviewData(formData: Record<string, any>, steps: Step[]) {
* The component displaying the Last Step in scaffolder template form.
* Which represents the summary of the input provided by the end user.
*/
export const ReviewStep = (props: ReviewStepComponentProps) => {
export const ReviewStep = (props: ReviewStepProps) => {
const {
disableButtons,
finishButtonLabel,
formData,
handleBack,
handleCreate,
handleReset,
onFinish,
steps,
} = props;
return (
@@ -94,7 +79,10 @@ export const ReviewStep = (props: ReviewStepComponentProps) => {
<Typography variant="h6">Review and create</Typography>
<StructuredMetadataTable
dense
metadata={getReviewData(formData, steps)}
metadata={getReviewData(
formData,
steps.map(step => ({ uiSchema: step.uiSchema })),
)}
/>
<Box mb={4} />
<Button onClick={handleBack} disabled={disableButtons}>
@@ -107,9 +95,9 @@ export const ReviewStep = (props: ReviewStepComponentProps) => {
variant="contained"
color="primary"
onClick={handleCreate}
disabled={!onFinish || disableButtons}
disabled={disableButtons}
>
{finishButtonLabel ?? 'Create'}
Create
</Button>
</Paper>
</Content>
+2 -2
View File
@@ -46,7 +46,7 @@ import {
} from '../routes';
import { ListTasksPage } from './ListTasksPage';
import { LayoutOptions, LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../layouts';
import { ReviewStepComponentProps } from './types';
import { ReviewStepProps } from './types';
/**
* The props for the entrypoint `ScaffolderPage` component the plugin.
@@ -54,7 +54,7 @@ import { ReviewStepComponentProps } from './types';
*/
export type RouterProps = {
components?: {
ReviewStepComponent?: ComponentType<ReviewStepComponentProps>;
ReviewStepComponent?: ComponentType<ReviewStepProps>;
TemplateCardComponent?:
| ComponentType<{ template: TemplateEntityV1beta3 }>
| undefined;
@@ -41,7 +41,7 @@ import {
} from '@backstage/core-plugin-api';
import { stringifyEntityRef } from '@backstage/catalog-model';
import { LayoutOptions } from '../../layouts';
import { ReviewStepComponentProps } from '../types';
import { ReviewStepProps } from '../types';
const useTemplateParameterSchema = (templateRef: string) => {
const scaffolderApi = useApi(scaffolderApiRef);
@@ -57,7 +57,7 @@ export const TemplatePage = ({
customFieldExtensions = [],
layouts = [],
}: {
ReviewStepComponent?: ComponentType<ReviewStepComponentProps>;
ReviewStepComponent?: ComponentType<ReviewStepProps>;
customFieldExtensions?: FieldExtensionOptions<any, any>[];
layouts?: LayoutOptions[];
}) => {
+1 -1
View File
@@ -19,4 +19,4 @@ export { TemplateTypePicker } from './TemplateTypePicker';
export * from './secrets';
export { TaskPage } from './TaskPage';
export type { RouterProps } from './Router';
export type { ReviewStepComponentProps, Step } from './types';
export type { ReviewStepProps, Step } from './types';
+9 -7
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { FormProps } from '@rjsf/core';
import { FormProps, UiSchema } from '@rjsf/core';
import { JsonObject } from '@backstage/types';
/**
@@ -33,13 +33,15 @@ export type Step = {
*
* @public
*/
export type ReviewStepComponentProps = {
export type ReviewStepProps = {
disableButtons: boolean;
finishButtonLabel?: string;
formData: Record<string, any>;
formData: JsonObject;
handleBack: () => void;
handleCreate: () => void;
handleReset: () => void;
onFinish?: () => Promise<void>;
steps: Step[];
handleCreate: () => void;
steps: {
uiSchema: UiSchema;
mergedSchema: JsonObject;
schema: JsonObject;
}[];
};