diff --git a/datahub-web-react/src/Mocks.tsx b/datahub-web-react/src/Mocks.tsx index 160174a04a..f606356e10 100644 --- a/datahub-web-react/src/Mocks.tsx +++ b/datahub-web-react/src/Mocks.tsx @@ -4352,3 +4352,25 @@ export const mockFineGrainedLineages1: GenericEntityProperties = { }, ], }; + +export const useEntityDataFunc = () => { + const value = { + entityData: { + parentContainers: { + containers: [ + { + properties: { + name: 'name1', + }, + }, + { + properties: { + name: 'name2', + }, + }, + ], + }, + }, + }; + return value; +}; diff --git a/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.empty.test.tsx b/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.empty.test.tsx new file mode 100644 index 0000000000..1121bbc6da --- /dev/null +++ b/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.empty.test.tsx @@ -0,0 +1,27 @@ +import { render } from '@testing-library/react'; +import React from 'react'; + +import LineageEntityView from '@app/lineage/manage/LineageEntityView'; +import { dataset1 } from '@src/Mocks'; +import { getTestEntityRegistry } from '@utils/test-utils/TestPageContainer'; + +const mockEntityRegistry = getTestEntityRegistry(); +vi.mock('../../useEntityRegistry', () => ({ + useEntityRegistry: () => mockEntityRegistry, +})); +vi.mock('@app/entity/shared/EntityContext', () => ({ + useEntityData: () => { + return {}; + }, +})); +describe('LineageEntityViewEmpty', () => { + it('should render an entity properly in LineageEntityView if no containers', () => { + const { getByTestId, getByText } = render(); + // expect platform logo, platform name, divider, entity type, and display name + expect(getByTestId('platform-logo')).toBeInTheDocument(); + expect(getByText(dataset1.platform.name)).toBeInTheDocument(); + expect(getByTestId('divider')).toBeInTheDocument(); + expect(getByText('Dataset')).toBeInTheDocument(); + expect(getByText(dataset1.properties.name)).toBeInTheDocument(); + }); +}); diff --git a/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.test.tsx b/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.test.tsx index 51e1ef121d..0d9d5c4dc4 100644 --- a/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.test.tsx +++ b/datahub-web-react/src/app/lineage/__tests__/LineageEntityView.test.tsx @@ -2,7 +2,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import LineageEntityView from '@app/lineage/manage/LineageEntityView'; -import { dataset1 } from '@src/Mocks'; +import { dataset1, useEntityDataFunc } from '@src/Mocks'; import { getTestEntityRegistry } from '@utils/test-utils/TestPageContainer'; const mockEntityRegistry = getTestEntityRegistry(); @@ -10,10 +10,15 @@ vi.mock('../../useEntityRegistry', () => ({ useEntityRegistry: () => mockEntityRegistry, })); +vi.mock('@app/entity/shared/EntityContext', () => ({ + useEntityData: () => { + return useEntityDataFunc(); + }, +})); + describe('LineageEntityView', () => { it('should render an entity properly in LineageEntityView', () => { const { getByTestId, getByText } = render(); - // expect platform logo, platform name, divider, entity type, and display name expect(getByTestId('platform-logo')).toBeInTheDocument(); expect(getByText(dataset1.platform.name)).toBeInTheDocument(); @@ -25,18 +30,26 @@ describe('LineageEntityView', () => { it('should render the subtype name if it exists and not the type name', () => { const datasetWithSubtype = { ...dataset1, subTypes: { typeNames: ['view'] } }; const { getByText, queryByText } = render(); - expect(queryByText('Dataset')).not.toBeInTheDocument(); expect(getByText('View')).toBeInTheDocument(); }); it('should not render a divider if there is no platform name', () => { + vi.mock('@app/entity/shared/EntityContext', () => ({ + useEntityData: () => { + return useEntityDataFunc(); + }, + })); + const datasetNoPlatformName = { ...dataset1, platform: { ...dataset1.platform, name: '', properties: { displayName: '' } }, }; const { queryByTestId } = render(); - expect(queryByTestId('divider')).not.toBeInTheDocument(); }); + + afterAll(() => { + vi.resetAllMocks(); + }); }); diff --git a/datahub-web-react/src/app/lineage/manage/ContainerView.tsx b/datahub-web-react/src/app/lineage/manage/ContainerView.tsx new file mode 100644 index 0000000000..046de602ee --- /dev/null +++ b/datahub-web-react/src/app/lineage/manage/ContainerView.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +import { StyledRightOutlined } from '@app/entity/shared/containers/profile/header/PlatformContent/ParentNodesView'; + +import { Container } from '@types'; + +export interface ContainerViewProps { + directContainer: Container | undefined | null; + remainingContainers: Container[] | undefined | null; +} + +export function ContainerView({ directContainer, remainingContainers }: ContainerViewProps) { + return ( + <> + {remainingContainers && + remainingContainers.map((c) => ( + <> + + {c?.properties?.name} + + ))} + {directContainer && ( + <> + + {directContainer?.properties?.name} + + )} + + ); +} diff --git a/datahub-web-react/src/app/lineage/manage/EntityEdge.tsx b/datahub-web-react/src/app/lineage/manage/EntityEdge.tsx index 609ccb7a29..41afef5ede 100644 --- a/datahub-web-react/src/app/lineage/manage/EntityEdge.tsx +++ b/datahub-web-react/src/app/lineage/manage/EntityEdge.tsx @@ -3,14 +3,36 @@ import Text from 'antd/lib/typography/Text'; import React from 'react'; import styled from 'styled-components/macro'; +import { useEntityData } from '@app/entity/shared/EntityContext'; import { ANTD_GRAY, DEFAULT_SYSTEM_ACTOR_URNS } from '@app/entity/shared/constants'; +import { getPlatformName } from '@app/entity/shared/utils'; +import { ContainerView } from '@app/lineage/manage/ContainerView'; import UserAvatar from '@app/lineage/manage/UserAvatar'; import { useEntityRegistry } from '@app/useEntityRegistry'; import { CorpUser, Entity } from '@types'; -const EntityItem = styled.div` +const PlatformContent = styled.div<{ removeMargin?: boolean }>` + display: flex; + align-items: center; + font-size: 10px; + margin-left: 5px; + color: ${ANTD_GRAY[7]}; +`; + +const PlatformName = styled.span` + margin-left: 0px; +`; + +const EntityItemOuter = styled.div` border-bottom: 1px solid ${ANTD_GRAY[4]}; + display: block; + align-items: center; + padding: 12px 0; + justify-content: space-between; +`; + +const EntityItem = styled.div` display: flex; align-items: center; padding: 12px 0; @@ -45,23 +67,33 @@ interface Props { export default function EntityEdge({ entity, removeEntity, createdActor, createdOn }: Props) { const entityRegistry = useEntityRegistry(); + const { entityData } = useEntityData(); const genericProps = entityRegistry.getGenericEntityProperties(entity.type, entity); const platformLogoUrl = genericProps?.platform?.properties?.logoUrl; const shouldDisplayAvatar = createdActor && !DEFAULT_SYSTEM_ACTOR_URNS.includes(createdActor.urn) && createdActor.properties !== null; - + const containers = entityData?.parentContainers?.containers; + const remainingContainers = containers?.slice(1); + const directContainer = containers ? containers[0] : null; + const platformName = getPlatformName(genericProps); return ( - - - {platformLogoUrl && }{' '} - - {entityRegistry.getDisplayName(entity.type, entity)} - - - - {shouldDisplayAvatar && } - removeEntity(entity)} /> - - + + + {platformName} + + + + + {platformLogoUrl && }{' '} + + {entityRegistry.getDisplayName(entity.type, entity)} + + + + {shouldDisplayAvatar && } + removeEntity(entity)} /> + + + ); } diff --git a/datahub-web-react/src/app/lineage/manage/LineageEntityView.tsx b/datahub-web-react/src/app/lineage/manage/LineageEntityView.tsx index 99fbd7310d..b84f37c438 100644 --- a/datahub-web-react/src/app/lineage/manage/LineageEntityView.tsx +++ b/datahub-web-react/src/app/lineage/manage/LineageEntityView.tsx @@ -2,8 +2,10 @@ import { Divider } from 'antd'; import React from 'react'; import styled from 'styled-components/macro'; +import { useEntityData } from '@app/entity/shared/EntityContext'; import { ANTD_GRAY } from '@app/entity/shared/constants'; import { getPlatformName } from '@app/entity/shared/utils'; +import { ContainerView } from '@app/lineage/manage/ContainerView'; import { capitalizeFirstLetterOnly } from '@app/shared/textUtil'; import { useEntityRegistry } from '@app/useEntityRegistry'; @@ -44,22 +46,27 @@ interface Props { export default function LineageEntityView({ entity, displaySearchResult }: Props) { const entityRegistry = useEntityRegistry(); const genericProps = entityRegistry.getGenericEntityProperties(entity.type, entity); + const { entityData } = useEntityData(); const platformLogoUrl = genericProps?.platform?.properties?.logoUrl; const platformName = getPlatformName(genericProps); + const containers = entityData?.parentContainers?.containers; + const remainingContainers = containers?.slice(1); + const directContainer = containers ? containers[0] : null; return ( - {platformLogoUrl && ( - - )} - {platformName} - {platformName && } {capitalizeFirstLetterOnly(genericProps?.subTypes?.typeNames?.[0]) || entityRegistry.getEntityName(entity.type)} + {platformName && } + {platformLogoUrl && ( + + )} + {platformName} + {entityRegistry.getDisplayName(entity.type, entity)}