From 5b99484be3d6dd9f10735268eed88690f5d39923 Mon Sep 17 00:00:00 2001 From: Hugo 07E8 Date: Wed, 2 Jul 2025 14:08:35 -0600 Subject: [PATCH] fix(EM-1788): display checkbox in fieldset --- common/mockData/formatterMockData.ts | 43 +++++++++++++ ...chemaFieldSetWithCheckboxExpectedMock.json | 64 +++++++++++++++++++ ...chemaFieldSetWithCheckboxExpectedMock.json | 21 ++++++ src/v1/generateUISchema.ts | 24 +++++++ src/v1/validateJsonSchema.ts | 3 + test/JsonFormatter.test.tsx | 16 +++++ 6 files changed, 171 insertions(+) create mode 100644 common/mockData/jsonSchemaFieldSetWithCheckboxExpectedMock.json create mode 100644 common/mockData/uiSchemaFieldSetWithCheckboxExpectedMock.json diff --git a/common/mockData/formatterMockData.ts b/common/mockData/formatterMockData.ts index b340a08..a6e04a8 100644 --- a/common/mockData/formatterMockData.ts +++ b/common/mockData/formatterMockData.ts @@ -391,6 +391,49 @@ export const JSON_SCHEMA_FIELD_SETS_FAKE_DATA = '{\n' + ' }\n' + '}'; +export const JSON_SCHEMA_FIELD_SET_WITH_CHECKBOX = '{\n' + + '"schema": {\n' + + ' "title": "Arrest Report (arrest_rep)",\n' + + ' "type": "object",\n' + + ' "required": [\n' + + ' "arrestrep_reasonforarrest"\n' + + ' ],\n' + + ' "properties": {\n' + + ' "arrestrep_reasonforarrest": {\n' + + ' "key": "arrest_reasonforarrest"\n' + + ' }\n' + + ' }\n' + + '},\n' + + '"definition": [\n' + + ' {\n' + + ' "type": "fieldset",\n' + + ' "title": "Arrest Details",\n' + + ' "htmlClass": "col-lg-12",\n' + + ' "items": []\n' + + ' },\n' + + ' {\n' + + ' "key": "arrestrep_reasonforarrest",\n' + + ' "htmlClass": "json-schema-checkbox-wrapper",\n' + + ' "type": "checkboxes",\n' + + ' "title": "Reason for Arrest",\n' + + ' "titleMap": [\n' + + ' {\n' + + ' "name": "Rhino",\n' + + ' "value": "rhino_value"\n' + + ' },\n' + + ' {\n' + + ' "name": "Black Rhino",\n' + + ' "value": "blackrhino_value"\n' + + ' },\n' + + ' {\n' + + ' "name": "White Rhino",\n' + + ' "value": "whiterhino"\n' + + ' }\n' + + ' ]\n' + + ' }\n' + + ']\n' + +'}'; + export const FIELD_SET_HEADER_FAKE_DATA = { fieldset__title_fieldset_title: { type: 'string', diff --git a/common/mockData/jsonSchemaFieldSetWithCheckboxExpectedMock.json b/common/mockData/jsonSchemaFieldSetWithCheckboxExpectedMock.json new file mode 100644 index 0000000..37c099c --- /dev/null +++ b/common/mockData/jsonSchemaFieldSetWithCheckboxExpectedMock.json @@ -0,0 +1,64 @@ +{ + "schema": { + "title": "Arrest Report (arrest_rep)", + "type": "object", + "required": [ + "arrestrep_reasonforarrest" + ], + "properties": { + "arrestrep_reasonforarrest": { + "type": "array", + "uniqueItems": true, + "isHidden": false, + "title": "Reason for Arrest", + "items": { + "enum": [ + "rhino_value", + "blackrhino_value", + "whiterhino" + ], + "enumNames": [ + "Rhino", + "Black Rhino", + "White Rhino" + ] + } + }, + "fieldset__title_arrest_details": { + "type": "string", + "readOnly": true, + "isHidden": false, + "display": "header", + "title": "Arrest Details" + } + } + }, + "definition": [ + { + "type": "fieldset", + "title": "Arrest Details", + "htmlClass": "col-lg-12", + "items": [] + }, + { + "key": "arrestrep_reasonforarrest", + "htmlClass": "json-schema-checkbox-wrapper", + "type": "checkboxes", + "title": "Reason for Arrest", + "titleMap": [ + { + "name": "Rhino", + "value": "rhino_value" + }, + { + "name": "Black Rhino", + "value": "blackrhino_value" + }, + { + "name": "White Rhino", + "value": "whiterhino" + } + ] + } + ] +} \ No newline at end of file diff --git a/common/mockData/uiSchemaFieldSetWithCheckboxExpectedMock.json b/common/mockData/uiSchemaFieldSetWithCheckboxExpectedMock.json new file mode 100644 index 0000000..f1c4b5c --- /dev/null +++ b/common/mockData/uiSchemaFieldSetWithCheckboxExpectedMock.json @@ -0,0 +1,21 @@ +{ + "type": "Category", + "elements": [ + { + "type": "Control", + "scope": "#/properties/fieldset__title_arrest_details", + "label": "Arrest Details", + "options": { + "format": "form-label" + } + }, + { + "type": "Control", + "scope": "#/properties/arrestrep_reasonforarrest", + "label": "Reason for Arrest", + "options": { + "format": "multiselect" + } + } + ] +} \ No newline at end of file diff --git a/src/v1/generateUISchema.ts b/src/v1/generateUISchema.ts index 8bf8411..59c5702 100644 --- a/src/v1/generateUISchema.ts +++ b/src/v1/generateUISchema.ts @@ -49,6 +49,22 @@ const getDateTimeControlFormat = (key: string, jsonSchema: any, fieldSetItem: an return undefined; }; +const getCheckboxDefinition = (key: string, jsonSchema: any) => { + try { + const definitionObject = jsonSchema.definition.find((object: any) => (object.key === key)); + + if (definitionObject.fieldHtmlClass === 'json-schema-checkbox-wrapper' || definitionObject.type === 'checkboxes') { + return definitionObject; + } + + return undefined; + } catch { + return undefined; + } + + return undefined; +}; + export const generateUISchema = (schema: any) => { const elements: Object[] = []; @@ -134,6 +150,7 @@ const getElementOptions = (format: string = '', display: string = '') => { const getUIElement = (key: string, schema: any, fieldSetItem: any = undefined) => { let options = {}; + switch (schema.schema.properties[key].type as SchemaTypes) { case SchemaTypes.Number: return getBaseUIObject(key, schema.schema.properties[key].title || ''); @@ -159,6 +176,13 @@ const getUIElement = (key: string, schema: any, fieldSetItem: any = undefined) = return getBaseUIObject(key, schema.schema.properties[key].title || '', options); case undefined: { + const checkboxDefinition = getCheckboxDefinition(key, schema); + + if (checkboxDefinition) { + options = getElementOptions(PropertyFormat.MultiSelect); + return getBaseUIObject(key, checkboxDefinition.title || '', options); + } + const dateTimeFormat = getDateTimeControlFormat(key, schema, fieldSetItem); if (!isEmptyString(dateTimeFormat)) { options = getElementOptions(PropertyFormat.DateTime, dateTimeFormat); diff --git a/src/v1/validateJsonSchema.ts b/src/v1/validateJsonSchema.ts index f94dccc..6379298 100644 --- a/src/v1/validateJsonSchema.ts +++ b/src/v1/validateJsonSchema.ts @@ -182,6 +182,9 @@ const validateFieldSetDefinition = (validations: any, schema: any) => { validateDefinition(validations, subItem, schema, item); } break; + case isCheckbox(item): + validateDefinition(validations, item, schema); + break; default: break; } diff --git a/test/JsonFormatter.test.tsx b/test/JsonFormatter.test.tsx index abf6b77..8740548 100644 --- a/test/JsonFormatter.test.tsx +++ b/test/JsonFormatter.test.tsx @@ -10,6 +10,7 @@ import { JSON_SCHEMA_DUPLICATED_REQUIRED_PROPERTIES_FAKE_DATA, JSON_SCHEMA_EDGE_CASE_NUMBERS, JSON_SCHEMA_EMPTY_CHOICES_FAKE_DATA, + JSON_SCHEMA_FIELD_SET_WITH_CHECKBOX, JSON_SCHEMA_FIELD_SETS_FAKE_DATA, JSON_SCHEMA_ID_$SCHEMA_FAKE_DATA, JSON_SCHEMA_INACTIVE_CHOICES_FAKE_DATA, @@ -26,6 +27,8 @@ import jsonSchemaFieldSets from "../common/mockData/jsonSchemaFielSetMock.json"; import jsonSchema from "../common/mockData/jsonSchemaMock.json"; import expectedUISchema from "../common/mockData/uiSchemaExpectedMock.json"; import expectedFieldSetUISchema from "../common/mockData/uiSchemaFielSetExpectedMock.json"; +import expectedFieldSetWithCheckboxUISchema from "../common/mockData/uiSchemaFieldSetWithCheckboxExpectedMock.json"; +import expectedFieldSetWithCheckboxJSONSchema from "../common/mockData/jsonSchemaFieldSetWithCheckboxExpectedMock.json"; import { generateUISchema } from "../src/v1/generateUISchema"; import { validateJSONSchema } from "../src/v1/validateJsonSchema"; import { normalizeDecimalSeparators } from "../src/v1/utils/utils"; @@ -115,6 +118,12 @@ describe("JSON Schema validation", () => { ); }); + it("Formats checkbox inside a field set", () => { + const validSchema = validateJSONSchema(JSON_SCHEMA_FIELD_SET_WITH_CHECKBOX); + + expect(validSchema).toMatchObject(expectedFieldSetWithCheckboxJSONSchema); + }); + it("Format collection field headers", () => { const validSchema = validateJSONSchema(JSON_SCHEMA_COLLECTION_FIELD_FAKE_DATA); expect(validSchema.schema.properties["help_value_0"]).toMatchObject(COLLECTION_FIELD_HEADER_FAKE_DATA.help_value_0); @@ -269,4 +278,11 @@ describe("JSON UI Schema generation", () => { const uiSchema = generateUISchema(validSchema); expect(uiSchema).toMatchObject(expectedFieldSetUISchema); }); + + it('Generates UI Schema for field set with checkbox inside', () => { + const validSchema = validateJSONSchema(JSON_SCHEMA_FIELD_SET_WITH_CHECKBOX); + const uiSchema = generateUISchema(validSchema); + + expect(uiSchema).toMatchObject(expectedFieldSetWithCheckboxUISchema); + }); });