From 804d88fab7bdacc6af494a223c56e5660c199d06 Mon Sep 17 00:00:00 2001 From: Ricardo M Date: Wed, 28 Feb 2024 11:20:57 +0100 Subject: [PATCH] fix(CanvasForm): Avoid adding `{}` to the Source code Currently, the uniforms library, initializes object fields with empty objects when there's a required property inside them. This is prevented by checking the value of the incoming change in the CanvasForm component, and while this works, it collides with the Kamelet's custom form, since the user might want to remove all annotations, leaving the form with an intended empty object. The fix for this issue is to remove said check and place it in the `setValue` function instead. The mechanism now is to check whether the value to assign is an empty object, in which case it's replaced with an `undefined` value instead. This prevents for this value to be serialized into the Source code. fix: https://github.com/KaotoIO/kaoto-next/issues/878 --- .../Visualization/Canvas/CanvasForm.tsx | 3 +-- packages/ui/src/utils/set-value.test.ts | 18 ++++++++++++++++++ packages/ui/src/utils/set-value.ts | 5 +++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/components/Visualization/Canvas/CanvasForm.tsx b/packages/ui/src/components/Visualization/Canvas/CanvasForm.tsx index 28e819c8f..aea7554a1 100644 --- a/packages/ui/src/components/Visualization/Canvas/CanvasForm.tsx +++ b/packages/ui/src/components/Visualization/Canvas/CanvasForm.tsx @@ -1,5 +1,4 @@ import { Card, CardBody, CardHeader } from '@patternfly/react-core'; -import isEmpty from 'lodash.isempty'; import { FunctionComponent, useCallback, useContext, useEffect, useMemo, useRef } from 'react'; import { EntitiesContext } from '../../../providers/entities.provider'; import { setValue } from '../../../utils'; @@ -44,7 +43,7 @@ export const CanvasForm: FunctionComponent = (props) => { const handleOnChangeIndividualProp = useCallback( (path: string, value: unknown) => { - if (!props.selectedNode.data?.vizNode || (typeof value === 'object' && isEmpty(value))) { + if (!props.selectedNode.data?.vizNode) { return; } diff --git a/packages/ui/src/utils/set-value.test.ts b/packages/ui/src/utils/set-value.test.ts index 0451d2b6a..600d1638b 100644 --- a/packages/ui/src/utils/set-value.test.ts +++ b/packages/ui/src/utils/set-value.test.ts @@ -2,6 +2,24 @@ import { ROOT_PATH } from './get-value'; import { setValue } from './set-value'; describe('setValue', () => { + it('replace empty objects `{}` with `undefined`', () => { + const obj = { a: {} }; + setValue(obj, 'a', {}); + expect(obj).toEqual({ a: undefined }); + }); + + it('should ignore empty objects `{}` when setting it at root path', () => { + const obj = {}; + setValue(obj, ROOT_PATH, {}); + expect(obj).toEqual({}); + }); + + it('should ignore empty objects `undefined` when setting it at root path', () => { + const obj = {}; + setValue(obj, ROOT_PATH, undefined); + expect(obj).toEqual({}); + }); + it('should set the value at the given path', () => { const obj = { a: { b: { c: 1 } } }; setValue(obj, 'a.b.c', 2); diff --git a/packages/ui/src/utils/set-value.ts b/packages/ui/src/utils/set-value.ts index 72ebf9120..06b54ac0f 100644 --- a/packages/ui/src/utils/set-value.ts +++ b/packages/ui/src/utils/set-value.ts @@ -1,8 +1,13 @@ import set from 'lodash.set'; import { ROOT_PATH } from './get-value'; +import isEmpty from 'lodash.isempty'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const setValue = (obj: any, path: string | string[], value: any): void => { + if (typeof value === 'object' && isEmpty(value)) { + value = undefined; + } + if (path === ROOT_PATH) { Object.assign(obj, value); return;