mirror of
https://github.com/datahub-project/datahub.git
synced 2025-09-26 09:35:23 +00:00
Issue-13594: Show database and schema. (#13856)
Co-authored-by: Maciek Rakowski <maciekrakowski@Macieks-MacBook-Pro.local> Co-authored-by: Andrew Sikowitz <andrew.sikowitz@acryl.io>
This commit is contained in:
parent
f04244fd69
commit
0242777c4b
@ -4352,3 +4352,25 @@ export const mockFineGrainedLineages1: GenericEntityProperties = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useEntityDataFunc = () => {
|
||||||
|
const value = {
|
||||||
|
entityData: {
|
||||||
|
parentContainers: {
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
name: 'name1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
name: 'name2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
@ -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(<LineageEntityView entity={dataset1} />);
|
||||||
|
// 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();
|
||||||
|
});
|
||||||
|
});
|
@ -2,7 +2,7 @@ import { render } from '@testing-library/react';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import LineageEntityView from '@app/lineage/manage/LineageEntityView';
|
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';
|
import { getTestEntityRegistry } from '@utils/test-utils/TestPageContainer';
|
||||||
|
|
||||||
const mockEntityRegistry = getTestEntityRegistry();
|
const mockEntityRegistry = getTestEntityRegistry();
|
||||||
@ -10,10 +10,15 @@ vi.mock('../../useEntityRegistry', () => ({
|
|||||||
useEntityRegistry: () => mockEntityRegistry,
|
useEntityRegistry: () => mockEntityRegistry,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock('@app/entity/shared/EntityContext', () => ({
|
||||||
|
useEntityData: () => {
|
||||||
|
return useEntityDataFunc();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe('LineageEntityView', () => {
|
describe('LineageEntityView', () => {
|
||||||
it('should render an entity properly in LineageEntityView', () => {
|
it('should render an entity properly in LineageEntityView', () => {
|
||||||
const { getByTestId, getByText } = render(<LineageEntityView entity={dataset1} />);
|
const { getByTestId, getByText } = render(<LineageEntityView entity={dataset1} />);
|
||||||
|
|
||||||
// expect platform logo, platform name, divider, entity type, and display name
|
// expect platform logo, platform name, divider, entity type, and display name
|
||||||
expect(getByTestId('platform-logo')).toBeInTheDocument();
|
expect(getByTestId('platform-logo')).toBeInTheDocument();
|
||||||
expect(getByText(dataset1.platform.name)).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', () => {
|
it('should render the subtype name if it exists and not the type name', () => {
|
||||||
const datasetWithSubtype = { ...dataset1, subTypes: { typeNames: ['view'] } };
|
const datasetWithSubtype = { ...dataset1, subTypes: { typeNames: ['view'] } };
|
||||||
const { getByText, queryByText } = render(<LineageEntityView entity={datasetWithSubtype} />);
|
const { getByText, queryByText } = render(<LineageEntityView entity={datasetWithSubtype} />);
|
||||||
|
|
||||||
expect(queryByText('Dataset')).not.toBeInTheDocument();
|
expect(queryByText('Dataset')).not.toBeInTheDocument();
|
||||||
expect(getByText('View')).toBeInTheDocument();
|
expect(getByText('View')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render a divider if there is no platform name', () => {
|
it('should not render a divider if there is no platform name', () => {
|
||||||
|
vi.mock('@app/entity/shared/EntityContext', () => ({
|
||||||
|
useEntityData: () => {
|
||||||
|
return useEntityDataFunc();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const datasetNoPlatformName = {
|
const datasetNoPlatformName = {
|
||||||
...dataset1,
|
...dataset1,
|
||||||
platform: { ...dataset1.platform, name: '', properties: { displayName: '' } },
|
platform: { ...dataset1.platform, name: '', properties: { displayName: '' } },
|
||||||
};
|
};
|
||||||
const { queryByTestId } = render(<LineageEntityView entity={datasetNoPlatformName} />);
|
const { queryByTestId } = render(<LineageEntityView entity={datasetNoPlatformName} />);
|
||||||
|
|
||||||
expect(queryByTestId('divider')).not.toBeInTheDocument();
|
expect(queryByTestId('divider')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
vi.resetAllMocks();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
30
datahub-web-react/src/app/lineage/manage/ContainerView.tsx
Normal file
30
datahub-web-react/src/app/lineage/manage/ContainerView.tsx
Normal file
@ -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) => (
|
||||||
|
<>
|
||||||
|
<StyledRightOutlined data-testid="right-arrow" />
|
||||||
|
<span>{c?.properties?.name}</span>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
{directContainer && (
|
||||||
|
<>
|
||||||
|
<StyledRightOutlined data-testid="right-arrow" />
|
||||||
|
<span>{directContainer?.properties?.name}</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -3,14 +3,36 @@ import Text from 'antd/lib/typography/Text';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components/macro';
|
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 { 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 UserAvatar from '@app/lineage/manage/UserAvatar';
|
||||||
import { useEntityRegistry } from '@app/useEntityRegistry';
|
import { useEntityRegistry } from '@app/useEntityRegistry';
|
||||||
|
|
||||||
import { CorpUser, Entity } from '@types';
|
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]};
|
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;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
@ -45,23 +67,33 @@ interface Props {
|
|||||||
|
|
||||||
export default function EntityEdge({ entity, removeEntity, createdActor, createdOn }: Props) {
|
export default function EntityEdge({ entity, removeEntity, createdActor, createdOn }: Props) {
|
||||||
const entityRegistry = useEntityRegistry();
|
const entityRegistry = useEntityRegistry();
|
||||||
|
const { entityData } = useEntityData();
|
||||||
const genericProps = entityRegistry.getGenericEntityProperties(entity.type, entity);
|
const genericProps = entityRegistry.getGenericEntityProperties(entity.type, entity);
|
||||||
const platformLogoUrl = genericProps?.platform?.properties?.logoUrl;
|
const platformLogoUrl = genericProps?.platform?.properties?.logoUrl;
|
||||||
const shouldDisplayAvatar =
|
const shouldDisplayAvatar =
|
||||||
createdActor && !DEFAULT_SYSTEM_ACTOR_URNS.includes(createdActor.urn) && createdActor.properties !== null;
|
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 (
|
return (
|
||||||
<EntityItem data-testid="lineage-entity-item">
|
<EntityItemOuter>
|
||||||
<NameAndLogoWrapper>
|
<PlatformContent>
|
||||||
{platformLogoUrl && <PlatformLogo src={platformLogoUrl} alt="platform logo" />}{' '}
|
<PlatformName>{platformName}</PlatformName>
|
||||||
<EntityName ellipsis={{ tooltip: entityRegistry.getDisplayName(entity.type, entity) }}>
|
<ContainerView remainingContainers={remainingContainers} directContainer={directContainer} />
|
||||||
{entityRegistry.getDisplayName(entity.type, entity)}
|
</PlatformContent>
|
||||||
</EntityName>
|
<EntityItem data-testid="lineage-entity-item">
|
||||||
</NameAndLogoWrapper>
|
<NameAndLogoWrapper>
|
||||||
<span>
|
{platformLogoUrl && <PlatformLogo src={platformLogoUrl} alt="platform logo" />}{' '}
|
||||||
{shouldDisplayAvatar && <UserAvatar createdActor={createdActor} createdOn={createdOn} />}
|
<EntityName ellipsis={{ tooltip: entityRegistry.getDisplayName(entity.type, entity) }}>
|
||||||
<StyledClose onClick={() => removeEntity(entity)} />
|
{entityRegistry.getDisplayName(entity.type, entity)}
|
||||||
</span>
|
</EntityName>
|
||||||
</EntityItem>
|
</NameAndLogoWrapper>
|
||||||
|
<span>
|
||||||
|
{shouldDisplayAvatar && <UserAvatar createdActor={createdActor} createdOn={createdOn} />}
|
||||||
|
<StyledClose onClick={() => removeEntity(entity)} />
|
||||||
|
</span>
|
||||||
|
</EntityItem>
|
||||||
|
</EntityItemOuter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ import { Divider } from 'antd';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components/macro';
|
import styled from 'styled-components/macro';
|
||||||
|
|
||||||
|
import { useEntityData } from '@app/entity/shared/EntityContext';
|
||||||
import { ANTD_GRAY } from '@app/entity/shared/constants';
|
import { ANTD_GRAY } from '@app/entity/shared/constants';
|
||||||
import { getPlatformName } from '@app/entity/shared/utils';
|
import { getPlatformName } from '@app/entity/shared/utils';
|
||||||
|
import { ContainerView } from '@app/lineage/manage/ContainerView';
|
||||||
import { capitalizeFirstLetterOnly } from '@app/shared/textUtil';
|
import { capitalizeFirstLetterOnly } from '@app/shared/textUtil';
|
||||||
import { useEntityRegistry } from '@app/useEntityRegistry';
|
import { useEntityRegistry } from '@app/useEntityRegistry';
|
||||||
|
|
||||||
@ -44,22 +46,27 @@ interface Props {
|
|||||||
export default function LineageEntityView({ entity, displaySearchResult }: Props) {
|
export default function LineageEntityView({ entity, displaySearchResult }: Props) {
|
||||||
const entityRegistry = useEntityRegistry();
|
const entityRegistry = useEntityRegistry();
|
||||||
const genericProps = entityRegistry.getGenericEntityProperties(entity.type, entity);
|
const genericProps = entityRegistry.getGenericEntityProperties(entity.type, entity);
|
||||||
|
const { entityData } = useEntityData();
|
||||||
|
|
||||||
const platformLogoUrl = genericProps?.platform?.properties?.logoUrl;
|
const platformLogoUrl = genericProps?.platform?.properties?.logoUrl;
|
||||||
const platformName = getPlatformName(genericProps);
|
const platformName = getPlatformName(genericProps);
|
||||||
|
const containers = entityData?.parentContainers?.containers;
|
||||||
|
const remainingContainers = containers?.slice(1);
|
||||||
|
const directContainer = containers ? containers[0] : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EntityWrapper shrinkPadding={displaySearchResult}>
|
<EntityWrapper shrinkPadding={displaySearchResult}>
|
||||||
<PlatformContent removeMargin={displaySearchResult}>
|
<PlatformContent removeMargin={displaySearchResult}>
|
||||||
{platformLogoUrl && (
|
|
||||||
<PlatformLogo src={platformLogoUrl} alt="platform logo" data-testid="platform-logo" />
|
|
||||||
)}
|
|
||||||
<span>{platformName}</span>
|
|
||||||
{platformName && <StyledDivider type="vertical" data-testid="divider" />}
|
|
||||||
<span>
|
<span>
|
||||||
{capitalizeFirstLetterOnly(genericProps?.subTypes?.typeNames?.[0]) ||
|
{capitalizeFirstLetterOnly(genericProps?.subTypes?.typeNames?.[0]) ||
|
||||||
entityRegistry.getEntityName(entity.type)}
|
entityRegistry.getEntityName(entity.type)}
|
||||||
</span>
|
</span>
|
||||||
|
{platformName && <StyledDivider type="vertical" data-testid="divider" />}
|
||||||
|
{platformLogoUrl && (
|
||||||
|
<PlatformLogo src={platformLogoUrl} alt="platform logo" data-testid="platform-logo" />
|
||||||
|
)}
|
||||||
|
<span>{platformName}</span>
|
||||||
|
<ContainerView remainingContainers={remainingContainers} directContainer={directContainer} />
|
||||||
</PlatformContent>
|
</PlatformContent>
|
||||||
<EntityName shrinkSize={displaySearchResult}>
|
<EntityName shrinkSize={displaySearchResult}>
|
||||||
{entityRegistry.getDisplayName(entity.type, entity)}
|
{entityRegistry.getDisplayName(entity.type, entity)}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user