mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 10:26:09 +00:00
fix#10662: Update tier functionality is not working as expected on the containers page (#10720)
* fix#10662: Update tier functionality is not working as expected on the containers page * chore: remove unwanted change * test: add unit test * chore: add container entity icon * chore: fix spacing issue * chore: add support for lineage info drawer * fix: locale missing key issue * refactor: entity info drawer
This commit is contained in:
parent
fb02cbfeed
commit
c6746507d9
@ -14,17 +14,21 @@
|
||||
import { CloseOutlined } from '@ant-design/icons';
|
||||
import { Col, Drawer, Row, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import ContainerSummary from 'components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.component';
|
||||
import DashboardSummary from 'components/Explore/EntitySummaryPanel/DashboardSummary/DashboardSummary.component';
|
||||
import MlModelSummary from 'components/Explore/EntitySummaryPanel/MlModelSummary/MlModelSummary.component';
|
||||
import PipelineSummary from 'components/Explore/EntitySummaryPanel/PipelineSummary/PipelineSummary.component';
|
||||
import TableSummary from 'components/Explore/EntitySummaryPanel/TableSummary/TableSummary.component';
|
||||
import TopicSummary from 'components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component';
|
||||
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
||||
import { Container } from 'generated/entity/data/container';
|
||||
import { Mlmodel } from 'generated/entity/data/mlmodel';
|
||||
import { EntityDetailUnion } from 'Models';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getDashboardByFqn } from 'rest/dashboardAPI';
|
||||
import { getMlModelByFQN } from 'rest/mlModelAPI';
|
||||
import { getContainerByName } from 'rest/objectStoreAPI';
|
||||
import { getPipelineByFqn } from 'rest/pipelineAPI';
|
||||
import { getTableDetailsByFQN } from 'rest/tableAPI';
|
||||
import { getTopicByFqn } from 'rest/topicsAPI';
|
||||
@ -45,8 +49,6 @@ import { SelectedNode } from '../EntityLineage/EntityLineage.interface';
|
||||
import { LineageDrawerProps } from './EntityInfoDrawer.interface';
|
||||
import './EntityInfoDrawer.style.less';
|
||||
|
||||
type EntityData = Table | Pipeline | Dashboard | Topic | Mlmodel;
|
||||
|
||||
const EntityInfoDrawer = ({
|
||||
show,
|
||||
onCancel,
|
||||
@ -54,136 +56,80 @@ const EntityInfoDrawer = ({
|
||||
isMainNode = false,
|
||||
}: LineageDrawerProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [entityDetail, setEntityDetail] = useState<EntityData>(
|
||||
{} as EntityData
|
||||
const [entityDetail, setEntityDetail] = useState<EntityDetailUnion>(
|
||||
{} as EntityDetailUnion
|
||||
);
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
const fetchEntityDetail = (selectedNode: SelectedNode) => {
|
||||
switch (selectedNode.type) {
|
||||
case EntityType.TABLE: {
|
||||
setIsLoading(true);
|
||||
getTableDetailsByFQN(getEncodedFqn(selectedNode.fqn), [
|
||||
'tags',
|
||||
'owner',
|
||||
'columns',
|
||||
'usageSummary',
|
||||
'profile',
|
||||
])
|
||||
.then((res) => {
|
||||
setEntityDetail(res);
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast(
|
||||
t('server.error-selected-node-name-details', {
|
||||
selectedNodeName: selectedNode.name,
|
||||
})
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
const fetchEntityDetail = async (selectedNode: SelectedNode) => {
|
||||
let response = {};
|
||||
const encodedFqn = getEncodedFqn(selectedNode.fqn);
|
||||
const commonFields = ['tags', 'owner'];
|
||||
|
||||
break;
|
||||
setIsLoading(true);
|
||||
try {
|
||||
switch (selectedNode.type) {
|
||||
case EntityType.TABLE: {
|
||||
response = await getTableDetailsByFQN(encodedFqn, [
|
||||
...commonFields,
|
||||
'columns',
|
||||
'usageSummary',
|
||||
'profile',
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.PIPELINE: {
|
||||
response = await getPipelineByFqn(encodedFqn, [
|
||||
...commonFields,
|
||||
'followers',
|
||||
'tasks',
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.TOPIC: {
|
||||
response = await getTopicByFqn(encodedFqn ?? '', commonFields);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.DASHBOARD: {
|
||||
response = await getDashboardByFqn(encodedFqn, [
|
||||
...commonFields,
|
||||
'charts',
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.MLMODEL: {
|
||||
response = await getMlModelByFQN(encodedFqn, [
|
||||
...commonFields,
|
||||
'dashboard',
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.CONTAINER: {
|
||||
response = await getContainerByName(
|
||||
encodedFqn,
|
||||
'dataModel,owner,tags'
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case EntityType.PIPELINE: {
|
||||
setIsLoading(true);
|
||||
getPipelineByFqn(getEncodedFqn(selectedNode.fqn), [
|
||||
'tags',
|
||||
'owner',
|
||||
'followers',
|
||||
'tasks',
|
||||
'tier',
|
||||
])
|
||||
.then((res) => {
|
||||
setEntityDetail(res);
|
||||
setIsLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast(
|
||||
t('server.error-selected-node-name-details', {
|
||||
selectedNodeName: selectedNode.name,
|
||||
})
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.TOPIC: {
|
||||
setIsLoading(true);
|
||||
getTopicByFqn(selectedNode.fqn ?? '', ['tags', 'owner'])
|
||||
.then((res) => {
|
||||
setEntityDetail(res);
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast(
|
||||
t('server.error-selected-node-name-details', {
|
||||
selectedNodeName: selectedNode.name,
|
||||
})
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.DASHBOARD: {
|
||||
setIsLoading(true);
|
||||
getDashboardByFqn(getEncodedFqn(selectedNode.fqn), [
|
||||
'tags',
|
||||
'owner',
|
||||
'charts',
|
||||
])
|
||||
.then((res) => {
|
||||
setEntityDetail(res);
|
||||
setIsLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast(
|
||||
t('server.error-selected-node-name-details', {
|
||||
selectedNodeName: selectedNode.name,
|
||||
})
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.MLMODEL: {
|
||||
setIsLoading(true);
|
||||
getMlModelByFQN(getEncodedFqn(selectedNode.fqn), [
|
||||
'tags',
|
||||
'owner',
|
||||
'dashboard',
|
||||
])
|
||||
.then((res) => {
|
||||
setEntityDetail(res);
|
||||
setIsLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast(
|
||||
t('server.error-selected-node-name-details', {
|
||||
selectedNodeName: selectedNode.name,
|
||||
})
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
setEntityDetail(response);
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
t('server.error-selected-node-name-details', {
|
||||
selectedNodeName: selectedNode.name,
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -243,6 +189,15 @@ const EntityInfoDrawer = ({
|
||||
tags={tags}
|
||||
/>
|
||||
);
|
||||
case EntityType.CONTAINER:
|
||||
return (
|
||||
<ContainerSummary
|
||||
componentType={DRAWER_NAVIGATION_OPTIONS.lineage}
|
||||
entityDetails={entityDetail as Container}
|
||||
isLoading={isLoading}
|
||||
tags={tags}
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
@ -160,7 +160,10 @@ const SuccessScreen = ({
|
||||
theme="primary"
|
||||
variant="outlined"
|
||||
onClick={handleViewServiceClick}>
|
||||
<span>{viewServiceText ?? 'View Service'}</span>
|
||||
<span>
|
||||
{viewServiceText ??
|
||||
t('label.view-entity', { entity: t('label.service') })}
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
{showIngestionButton && (
|
||||
|
@ -247,4 +247,12 @@ declare module 'Models' {
|
||||
}
|
||||
|
||||
export type PagingWithoutTotal = Omit<Paging, 'total'>;
|
||||
|
||||
type EntityDetailUnion =
|
||||
| Table
|
||||
| Pipeline
|
||||
| Dashboard
|
||||
| Topic
|
||||
| Mlmodel
|
||||
| Container;
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
export const CONTAINER_DATA = {
|
||||
id: '5d11e32a-8673-4a84-a9be-ccd9651ba9fc',
|
||||
name: 'transactions',
|
||||
fullyQualifiedName: 's3_object_store_sample.transactions',
|
||||
displayName: 'Company Transactions',
|
||||
description: "Bucket containing all the company's transactions",
|
||||
version: 0.7,
|
||||
updatedAt: 1679567030351,
|
||||
updatedBy: 'admin',
|
||||
href: 'http://localhost:8585/api/v1/containers/5d11e32a-8673-4a84-a9be-ccd9651ba9fc',
|
||||
owner: {
|
||||
id: '28b43857-288b-4e4e-8fac-c9cd34e06393',
|
||||
type: 'team',
|
||||
name: 'Applications',
|
||||
fullyQualifiedName: 'Applications',
|
||||
deleted: false,
|
||||
href: 'http://localhost:8585/api/v1/teams/28b43857-288b-4e4e-8fac-c9cd34e06393',
|
||||
},
|
||||
service: {
|
||||
id: 'cbc2a5e8-b7d3-4140-9a44-a4b331e5372f',
|
||||
type: 'objectStoreService',
|
||||
name: 's3_object_store_sample',
|
||||
fullyQualifiedName: 's3_object_store_sample',
|
||||
deleted: false,
|
||||
href: 'http://localhost:8585/api/v1/services/objectstoreServices/cbc2a5e8-b7d3-4140-9a44-a4b331e5372f',
|
||||
},
|
||||
dataModel: {
|
||||
isPartitioned: true,
|
||||
columns: [
|
||||
{
|
||||
name: 'transaction_id',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
description:
|
||||
'The ID of the executed transaction. This column is the primary key for this table.',
|
||||
fullyQualifiedName:
|
||||
's3_object_store_sample.transactions.transaction_id',
|
||||
tags: [],
|
||||
constraint: 'PRIMARY_KEY',
|
||||
ordinalPosition: 1,
|
||||
},
|
||||
{
|
||||
name: 'merchant',
|
||||
dataType: 'VARCHAR',
|
||||
dataLength: 100,
|
||||
dataTypeDisplay: 'varchar',
|
||||
description: 'The merchant for this transaction.',
|
||||
fullyQualifiedName: 's3_object_store_sample.transactions.merchant',
|
||||
tags: [],
|
||||
ordinalPosition: 2,
|
||||
},
|
||||
{
|
||||
name: 'transaction_time',
|
||||
dataType: 'TIMESTAMP',
|
||||
dataTypeDisplay: 'timestamp',
|
||||
description: 'The time the transaction took place.',
|
||||
fullyQualifiedName:
|
||||
's3_object_store_sample.transactions.transaction_time',
|
||||
tags: [],
|
||||
ordinalPosition: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
prefix: '/transactions/',
|
||||
numberOfObjects: 50,
|
||||
size: 102400,
|
||||
fileFormats: ['parquet'],
|
||||
serviceType: 'S3',
|
||||
followers: [],
|
||||
tags: [
|
||||
{
|
||||
tagFQN: 'Tier.Tier5',
|
||||
description: '',
|
||||
source: 'Classification',
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
},
|
||||
],
|
||||
deleted: false,
|
||||
};
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* 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 { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { getContainerByName } from 'rest/objectStoreAPI';
|
||||
import ContainerPage from './ContainerPage';
|
||||
import { CONTAINER_DATA } from './ContainerPage.mock';
|
||||
|
||||
jest.mock('components/PermissionProvider/PermissionProvider', () => ({
|
||||
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||
getEntityPermissionByFqn: jest.fn().mockResolvedValue({
|
||||
Create: true,
|
||||
Delete: true,
|
||||
EditAll: true,
|
||||
EditCustomFields: true,
|
||||
EditDataProfile: true,
|
||||
EditDescription: true,
|
||||
EditDisplayName: true,
|
||||
EditLineage: true,
|
||||
EditOwner: true,
|
||||
EditQueries: true,
|
||||
EditSampleData: true,
|
||||
EditTags: true,
|
||||
EditTests: true,
|
||||
EditTier: true,
|
||||
ViewAll: true,
|
||||
ViewDataProfile: true,
|
||||
ViewQueries: true,
|
||||
ViewSampleData: true,
|
||||
ViewTests: true,
|
||||
ViewUsage: true,
|
||||
}),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('components/common/CustomPropertyTable/CustomPropertyTable', () => {
|
||||
return {
|
||||
CustomPropertyTable: jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<div data-testid="custom-properties-table">CustomPropertyTable</div>
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('components/common/description/Description', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="description">Description</div>);
|
||||
});
|
||||
|
||||
jest.mock('components/common/entityPageInfo/EntityPageInfo', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="entity-page-info">EntityPageInfo</div>);
|
||||
});
|
||||
|
||||
jest.mock('components/common/error-with-placeholder/ErrorPlaceHolder', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<div data-testid="error-placeholder">ErrorPlaceHolder</div>
|
||||
);
|
||||
});
|
||||
|
||||
jest.mock(
|
||||
'components/ContainerDetail/ContainerChildren/ContainerChildren',
|
||||
() => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<div data-testid="containers-children">ContainerChildren</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
jest.mock(
|
||||
'components/ContainerDetail/ContainerDataModel/ContainerDataModel',
|
||||
() => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<div data-testid="container-data-model">ContainerDataModel</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
jest.mock('components/containers/PageContainerV1', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockImplementation(({ children }) => (
|
||||
<div data-testid="container-children">{children}</div>
|
||||
));
|
||||
});
|
||||
|
||||
jest.mock('components/EntityLineage/EntityLineage.component', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="entity-lineage">EntityLineage</div>);
|
||||
});
|
||||
|
||||
jest.mock('components/Loader/Loader', () => {
|
||||
return jest.fn().mockReturnValue(<div data-testid="loader">Loader</div>);
|
||||
});
|
||||
|
||||
jest.mock('rest/lineageAPI', () => ({
|
||||
getLineageByFQN: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('rest/miscAPI', () => ({
|
||||
deleteLineageEdge: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
addLineage: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('rest/objectStoreAPI', () => ({
|
||||
addContainerFollower: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
getContainerByName: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(CONTAINER_DATA)),
|
||||
patchContainerDetails: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
removeContainerFollower: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve()),
|
||||
restoreContainer: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
let mockParams = {
|
||||
entityFQN: 'entityTypeFQN',
|
||||
tab: 'schema',
|
||||
};
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
useHistory: jest.fn(),
|
||||
useParams: jest.fn().mockImplementation(() => mockParams),
|
||||
}));
|
||||
|
||||
describe('Container Page Component', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('Should render the child components', async () => {
|
||||
await act(async () => {
|
||||
render(<ContainerPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const pageTopInfo = screen.getByTestId('entity-page-info');
|
||||
const tabs = screen.getAllByRole('tab');
|
||||
|
||||
expect(pageTopInfo).toBeInTheDocument();
|
||||
expect(tabs).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('Should render the schema tab component', async () => {
|
||||
await act(async () => {
|
||||
render(<ContainerPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
const tabs = screen.getAllByRole('tab');
|
||||
|
||||
const schemaTab = tabs[0];
|
||||
|
||||
expect(schemaTab).toHaveAttribute('aria-selected', 'true');
|
||||
|
||||
const description = screen.getByTestId('description');
|
||||
|
||||
expect(description).toBeInTheDocument();
|
||||
|
||||
const dataModel = screen.getByTestId('container-data-model');
|
||||
|
||||
expect(dataModel).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the children tab component', async () => {
|
||||
mockParams = { ...mockParams, tab: 'children' };
|
||||
|
||||
await act(async () => {
|
||||
render(<ContainerPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const containerChildren = screen.getByTestId('containers-children');
|
||||
|
||||
expect(containerChildren).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the lineage tab component', async () => {
|
||||
mockParams = { ...mockParams, tab: 'lineage' };
|
||||
|
||||
await act(async () => {
|
||||
render(<ContainerPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const lineage = screen.getByTestId('entity-lineage');
|
||||
|
||||
expect(lineage).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the custom properties tab component', async () => {
|
||||
mockParams = { ...mockParams, tab: 'custom-properties' };
|
||||
|
||||
await act(async () => {
|
||||
render(<ContainerPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const customPropertyTable = screen.getByTestId('custom-properties-table');
|
||||
|
||||
expect(customPropertyTable).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render error placeholder on API fail', async () => {
|
||||
mockParams = { ...mockParams, tab: 'schema' };
|
||||
(getContainerByName as jest.Mock).mockImplementationOnce(() =>
|
||||
Promise.reject()
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
render(<ContainerPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
});
|
||||
|
||||
const errorPlaceholder = screen.getByTestId('error-placeholder');
|
||||
|
||||
expect(errorPlaceholder).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -37,7 +37,6 @@ import {
|
||||
} from 'components/PermissionProvider/PermissionProvider.interface';
|
||||
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
||||
import { getServiceDetailsPath } from 'constants/constants';
|
||||
import { ENTITY_CARD_CLASS } from 'constants/entity.constants';
|
||||
import { NO_PERMISSION_TO_VIEW } from 'constants/HelperTextUtil';
|
||||
import { EntityInfo, EntityType } from 'enums/entity.enum';
|
||||
import { ServiceCategory } from 'enums/service.enum';
|
||||
@ -426,7 +425,7 @@ const ContainerPage = () => {
|
||||
const { tags: newTags, version } = await handleUpdateContainerData({
|
||||
...(containerData as Container),
|
||||
tags: [
|
||||
...(containerData?.tags ?? []),
|
||||
...getTagsWithoutTier(containerData?.tags ?? []),
|
||||
{
|
||||
tagFQN: updatedTier,
|
||||
labelType: LabelType.Manual,
|
||||
@ -705,7 +704,7 @@ const ContainerPage = () => {
|
||||
</span>
|
||||
}>
|
||||
<Card
|
||||
className={`${ENTITY_CARD_CLASS} card-body-full`}
|
||||
className="h-full card-body-full"
|
||||
data-testid="lineage-details">
|
||||
<EntityLineageComponent
|
||||
addLineageHandler={handleAddLineage}
|
||||
@ -732,7 +731,7 @@ const ContainerPage = () => {
|
||||
{t('label.custom-property-plural')}
|
||||
</span>
|
||||
}>
|
||||
<Card className={ENTITY_CARD_CLASS}>
|
||||
<Card className="h-full">
|
||||
<CustomPropertyTable
|
||||
entityDetails={
|
||||
containerData as CustomPropertyProps['entityDetails']
|
||||
|
@ -24,7 +24,7 @@ import { Container } from 'generated/entity/data/container';
|
||||
import { Mlmodel } from 'generated/entity/data/mlmodel';
|
||||
import i18next from 'i18next';
|
||||
import { isEmpty, isNil, isUndefined, lowerCase, startCase } from 'lodash';
|
||||
import { Bucket } from 'Models';
|
||||
import { Bucket, EntityDetailUnion } from 'Models';
|
||||
import React, { Fragment } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
||||
@ -48,7 +48,6 @@ import {
|
||||
Table,
|
||||
TableType,
|
||||
} from '../generated/entity/data/table';
|
||||
import { Topic } from '../generated/entity/data/topic';
|
||||
import { Edge, EntityLineage } from '../generated/type/entityLineage';
|
||||
import { EntityReference } from '../generated/type/entityUsage';
|
||||
import { TagLabel } from '../generated/type/tagLabel';
|
||||
@ -85,7 +84,7 @@ export const getEntityId = (entity?: { id?: string }) => entity?.id || '';
|
||||
|
||||
export const getEntityTags = (
|
||||
type: string,
|
||||
entityDetail: Table | Pipeline | Dashboard | Topic | Mlmodel
|
||||
entityDetail: EntityDetailUnion
|
||||
): Array<TagLabel> => {
|
||||
switch (type) {
|
||||
case EntityType.TABLE: {
|
||||
@ -434,25 +433,30 @@ export const getEntityOverview = (
|
||||
const { numberOfObjects, serviceType, dataModel } =
|
||||
entityDetail as Container;
|
||||
|
||||
const visible = [
|
||||
DRAWER_NAVIGATION_OPTIONS.lineage,
|
||||
DRAWER_NAVIGATION_OPTIONS.explore,
|
||||
];
|
||||
|
||||
const overview = [
|
||||
{
|
||||
name: i18next.t('label.number-of-object'),
|
||||
value: numberOfObjects,
|
||||
isLink: false,
|
||||
visible: [DRAWER_NAVIGATION_OPTIONS.explore],
|
||||
visible,
|
||||
},
|
||||
{
|
||||
name: i18next.t('label.service-type'),
|
||||
value: serviceType,
|
||||
isLink: false,
|
||||
visible: [DRAWER_NAVIGATION_OPTIONS.explore],
|
||||
visible,
|
||||
},
|
||||
{
|
||||
name: i18next.t('label.column-plural'),
|
||||
value:
|
||||
dataModel && dataModel.columns ? dataModel.columns.length : NO_DATA,
|
||||
isLink: false,
|
||||
visible: [DRAWER_NAVIGATION_OPTIONS.explore],
|
||||
visible,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
import Icon from '@ant-design/icons';
|
||||
import { Tooltip } from 'antd';
|
||||
import { ExpandableConfig } from 'antd/lib/table/interface';
|
||||
import { ReactComponent as ContainerIcon } from 'assets/svg/ic-object-store.svg';
|
||||
import classNames from 'classnames';
|
||||
import { t } from 'i18next';
|
||||
import { upperCase } from 'lodash';
|
||||
@ -321,6 +322,10 @@ export const getEntityIcon = (indexType: string) => {
|
||||
case EntityType.PIPELINE:
|
||||
return <PipelineIcon />;
|
||||
|
||||
case SearchIndex.CONTAINER:
|
||||
case EntityType.CONTAINER:
|
||||
return <ContainerIcon />;
|
||||
|
||||
case SearchIndex.TABLE:
|
||||
case EntityType.TABLE:
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user