Fixed API throwing error while fetching soft-deleted MLmodel entity #5596 (#9262)

* Fixed API throwing error while fetching soft-deleted MLmodel entity #5596

* added unit test for soft deleted details

* addressing comment

* updated localization value
This commit is contained in:
Shailesh Parmar 2022-12-14 12:16:23 +05:30 committed by GitHub
parent 0c7bf13901
commit c29e42964b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 3 deletions

View File

@ -13,15 +13,25 @@
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
import { Operation } from 'fast-json-patch'; import { Operation } from 'fast-json-patch';
import { RestoreRequestType } from 'Models';
import { Mlmodel } from '../generated/entity/data/mlmodel'; import { Mlmodel } from '../generated/entity/data/mlmodel';
import { EntityReference } from '../generated/type/entityReference'; import { EntityReference } from '../generated/type/entityReference';
import { Include } from '../generated/type/include';
import { Paging } from '../generated/type/paging'; import { Paging } from '../generated/type/paging';
import { ServicePageData } from '../pages/service'; import { ServicePageData } from '../pages/service';
import { getURLWithQueryFields } from '../utils/APIUtils'; import { getURLWithQueryFields } from '../utils/APIUtils';
import APIClient from './index'; import APIClient from './index';
export const getMlModelByFQN = async (fqn: string, arrQueryFields: string) => { export const getMlModelByFQN = async (
const url = getURLWithQueryFields(`mlmodels/name/${fqn}`, arrQueryFields); fqn: string,
arrQueryFields: string,
include = Include.All
) => {
const url = getURLWithQueryFields(
`mlmodels/name/${fqn}`,
arrQueryFields,
`include=${include}`
);
const response = await APIClient.get<Mlmodel>(url); const response = await APIClient.get<Mlmodel>(url);
@ -89,3 +99,12 @@ export const removeFollower = async (mlModelId: string, userId: string) => {
return response.data; return response.data;
}; };
export const restoreMlmodel = async (id: string) => {
const response = await APIClient.put<
RestoreRequestType,
AxiosResponse<Mlmodel>
>('/mlmodels/restore', { id });
return response.data;
};

View File

@ -323,4 +323,30 @@ describe('Test MlModel entity detail component', () => {
expect(customProperties).toBeInTheDocument(); expect(customProperties).toBeInTheDocument();
}); });
it('Soft deleted mlmodel should be visible', async () => {
const { container } = render(
<MlModelDetailComponent
{...mockProp}
mlModelDetail={{ ...mockData, deleted: true } as Mlmodel}
/>,
{
wrapper: MemoryRouter,
}
);
const detailContainer = await findByTestId(container, 'mlmodel-details');
const entityInfo = await findByText(container, /EntityPageInfo/i);
const entityTabs = await findByTestId(container, 'tabs');
const entityFeatureList = await findByText(
container,
/MlModelFeaturesList/i
);
const entityDescription = await findByText(container, /Description/i);
expect(detailContainer).toBeInTheDocument();
expect(entityInfo).toBeInTheDocument();
expect(entityTabs).toBeInTheDocument();
expect(entityFeatureList).toBeInTheDocument();
expect(entityDescription).toBeInTheDocument();
});
}); });

View File

@ -13,6 +13,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 { AxiosError } from 'axios';
import classNames from 'classnames'; import classNames from 'classnames';
import { isEmpty, isUndefined, startCase, uniqueId } from 'lodash'; import { isEmpty, isUndefined, startCase, uniqueId } from 'lodash';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
@ -29,6 +30,7 @@ import React, {
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import AppState from '../../AppState'; import AppState from '../../AppState';
import { restoreMlmodel } from '../../axiosAPIs/mlModelAPI';
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
import { import {
getDashboardDetailsPath, getDashboardDetailsPath,
@ -52,13 +54,14 @@ import {
getEntityName, getEntityName,
getEntityPlaceHolder, getEntityPlaceHolder,
getOwnerValue, getOwnerValue,
refreshPage,
} from '../../utils/CommonUtils'; } from '../../utils/CommonUtils';
import { getEntityFieldThreadCounts } from '../../utils/FeedUtils'; import { getEntityFieldThreadCounts } from '../../utils/FeedUtils';
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils'; import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
import { getLineageViewPath } from '../../utils/RouterUtils'; import { getLineageViewPath } from '../../utils/RouterUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils'; import { serviceTypeLogo } from '../../utils/ServiceUtils';
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils'; import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
import ActivityFeedList from '../ActivityFeed/ActivityFeedList/ActivityFeedList'; import ActivityFeedList from '../ActivityFeed/ActivityFeedList/ActivityFeedList';
import ActivityThreadPanel from '../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel'; import ActivityThreadPanel from '../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
import { CustomPropertyTable } from '../common/CustomPropertyTable/CustomPropertyTable'; import { CustomPropertyTable } from '../common/CustomPropertyTable/CustomPropertyTable';
@ -376,6 +379,27 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
} }
}; };
const handleRestoreMlmodel = async () => {
try {
await restoreMlmodel(mlModelDetail.id);
showSuccessToast(
t('message.restore-entities-success', {
entity: t('label.mlmodel'),
}),
// Autoclose timer
2000
);
refreshPage();
} catch (error) {
showErrorToast(
error as AxiosError,
t('message.restore-entities-error', {
entity: t('label.mlmodel'),
})
);
}
};
const onFeaturesUpdate = async (features: Mlmodel['mlFeatures']) => { const onFeaturesUpdate = async (features: Mlmodel['mlFeatures']) => {
await updateMlModelFeatures({ ...mlModelDetail, mlFeatures: features }); await updateMlModelFeatures({ ...mlModelDetail, mlFeatures: features });
}; };
@ -567,6 +591,7 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
? onTierUpdate ? onTierUpdate
: undefined : undefined
} }
onRestoreEntity={handleRestoreMlmodel}
onThreadLinkSelect={handleThreadLinkSelect} onThreadLinkSelect={handleThreadLinkSelect}
/> />

View File

@ -498,6 +498,7 @@
"test-suite-status": "Test Suite Status", "test-suite-status": "Test Suite Status",
"last-run-result": "Last Run Result", "last-run-result": "Last Run Result",
"last-run": "Last Run", "last-run": "Last Run",
"mlmodel": "ML Model",
"search-entity": "Search {{entity}}", "search-entity": "Search {{entity}}",
"more": "More", "more": "More",
"update": "Update" "update": "Update"