mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-01 11:09:14 +00:00
Minor: add base class for entity utils (#14651)
* Minor: add base class for entity utils * test: add unit test for entity util class * add user and team entity type case
This commit is contained in:
parent
dcac5c2367
commit
6646641b77
@ -41,7 +41,6 @@ jest.mock('../../../../utils/CommonUtils', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/TableUtils', () => ({
|
||||
getEntityLink: jest.fn(),
|
||||
getTierTags: jest.fn(),
|
||||
getTagsWithoutTier: jest.fn(),
|
||||
}));
|
||||
|
||||
@ -28,7 +28,9 @@ import {
|
||||
getEntityFQN,
|
||||
getEntityType,
|
||||
} from '../../../../utils/FeedUtils';
|
||||
import { getEntityLink } from '../../../../utils/TableUtils';
|
||||
|
||||
import { EntityType } from '../../../../enums/entity.enum';
|
||||
import entityUtilClassBase from '../../../../utils/EntityUtilClassBase';
|
||||
import UserPopOverCard from '../../../common/PopOverCard/UserPopOverCard';
|
||||
import './feed-card-header-v1.style.less';
|
||||
|
||||
@ -53,6 +55,7 @@ const FeedCardHeaderV1 = ({
|
||||
const entityFQN = getEntityFQN(entityLink) ?? '';
|
||||
const entityField = getEntityField(entityLink) ?? '';
|
||||
const entityCheck = !isUndefined(entityFQN) && !isUndefined(entityType);
|
||||
const isUserOrTeam = [EntityType.USER, EntityType.TEAM].includes(entityType);
|
||||
|
||||
const getFeedLinkElement = entityCheck && (
|
||||
<span className="font-normal" data-testid="headerText">
|
||||
@ -64,14 +67,28 @@ const FeedCardHeaderV1 = ({
|
||||
) : (
|
||||
<>
|
||||
<span data-testid="entityType">{entityType} </span>
|
||||
<EntityPopOverCard entityFQN={entityFQN} entityType={entityType}>
|
||||
<Link
|
||||
className="break-all"
|
||||
data-testid="entitylink"
|
||||
to={getEntityLink(entityType, entityFQN)}>
|
||||
<span>{entityDisplayName(entityType, entityFQN)}</span>
|
||||
</Link>
|
||||
</EntityPopOverCard>
|
||||
{isUserOrTeam ? (
|
||||
<UserPopOverCard
|
||||
showUserName
|
||||
showUserProfile={false}
|
||||
userName={createdBy}>
|
||||
<Link
|
||||
className="break-all"
|
||||
data-testid="entitylink"
|
||||
to={entityUtilClassBase.getEntityLink(entityType, entityFQN)}>
|
||||
<span>{entityDisplayName(entityType, entityFQN)}</span>
|
||||
</Link>
|
||||
</UserPopOverCard>
|
||||
) : (
|
||||
<EntityPopOverCard entityFQN={entityFQN} entityType={entityType}>
|
||||
<Link
|
||||
className="break-all"
|
||||
data-testid="entitylink"
|
||||
to={entityUtilClassBase.getEntityLink(entityType, entityFQN)}>
|
||||
<span>{entityDisplayName(entityType, entityFQN)}</span>
|
||||
</Link>
|
||||
</EntityPopOverCard>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
|
||||
@ -18,6 +18,7 @@ import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import CloseIcon from '../../../components/Modals/CloseIcon.component';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import {
|
||||
entityDisplayName,
|
||||
getEntityField,
|
||||
@ -26,7 +27,6 @@ import {
|
||||
getEntityType,
|
||||
getFeedPanelHeaderText,
|
||||
} from '../../../utils/FeedUtils';
|
||||
import { getEntityLink } from '../../../utils/TableUtils';
|
||||
import { FeedPanelHeaderProp } from './ActivityFeedPanel.interface';
|
||||
|
||||
const FeedPanelHeader: FC<FeedPanelHeaderProp> = ({
|
||||
@ -57,7 +57,7 @@ const FeedPanelHeader: FC<FeedPanelHeaderProp> = ({
|
||||
<Link
|
||||
className="break-all"
|
||||
data-testid="entitylink"
|
||||
to={getEntityLink(entityType, entityFQN)}>
|
||||
to={entityUtilClassBase.getEntityLink(entityType, entityFQN)}>
|
||||
<span>{entityDisplayName(entityType, entityFQN)}</span>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
@ -58,10 +58,6 @@ jest.mock('../../../utils/TasksUtils', () => ({
|
||||
getTaskDetailPath: jest.fn().mockReturnValue('/'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/TableUtils', () => ({
|
||||
getEntityLink: jest.fn().mockReturnValue('/'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/FeedUtils', () => ({
|
||||
getEntityFQN: jest.fn().mockReturnValue('entityFQN'),
|
||||
getEntityType: jest.fn().mockReturnValue('entityType'),
|
||||
|
||||
@ -35,7 +35,8 @@ import {
|
||||
} from '../../../utils/date-time/DateTimeUtils';
|
||||
import EntityLink from '../../../utils/EntityLink';
|
||||
import { getEntityFQN, getEntityType } from '../../../utils/FeedUtils';
|
||||
import { getEntityLink } from '../../../utils/TableUtils';
|
||||
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import { getTaskDetailPath } from '../../../utils/TasksUtils';
|
||||
import ProfilePicture from '../../common/ProfilePicture/ProfilePicture';
|
||||
import { useActivityFeedProvider } from '../ActivityFeedProvider/ActivityFeedProvider';
|
||||
@ -123,7 +124,7 @@ const TaskFeedCard = ({
|
||||
<Link
|
||||
className="break-all"
|
||||
data-testid="entity-link"
|
||||
to={getEntityLink(entityType, entityFQN)}
|
||||
to={entityUtilClassBase.getEntityLink(entityType, entityFQN)}
|
||||
onClick={(e) => e.stopPropagation()}>
|
||||
{getNameFromFQN(entityFQN)}
|
||||
</Link>
|
||||
|
||||
@ -25,9 +25,9 @@ import { CSMode } from '../../../enums/codemirror.enum';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import { getNameFromFQN } from '../../../utils/CommonUtils';
|
||||
import { getLineageDetailsObject } from '../../../utils/EntityLineageUtils';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getEncodedFqn } from '../../../utils/StringsUtils';
|
||||
import { getEntityLink } from '../../../utils/TableUtils';
|
||||
import Loader from '../../Loader/Loader';
|
||||
import { ModalWithQueryEditor } from '../../Modals/ModalWithQueryEditor/ModalWithQueryEditor';
|
||||
import SchemaEditor from '../../SchemaEditor/SchemaEditor';
|
||||
@ -75,7 +75,7 @@ const EdgeInfoDrawer = ({
|
||||
value: sourceData && getEntityName(sourceData?.data?.node),
|
||||
link:
|
||||
sourceData &&
|
||||
getEntityLink(
|
||||
entityUtilClassBase.getEntityLink(
|
||||
data.sourceType,
|
||||
sourceData.data.node.fullyQualifiedName
|
||||
),
|
||||
@ -89,7 +89,7 @@ const EdgeInfoDrawer = ({
|
||||
value: targetData ? getEntityName(targetData?.data?.node) : undefined,
|
||||
link:
|
||||
targetData &&
|
||||
getEntityLink(
|
||||
entityUtilClassBase.getEntityLink(
|
||||
data.targetData,
|
||||
targetData.data.node.fullyQualifiedName
|
||||
),
|
||||
@ -105,7 +105,7 @@ const EdgeInfoDrawer = ({
|
||||
: undefined,
|
||||
link:
|
||||
data?.edge?.pipeline &&
|
||||
getEntityLink(
|
||||
entityUtilClassBase.getEntityLink(
|
||||
data?.edge?.pipeline.type,
|
||||
getEncodedFqn(data?.edge?.pipeline.fullyQualifiedName)
|
||||
),
|
||||
|
||||
@ -16,8 +16,9 @@ import { isEmpty } from 'lodash';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { EntityReference } from '../../../generated/entity/type';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getEntityIcon, getEntityLink } from '../../../utils/TableUtils';
|
||||
import { getEntityIcon } from '../../../utils/TableUtils';
|
||||
import EntityListSkeleton from '../../Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component';
|
||||
import './entity.less';
|
||||
|
||||
@ -68,7 +69,7 @@ export const EntityListWithV1: FunctionComponent<AntdEntityListProp> = ({
|
||||
<div className="flex items-center">
|
||||
<Link
|
||||
className="font-medium"
|
||||
to={getEntityLink(
|
||||
to={entityUtilClassBase.getEntityLink(
|
||||
item.type || '',
|
||||
item.fullyQualifiedName ?? ''
|
||||
)}>
|
||||
|
||||
@ -18,7 +18,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { EntityType } from '../../enums/entity.enum';
|
||||
import { MlFeature } from '../../generated/entity/data/mlmodel';
|
||||
import { getEntityLink } from '../../utils/TableUtils';
|
||||
import entityUtilClassBase from '../../utils/EntityUtilClassBase';
|
||||
import './source-list.less';
|
||||
|
||||
const SourceList = ({ feature }: { feature: MlFeature }) => {
|
||||
@ -77,7 +77,7 @@ const SourceList = ({ feature }: { feature: MlFeature }) => {
|
||||
</Col>
|
||||
<Col flex="auto">
|
||||
<Link
|
||||
to={getEntityLink(
|
||||
to={entityUtilClassBase.getEntityLink(
|
||||
EntityType.TABLE,
|
||||
source.dataSource?.fullyQualifiedName ||
|
||||
source.dataSource?.name ||
|
||||
|
||||
@ -28,8 +28,9 @@ import { SearchIndex } from '../../../enums/search.enum';
|
||||
import { WidgetCommonProps } from '../../../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import { searchData } from '../../../rest/miscAPI';
|
||||
import { Transi18next } from '../../../utils/CommonUtils';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getEntityIcon, getEntityLink } from '../../../utils/TableUtils';
|
||||
import { getEntityIcon } from '../../../utils/TableUtils';
|
||||
import { useAuthContext } from '../../Auth/AuthProviders/AuthProvider';
|
||||
import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import { SourceType } from '../../SearchedData/SearchedData.interface';
|
||||
@ -163,7 +164,7 @@ const MyDataWidgetInternal = ({
|
||||
<div className="d-flex items-center">
|
||||
<Link
|
||||
className=""
|
||||
to={getEntityLink(
|
||||
to={entityUtilClassBase.getEntityLink(
|
||||
item.entityType ?? '',
|
||||
item.fullyQualifiedName as string
|
||||
)}>
|
||||
|
||||
@ -64,7 +64,6 @@ jest.mock('../../../utils/EntityUtils', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/TableUtils', () => ({
|
||||
getEntityLink: jest.fn().mockImplementation((link) => link),
|
||||
getEntityIcon: jest.fn().mockImplementation((obj) => obj.name),
|
||||
}));
|
||||
|
||||
|
||||
@ -88,10 +88,6 @@ jest.mock('../../../utils/FeedUtils', () => ({
|
||||
getEntityFQN: jest.fn().mockReturnValue('getEntityFQN'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/TableUtils', () => ({
|
||||
getEntityLink: jest.fn().mockReturnValue('getEntityLink'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/TasksUtils', () => ({
|
||||
fetchOptions: jest.fn().mockReturnValue('getEntityLink'),
|
||||
getTaskDetailPath: jest.fn().mockReturnValue('/'),
|
||||
|
||||
@ -76,10 +76,10 @@ import { updateTask, updateThread } from '../../../rest/feedsAPI';
|
||||
import { postTestCaseIncidentStatus } from '../../../rest/incidentManagerAPI';
|
||||
import { getNameFromFQN } from '../../../utils/CommonUtils';
|
||||
import EntityLink from '../../../utils/EntityLink';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getEntityFQN } from '../../../utils/FeedUtils';
|
||||
import { checkPermission } from '../../../utils/PermissionsUtils';
|
||||
import { getEntityLink } from '../../../utils/TableUtils';
|
||||
import {
|
||||
fetchOptions,
|
||||
getTaskDetailPath,
|
||||
@ -202,7 +202,7 @@ export const TaskTab = ({
|
||||
<Link
|
||||
className="break-all p-r-xss"
|
||||
data-testid="entitylink"
|
||||
to={getEntityLink(entityType, entityFQN)}
|
||||
to={entityUtilClassBase.getEntityLink(entityType, entityFQN)}
|
||||
onClick={(e) => e.stopPropagation()}>
|
||||
<Typography.Text className="text-md font-medium text-color-inherit">
|
||||
{' '}
|
||||
|
||||
@ -25,8 +25,9 @@ import {
|
||||
getRecentlyViewedData,
|
||||
prepareLabel,
|
||||
} from '../../../utils/CommonUtils';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getEntityIcon, getEntityLink } from '../../../utils/TableUtils';
|
||||
import { getEntityIcon } from '../../../utils/TableUtils';
|
||||
import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import EntityListSkeleton from '../../Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component';
|
||||
import './recently-viewed.less';
|
||||
@ -126,7 +127,7 @@ const RecentlyViewed = ({
|
||||
<div className=" flex items-center">
|
||||
<Link
|
||||
className=""
|
||||
to={getEntityLink(
|
||||
to={entityUtilClassBase.getEntityLink(
|
||||
item.type || '',
|
||||
item.fullyQualifiedName as string
|
||||
)}>
|
||||
|
||||
@ -17,7 +17,6 @@ import { MemoryRouter } from 'react-router-dom';
|
||||
import TableDataCardV2 from './TableDataCardV2';
|
||||
|
||||
jest.mock('../../../utils/TableUtils', () => ({
|
||||
getEntityLink: jest.fn().mockReturnValue('EntityLink'),
|
||||
getServiceIcon: jest.fn(),
|
||||
getEntityIcon: jest.fn().mockReturnValue(<p>icon</p>),
|
||||
getUsagePercentile: jest
|
||||
|
||||
@ -29,7 +29,6 @@ import { EntityType } from '../../enums/entity.enum';
|
||||
import { DatabaseSchema } from '../../generated/entity/data/databaseSchema';
|
||||
import { Table } from '../../generated/entity/data/table';
|
||||
import { getEntityName } from '../../utils/EntityUtils';
|
||||
import { getEntityLink } from '../../utils/TableUtils';
|
||||
|
||||
interface SchemaTablesTabProps {
|
||||
databaseSchemaDetails: DatabaseSchema;
|
||||
@ -81,10 +80,7 @@ function SchemaTablesTab({
|
||||
<Link
|
||||
className="break-word"
|
||||
data-testid="table-name-link"
|
||||
to={getEntityLink(
|
||||
EntityType.TABLE,
|
||||
record.fullyQualifiedName as string
|
||||
)}>
|
||||
to={(EntityType.TABLE, record.fullyQualifiedName as string)}>
|
||||
{getEntityName(record)}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@ -60,7 +60,6 @@ jest.mock('../../utils/StringsUtils', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('../../utils/TableUtils', () => ({
|
||||
getEntityLink: jest.fn().mockImplementation((link) => link),
|
||||
getTableExpandableConfig: jest.fn(),
|
||||
}));
|
||||
|
||||
|
||||
@ -28,9 +28,9 @@ import { Paging } from '../../generated/type/paging';
|
||||
import { usePaging } from '../../hooks/paging/usePaging';
|
||||
import { ServicePageData } from '../../pages/ServiceDetailsPage/ServiceDetailsPage';
|
||||
import { getStoredProceduresList } from '../../rest/storedProceduresAPI';
|
||||
import entityUtilClassBase from '../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../utils/EntityUtils';
|
||||
import { getDecodedFqn } from '../../utils/StringsUtils';
|
||||
import { getEntityLink } from '../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
|
||||
const StoredProcedureTab = () => {
|
||||
@ -101,7 +101,7 @@ const StoredProcedureTab = () => {
|
||||
<div className="d-inline-flex w-max-90">
|
||||
<Link
|
||||
className="break-word"
|
||||
to={getEntityLink(
|
||||
to={entityUtilClassBase.getEntityLink(
|
||||
EntityType.STORED_PROCEDURE,
|
||||
record.fullyQualifiedName ?? ''
|
||||
)}>
|
||||
|
||||
@ -20,7 +20,8 @@ import { SUPPORTED_TABLE_CONSTRAINTS } from '../../../constants/Table.constants'
|
||||
import { EntityType, FqnPart } from '../../../enums/entity.enum';
|
||||
import { ConstraintType, Table } from '../../../generated/entity/data/table';
|
||||
import { getPartialNameFromTableFQN } from '../../../utils/CommonUtils';
|
||||
import { getEntityLink } from '../../../utils/TableUtils';
|
||||
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
import ForeignKeyConstraint from './ForeignKeyConstraint';
|
||||
import PrimaryKeyConstraint from './PrimaryKeyConstraint';
|
||||
import './table-constraints.less';
|
||||
@ -96,7 +97,7 @@ const TableConstraints: FC<TableConstraintsProps> = ({ constraints }) => {
|
||||
trigger="hover">
|
||||
<Link
|
||||
className="no-underline"
|
||||
to={getEntityLink(
|
||||
to={entityUtilClassBase.getEntityLink(
|
||||
EntityType.TABLE,
|
||||
getPartialNameFromTableFQN(
|
||||
referredColumn,
|
||||
|
||||
@ -73,8 +73,8 @@ import {
|
||||
getPartialNameFromTableFQN,
|
||||
prepareLabel,
|
||||
} from './CommonUtils';
|
||||
import entityUtilClassBase from './EntityUtilClassBase';
|
||||
import { getDecodedFqn } from './StringsUtils';
|
||||
import { getEntityLink } from './TableUtils';
|
||||
import { showErrorToast } from './ToastUtils';
|
||||
|
||||
export const MAX_LINEAGE_LENGTH = 20;
|
||||
@ -100,7 +100,7 @@ export const getHeaderLabel = (
|
||||
className="m-b-0 text-base"
|
||||
level={5}
|
||||
title={name || prepareLabel(type, fqn, false)}>
|
||||
<Link className="" to={getEntityLink(type, fqn)}>
|
||||
<Link className="" to={entityUtilClassBase.getEntityLink(type, fqn)}>
|
||||
<Button
|
||||
className="text-base font-semibold p-0"
|
||||
data-testid="link-button"
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2024 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 {
|
||||
getDashboardDetailsPath,
|
||||
getDatabaseDetailsPath,
|
||||
getDatabaseSchemaDetailsPath,
|
||||
getPipelineDetailsPath,
|
||||
getTableDetailsPath,
|
||||
getTopicDetailsPath,
|
||||
} from '../constants/constants';
|
||||
import { EntityType } from '../enums/entity.enum';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import { EntityUtilClassBase } from './EntityUtilClassBase';
|
||||
import { getGlossaryPath } from './RouterUtils';
|
||||
|
||||
jest.mock('../constants/constants', () => ({
|
||||
getContainerDetailPath: jest.fn(),
|
||||
getDashboardDetailsPath: jest.fn(),
|
||||
getDatabaseDetailsPath: jest.fn(),
|
||||
getDatabaseSchemaDetailsPath: jest.fn(),
|
||||
getDataModelDetailsPath: jest.fn(),
|
||||
getEditWebhookPath: jest.fn(),
|
||||
getMlModelPath: jest.fn(),
|
||||
getPipelineDetailsPath: jest.fn(),
|
||||
getServiceDetailsPath: jest.fn(),
|
||||
getStoredProcedureDetailPath: jest.fn(),
|
||||
getTableDetailsPath: jest.fn(),
|
||||
getTableTabPath: jest.fn(),
|
||||
getTagsDetailsPath: jest.fn(),
|
||||
getTopicDetailsPath: jest.fn(),
|
||||
getUserPath: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./CommonUtils', () => ({
|
||||
getTableFQNFromColumnFQN: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./RouterUtils', () => ({
|
||||
getDataProductsDetailsPath: jest.fn(),
|
||||
getDomainDetailsPath: jest.fn(),
|
||||
getGlossaryPath: jest.fn(),
|
||||
getSettingPath: jest.fn(),
|
||||
getTeamsWithFqnPath: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./SearchIndexUtils', () => ({
|
||||
getSearchIndexDetailsPath: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./StringsUtils', () => ({
|
||||
getDecodedFqn: jest.fn().mockImplementation((fqn: string) => fqn),
|
||||
}));
|
||||
|
||||
describe('EntityUtilClassBase', () => {
|
||||
let entityUtil: EntityUtilClassBase;
|
||||
|
||||
beforeEach(() => {
|
||||
entityUtil = new EntityUtilClassBase();
|
||||
});
|
||||
|
||||
it('should return topic details path for topic index type', () => {
|
||||
const fqn = 'test.topic';
|
||||
entityUtil.getEntityLink(SearchIndex.TOPIC, fqn);
|
||||
|
||||
expect(getTopicDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('should return dashboard details path for dashboard index type', () => {
|
||||
const fqn = 'test.dashboard';
|
||||
entityUtil.getEntityLink(SearchIndex.DASHBOARD, fqn);
|
||||
|
||||
expect(getDashboardDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('should return pipeline details path for pipeline index type', () => {
|
||||
const fqn = 'test.pipeline';
|
||||
entityUtil.getEntityLink(SearchIndex.PIPELINE, fqn);
|
||||
|
||||
expect(getPipelineDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('Should return database details path for database EntityType', () => {
|
||||
const fqn = 'test.database';
|
||||
entityUtil.getEntityLink(EntityType.DATABASE, fqn);
|
||||
|
||||
expect(getDatabaseDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('Should return database schema details path for database EntityType', () => {
|
||||
const fqn = 'test.database.schema';
|
||||
entityUtil.getEntityLink(EntityType.DATABASE_SCHEMA, fqn);
|
||||
|
||||
expect(getDatabaseSchemaDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('Should return glossary details path for database EntityType', () => {
|
||||
const fqn = 'testingGlossary';
|
||||
entityUtil.getEntityLink(EntityType.GLOSSARY, fqn);
|
||||
|
||||
expect(getGlossaryPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('should return table details path for table index type', () => {
|
||||
const fqn = 'test.table';
|
||||
entityUtil.getEntityLink(SearchIndex.TABLE, fqn);
|
||||
|
||||
expect(getTableDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
|
||||
it('should return table details path for default case', () => {
|
||||
const fqn = 'test.default';
|
||||
entityUtil.getEntityLink('default', fqn);
|
||||
|
||||
expect(getTableDetailsPath).toHaveBeenCalledWith(fqn);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2024 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 {
|
||||
getContainerDetailPath,
|
||||
getDashboardDetailsPath,
|
||||
getDatabaseDetailsPath,
|
||||
getDatabaseSchemaDetailsPath,
|
||||
getDataModelDetailsPath,
|
||||
getEditWebhookPath,
|
||||
getMlModelPath,
|
||||
getPipelineDetailsPath,
|
||||
getServiceDetailsPath,
|
||||
getStoredProcedureDetailPath,
|
||||
getTableDetailsPath,
|
||||
getTableTabPath,
|
||||
getTagsDetailsPath,
|
||||
getTopicDetailsPath,
|
||||
getUserPath,
|
||||
} from '../constants/constants';
|
||||
import { GlobalSettingsMenuCategory } from '../constants/GlobalSettings.constants';
|
||||
import { EntityTabs, EntityType } from '../enums/entity.enum';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import { getTableFQNFromColumnFQN } from './CommonUtils';
|
||||
import {
|
||||
getDataProductsDetailsPath,
|
||||
getDomainDetailsPath,
|
||||
getGlossaryPath,
|
||||
getSettingPath,
|
||||
getTeamsWithFqnPath,
|
||||
} from './RouterUtils';
|
||||
import { getSearchIndexDetailsPath } from './SearchIndexUtils';
|
||||
import { getDecodedFqn } from './StringsUtils';
|
||||
|
||||
class EntityUtilClassBase {
|
||||
public getEntityLink(indexType: string, fullyQualifiedName: string) {
|
||||
// encode the FQN for entities that can have "/" in their names
|
||||
fullyQualifiedName = encodeURIComponent(fullyQualifiedName);
|
||||
switch (indexType) {
|
||||
case SearchIndex.TOPIC:
|
||||
case EntityType.TOPIC:
|
||||
return getTopicDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case SearchIndex.DASHBOARD:
|
||||
case EntityType.DASHBOARD:
|
||||
return getDashboardDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case SearchIndex.PIPELINE:
|
||||
case EntityType.PIPELINE:
|
||||
return getPipelineDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.DATABASE:
|
||||
return getDatabaseDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.DATABASE_SCHEMA:
|
||||
return getDatabaseSchemaDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.GLOSSARY:
|
||||
case EntityType.GLOSSARY_TERM:
|
||||
case SearchIndex.GLOSSARY:
|
||||
return getGlossaryPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.DATABASE_SERVICE:
|
||||
case EntityType.DASHBOARD_SERVICE:
|
||||
case EntityType.MESSAGING_SERVICE:
|
||||
case EntityType.PIPELINE_SERVICE:
|
||||
case EntityType.MLMODEL_SERVICE:
|
||||
case EntityType.METADATA_SERVICE:
|
||||
case EntityType.STORAGE_SERVICE:
|
||||
case EntityType.SEARCH_SERVICE:
|
||||
return getServiceDetailsPath(fullyQualifiedName, `${indexType}s`);
|
||||
|
||||
case EntityType.WEBHOOK:
|
||||
return getEditWebhookPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.TYPE:
|
||||
return getSettingPath(
|
||||
GlobalSettingsMenuCategory.CUSTOM_ATTRIBUTES,
|
||||
`${fullyQualifiedName}s`
|
||||
);
|
||||
|
||||
case EntityType.MLMODEL:
|
||||
case SearchIndex.MLMODEL:
|
||||
return getMlModelPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.CONTAINER:
|
||||
case SearchIndex.CONTAINER:
|
||||
return getContainerDetailPath(getDecodedFqn(fullyQualifiedName));
|
||||
case SearchIndex.TAG:
|
||||
return getTagsDetailsPath(fullyQualifiedName);
|
||||
|
||||
case SearchIndex.DASHBOARD_DATA_MODEL:
|
||||
case EntityType.DASHBOARD_DATA_MODEL:
|
||||
return getDataModelDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case SearchIndex.STORED_PROCEDURE:
|
||||
case EntityType.STORED_PROCEDURE:
|
||||
return getStoredProcedureDetailPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.TEST_CASE:
|
||||
return `${getTableTabPath(
|
||||
getTableFQNFromColumnFQN(fullyQualifiedName),
|
||||
EntityTabs.PROFILER
|
||||
)}?activeTab=Data Quality`;
|
||||
|
||||
case EntityType.SEARCH_INDEX:
|
||||
case SearchIndex.SEARCH_INDEX:
|
||||
return getSearchIndexDetailsPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.DOMAIN:
|
||||
case SearchIndex.DOMAIN:
|
||||
return getDomainDetailsPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.DATA_PRODUCT:
|
||||
case SearchIndex.DATA_PRODUCT:
|
||||
return getDataProductsDetailsPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.USER:
|
||||
case SearchIndex.USER:
|
||||
return getUserPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.TEAM:
|
||||
case SearchIndex.TEAM:
|
||||
return getTeamsWithFqnPath(fullyQualifiedName);
|
||||
|
||||
case SearchIndex.TABLE:
|
||||
case EntityType.TABLE:
|
||||
default:
|
||||
return getTableDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const entityUtilClassBase = new EntityUtilClassBase();
|
||||
|
||||
export default entityUtilClassBase;
|
||||
|
||||
export { EntityUtilClassBase };
|
||||
@ -99,10 +99,6 @@ jest.mock('./StringsUtils', () => ({
|
||||
getEncodedFqn: jest.fn().mockImplementation((fqn) => fqn),
|
||||
}));
|
||||
|
||||
jest.mock('./TableUtils', () => ({
|
||||
getEntityLink: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./FeedUtils', () => ({
|
||||
...jest.requireActual('./FeedUtils'),
|
||||
getEntityField: jest.fn().mockReturnValue('entityField'),
|
||||
|
||||
@ -68,6 +68,7 @@ import {
|
||||
} from './CommonUtils';
|
||||
import { getRelativeCalendar } from './date-time/DateTimeUtils';
|
||||
import EntityLink from './EntityLink';
|
||||
import entityUtilClassBase from './EntityUtilClassBase';
|
||||
import { ENTITY_LINK_SEPARATOR, getEntityBreadcrumbs } from './EntityUtils';
|
||||
import Fqn from './Fqn';
|
||||
import {
|
||||
@ -75,7 +76,6 @@ import {
|
||||
ImageQuality,
|
||||
} from './ProfilerUtils';
|
||||
import { getEncodedFqn } from './StringsUtils';
|
||||
import { getEntityLink } from './TableUtils';
|
||||
import { showErrorToast } from './ToastUtils';
|
||||
|
||||
export const getEntityType = (entityLink: string) => {
|
||||
@ -561,7 +561,7 @@ export const prepareFeedLink = (entityType: string, entityFQN: string) => {
|
||||
EntityType.TYPE,
|
||||
];
|
||||
|
||||
const entityLink = getEntityLink(entityType, entityFQN);
|
||||
const entityLink = entityUtilClassBase.getEntityLink(entityType, entityFQN);
|
||||
|
||||
if (!withoutFeedEntities.includes(entityType as EntityType)) {
|
||||
return `${entityLink}/${TabSpecificField.ACTIVITY_FEED}`;
|
||||
@ -602,7 +602,7 @@ export const entityDisplayName = (entityType: string, entityFQN: string) => {
|
||||
) {
|
||||
displayName = entityFQN.split(FQN_SEPARATOR_CHAR).pop();
|
||||
} else {
|
||||
displayName = getPartialNameFromFQN(entityFQN, ['database']);
|
||||
displayName = getPartialNameFromFQN(entityFQN, ['database']) || entityFQN;
|
||||
}
|
||||
|
||||
// Remove quotes if the name is wrapped in quotes
|
||||
|
||||
@ -52,9 +52,9 @@ import {
|
||||
replaceAllSpacialCharWith_,
|
||||
} from './CommonUtils';
|
||||
import { getDashboardURL } from './DashboardServiceUtils';
|
||||
import entityUtilClassBase from './EntityUtilClassBase';
|
||||
import { getBrokers } from './MessagingServiceUtils';
|
||||
import { getEncodedFqn } from './StringsUtils';
|
||||
import { getEntityLink } from './TableUtils';
|
||||
import { showErrorToast } from './ToastUtils';
|
||||
|
||||
export const getFormattedGuideText = (
|
||||
@ -456,22 +456,22 @@ export const getEntityTypeFromServiceCategory = (
|
||||
export const getLinkForFqn = (serviceCategory: ServiceTypes, fqn: string) => {
|
||||
switch (serviceCategory) {
|
||||
case ServiceCategory.MESSAGING_SERVICES:
|
||||
return getEntityLink(SearchIndex.TOPIC, fqn);
|
||||
return entityUtilClassBase.getEntityLink(SearchIndex.TOPIC, fqn);
|
||||
|
||||
case ServiceCategory.DASHBOARD_SERVICES:
|
||||
return getEntityLink(SearchIndex.DASHBOARD, fqn);
|
||||
return entityUtilClassBase.getEntityLink(SearchIndex.DASHBOARD, fqn);
|
||||
|
||||
case ServiceCategory.PIPELINE_SERVICES:
|
||||
return getEntityLink(SearchIndex.PIPELINE, fqn);
|
||||
return entityUtilClassBase.getEntityLink(SearchIndex.PIPELINE, fqn);
|
||||
|
||||
case ServiceCategory.ML_MODEL_SERVICES:
|
||||
return getEntityLink(SearchIndex.MLMODEL, fqn);
|
||||
return entityUtilClassBase.getEntityLink(SearchIndex.MLMODEL, fqn);
|
||||
|
||||
case ServiceCategory.STORAGE_SERVICES:
|
||||
return getEntityLink(EntityType.CONTAINER, fqn);
|
||||
return entityUtilClassBase.getEntityLink(EntityType.CONTAINER, fqn);
|
||||
|
||||
case ServiceCategory.SEARCH_SERVICES:
|
||||
return getEntityLink(EntityType.SEARCH_INDEX, fqn);
|
||||
return entityUtilClassBase.getEntityLink(EntityType.SEARCH_INDEX, fqn);
|
||||
|
||||
case ServiceCategory.DATABASE_SERVICES:
|
||||
default:
|
||||
|
||||
@ -56,25 +56,10 @@ import { SourceType } from '../components/SearchedData/SearchedData.interface';
|
||||
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
||||
import {
|
||||
DE_ACTIVE_COLOR,
|
||||
getContainerDetailPath,
|
||||
getDashboardDetailsPath,
|
||||
getDatabaseDetailsPath,
|
||||
getDatabaseSchemaDetailsPath,
|
||||
getDataModelDetailsPath,
|
||||
getEditWebhookPath,
|
||||
getMlModelPath,
|
||||
getPipelineDetailsPath,
|
||||
getServiceDetailsPath,
|
||||
getStoredProcedureDetailPath,
|
||||
getTableDetailsPath,
|
||||
getTableTabPath,
|
||||
getTagsDetailsPath,
|
||||
getTopicDetailsPath,
|
||||
PRIMERY_COLOR,
|
||||
TEXT_BODY_COLOR,
|
||||
} from '../constants/constants';
|
||||
import { GlobalSettingsMenuCategory } from '../constants/GlobalSettings.constants';
|
||||
import { EntityTabs, EntityType, FqnPart } from '../enums/entity.enum';
|
||||
import { EntityType, FqnPart } from '../enums/entity.enum';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import { ConstraintTypes, PrimaryTableDataTypes } from '../enums/table.enum';
|
||||
import { SearchIndexField } from '../generated/entity/data/searchIndex';
|
||||
@ -90,15 +75,8 @@ import {
|
||||
getTableFQNFromColumnFQN,
|
||||
sortTagsCaseInsensitive,
|
||||
} from './CommonUtils';
|
||||
import {
|
||||
getDataProductsDetailsPath,
|
||||
getDomainDetailsPath,
|
||||
getGlossaryPath,
|
||||
getSettingPath,
|
||||
} from './RouterUtils';
|
||||
import { getSearchIndexDetailsPath } from './SearchIndexUtils';
|
||||
import serviceUtilClassBase from './ServiceUtilClassBase';
|
||||
import { getDecodedFqn, ordinalize } from './StringsUtils';
|
||||
import { ordinalize } from './StringsUtils';
|
||||
import { TableFieldsInfoCommonEntities } from './TableUtils.interface';
|
||||
|
||||
export const getUsagePercentile = (pctRank: number, isLiteral = false) => {
|
||||
@ -210,98 +188,6 @@ export const getConstraintIcon = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const getEntityLink = (
|
||||
indexType: string,
|
||||
fullyQualifiedName: string
|
||||
) => {
|
||||
// encode the FQN for entities that can have "/" in their names
|
||||
fullyQualifiedName = encodeURIComponent(fullyQualifiedName);
|
||||
switch (indexType) {
|
||||
case SearchIndex.TOPIC:
|
||||
case EntityType.TOPIC:
|
||||
return getTopicDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case SearchIndex.DASHBOARD:
|
||||
case EntityType.DASHBOARD:
|
||||
return getDashboardDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case SearchIndex.PIPELINE:
|
||||
case EntityType.PIPELINE:
|
||||
return getPipelineDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.DATABASE:
|
||||
return getDatabaseDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.DATABASE_SCHEMA:
|
||||
return getDatabaseSchemaDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.GLOSSARY:
|
||||
case EntityType.GLOSSARY_TERM:
|
||||
case SearchIndex.GLOSSARY:
|
||||
return getGlossaryPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.DATABASE_SERVICE:
|
||||
case EntityType.DASHBOARD_SERVICE:
|
||||
case EntityType.MESSAGING_SERVICE:
|
||||
case EntityType.PIPELINE_SERVICE:
|
||||
case EntityType.MLMODEL_SERVICE:
|
||||
case EntityType.METADATA_SERVICE:
|
||||
case EntityType.STORAGE_SERVICE:
|
||||
case EntityType.SEARCH_SERVICE:
|
||||
return getServiceDetailsPath(fullyQualifiedName, `${indexType}s`);
|
||||
|
||||
case EntityType.WEBHOOK:
|
||||
return getEditWebhookPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.TYPE:
|
||||
return getSettingPath(
|
||||
GlobalSettingsMenuCategory.CUSTOM_ATTRIBUTES,
|
||||
`${fullyQualifiedName}s`
|
||||
);
|
||||
|
||||
case EntityType.MLMODEL:
|
||||
case SearchIndex.MLMODEL:
|
||||
return getMlModelPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.CONTAINER:
|
||||
case SearchIndex.CONTAINER:
|
||||
return getContainerDetailPath(getDecodedFqn(fullyQualifiedName));
|
||||
case SearchIndex.TAG:
|
||||
return getTagsDetailsPath(fullyQualifiedName);
|
||||
|
||||
case SearchIndex.DASHBOARD_DATA_MODEL:
|
||||
case EntityType.DASHBOARD_DATA_MODEL:
|
||||
return getDataModelDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case SearchIndex.STORED_PROCEDURE:
|
||||
case EntityType.STORED_PROCEDURE:
|
||||
return getStoredProcedureDetailPath(getDecodedFqn(fullyQualifiedName));
|
||||
|
||||
case EntityType.TEST_CASE:
|
||||
return `${getTableTabPath(
|
||||
getTableFQNFromColumnFQN(fullyQualifiedName),
|
||||
EntityTabs.PROFILER
|
||||
)}?activeTab=Data Quality`;
|
||||
|
||||
case EntityType.SEARCH_INDEX:
|
||||
case SearchIndex.SEARCH_INDEX:
|
||||
return getSearchIndexDetailsPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.DOMAIN:
|
||||
case SearchIndex.DOMAIN:
|
||||
return getDomainDetailsPath(fullyQualifiedName);
|
||||
|
||||
case EntityType.DATA_PRODUCT:
|
||||
case SearchIndex.DATA_PRODUCT:
|
||||
return getDataProductsDetailsPath(fullyQualifiedName);
|
||||
|
||||
case SearchIndex.TABLE:
|
||||
case EntityType.TABLE:
|
||||
default:
|
||||
return getTableDetailsPath(getDecodedFqn(fullyQualifiedName));
|
||||
}
|
||||
};
|
||||
|
||||
export const getServiceIcon = (source: SourceType) => {
|
||||
if (source.entityType === EntityType.GLOSSARY_TERM) {
|
||||
return (
|
||||
|
||||
@ -76,6 +76,7 @@ import { DatabaseFields } from './Database/Database.util';
|
||||
import { defaultFields as DatabaseSchemaFields } from './DatabaseSchemaDetailsUtils';
|
||||
import { defaultFields as DataModelFields } from './DataModelsUtils';
|
||||
import { defaultFields as TableFields } from './DatasetDetailsUtils';
|
||||
import entityUtilClassBase from './EntityUtilClassBase';
|
||||
import { getEntityName } from './EntityUtils';
|
||||
import { getEntityFQN, getEntityType } from './FeedUtils';
|
||||
import { getGlossaryBreadcrumbs } from './GlossaryUtils';
|
||||
@ -84,7 +85,6 @@ import { defaultFields as PipelineFields } from './PipelineDetailsUtils';
|
||||
import serviceUtilClassBase from './ServiceUtilClassBase';
|
||||
import { STORED_PROCEDURE_DEFAULT_FIELDS } from './StoredProceduresUtils';
|
||||
import { getDecodedFqn, getEncodedFqn } from './StringsUtils';
|
||||
import { getEntityLink } from './TableUtils';
|
||||
import { showErrorToast } from './ToastUtils';
|
||||
|
||||
export const getRequestDescriptionPath = (
|
||||
@ -299,7 +299,10 @@ export const getBreadCrumbList = (
|
||||
) => {
|
||||
const activeEntity = {
|
||||
name: getEntityName(entityData),
|
||||
url: getEntityLink(entityType, entityData.fullyQualifiedName || ''),
|
||||
url: entityUtilClassBase.getEntityLink(
|
||||
entityType,
|
||||
entityData.fullyQualifiedName || ''
|
||||
),
|
||||
};
|
||||
|
||||
const database = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user