diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx index 95f5d76212..d320ad80a6 100644 --- a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx +++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx @@ -18,7 +18,7 @@ import { StructuredMetadataTable } from '@backstage/core-components'; import { JsonObject } from '@backstage/types'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { ParsedTemplateSchema } from '../../hooks/useTemplateSchema'; -import { flattenObject, isJsonObject } from './util'; +import { processEntry } from './util'; /** * The props for the {@link ReviewState} component. @@ -38,49 +38,11 @@ export const ReviewState = (props: ReviewStateProps) => { Object.entries(props.formState) .flatMap(([key, value]) => { for (const step of props.schemas) { - const parsedSchema = new JSONSchema(step.mergedSchema); - const definitionInSchema = parsedSchema.getSchema({ - pointer: `#/${key}`, - data: props.formState, - }); - - if (definitionInSchema) { - const backstageReviewOptions = - definitionInSchema['ui:backstage']?.review; - - if (backstageReviewOptions) { - if (backstageReviewOptions.mask) { - return [[key, backstageReviewOptions.mask]]; - } - if (backstageReviewOptions.show === false) { - return []; - } - if (backstageReviewOptions.explode && isJsonObject(value)) { - return flattenObject(value, key, parsedSchema, props.formState); - } - } - - if (definitionInSchema['ui:widget'] === 'password') { - return [[key, '******']]; - } - - if (definitionInSchema.enum && definitionInSchema.enumNames) { - return [ - [ - key, - definitionInSchema.enumNames[ - definitionInSchema.enum.indexOf(value) - ] || value, - ], - ]; - } - } + return processEntry(key, value, step, props.formState); } - return [[key, value]]; }) .filter(prop => prop.length > 0), ); - return ; }; diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/util.ts b/plugins/scaffolder-react/src/next/components/ReviewState/util.ts index 0bb6fc08d2..e040b851d3 100644 --- a/plugins/scaffolder-react/src/next/components/ReviewState/util.ts +++ b/plugins/scaffolder-react/src/next/components/ReviewState/util.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ /* * Copyright 2022 The Backstage Authors * @@ -16,34 +17,63 @@ import { JsonObject, JsonValue } from '@backstage/types'; import { Draft07 as JSONSchema } from 'json-schema-library'; - -export function flattenObject( - obj: JsonObject, - prefix: string, - schema: JSONSchema, - formState: JsonObject, -): [string, JsonValue | undefined][] { - return Object.entries(obj).flatMap(([key, value]) => { - const prefixedKey = prefix ? `${prefix}/${key}` : key; - - const definitionInSchema = schema.getSchema({ - pointer: `#/${prefixedKey}`, - data: formState, - }); - - if (definitionInSchema) { - const backstageReviewOptions = definitionInSchema['ui:backstage']?.review; - - // Recurse into nested objects - if (backstageReviewOptions?.explode && isJsonObject(value)) { - return flattenObject(value, prefixedKey, schema, formState); - } - } - - return [[key, value]]; - }); -} +import { ParsedTemplateSchema } from '../../hooks'; export function isJsonObject(value?: JsonValue): value is JsonObject { return typeof value === 'object' && value !== null && !Array.isArray(value); } + +export function processEntry( + key: string, + value: JsonValue | undefined, + schema: ParsedTemplateSchema, + formState: JsonObject, +): [string, JsonValue | undefined][] { + const parsedSchema = new JSONSchema(schema.mergedSchema); + const definitionInSchema = parsedSchema.getSchema({ + pointer: `#/${key}`, + data: formState, + }); + + if (definitionInSchema) { + const backstageReviewOptions = definitionInSchema['ui:backstage']?.review; + if (backstageReviewOptions) { + if (backstageReviewOptions.mask) { + return [[getLastKey(key), backstageReviewOptions.mask]]; + } + if (backstageReviewOptions.show === false) { + return []; + } + } + + if (isJsonObject(value)) { + // Process nested objects + return Object.entries(value).flatMap(([nestedKey, nestedValue]) => + processEntry(`${key}/${nestedKey}`, nestedValue, schema, formState), + ); + } + + if (definitionInSchema['ui:widget'] === 'password') { + return [[getLastKey(key), '******']]; + } + + if (definitionInSchema.enum && definitionInSchema.enumNames) { + return [ + [ + getLastKey(key), + definitionInSchema.enumNames[ + definitionInSchema.enum.indexOf(value) + ] || value, + ], + ]; + } + } + + return [[getLastKey(key), value]]; +} + +// Helper function to get the last part of the key +function getLastKey(key: string): string { + const parts = key.split('/'); + return parts[parts.length - 1]; +}