From cb0206b2b47ff9473725e684961852a7e6266332 Mon Sep 17 00:00:00 2001 From: James Turley Date: Fri, 16 Apr 2021 12:01:54 +0100 Subject: [PATCH] Extract top-level UI schema keys in multistep form Signed-off-by: James Turley --- .changeset/fluffy-suns-repair.md | 5 +++ .../MultistepJsonForm/schema.test.ts | 2 + .../components/MultistepJsonForm/schema.ts | 44 +++++++++---------- 3 files changed, 28 insertions(+), 23 deletions(-) create mode 100644 .changeset/fluffy-suns-repair.md diff --git a/.changeset/fluffy-suns-repair.md b/.changeset/fluffy-suns-repair.md new file mode 100644 index 0000000000..6f45905219 --- /dev/null +++ b/.changeset/fluffy-suns-repair.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Respect top-level UI schema keys in scaffolder forms. Allows more advanced RJSF features such as explicit field ordering. diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts index e02e5be01c..b83725c2bb 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts @@ -20,6 +20,7 @@ describe('transformSchemaToProps', () => { it('transforms deep schema', () => { const inputSchema = { type: 'object', + 'ui:welp': 'warp', properties: { field1: { type: 'string', @@ -53,6 +54,7 @@ describe('transformSchemaToProps', () => { }, }; const expectedUiSchema = { + 'ui:welp': 'warp', field1: { 'ui:derp': 'herp', }, diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts index 0e1c0a4b50..e591589bd8 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts @@ -22,41 +22,39 @@ function isObject(value: unknown): value is JsonObject { } function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { + if (!isObject(schema)) { + return; + } + const { properties } = schema; + + for (const propName in schema) { + if (!schema.hasOwnProperty(propName)) { + continue; + } + + if (propName.startsWith('ui:')) { + uiSchema[propName] = schema[propName]; + delete schema[propName]; + } + } + if (!isObject(properties)) { return; } + for (const propName in properties) { if (!properties.hasOwnProperty(propName)) { continue; } + const schemaNode = properties[propName]; if (!isObject(schemaNode)) { continue; } - - if (schemaNode.type === 'object') { - const innerUiSchema = {}; - uiSchema[propName] = innerUiSchema; - extractUiSchema(schemaNode, innerUiSchema); - } else { - for (const innerKey in schemaNode) { - if (!schemaNode.hasOwnProperty(innerKey)) { - continue; - } - const innerValue = schemaNode[innerKey]; - if (innerKey.startsWith('ui:')) { - const innerUiSchema = uiSchema[propName] || {}; - if (!isObject(innerUiSchema)) { - throw new TypeError('Unexpected non-object in uiSchema'); - } - uiSchema[propName] = innerUiSchema; - - innerUiSchema[innerKey] = innerValue; - delete schemaNode[innerKey]; - } - } - } + const innerUiSchema = {}; + uiSchema[propName] = innerUiSchema; + extractUiSchema(schemaNode, innerUiSchema); } }