Skip to content

Commit

Permalink
Added oneOf enum case
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxouwell committed Feb 20, 2024
1 parent 95712f6 commit 938e125
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 32 deletions.
113 changes: 88 additions & 25 deletions packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
findUISchema,
JsonFormsRendererRegistryEntry,
JsonSchema,
JsonSchema4,
JsonSchema7,
moveDown,
moveUp,
Resolve,
Expand All @@ -33,6 +35,7 @@ import {
ArrayTranslations,
encode,
enumToEnumOptionMapper,
oneOfToEnumOptionMapper,
getI18nKeyPrefix,
} from '@jsonforms/core';
import {
Expand Down Expand Up @@ -299,35 +302,36 @@ export const withContextToExpandPanelProps = (
props,
}: JsonFormsStateContext & ExpandPanelProps) {
const dispatchProps = ctxDispatchToExpandPanelProps(ctx.dispatch);
const { childLabelProp, schema, rootSchema, path, index, uischemas } =
props;
const {
childLabelProp,
schema,
uischema,
rootSchema,
path,
index,
uischemas,
} = props;
const childPath = composePaths(path, `${index}`);
const childData = Resolve.data(ctx.core.data, childPath);

let childLabel;
if (childLabelProp) {
childLabel = get(childData, childLabelProp, '');

const childSchema = Resolve.schema(
const childLabel = useMemo(() => {
return computeChildLabel(
ctx.core.data,
childPath,
childLabelProp,
schema,
`#/properties/${encode(childLabelProp)}`,
rootSchema
rootSchema,
ctx.i18n.translate,
uischema
);
if (
childSchema &&
childSchema.type === 'string' &&
(childSchema.enum !== undefined || childSchema.const !== undefined)
) {
const enumChildLabel = enumToEnumOptionMapper(
childLabel,
ctx.i18n.translate,
getI18nKeyPrefix(props.schema, props.uischema, childPath)
);
childLabel = enumChildLabel.label;
}
} else {
childLabel = get(childData, getFirstPrimitiveProp(schema), '');
}
}, [
ctx.core.data,
childPath,
childLabelProp,
schema,
rootSchema,
ctx.i18n.translate,
uischema,
]);

return (
<Component
Expand All @@ -340,6 +344,65 @@ export const withContextToExpandPanelProps = (
);
};

function hasEnumField(schema: JsonSchema4 | JsonSchema7) {
return schema && (schema.enum !== undefined || schema.const !== undefined);
}

function hasOneOfField(schema: JsonSchema4 | JsonSchema7) {
return schema && schema.oneOf !== undefined;
}

function computeChildLabel(
data: any,
childPath: string,
childLabelProp: any,
schema: any,
rootSchema: any,
translateFct: any,
uiSchema: any
) {
const childData = Resolve.data(data, childPath);

if (childLabelProp) {
const currentValue = get(childData, childLabelProp, '');

const childSchema = Resolve.schema(
schema,
`#/properties/${encode(childLabelProp)}`,
rootSchema
);

if (hasEnumField(childSchema)) {
const enumChildLabel = enumToEnumOptionMapper(
currentValue,
translateFct,
getI18nKeyPrefix(schema, uiSchema, childPath)
);

return enumChildLabel.label;
} else if (hasOneOfField(childSchema)) {
const oneOfArray = childSchema.oneOf as (JsonSchema4 | JsonSchema7)[];
const oneOfSchema = oneOfArray.find(
(e: JsonSchema4 | JsonSchema7) => e.const === currentValue
);

if (oneOfSchema === undefined) return currentValue;

const oneOfChildLabel = oneOfToEnumOptionMapper(
oneOfSchema,
translateFct,
getI18nKeyPrefix(schema, uiSchema, childPath)
);

return oneOfChildLabel.label;
} else {
return currentValue;
}
} else {
return get(childData, getFirstPrimitiveProp(schema), '');
}
}

export const withJsonFormsExpandPanelProps = (
Component: ComponentType<ExpandPanelProps>
): ComponentType<OwnPropsOfExpandPanel> =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const data = [
},
];

const enumData = [
const enumOrOneOfData = [
{
message: 'El Barto was here',
messageType: 'MSG_TYPE_1',
Expand Down Expand Up @@ -94,6 +94,32 @@ const enumSchema: JsonSchema7 = {
},
};

const oneOfSchema = {
type: 'array',
items: {
type: 'object',
properties: {
message: {
type: 'string',
maxLength: 3,
},
messageType: {
type: 'string',
oneOf: [
{
const: 'MSG_TYPE_1',
title: 'First message type',
},
{
const: 'MSG_TYPE_2',
title: 'Second message type',
},
],
},
},
},
};

const nestedSchema: JsonSchema7 = {
type: 'array',
items: {
Expand Down Expand Up @@ -166,7 +192,7 @@ const uischemaWithChildLabelProp: ControlElement = {
},
};

const uischemaWithEnumChildLabelProp: ControlElement = {
const uiSchemaWithEnumOrOneOfChildLabelProp: ControlElement = {
type: 'Control',
scope: '#',
options: {
Expand Down Expand Up @@ -655,36 +681,84 @@ describe('Material array layout', () => {
});

it('should render configured enum child label property as translated label', () => {
const core = initCore(enumSchema, uischemaWithEnumChildLabelProp, enumData);
const core = initCore(
enumSchema,
uiSchemaWithEnumOrOneOfChildLabelProp,
enumOrOneOfData
);
const translate = () => 'Translated';

// Enum Case - No translation
wrapper = mount(
<JsonFormsStateProvider
initState={{ renderers: materialRenderers, core }}
>
<MaterialArrayLayout
schema={enumSchema}
uischema={uiSchemaWithEnumOrOneOfChildLabelProp}
/>
</JsonFormsStateProvider>
);

expect(wrapper.find(MaterialArrayLayout).length).toBeTruthy();

expect(getChildLabel(wrapper, 0)).toBe('MSG_TYPE_1');

// Enum Case - Translation
wrapper = mount(
<JsonFormsStateProvider
initState={{ renderers: materialRenderers, core, i18n: { translate } }}
>
<MaterialArrayLayout
schema={enumSchema}
uischema={uischemaWithEnumChildLabelProp}
uischema={uiSchemaWithEnumOrOneOfChildLabelProp}
/>
</JsonFormsStateProvider>
);

expect(wrapper.find(MaterialArrayLayout).length).toBeTruthy();

expect(getChildLabel(wrapper, 0)).toBe('Translated');
});

it('should render configured oneOf child label property as translated label', () => {
const core = initCore(
oneOfSchema,
uiSchemaWithEnumOrOneOfChildLabelProp,
enumOrOneOfData
);
const translate = () => 'Translated';

// OneOf - No translation
wrapper = mount(
<JsonFormsStateProvider
initState={{ renderers: materialRenderers, core }}
>
<MaterialArrayLayout
schema={enumSchema}
uischema={uischemaWithEnumChildLabelProp}
schema={oneOfSchema}
uischema={uiSchemaWithEnumOrOneOfChildLabelProp}
/>
</JsonFormsStateProvider>
);

expect(wrapper.find(MaterialArrayLayout).length).toBeTruthy();

expect(getChildLabel(wrapper, 0)).toBe('MSG_TYPE_1');
expect(getChildLabel(wrapper, 0)).toBe('First message type');

// OneOf Case - Translation
wrapper = mount(
<JsonFormsStateProvider
initState={{ renderers: materialRenderers, core, i18n: { translate } }}
>
<MaterialArrayLayout
schema={oneOfSchema}
uischema={uiSchemaWithEnumOrOneOfChildLabelProp}
/>
</JsonFormsStateProvider>
);

expect(wrapper.find(MaterialArrayLayout).length).toBeTruthy();

expect(getChildLabel(wrapper, 0)).toBe('Translated');
});
});

0 comments on commit 938e125

Please sign in to comment.