diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts index bb6abdb097b..a06e1d69412 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts @@ -118,7 +118,7 @@ export const getEntityTypeSearchIndexMapping = (entityType: string) => { export const toastNotification = async ( page: Page, message: string | RegExp, - timeout: number + timeout?: number ) => { await expect(page.getByTestId('alert-bar')).toHaveText(message, { timeout }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts index 8d313bcb9ab..79027a61eae 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts @@ -829,17 +829,13 @@ export const deleteGlossaryOrGlossaryTerm = async ( await page.fill('[data-testid="confirmation-text-input"]', 'DELETE'); const endpoint = isGlossaryTerm - ? '/api/v1/glossaryTerms/*' - : '/api/v1/glossaries/*'; + ? '/api/v1/glossaryTerms/async/*' + : '/api/v1/glossaries/async/*'; const deleteRes = page.waitForResponse(endpoint); await page.click('[data-testid="confirm-button"]'); await deleteRes; - if (isGlossaryTerm) { - await toastNotification(page, /"Glossary Term" deleted successfully!/); - } else { - await toastNotification(page, /"Glossary" deleted successfully!/); - } + await toastNotification(page, /deleted successfully!/); }; export const addSynonyms = async (page: Page, synonyms: string[]) => { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx index 0a28f95e832..fe9f625f850 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx @@ -23,6 +23,7 @@ import React, { } from 'react'; import { useTranslation } from 'react-i18next'; import { useHistory, useParams } from 'react-router-dom'; +import { DeleteType } from '../../../components/common/DeleteWidget/DeleteWidget.interface'; import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder'; import Loader from '../../../components/common/Loader/Loader'; import ResizableLeftPanels from '../../../components/common/ResizablePanels/ResizableLeftPanels'; @@ -39,10 +40,15 @@ import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants'; import { PAGE_SIZE_LARGE, ROUTES } from '../../../constants/constants'; import { GLOSSARIES_DOCS } from '../../../constants/docs.constants'; import { observerOptions } from '../../../constants/Mydata.constants'; +import { useAsyncDeleteProvider } from '../../../context/AsyncDeleteProvider/AsyncDeleteProvider'; import { usePermissionProvider } from '../../../context/PermissionProvider/PermissionProvider'; import { ResourceEntity } from '../../../context/PermissionProvider/PermissionProvider.interface'; import { ERROR_PLACEHOLDER_TYPE, SIZE } from '../../../enums/common.enum'; -import { EntityAction, TabSpecificField } from '../../../enums/entity.enum'; +import { + EntityAction, + EntityType, + TabSpecificField, +} from '../../../enums/entity.enum'; import { Glossary } from '../../../generated/entity/data/glossary'; import { GlossaryTerm } from '../../../generated/entity/data/glossaryTerm'; import { Operation } from '../../../generated/entity/policies/policy'; @@ -51,8 +57,6 @@ import { usePaging } from '../../../hooks/paging/usePaging'; import { useElementInView } from '../../../hooks/useElementInView'; import { useFqn } from '../../../hooks/useFqn'; import { - deleteGlossary, - deleteGlossaryTerm, getGlossariesList, getGlossaryTermByFQN, patchGlossaries, @@ -64,7 +68,7 @@ import Fqn from '../../../utils/Fqn'; import i18n from '../../../utils/i18next/LocalUtil'; import { checkPermission } from '../../../utils/PermissionsUtils'; import { getGlossaryPath } from '../../../utils/RouterUtils'; -import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils'; +import { showErrorToast } from '../../../utils/ToastUtils'; import GlossaryLeftPanel from '../GlossaryLeftPanel/GlossaryLeftPanel.component'; const GlossaryPage = () => { @@ -72,6 +76,7 @@ const GlossaryPage = () => { const { fqn: glossaryFqn } = useFqn(); const { t } = useTranslation(); const history = useHistory(); + const { handleOnAsyncEntityDeleteConfirm } = useAsyncDeleteProvider(); const { action } = useParams<{ action: EntityAction }>(); const [initialised, setInitialised] = useState(false); @@ -328,22 +333,14 @@ const GlossaryPage = () => { const handleGlossaryDelete = useCallback( async (id: string) => { try { - await deleteGlossary(id); - showSuccessToast( - t('server.entity-deleted-successfully', { - entity: t('label.glossary'), - }) - ); - setIsLoading(true); - // check if the glossary is available - const updatedGlossaries = glossaries.filter((item) => item.id !== id); - setGlossaries(updatedGlossaries); - const glossaryPath = - updatedGlossaries.length > 0 - ? getGlossaryPath(updatedGlossaries[0].fullyQualifiedName) - : getGlossaryPath(); - - history.push(glossaryPath); + await handleOnAsyncEntityDeleteConfirm({ + entityName: activeGlossary?.name, + entityId: id, + entityType: EntityType.GLOSSARY, + deleteType: DeleteType.HARD_DELETE, + prepareType: true, + isRecursiveDelete: true, + }); } catch (error) { showErrorToast( error as AxiosError, @@ -351,11 +348,9 @@ const GlossaryPage = () => { entity: t('label.glossary'), }) ); - } finally { - setIsLoading(false); } }, - [glossaries, history] + [glossaries, activeGlossary] ); const handleGlossaryTermUpdate = useCallback( @@ -393,13 +388,14 @@ const GlossaryPage = () => { const handleGlossaryTermDelete = useCallback( async (id: string) => { try { - await deleteGlossaryTerm(id); - - showSuccessToast( - t('server.entity-deleted-successfully', { - entity: t('label.glossary-term'), - }) - ); + await handleOnAsyncEntityDeleteConfirm({ + entityName: activeGlossary?.name, + entityId: id, + entityType: EntityType.GLOSSARY_TERM, + deleteType: DeleteType.HARD_DELETE, + prepareType: true, + isRecursiveDelete: true, + }); let fqn; if (glossaryFqn) { @@ -407,10 +403,7 @@ const GlossaryPage = () => { fqnArr.pop(); fqn = fqnArr.join(FQN_SEPARATOR_CHAR); } - - setIsLoading(true); history.push(getGlossaryPath(fqn)); - fetchGlossaryList(); } catch (err) { showErrorToast( err as AxiosError, @@ -420,7 +413,7 @@ const GlossaryPage = () => { ); } }, - [glossaryFqn, history, fetchGlossaryList] + [glossaryFqn, activeGlossary] ); const handleAssetClick = useCallback( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.test.tsx index 0b9e533901a..d6853f0271d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.test.tsx @@ -14,11 +14,7 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; import { MOCK_GLOSSARY } from '../../../mocks/Glossary.mock'; -import { - deleteGlossary, - deleteGlossaryTerm, - patchGlossaryTerm, -} from '../../../rest/glossaryAPI'; +import { patchGlossaryTerm } from '../../../rest/glossaryAPI'; import GlossaryPage from './GlossaryPage.component'; jest.mock('../../../hooks/useFqn', () => ({ @@ -101,17 +97,19 @@ jest.mock('../GlossaryLeftPanel/GlossaryLeftPanel.component', () => {
Left Panel
)); }); + jest.mock('../../../rest/glossaryAPI', () => ({ deleteGlossary: jest.fn().mockImplementation(() => Promise.resolve()), deleteGlossaryTerm: jest.fn().mockImplementation(() => Promise.resolve()), getGlossaryTermByFQN: jest .fn() .mockImplementation(() => Promise.resolve({ data: MOCK_GLOSSARY })), - getGlossariesList: jest - .fn() - .mockImplementation(() => - Promise.resolve({ data: [MOCK_GLOSSARY], paging: { total: 1 } }) - ), + getGlossariesList: jest.fn().mockImplementation(() => + Promise.resolve({ + data: [MOCK_GLOSSARY], + paging: { total: 1 }, + }) + ), patchGlossaryTerm: jest .fn() .mockImplementation(() => Promise.resolve({ data: MOCK_GLOSSARY })), @@ -180,38 +178,6 @@ describe('Test GlossaryComponent page', () => { }); describe('Render Sad Paths', () => { - it('show error if deleteGlossaryTerm API fails', async () => { - (deleteGlossaryTerm as jest.Mock).mockImplementationOnce(() => - Promise.reject() - ); - render(); - const handleGlossaryTermDelete = await screen.findByTestId( - 'handleGlossaryTermDelete' - ); - - expect(handleGlossaryTermDelete).toBeInTheDocument(); - - await act(async () => { - fireEvent.click(handleGlossaryTermDelete); - }); - }); - - it('show error if deleteGlossary API fails', async () => { - (deleteGlossary as jest.Mock).mockImplementationOnce(() => - Promise.reject() - ); - render(); - const handleGlossaryDelete = await screen.findByTestId( - 'handleGlossaryDelete' - ); - - expect(handleGlossaryDelete).toBeInTheDocument(); - - await act(async () => { - fireEvent.click(handleGlossaryDelete); - }); - }); - it('show error if patchGlossaryTerm API resolves without data', async () => { (patchGlossaryTerm as jest.Mock).mockImplementation(() => Promise.resolve({ data: '' }) diff --git a/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts b/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts index d95169bc6d4..8b89002aee5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts @@ -164,16 +164,6 @@ export const patchGlossaryTerm = async (id: string, patch: Operation[]) => { return response.data; }; -export const deleteGlossary = (id: string) => { - return APIClient.delete(`/glossaries/${id}?recursive=true&hardDelete=true`); -}; - -export const deleteGlossaryTerm = (id: string) => { - return APIClient.delete( - `/glossaryTerms/${id}?recursive=true&hardDelete=true` - ); -}; - export const exportGlossaryInCSVFormat = async (glossaryName: string) => { const response = await APIClient.get( `/glossaries/name/${getEncodedFqn(glossaryName)}/exportAsync` diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DeleteWidget/DeleteWidgetClassBase.ts b/openmetadata-ui/src/main/resources/ui/src/utils/DeleteWidget/DeleteWidgetClassBase.ts index c9ad74cf7f8..2cebbc7cbfa 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DeleteWidget/DeleteWidgetClassBase.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DeleteWidget/DeleteWidgetClassBase.ts @@ -35,6 +35,8 @@ class DeleteWidgetClassBase { return `services/${entityType}s`; } else if (entityType === EntityType.GLOSSARY) { return `glossaries`; + } else if (entityType === EntityType.GLOSSARY_TERM) { + return `glossaryTerms`; } else if (entityType === EntityType.POLICY) { return 'policies'; } else if (entityType === EntityType.KPI) {