From 478cd97db47c834eee1c2a90542d2c8285c71f23 Mon Sep 17 00:00:00 2001 From: purnimagarg1 <139125209+purnimagarg1@users.noreply.github.com> Date: Thu, 18 Sep 2025 21:32:48 +0530 Subject: [PATCH] improvement(ui/summary-tab): handle deleted structured properties in properties header of asset summary (#14805) --- .../context/hooks/useTemplateOperations.ts | 5 +- .../homeV3/context/hooks/useTemplateState.ts | 10 +- .../homeV3/context/hooks/utils/utils.test.ts | 179 +++++++++++++++++- .../app/homeV3/context/hooks/utils/utils.ts | 6 + 4 files changed, 196 insertions(+), 4 deletions(-) diff --git a/datahub-web-react/src/app/homeV3/context/hooks/useTemplateOperations.ts b/datahub-web-react/src/app/homeV3/context/hooks/useTemplateOperations.ts index 87addd4b61..0a71de2c76 100644 --- a/datahub-web-react/src/app/homeV3/context/hooks/useTemplateOperations.ts +++ b/datahub-web-react/src/app/homeV3/context/hooks/useTemplateOperations.ts @@ -2,6 +2,7 @@ import { useCallback } from 'react'; import { useEntityContext } from '@app/entity/shared/EntityContext'; import { insertModuleIntoRows } from '@app/homeV3/context/hooks/utils/moduleOperationsUtils'; +import { filterNonExistentStructuredProperties } from '@app/homeV3/context/hooks/utils/utils'; import { DEFAULT_TEMPLATE_URN } from '@app/homeV3/modules/constants'; import { ModulePositionInput } from '@app/homeV3/template/types'; import useShowToast from '@app/homeV3/toast/useShowToast'; @@ -211,7 +212,9 @@ export function useTemplateOperations( templateToUpsert.properties.assetSummary?.summaryElements !== undefined ? { summaryElements: - templateToUpsert.properties.assetSummary?.summaryElements?.map((el) => ({ + filterNonExistentStructuredProperties( + templateToUpsert.properties.assetSummary?.summaryElements || [], + ).map((el) => ({ elementType: el.elementType, structuredPropertyUrn: el.structuredProperty?.urn, })) || [], diff --git a/datahub-web-react/src/app/homeV3/context/hooks/useTemplateState.ts b/datahub-web-react/src/app/homeV3/context/hooks/useTemplateState.ts index 8e29eb5b4b..73375e7f87 100644 --- a/datahub-web-react/src/app/homeV3/context/hooks/useTemplateState.ts +++ b/datahub-web-react/src/app/homeV3/context/hooks/useTemplateState.ts @@ -5,7 +5,10 @@ import { useUserContext } from '@app/context/useUserContext'; import { useEntityContext } from '@app/entity/shared/EntityContext'; import { mapSummaryElement } from '@app/entityV2/summary/properties/utils'; import { filterOutNonExistentModulesFromTemplate } from '@app/homeV3/context/hooks/utils/moduleOperationsUtils'; -import { getDefaultSummaryPageTemplate } from '@app/homeV3/context/hooks/utils/utils'; +import { + filterNonExistentStructuredProperties, + getDefaultSummaryPageTemplate, +} from '@app/homeV3/context/hooks/utils/utils'; import { DEFAULT_TEMPLATE } from '@app/homeV3/modules/constants'; import { useEntityRegistryV2 } from '@app/useEntityRegistry'; @@ -73,7 +76,10 @@ export function useTemplateState(templateType: PageTemplateSurfaceType) { }; const summaryElements = useMemo( - () => template?.properties.assetSummary?.summaryElements?.map((el) => mapSummaryElement(el, entityRegistry)), + () => + filterNonExistentStructuredProperties(template?.properties.assetSummary?.summaryElements || []).map((el) => + mapSummaryElement(el, entityRegistry), + ), [template, entityRegistry], ); diff --git a/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.test.ts b/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.test.ts index 0512ac6c42..72f51ddc7e 100644 --- a/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.test.ts +++ b/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.test.ts @@ -1,4 +1,7 @@ -import { getDefaultSummaryPageTemplate } from '@app/homeV3/context/hooks/utils/utils'; +import { + filterNonExistentStructuredProperties, + getDefaultSummaryPageTemplate, +} from '@app/homeV3/context/hooks/utils/utils'; import { ASSETS_MODULE, CHILD_HIERARCHY_MODULE, @@ -190,3 +193,177 @@ describe('getDefaultSummaryPageTemplate', () => { ); }); }); + +describe('filterNonExistentStructuredProperties', () => { + it('should return empty array for empty input', () => { + expect(filterNonExistentStructuredProperties([])).toEqual([]); + }); + + it('should keep all non-StructuredProperty elements', () => { + const input = [{ elementType: SummaryElementType.Created }, { elementType: SummaryElementType.Domain }]; + expect(filterNonExistentStructuredProperties(input)).toEqual(input); + }); + + it('should keep StructuredProperty elements with exists=true', () => { + const input = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:1', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + expect(filterNonExistentStructuredProperties(input)).toEqual(input); + }); + + it('should remove StructuredProperty elements with exists=false', () => { + const input = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:1', + exists: false, + type: EntityType.StructuredProperty, + }, + }, + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + const expected = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + expect(filterNonExistentStructuredProperties(input)).toEqual(expected); + }); + + it('should remove StructuredProperty if structuredProperty is missing', () => { + const input = [ + { elementType: SummaryElementType.StructuredProperty }, // no structuredProperty + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + const expected = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + expect(filterNonExistentStructuredProperties(input)).toEqual(expected); + }); + + it('should handle mixed elements keeping valid StructuredProperty and non-StructuredProperty', () => { + const input = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:1', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + { elementType: SummaryElementType.Created }, + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: false, + type: EntityType.StructuredProperty, + }, + }, + { elementType: SummaryElementType.Domain }, + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:3', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + const expected = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:1', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + { elementType: SummaryElementType.Created }, + { elementType: SummaryElementType.Domain }, + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:3', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + expect(filterNonExistentStructuredProperties(input)).toEqual(expected); + }); + + it('should remove StructuredProperty when structuredProperty.exists is undefined', () => { + const input = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:1', + exists: undefined as any, + type: EntityType.StructuredProperty, + }, + }, + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + const expected = [ + { + elementType: SummaryElementType.StructuredProperty, + structuredProperty: { + urn: 'urn:2', + exists: true, + type: EntityType.StructuredProperty, + }, + }, + ]; + expect(filterNonExistentStructuredProperties(input)).toEqual(expected); + }); +}); diff --git a/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.ts b/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.ts index 761217d73c..6843dd633c 100644 --- a/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.ts +++ b/datahub-web-react/src/app/homeV3/context/hooks/utils/utils.ts @@ -54,3 +54,9 @@ export function getDefaultSummaryPageTemplate(entityType: EntityType): PageTempl }, }; } + +export function filterNonExistentStructuredProperties(summaryElements) { + return summaryElements.filter((element) => + element.elementType === SummaryElementType.StructuredProperty ? element.structuredProperty?.exists : true, + ); +}