diff --git a/datahub-web-react/src/app/entity/shared/__tests__/siblingsUtils.test.ts b/datahub-web-react/src/app/entity/shared/__tests__/siblingsUtils.test.ts index 03ffb67ea8198d..06214352873179 100644 --- a/datahub-web-react/src/app/entity/shared/__tests__/siblingsUtils.test.ts +++ b/datahub-web-react/src/app/entity/shared/__tests__/siblingsUtils.test.ts @@ -1,5 +1,5 @@ import { dataset3WithLineage, dataset4WithLineage } from '../../../../Mocks'; -import { EntityType } from '../../../../types.generated'; +import { EntityType, SchemaFieldDataType } from '../../../../types.generated'; import { combineEntityDataWithSiblings, combineSiblingsInSearchResults, @@ -106,6 +106,26 @@ const datasetUnprimary = { }, ], }, + schemaMetadata: { + ...dataset4WithLineage.schemaMetadata, + fields: [ + { + __typename: 'SchemaField', + nullable: false, + recursive: false, + fieldPath: 'new_one', + description: 'Test to make sure fields merge works', + type: SchemaFieldDataType.String, + nativeDataType: 'varchar(100)', + isPartOfKey: false, + jsonPath: null, + globalTags: null, + glossaryTerms: null, + label: 'hi', + }, + ...(dataset4WithLineage.schemaMetadata?.fields || []), + ], + }, siblings: { isPrimary: false, }, @@ -471,6 +491,12 @@ describe('siblingUtils', () => { expect(combinedData.dataset.globalTags.tags[0].tag.urn).toEqual('urn:li:tag:unprimary-tag'); expect(combinedData.dataset.globalTags.tags[1].tag.urn).toEqual('urn:li:tag:primary-tag'); + // merges schema metadata properly by fieldPath + expect(combinedData.dataset.schemaMetadata?.fields).toHaveLength(3); + expect(combinedData.dataset.schemaMetadata?.fields[0].fieldPath).toEqual('new_one'); + expect(combinedData.dataset.schemaMetadata?.fields[1].fieldPath).toEqual('user_id'); + expect(combinedData.dataset.schemaMetadata?.fields[2].fieldPath).toEqual('user_name'); + // will overwrite string properties w/ primary expect(combinedData.dataset.editableProperties.description).toEqual('secondary description'); diff --git a/datahub-web-react/src/app/entity/shared/siblingUtils.ts b/datahub-web-react/src/app/entity/shared/siblingUtils.ts index c4ea7c4c9942ab..e13fe8ee85441b 100644 --- a/datahub-web-react/src/app/entity/shared/siblingUtils.ts +++ b/datahub-web-react/src/app/entity/shared/siblingUtils.ts @@ -1,5 +1,5 @@ import merge from 'deepmerge'; -import { unionBy } from 'lodash'; +import { unionBy, keyBy, values } from 'lodash'; import { useLocation } from 'react-router-dom'; import * as QueryString from 'query-string'; import { Entity, MatchedField, Maybe, SiblingProperties } from '../../../types.generated'; @@ -51,6 +51,11 @@ const combineMerge = (target, source, options) => { return destination; }; +// use when you want to merge and array of objects by key in the object as opposed to by index of array +const mergeArrayOfObjectsByKey = (destinationArray: any[], sourceArray: any[], key: string) => { + return values(merge(keyBy(destinationArray, key), keyBy(sourceArray, key))); +}; + const mergeTags = (destinationArray, sourceArray, _options) => { return unionBy(destinationArray, sourceArray, 'tag.urn'); }; @@ -71,6 +76,10 @@ const mergeOwners = (destinationArray, sourceArray, _options) => { return unionBy(destinationArray, sourceArray, 'owner.urn'); }; +const mergeFields = (destinationArray, sourceArray, _options) => { + return mergeArrayOfObjectsByKey(destinationArray, sourceArray, 'fieldPath'); +}; + function getArrayMergeFunction(key) { switch (key) { case 'tags': @@ -83,6 +92,8 @@ function getArrayMergeFunction(key) { return mergeProperties; case 'owners': return mergeOwners; + case 'fields': + return mergeFields; default: return undefined; } @@ -96,7 +107,14 @@ const customMerge = (isPrimary, key) => { if (key === 'platform' || key === 'siblings') { return (secondary, primary) => (isPrimary ? primary : secondary); } - if (key === 'tags' || key === 'terms' || key === 'assertions' || key === 'customProperties' || key === 'owners') { + if ( + key === 'tags' || + key === 'terms' || + key === 'assertions' || + key === 'customProperties' || + key === 'owners' || + key === 'fields' + ) { return (secondary, primary) => { return merge(secondary, primary, { arrayMerge: getArrayMergeFunction(key),