diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.test.tsx index 23b63bed87c..76756b91561 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.test.tsx @@ -11,7 +11,12 @@ * limitations under the License. */ -import { findByTestId, findByText, render } from '@testing-library/react'; +import { + findAllByText, + findByTestId, + findByText, + render, +} from '@testing-library/react'; import { LeafNodes } from 'Models'; import React from 'react'; import { MemoryRouter } from 'react-router-dom'; @@ -205,6 +210,7 @@ jest.mock('../../utils/CommonUtils', () => { getEntityName: jest.fn().mockReturnValue('entityName'), getEntityPlaceHolder: jest.fn().mockReturnValue('entityPlaceholder'), getOwnerValue: jest.fn().mockReturnValue('Owner'), + getEmptyPlaceholder: jest.fn().mockReturnValue(

ErrorPlaceHolder

), }; }); @@ -244,6 +250,32 @@ describe('Test MlModel entity detail component', () => { }); it('Should render hyper parameter and ml store table for details tab', async () => { + const mockPropDetails = { + ...mockProp, + mlModelDetail: { + ...mockProp.mlModelDetail, + mlHyperParameters: [], + mlStore: undefined, + }, + }; + const { container } = render( + , + { + wrapper: MemoryRouter, + } + ); + + const detailContainer = await findByTestId(container, 'mlmodel-details'); + const emptyTablePlaceholder = await findAllByText( + container, + 'ErrorPlaceHolder' + ); + + expect(detailContainer).toBeInTheDocument(); + expect(emptyTablePlaceholder).toHaveLength(2); + }); + + it('Should render no data placeholder hyper parameter and ml store details tab', async () => { const { container } = render( , { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.tsx index aaad9b9be5b..6fd4f67fd65 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/MlModelDetail/MlModelDetail.component.tsx @@ -14,7 +14,7 @@ import { Col, Row, Table } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import classNames from 'classnames'; -import { isUndefined, startCase, uniqueId } from 'lodash'; +import { isEmpty, isUndefined, startCase, uniqueId } from 'lodash'; import { observer } from 'mobx-react'; import { EntityTags, ExtraInfo } from 'Models'; import React, { @@ -26,6 +26,7 @@ import React, { useMemo, useState, } from 'react'; +import { useTranslation } from 'react-i18next'; import AppState from '../../AppState'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; import { @@ -46,6 +47,7 @@ import { LabelType, State, TagLabel } from '../../generated/type/tagLabel'; import { useInfiniteScroll } from '../../hooks/useInfiniteScroll'; import jsonData from '../../jsons/en'; import { + getEmptyPlaceholder, getEntityName, getEntityPlaceHolder, getOwnerValue, @@ -95,6 +97,7 @@ const MlModelDetail: FC = ({ entityFieldTaskCount, entityFieldThreadCount, }) => { + const { t } = useTranslation(); const [followersCount, setFollowersCount] = useState(0); const [isFollowing, setIsFollowing] = useState(false); @@ -379,12 +382,12 @@ const MlModelDetail: FC = ({ const getMlHyperParametersColumn: ColumnsType = useMemo( () => [ { - title: 'Name', + title: t('label.name'), dataIndex: 'name', key: 'name', }, { - title: 'Value', + title: t('label.value'), dataIndex: 'value', key: 'value', }, @@ -395,16 +398,22 @@ const MlModelDetail: FC = ({ const getMlHyperParameters = () => { return (
-
Hyper Parameters
+
+ {t('label.hyper-parameters')}{' '} +
- + {isEmpty(mlModelDetail.mlHyperParameters) ? ( + getEmptyPlaceholder() + ) : ( +
+ )} ); @@ -413,7 +422,7 @@ const MlModelDetail: FC = ({ const getMlModelStore = () => { return (
-
Model Store
+
{t('label.model-store')}
{mlModelDetail.mlStore ? (
= ({
) : ( - No Data + getEmptyPlaceholder() )}
); diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index b114fdeea95..35822789ed8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -35,12 +35,15 @@ "table-metrics-summary": "Table Metrics Summary", "table-tests-summary": "Table Tests Summary", "frequently-joined-columns": "Frequently joined columns", - "no-description": "No description", "request-tags": "Request tags", "update-request-tags": "Update request tags", "request-description": "Request description", "request-update-description": "Request update description", - "enter-column-description": "Enter Column Description" + "enter-column-description": "Enter Column Description", + "hyper-parameters": "Hyper Parameters", + "model-store": "Model Store", + "value": "Value", + "no-data-available": "No data available" }, "message": {}, "server": {}, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx index 0bba49b68bd..402e503c313 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx @@ -11,10 +11,11 @@ * limitations under the License. */ -import { Popover, Space, Tag } from 'antd'; +import { Popover, Space, Tag, Typography } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import { AxiosError } from 'axios'; import classNames from 'classnames'; +import i18n from 'i18next'; import { capitalize, differenceWith, @@ -43,6 +44,7 @@ import { getDayCron, getHourCron, } from '../components/common/CronEditor/CronEditor.constant'; +import ErrorPlaceHolder from '../components/common/error-with-placeholder/ErrorPlaceHolder'; import PopOver from '../components/common/popover/PopOver'; import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; import { @@ -57,6 +59,7 @@ import { UrlEntityCharRegEx, validEmailRegEx, } from '../constants/regex.constants'; +import { SIZE } from '../enums/common.enum'; import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum'; import { Ownership } from '../enums/mydata.enum'; import { Bot } from '../generated/entity/bot'; @@ -1040,3 +1043,13 @@ export const getIngestionFrequency = (pipelineType: PipelineType) => { return getDayCron(value); } }; + +export const getEmptyPlaceholder = () => { + return ( + + + {i18n.t('label.no-data-available')} + + + ); +};