Skip to content

Commit

Permalink
Allow the translation of enum value used for elementLabelProp in Expa…
Browse files Browse the repository at this point in the history
…ndPanelRenderer
  • Loading branch information
Maxouwell committed Feb 20, 2024
1 parent 1d73eb7 commit 42ef5c1
Show file tree
Hide file tree
Showing 2 changed files with 245 additions and 5 deletions.
99 changes: 94 additions & 5 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 @@ -31,6 +33,10 @@ import {
createId,
removeId,
ArrayTranslations,
encode,
enumToEnumOptionMapper,
oneOfToEnumOptionMapper,
getI18nKeyPrefix,
} from '@jsonforms/core';
import {
Accordion,
Expand Down Expand Up @@ -296,12 +302,36 @@ export const withContextToExpandPanelProps = (
props,
}: JsonFormsStateContext & ExpandPanelProps) {
const dispatchProps = ctxDispatchToExpandPanelProps(ctx.dispatch);
const { childLabelProp, schema, 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);
const childLabel = childLabelProp
? get(childData, childLabelProp, '')
: get(childData, getFirstPrimitiveProp(schema), '');

const childLabel = useMemo(() => {
return computeChildLabel(
ctx.core.data,
childPath,
childLabelProp,
schema,
rootSchema,
ctx.i18n.translate,
uischema
);
}, [
ctx.core.data,
childPath,
childLabelProp,
schema,
rootSchema,
ctx.i18n.translate,
uischema,
]);

return (
<Component
Expand All @@ -314,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 @@ -52,6 +52,17 @@ const data = [
];

const emptyData: any[] = [];

const enumOrOneOfData = [
{
message: 'El Barto was here',
messageType: 'MSG_TYPE_1',
},
{
message: 'Yolo',
},
];

const schema: JsonSchema7 = {
type: 'array',
items: {
Expand All @@ -68,6 +79,49 @@ const schema: JsonSchema7 = {
},
};

const enumSchema: JsonSchema7 = {
type: 'array',
items: {
type: 'object',
properties: {
message: {
type: 'string',
maxLength: 3,
},
messageType: {
type: 'string',
enum: ['MSG_TYPE_1', 'MSG_TYPE_2'],
},
},
},
};

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 @@ -140,6 +194,21 @@ const uischemaWithChildLabelProp: ControlElement = {
},
};

const uiSchemaWithEnumOrOneOfChildLabelProp: ControlElement = {
type: 'Control',
scope: '#',
options: {
elementLabelProp: 'messageType',
detail: {
type: 'HorizontalLayout',
elements: [
{ type: 'Control', scope: '#/properties/message' },
{ type: 'Control', scope: '#/properties/messageType' },
],
},
},
};

const uischemaOptions: {
generate: ControlElement;
default: ControlElement;
Expand Down Expand Up @@ -629,4 +698,86 @@ describe('Material array layout', () => {
const noDataLabel = wrapper.find('div>div>p').text();
expect(noDataLabel.includes('Translated')).toBeTruthy();
});

it('should render configured enum child label property as translated label', () => {
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={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={oneOfSchema}
uischema={uiSchemaWithEnumOrOneOfChildLabelProp}
/>
</JsonFormsStateProvider>
);

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

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 42ef5c1

Please sign in to comment.