diff --git a/spiffworkflow-frontend/src/components/CustomForm.tsx b/spiffworkflow-frontend/src/components/CustomForm.tsx index def3faaa4..e4d7bd35a 100644 --- a/spiffworkflow-frontend/src/components/CustomForm.tsx +++ b/spiffworkflow-frontend/src/components/CustomForm.tsx @@ -152,8 +152,18 @@ export default function CustomForm({ formDataToCheck: any, propertyKey: string, errors: any, - jsonSchema: any + jsonSchema: any, + uiSchemaPassedIn?: any ) => { + // this validation only applies to checkboxes, + // other forms of booleans are validated differently + if ( + uiSchemaPassedIn && + 'ui:widget' in uiSchemaPassedIn && + uiSchemaPassedIn['ui:widget'] !== 'checkbox' + ) { + return; + } if ( jsonSchema.required && jsonSchema.required.includes(propertyKey) && @@ -169,7 +179,8 @@ export default function CustomForm({ const checkFieldsWithCustomValidations = ( jsonSchema: any, formDataToCheck: any, - errors: any + errors: any, + uiSchemaPassedIn?: any // eslint-disable-next-line sonarjs/cognitive-complexity ) => { // if the jsonSchema has an items attribute then assume the element itself @@ -177,9 +188,21 @@ export default function CustomForm({ const jsonSchemaToUse = 'items' in jsonSchema ? jsonSchema.items : jsonSchema; + let uiSchemaToUse = uiSchemaPassedIn; + if (!uiSchemaToUse) { + uiSchemaToUse = uiSchema; + } + if ('items' in uiSchemaToUse) { + uiSchemaToUse = uiSchemaToUse.items; + } + if ('properties' in jsonSchemaToUse) { Object.keys(jsonSchemaToUse.properties).forEach((propertyKey: string) => { const propertyMetadata = jsonSchemaToUse.properties[propertyKey]; + let currentUiSchema: any = null; + if (propertyKey in uiSchemaToUse) { + currentUiSchema = uiSchemaToUse[propertyKey]; + } if ('minimumDate' in propertyMetadata) { checkMinimumDate( formDataToCheck, @@ -195,7 +218,8 @@ export default function CustomForm({ formDataToCheck, propertyKey, errors, - jsonSchemaToUse + jsonSchemaToUse, + currentUiSchema ); } @@ -213,7 +237,8 @@ export default function CustomForm({ checkFieldsWithCustomValidations( propertyMetadata, item, - errorsToSend + errorsToSend, + currentUiSchema ); }); } diff --git a/spiffworkflow-frontend/src/rjsf/carbon_theme/CheckboxWidget/CheckboxWidget.tsx b/spiffworkflow-frontend/src/rjsf/carbon_theme/CheckboxWidget/CheckboxWidget.tsx index 25fca6043..005a9f3ae 100644 --- a/spiffworkflow-frontend/src/rjsf/carbon_theme/CheckboxWidget/CheckboxWidget.tsx +++ b/spiffworkflow-frontend/src/rjsf/carbon_theme/CheckboxWidget/CheckboxWidget.tsx @@ -57,7 +57,7 @@ function CheckboxWidget(props: WidgetProps) { title={commonAttributes.tooltipText} autoFocus={autofocus} invalid={commonAttributes.invalid} - invalidText={commonAttributes.errorMessageForField} + invalidText={commonAttributes.errorMessageForFieldWithoutLabel} helperText={commonAttributes.helperText} labelText={ required diff --git a/spiffworkflow-frontend/src/rjsf/carbon_theme/RadioWidget/RadioWidget.tsx b/spiffworkflow-frontend/src/rjsf/carbon_theme/RadioWidget/RadioWidget.tsx index 2f65bca97..fb773395b 100644 --- a/spiffworkflow-frontend/src/rjsf/carbon_theme/RadioWidget/RadioWidget.tsx +++ b/spiffworkflow-frontend/src/rjsf/carbon_theme/RadioWidget/RadioWidget.tsx @@ -1,11 +1,9 @@ -import React from "react"; -import FormControlLabel from "@mui/material/FormControlLabel"; -import FormLabel from "@mui/material/FormLabel"; -import Radio from "@mui/material/Radio"; -import RadioGroup from "@mui/material/RadioGroup"; -import { WidgetProps } from "@rjsf/utils"; +import React from 'react'; +import { RadioButtonGroup, RadioButton } from '@carbon/react'; +import { WidgetProps } from '@rjsf/utils'; +import { getCommonAttributes } from '../../helpers'; -const RadioWidget = ({ +function RadioWidget({ id, schema, options, @@ -17,11 +15,19 @@ const RadioWidget = ({ onChange, onBlur, onFocus, -}: WidgetProps) => { + uiSchema, + rawErrors, +}: WidgetProps) { const { enumOptions, enumDisabled } = options; - const _onChange = (_: any, value: any) => - onChange(schema.type == "boolean" ? value !== "false" : value); + const _onChange = (newValue: any, _radioButtonId: any) => { + if (schema.type === 'boolean') { + const v: any = newValue === 'true' || newValue === true; + onChange(v); + } else { + onChange(newValue); + } + }; const _onBlur = ({ target: { value } }: React.FocusEvent) => onBlur(id, value); const _onFocus = ({ @@ -30,43 +36,39 @@ const RadioWidget = ({ const row = options ? options.inline : false; - return ( - <> - - {Array.isArray(enumOptions) && - enumOptions.map((option) => { - const itemDisabled = - Array.isArray(enumDisabled) && - enumDisabled.indexOf(option.value) !== -1; - const radio = ( - - } - label={`${option.label}`} - value={`${option.value}`} - key={option.value} - disabled={disabled || itemDisabled || readonly} - /> - ); - - return radio; - })} - - + const commonAttributes = getCommonAttributes( + label, + schema, + uiSchema, + rawErrors ); -}; + + // pass values in as strings so we can support both boolean and string radio buttons + return ( + + {Array.isArray(enumOptions) && + enumOptions.map((option) => { + return ( + + ); + })} + + ); +} export default RadioWidget; diff --git a/spiffworkflow-frontend/src/rjsf/helpers.tsx b/spiffworkflow-frontend/src/rjsf/helpers.tsx index f4dbf4703..ae87f9d19 100644 --- a/spiffworkflow-frontend/src/rjsf/helpers.tsx +++ b/spiffworkflow-frontend/src/rjsf/helpers.tsx @@ -25,12 +25,17 @@ export const getCommonAttributes = ( } } + // some rjsf validations add in labels by default so avoid showing it twice + let errorMessageForFieldWithoutLabel = null; + let invalid = false; let errorMessageForField = null; if (rawErrors && rawErrors.length > 0) { invalid = true; + [errorMessageForFieldWithoutLabel] = rawErrors; if ('validationErrorMessage' in schema) { errorMessageForField = (schema as any).validationErrorMessage; + errorMessageForFieldWithoutLabel = errorMessageForField; } else { errorMessageForField = `${labelToUse.replace(/\*$/, '')} ${rawErrors[0]}`; } @@ -41,6 +46,7 @@ export const getCommonAttributes = ( label: labelToUse, invalid, errorMessageForField, + errorMessageForFieldWithoutLabel, labelWithRequiredIndicator, tooltipText, };