UI :- Added EmptyPlaceholder for no data Modal store (#8220)

* Added EmptyPlaceholder for no data  Modal store

* import fix for table

* added unit test along

* changes as per comments
This commit is contained in:
Ashish Gupta 2022-10-20 17:45:42 +05:30 committed by GitHub
parent 38cd7eb6af
commit 6ad828ef98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 18 deletions

View File

@ -11,7 +11,12 @@
* limitations under the License. * 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 { LeafNodes } from 'Models';
import React from 'react'; import React from 'react';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
@ -205,6 +210,7 @@ jest.mock('../../utils/CommonUtils', () => {
getEntityName: jest.fn().mockReturnValue('entityName'), getEntityName: jest.fn().mockReturnValue('entityName'),
getEntityPlaceHolder: jest.fn().mockReturnValue('entityPlaceholder'), getEntityPlaceHolder: jest.fn().mockReturnValue('entityPlaceholder'),
getOwnerValue: jest.fn().mockReturnValue('Owner'), getOwnerValue: jest.fn().mockReturnValue('Owner'),
getEmptyPlaceholder: jest.fn().mockReturnValue(<p>ErrorPlaceHolder</p>),
}; };
}); });
@ -244,6 +250,32 @@ describe('Test MlModel entity detail component', () => {
}); });
it('Should render hyper parameter and ml store table for details tab', async () => { 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(
<MlModelDetailComponent {...mockPropDetails} activeTab={3} />,
{
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( const { container } = render(
<MlModelDetailComponent {...mockProp} activeTab={3} />, <MlModelDetailComponent {...mockProp} activeTab={3} />,
{ {

View File

@ -14,7 +14,7 @@
import { Col, Row, Table } from 'antd'; import { Col, Row, Table } from 'antd';
import { ColumnsType } from 'antd/lib/table'; import { ColumnsType } from 'antd/lib/table';
import classNames from 'classnames'; import classNames from 'classnames';
import { isUndefined, startCase, uniqueId } from 'lodash'; import { isEmpty, isUndefined, startCase, uniqueId } from 'lodash';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { EntityTags, ExtraInfo } from 'Models'; import { EntityTags, ExtraInfo } from 'Models';
import React, { import React, {
@ -26,6 +26,7 @@ import React, {
useMemo, useMemo,
useState, useState,
} from 'react'; } from 'react';
import { useTranslation } from 'react-i18next';
import AppState from '../../AppState'; import AppState from '../../AppState';
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
import { import {
@ -46,6 +47,7 @@ import { LabelType, State, TagLabel } from '../../generated/type/tagLabel';
import { useInfiniteScroll } from '../../hooks/useInfiniteScroll'; import { useInfiniteScroll } from '../../hooks/useInfiniteScroll';
import jsonData from '../../jsons/en'; import jsonData from '../../jsons/en';
import { import {
getEmptyPlaceholder,
getEntityName, getEntityName,
getEntityPlaceHolder, getEntityPlaceHolder,
getOwnerValue, getOwnerValue,
@ -95,6 +97,7 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
entityFieldTaskCount, entityFieldTaskCount,
entityFieldThreadCount, entityFieldThreadCount,
}) => { }) => {
const { t } = useTranslation();
const [followersCount, setFollowersCount] = useState<number>(0); const [followersCount, setFollowersCount] = useState<number>(0);
const [isFollowing, setIsFollowing] = useState<boolean>(false); const [isFollowing, setIsFollowing] = useState<boolean>(false);
@ -379,12 +382,12 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
const getMlHyperParametersColumn: ColumnsType<MlHyperParameter> = useMemo( const getMlHyperParametersColumn: ColumnsType<MlHyperParameter> = useMemo(
() => [ () => [
{ {
title: 'Name', title: t('label.name'),
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
}, },
{ {
title: 'Value', title: t('label.value'),
dataIndex: 'value', dataIndex: 'value',
key: 'value', key: 'value',
}, },
@ -395,16 +398,22 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
const getMlHyperParameters = () => { const getMlHyperParameters = () => {
return ( return (
<div className="flex flex-col m-t-xs"> <div className="flex flex-col m-t-xs">
<h6 className="font-medium text-base">Hyper Parameters</h6> <h6 className="font-medium text-base">
{t('label.hyper-parameters')}{' '}
</h6>
<div className="m-t-xs"> <div className="m-t-xs">
<Table {isEmpty(mlModelDetail.mlHyperParameters) ? (
columns={getMlHyperParametersColumn} getEmptyPlaceholder()
data-testid="hyperparameters-table" ) : (
dataSource={mlModelDetail.mlHyperParameters} <Table
pagination={false} columns={getMlHyperParametersColumn}
rowKey="name" data-testid="hyperparameters-table"
size="small" dataSource={mlModelDetail.mlHyperParameters}
/> pagination={false}
rowKey="name"
size="small"
/>
)}
</div> </div>
</div> </div>
); );
@ -413,7 +422,7 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
const getMlModelStore = () => { const getMlModelStore = () => {
return ( return (
<div className="flex flex-col m-t-xs"> <div className="flex flex-col m-t-xs">
<h6 className="font-medium text-base">Model Store</h6> <h6 className="font-medium text-base">{t('label.model-store')}</h6>
{mlModelDetail.mlStore ? ( {mlModelDetail.mlStore ? (
<div className="m-t-xs tw-table-container"> <div className="m-t-xs tw-table-container">
<table <table
@ -459,7 +468,7 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
</table> </table>
</div> </div>
) : ( ) : (
<span className="tw-text-grey-muted tw-text-center">No Data</span> getEmptyPlaceholder()
)} )}
</div> </div>
); );

View File

@ -35,12 +35,15 @@
"table-metrics-summary": "Table Metrics Summary", "table-metrics-summary": "Table Metrics Summary",
"table-tests-summary": "Table Tests Summary", "table-tests-summary": "Table Tests Summary",
"frequently-joined-columns": "Frequently joined columns", "frequently-joined-columns": "Frequently joined columns",
"no-description": "No description",
"request-tags": "Request tags", "request-tags": "Request tags",
"update-request-tags": "Update request tags", "update-request-tags": "Update request tags",
"request-description": "Request description", "request-description": "Request description",
"request-update-description": "Request update 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": {}, "message": {},
"server": {}, "server": {},

View File

@ -11,10 +11,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { Popover, Space, Tag } from 'antd'; import { Popover, Space, Tag, Typography } from 'antd';
import { ColumnsType } from 'antd/lib/table'; import { ColumnsType } from 'antd/lib/table';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import classNames from 'classnames'; import classNames from 'classnames';
import i18n from 'i18next';
import { import {
capitalize, capitalize,
differenceWith, differenceWith,
@ -43,6 +44,7 @@ import {
getDayCron, getDayCron,
getHourCron, getHourCron,
} from '../components/common/CronEditor/CronEditor.constant'; } from '../components/common/CronEditor/CronEditor.constant';
import ErrorPlaceHolder from '../components/common/error-with-placeholder/ErrorPlaceHolder';
import PopOver from '../components/common/popover/PopOver'; import PopOver from '../components/common/popover/PopOver';
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
import { import {
@ -57,6 +59,7 @@ import {
UrlEntityCharRegEx, UrlEntityCharRegEx,
validEmailRegEx, validEmailRegEx,
} from '../constants/regex.constants'; } from '../constants/regex.constants';
import { SIZE } from '../enums/common.enum';
import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum'; import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum';
import { Ownership } from '../enums/mydata.enum'; import { Ownership } from '../enums/mydata.enum';
import { Bot } from '../generated/entity/bot'; import { Bot } from '../generated/entity/bot';
@ -1040,3 +1043,13 @@ export const getIngestionFrequency = (pipelineType: PipelineType) => {
return getDayCron(value); return getDayCron(value);
} }
}; };
export const getEmptyPlaceholder = () => {
return (
<ErrorPlaceHolder size={SIZE.MEDIUM}>
<Typography.Paragraph>
{i18n.t('label.no-data-available')}
</Typography.Paragraph>
</ErrorPlaceHolder>
);
};