mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-26 17:34:41 +00:00
fix(ui): parent container is not populating in breadcrumb (#12294)
* fix(ui): parent container is not populating in breadcrumb * fixed cypress for tagsAddRemove spec * updated parent hierarchy in breadcrumb for container * move fetch logic from container page to data header component * addressing comments * removed unwanted prop and added unit test for the change
This commit is contained in:
parent
b89cf64f14
commit
9bb4b18628
@ -19,13 +19,12 @@ import {
|
|||||||
import { TAGS_ADD_REMOVE_ENTITIES } from '../../constants/tagsAddRemove.constants';
|
import { TAGS_ADD_REMOVE_ENTITIES } from '../../constants/tagsAddRemove.constants';
|
||||||
|
|
||||||
const addTags = (tag) => {
|
const addTags = (tag) => {
|
||||||
cy.get('[data-testid="tag-selector"]')
|
const tagName = Cypress._.split(tag, '.')[1];
|
||||||
.scrollIntoView()
|
|
||||||
.should('be.visible')
|
|
||||||
.click()
|
|
||||||
.type(tag.split('.')[1]);
|
|
||||||
|
|
||||||
cy.get(`[data-testid='tag-${tag}']`).should('be.visible').click();
|
cy.get('[data-testid="tag-selector"]').scrollIntoView().should('be.visible');
|
||||||
|
cy.get('[data-testid="tag-selector"]').click().type(tagName);
|
||||||
|
|
||||||
|
cy.get(`[data-testid='tag-${tag}']`).click();
|
||||||
cy.get('[data-testid="tag-selector"] > .ant-select-selector').contains(tag);
|
cy.get('[data-testid="tag-selector"] > .ant-select-selector').contains(tag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,8 +53,10 @@ import React, { useEffect, useMemo, useState } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { getActiveAnnouncement, getFeedCount } from 'rest/feedsAPI';
|
import { getActiveAnnouncement, getFeedCount } from 'rest/feedsAPI';
|
||||||
|
import { getContainerByName } from 'rest/storageAPI';
|
||||||
import { getCurrentUserId, getEntityDetailLink } from 'utils/CommonUtils';
|
import { getCurrentUserId, getEntityDetailLink } from 'utils/CommonUtils';
|
||||||
import {
|
import {
|
||||||
|
getBreadcrumbForContainer,
|
||||||
getBreadcrumbForEntitiesWithServiceOnly,
|
getBreadcrumbForEntitiesWithServiceOnly,
|
||||||
getBreadcrumbForTable,
|
getBreadcrumbForTable,
|
||||||
getEntityBreadcrumbs,
|
getEntityBreadcrumbs,
|
||||||
@ -128,6 +130,8 @@ export const DataAssetsHeader = ({
|
|||||||
const { isTourPage } = useTourProvider();
|
const { isTourPage } = useTourProvider();
|
||||||
const { onCopyToClipBoard } = useClipboard(window.location.href);
|
const { onCopyToClipBoard } = useClipboard(window.location.href);
|
||||||
const [taskCount, setTaskCount] = useState(0);
|
const [taskCount, setTaskCount] = useState(0);
|
||||||
|
const [parentContainers, setParentContainers] = useState<Container[]>([]);
|
||||||
|
const [isBreadcrumbLoading, setIsBreadcrumbLoading] = useState(false);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const icon = useMemo(
|
const icon = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -196,12 +200,42 @@ export const DataAssetsHeader = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchContainerParent = async (
|
||||||
|
parentName: string,
|
||||||
|
parents = [] as Container[]
|
||||||
|
) => {
|
||||||
|
if (isEmpty(parentName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setIsBreadcrumbLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await getContainerByName(parentName, 'parent');
|
||||||
|
const updatedParent = [response, ...parents];
|
||||||
|
if (response?.parent?.fullyQualifiedName) {
|
||||||
|
await fetchContainerParent(
|
||||||
|
response.parent.fullyQualifiedName,
|
||||||
|
updatedParent
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setParentContainers(updatedParent);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError, t('server.unexpected-response'));
|
||||||
|
} finally {
|
||||||
|
setIsBreadcrumbLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dataAsset.fullyQualifiedName && !isTourPage) {
|
if (dataAsset.fullyQualifiedName && !isTourPage) {
|
||||||
fetchActiveAnnouncement();
|
fetchActiveAnnouncement();
|
||||||
fetchTaskCount();
|
fetchTaskCount();
|
||||||
}
|
}
|
||||||
}, [dataAsset.fullyQualifiedName]);
|
if (entityType === EntityType.CONTAINER) {
|
||||||
|
const asset = dataAsset as Container;
|
||||||
|
fetchContainerParent(asset.parent?.fullyQualifiedName ?? '');
|
||||||
|
}
|
||||||
|
}, [dataAsset]);
|
||||||
|
|
||||||
const { extraInfo, breadcrumbs }: DataAssetHeaderInfo = useMemo(() => {
|
const { extraInfo, breadcrumbs }: DataAssetHeaderInfo = useMemo(() => {
|
||||||
const returnData: DataAssetHeaderInfo = {
|
const returnData: DataAssetHeaderInfo = {
|
||||||
@ -354,8 +388,10 @@ export const DataAssetsHeader = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
returnData.breadcrumbs =
|
returnData.breadcrumbs = getBreadcrumbForContainer({
|
||||||
getBreadcrumbForEntitiesWithServiceOnly(containerDetails);
|
entity: containerDetails,
|
||||||
|
parents: parentContainers,
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -430,7 +466,7 @@ export const DataAssetsHeader = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return returnData;
|
return returnData;
|
||||||
}, [dataAsset, entityType]);
|
}, [dataAsset, entityType, parentContainers]);
|
||||||
|
|
||||||
const handleOpenTaskClick = () => {
|
const handleOpenTaskClick = () => {
|
||||||
if (!dataAsset.fullyQualifiedName) {
|
if (!dataAsset.fullyQualifiedName) {
|
||||||
@ -460,7 +496,10 @@ export const DataAssetsHeader = ({
|
|||||||
<Col className="self-center" span={18}>
|
<Col className="self-center" span={18}>
|
||||||
<Row gutter={[16, 12]}>
|
<Row gutter={[16, 12]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<TitleBreadcrumb titleLinks={breadcrumbs} />
|
<TitleBreadcrumb
|
||||||
|
loading={isBreadcrumbLoading}
|
||||||
|
titleLinks={breadcrumbs}
|
||||||
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<EntityHeaderTitle
|
<EntityHeaderTitle
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Collate.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { EntityType } from 'enums/entity.enum';
|
||||||
|
import { Container } from 'generated/entity/data/container';
|
||||||
|
import React from 'react';
|
||||||
|
import { getContainerByName } from 'rest/storageAPI';
|
||||||
|
import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils';
|
||||||
|
import { DataAssetsHeader } from './DataAssetsHeader.component';
|
||||||
|
import { DataAssetsHeaderProps } from './DataAssetsHeader.interface';
|
||||||
|
|
||||||
|
const mockProps: DataAssetsHeaderProps = {
|
||||||
|
dataAsset: {
|
||||||
|
id: 'assets-id',
|
||||||
|
name: 'testContainer',
|
||||||
|
parent: {
|
||||||
|
id: 'id',
|
||||||
|
type: 'container',
|
||||||
|
fullyQualifiedName: 'fullyQualifiedName',
|
||||||
|
},
|
||||||
|
service: {
|
||||||
|
id: 'service-id',
|
||||||
|
name: 's3_storage_sample',
|
||||||
|
type: 'storageService',
|
||||||
|
},
|
||||||
|
} as Container,
|
||||||
|
entityType: EntityType.CONTAINER,
|
||||||
|
permissions: DEFAULT_ENTITY_PERMISSION,
|
||||||
|
onRestoreDataAsset: jest.fn(),
|
||||||
|
onDisplayNameUpdate: jest.fn(),
|
||||||
|
onFollowClick: jest.fn(),
|
||||||
|
onVersionClick: jest.fn(),
|
||||||
|
onTierUpdate: jest.fn(),
|
||||||
|
onOwnerUpdate: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'components/common/title-breadcrumb/title-breadcrumb.component',
|
||||||
|
() => {
|
||||||
|
return jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => <div>TitleBreadcrumb.component</div>);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
jest.mock(
|
||||||
|
'components/Entity/EntityHeaderTitle/EntityHeaderTitle.component',
|
||||||
|
() => {
|
||||||
|
return jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => <div>EntityHeaderTitle.component</div>);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
jest.mock('components/common/OwnerLabel/OwnerLabel.component', () => ({
|
||||||
|
OwnerLabel: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => <div>OwnerLabel.component</div>),
|
||||||
|
}));
|
||||||
|
jest.mock('components/common/TierCard/TierCard', () =>
|
||||||
|
jest.fn().mockImplementation(({ children }) => (
|
||||||
|
<div>
|
||||||
|
TierCard.component
|
||||||
|
<div>{children}</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
);
|
||||||
|
jest.mock('components/common/entityPageInfo/ManageButton/ManageButton', () =>
|
||||||
|
jest.fn().mockImplementation(() => <div>ManageButton.component</div>)
|
||||||
|
);
|
||||||
|
jest.mock(
|
||||||
|
'components/common/entityPageInfo/AnnouncementCard/AnnouncementCard',
|
||||||
|
() =>
|
||||||
|
jest.fn().mockImplementation(() => <div>AnnouncementCard.component</div>)
|
||||||
|
);
|
||||||
|
jest.mock(
|
||||||
|
'components/common/entityPageInfo/AnnouncementDrawer/AnnouncementDrawer',
|
||||||
|
() =>
|
||||||
|
jest.fn().mockImplementation(() => <div>AnnouncementDrawer.component</div>)
|
||||||
|
);
|
||||||
|
jest.mock('rest/storageAPI', () => ({
|
||||||
|
getContainerByName: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => Promise.resolve({ name: 'test' })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('DataAssetsHeader component', () => {
|
||||||
|
it('should call getContainerByName API on Page load for container assets', () => {
|
||||||
|
const mockGetContainerByName = getContainerByName as jest.Mock;
|
||||||
|
render(<DataAssetsHeader {...mockProps} />);
|
||||||
|
|
||||||
|
expect(mockGetContainerByName).toHaveBeenCalledWith(
|
||||||
|
'fullyQualifiedName',
|
||||||
|
'parent'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call getContainerByName API if parent is undefined', () => {
|
||||||
|
const mockGetContainerByName = getContainerByName as jest.Mock;
|
||||||
|
render(
|
||||||
|
<DataAssetsHeader
|
||||||
|
{...mockProps}
|
||||||
|
dataAsset={{ ...mockProps.dataAsset, parent: undefined }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(mockGetContainerByName).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -10,29 +10,32 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { Skeleton } from 'antd';
|
import { Col, Row, Skeleton } from 'antd';
|
||||||
import { uniqueId } from 'lodash';
|
import { uniqueId } from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TitleBreadcrumbSkeletonProps } from '../Skeleton.interfaces';
|
import { TitleBreadcrumbSkeletonProps } from '../Skeleton.interfaces';
|
||||||
|
|
||||||
const TitleBreadcrumbSkeleton = ({
|
const TitleBreadcrumbSkeleton = ({
|
||||||
titleLinks,
|
loading,
|
||||||
children,
|
children,
|
||||||
}: TitleBreadcrumbSkeletonProps) =>
|
}: TitleBreadcrumbSkeletonProps) =>
|
||||||
titleLinks.length === 0 ? (
|
loading ? (
|
||||||
<div className="flex">
|
<Row gutter={16}>
|
||||||
{titleLinks.map(() => (
|
{Array(3)
|
||||||
<Skeleton
|
.fill(null)
|
||||||
active
|
.map(() => (
|
||||||
className="m-l-xs"
|
<Col key={uniqueId()}>
|
||||||
key={uniqueId()}
|
<Skeleton
|
||||||
paragraph={{ rows: 0 }}
|
active
|
||||||
title={{
|
className="m-l-xs"
|
||||||
width: 150,
|
paragraph={{ rows: 0 }}
|
||||||
}}
|
title={{
|
||||||
/>
|
width: 150,
|
||||||
))}
|
}}
|
||||||
</div>
|
/>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
) : (
|
) : (
|
||||||
children
|
children
|
||||||
);
|
);
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
import { SkeletonProps } from 'antd';
|
import { SkeletonProps } from 'antd';
|
||||||
import { SkeletonButtonProps } from 'antd/lib/skeleton/Button';
|
import { SkeletonButtonProps } from 'antd/lib/skeleton/Button';
|
||||||
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
|
|
||||||
|
|
||||||
export interface Key {
|
export interface Key {
|
||||||
key?: React.Key | null | undefined;
|
key?: React.Key | null | undefined;
|
||||||
@ -26,7 +25,7 @@ export interface SkeletonInterface extends Children {
|
|||||||
dataLength?: number;
|
dataLength?: number;
|
||||||
}
|
}
|
||||||
export interface TitleBreadcrumbSkeletonProps extends Children {
|
export interface TitleBreadcrumbSkeletonProps extends Children {
|
||||||
titleLinks: TitleBreadcrumbProps['titleLinks'];
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonSkeletonProps
|
export interface ButtonSkeletonProps
|
||||||
|
@ -28,6 +28,7 @@ const TitleBreadcrumb: FunctionComponent<TitleBreadcrumbProps> = ({
|
|||||||
titleLinks,
|
titleLinks,
|
||||||
className = '',
|
className = '',
|
||||||
noLink = false,
|
noLink = false,
|
||||||
|
loading = false,
|
||||||
widthDeductions,
|
widthDeductions,
|
||||||
}: TitleBreadcrumbProps) => {
|
}: TitleBreadcrumbProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -59,7 +60,7 @@ const TitleBreadcrumb: FunctionComponent<TitleBreadcrumbProps> = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TitleBreadcrumbSkeleton titleLinks={titleLinks}>
|
<TitleBreadcrumbSkeleton loading={loading}>
|
||||||
<nav className={className} data-testid="breadcrumb">
|
<nav className={className} data-testid="breadcrumb">
|
||||||
<ol className="rounded-4 d-flex flex-wrap">
|
<ol className="rounded-4 d-flex flex-wrap">
|
||||||
{titleLinks.map((link, index) => {
|
{titleLinks.map((link, index) => {
|
||||||
|
@ -20,5 +20,6 @@ export type TitleBreadcrumbProps = {
|
|||||||
}>;
|
}>;
|
||||||
className?: string;
|
className?: string;
|
||||||
noLink?: boolean;
|
noLink?: boolean;
|
||||||
|
loading?: boolean;
|
||||||
widthDeductions?: number;
|
widthDeductions?: number;
|
||||||
};
|
};
|
||||||
|
@ -105,7 +105,6 @@ const ContainerPage = () => {
|
|||||||
const [isEditDescription, setIsEditDescription] = useState<boolean>(false);
|
const [isEditDescription, setIsEditDescription] = useState<boolean>(false);
|
||||||
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
const [, setParentContainers] = useState<Container[]>([]);
|
|
||||||
const [containerData, setContainerData] = useState<Container>();
|
const [containerData, setContainerData] = useState<Container>();
|
||||||
const [containerChildrenData, setContainerChildrenData] = useState<
|
const [containerChildrenData, setContainerChildrenData] = useState<
|
||||||
Container['children']
|
Container['children']
|
||||||
@ -134,24 +133,6 @@ const ContainerPage = () => {
|
|||||||
ThreadType.Conversation
|
ThreadType.Conversation
|
||||||
);
|
);
|
||||||
|
|
||||||
// data fetching methods
|
|
||||||
const fetchContainerParent = async (
|
|
||||||
parentName: string,
|
|
||||||
newContainer = false
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const response = await getContainerByName(parentName, 'parent');
|
|
||||||
setParentContainers((prev) =>
|
|
||||||
newContainer ? [response] : [response, ...prev]
|
|
||||||
);
|
|
||||||
if (response.parent && response.parent.fullyQualifiedName) {
|
|
||||||
await fetchContainerParent(response.parent.fullyQualifiedName);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
showErrorToast(error as AxiosError, t('server.unexpected-response'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchContainerDetail = async (containerFQN: string) => {
|
const fetchContainerDetail = async (containerFQN: string) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -172,9 +153,6 @@ const ContainerPage = () => {
|
|||||||
...response,
|
...response,
|
||||||
tags: sortTagsCaseInsensitive(response.tags || []),
|
tags: sortTagsCaseInsensitive(response.tags || []),
|
||||||
});
|
});
|
||||||
if (response.parent && response.parent.fullyQualifiedName) {
|
|
||||||
await fetchContainerParent(response.parent.fullyQualifiedName, true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
setHasError(true);
|
setHasError(true);
|
||||||
@ -795,8 +773,6 @@ const ContainerPage = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchResourcePermission(containerName);
|
fetchResourcePermission(containerName);
|
||||||
// reset parent containers list on containername change
|
|
||||||
setParentContainers([]);
|
|
||||||
}, [containerName]);
|
}, [containerName]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -915,6 +915,35 @@ export const getEntityReferenceListFromEntities = <
|
|||||||
return entities.map((entity) => getEntityReferenceFromEntity(entity, type));
|
return entities.map((entity) => getEntityReferenceFromEntity(entity, type));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getEntityLinkFromType = (
|
||||||
|
fullyQualifiedName: string,
|
||||||
|
entityType: EntityType
|
||||||
|
) => {
|
||||||
|
switch (entityType) {
|
||||||
|
case EntityType.TABLE:
|
||||||
|
return getTableDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.GLOSSARY:
|
||||||
|
case EntityType.GLOSSARY_TERM:
|
||||||
|
return getGlossaryTermDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.TAG:
|
||||||
|
return getTagsDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.TOPIC:
|
||||||
|
return getTopicDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.DASHBOARD:
|
||||||
|
return getDashboardDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.PIPELINE:
|
||||||
|
return getPipelineDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.MLMODEL:
|
||||||
|
return getMlModelDetailsPath(fullyQualifiedName);
|
||||||
|
case EntityType.CONTAINER:
|
||||||
|
return getContainerDetailPath(fullyQualifiedName);
|
||||||
|
case EntityType.DATABASE:
|
||||||
|
return getDatabaseDetailsPath(fullyQualifiedName);
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getBreadcrumbForTable = (
|
export const getBreadcrumbForTable = (
|
||||||
entity: Table,
|
entity: Table,
|
||||||
includeCurrent = false
|
includeCurrent = false
|
||||||
@ -987,6 +1016,49 @@ export const getBreadcrumbForEntitiesWithServiceOnly = (
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBreadcrumbForContainer = (data: {
|
||||||
|
entity: Container;
|
||||||
|
includeCurrent?: boolean;
|
||||||
|
parents?: Container[];
|
||||||
|
}) => {
|
||||||
|
const { entity, includeCurrent = false, parents = [] } = data;
|
||||||
|
const { service } = entity;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: getEntityName(service),
|
||||||
|
url: service?.name
|
||||||
|
? getServiceDetailsPath(
|
||||||
|
service?.name,
|
||||||
|
ServiceCategoryPlural[
|
||||||
|
service?.type as keyof typeof ServiceCategoryPlural
|
||||||
|
]
|
||||||
|
)
|
||||||
|
: '',
|
||||||
|
},
|
||||||
|
...(parents.length > 0
|
||||||
|
? parents.map((parent) => ({
|
||||||
|
name: getEntityName(parent),
|
||||||
|
url: getEntityLinkFromType(
|
||||||
|
parent?.fullyQualifiedName ?? '',
|
||||||
|
EntityType.CONTAINER
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
: []),
|
||||||
|
...(includeCurrent
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
name: entity.name,
|
||||||
|
url: getEntityLinkFromType(
|
||||||
|
entity.fullyQualifiedName ?? '',
|
||||||
|
(entity as SourceType).entityType as EntityType
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
export const getEntityBreadcrumbs = (
|
export const getEntityBreadcrumbs = (
|
||||||
entity:
|
entity:
|
||||||
| SearchedDataProps['data'][number]['_source']
|
| SearchedDataProps['data'][number]['_source']
|
||||||
@ -1061,35 +1133,6 @@ export const getEntityBreadcrumbs = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getEntityLinkFromType = (
|
|
||||||
fullyQualifiedName: string,
|
|
||||||
entityType: EntityType
|
|
||||||
) => {
|
|
||||||
switch (entityType) {
|
|
||||||
case EntityType.TABLE:
|
|
||||||
return getTableDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.GLOSSARY:
|
|
||||||
case EntityType.GLOSSARY_TERM:
|
|
||||||
return getGlossaryTermDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.TAG:
|
|
||||||
return getTagsDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.TOPIC:
|
|
||||||
return getTopicDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.DASHBOARD:
|
|
||||||
return getDashboardDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.PIPELINE:
|
|
||||||
return getPipelineDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.MLMODEL:
|
|
||||||
return getMlModelDetailsPath(fullyQualifiedName);
|
|
||||||
case EntityType.CONTAINER:
|
|
||||||
return getContainerDetailPath(fullyQualifiedName);
|
|
||||||
case EntityType.DATABASE:
|
|
||||||
return getDatabaseDetailsPath(fullyQualifiedName);
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getEntityThreadLink = (
|
export const getEntityThreadLink = (
|
||||||
entityFieldThreadCount: EntityFieldThreadCount[]
|
entityFieldThreadCount: EntityFieldThreadCount[]
|
||||||
) => {
|
) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user