mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-23 08:28:10 +00:00
fix glossary duplicates (#20801)
This commit is contained in:
parent
555be6d961
commit
db41fc5ac5
@ -55,6 +55,7 @@ import {
|
|||||||
deselectColumns,
|
deselectColumns,
|
||||||
dragAndDropColumn,
|
dragAndDropColumn,
|
||||||
dragAndDropTerm,
|
dragAndDropTerm,
|
||||||
|
fillGlossaryTermDetails,
|
||||||
filterStatus,
|
filterStatus,
|
||||||
goToAssetsTab,
|
goToAssetsTab,
|
||||||
openColumnDropdown,
|
openColumnDropdown,
|
||||||
@ -1384,6 +1385,55 @@ test.describe('Glossary tests', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Check for duplicate Glossary Term', async ({ browser }) => {
|
||||||
|
const { page, afterAction, apiContext } = await performAdminLogin(browser);
|
||||||
|
const glossary1 = new Glossary('PW_TEST_GLOSSARY');
|
||||||
|
const glossaryTerm1 = new GlossaryTerm(
|
||||||
|
glossary1,
|
||||||
|
undefined,
|
||||||
|
'PW_TEST_TERM'
|
||||||
|
);
|
||||||
|
const glossaryTerm2 = new GlossaryTerm(
|
||||||
|
glossary1,
|
||||||
|
undefined,
|
||||||
|
'Pw_test_term'
|
||||||
|
);
|
||||||
|
await glossary1.create(apiContext);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sidebarClick(page, SidebarItem.GLOSSARY);
|
||||||
|
await selectActiveGlossary(page, glossary1.data.displayName);
|
||||||
|
|
||||||
|
await test.step('Create Glossary Term One', async () => {
|
||||||
|
await fillGlossaryTermDetails(page, glossaryTerm1.data, false, false);
|
||||||
|
|
||||||
|
const glossaryTermResponse = page.waitForResponse(
|
||||||
|
'/api/v1/glossaryTerms'
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="save-glossary-term"]');
|
||||||
|
await glossaryTermResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Create Glossary Term Two', async () => {
|
||||||
|
await fillGlossaryTermDetails(page, glossaryTerm2.data, false, false);
|
||||||
|
|
||||||
|
const glossaryTermResponse = page.waitForResponse(
|
||||||
|
'/api/v1/glossaryTerms'
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="save-glossary-term"]');
|
||||||
|
await glossaryTermResponse;
|
||||||
|
|
||||||
|
await expect(page.locator('#name_help')).toHaveText(
|
||||||
|
`A term with the name '${glossaryTerm2.data.name}' already exists in '${glossary1.data.name}' glossary.`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await glossaryTerm1.delete(apiContext);
|
||||||
|
await glossary1.delete(apiContext);
|
||||||
|
await afterAction();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test.afterAll(async ({ browser }) => {
|
test.afterAll(async ({ browser }) => {
|
||||||
const { afterAction, apiContext } = await performAdminLogin(browser);
|
const { afterAction, apiContext } = await performAdminLogin(browser);
|
||||||
await user1.delete(apiContext);
|
await user1.delete(apiContext);
|
||||||
|
@ -73,6 +73,33 @@ const GlossaryTermModal: FC<Props> = ({
|
|||||||
setSaving(true);
|
setSaving(true);
|
||||||
try {
|
try {
|
||||||
await onSave(values);
|
await onSave(values);
|
||||||
|
} catch (error) {
|
||||||
|
if ((error as AxiosError)?.response?.status === 400) {
|
||||||
|
const errorMessage =
|
||||||
|
(error as AxiosError<{ message: string }>)?.response?.data?.message ??
|
||||||
|
'';
|
||||||
|
|
||||||
|
// Handle name duplication error
|
||||||
|
if (errorMessage.includes('already exists')) {
|
||||||
|
form.setFields([
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
errors: [errorMessage],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
// Handle tag mutual exclusivity error
|
||||||
|
else if (errorMessage.includes('mutually exclusive')) {
|
||||||
|
form.setFields([
|
||||||
|
{
|
||||||
|
name: 'tags',
|
||||||
|
errors: [errorMessage],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
}
|
}
|
||||||
@ -84,7 +111,9 @@ const GlossaryTermModal: FC<Props> = ({
|
|||||||
} else {
|
} else {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
!visible && form.resetFields();
|
if (!visible) {
|
||||||
|
form.resetFields();
|
||||||
|
}
|
||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -18,7 +18,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
|
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
|
||||||
import { HTTP_STATUS_CODE } from '../../constants/Auth.constants';
|
|
||||||
import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider';
|
||||||
import {
|
import {
|
||||||
OperationPermission,
|
OperationPermission,
|
||||||
@ -196,40 +195,21 @@ const GlossaryV1 = ({
|
|||||||
currentData: GlossaryTerm,
|
currentData: GlossaryTerm,
|
||||||
updatedData: GlossaryTerm
|
updatedData: GlossaryTerm
|
||||||
) => {
|
) => {
|
||||||
try {
|
const jsonPatch = compare(currentData, updatedData);
|
||||||
const jsonPatch = compare(currentData, updatedData);
|
const response = await patchGlossaryTerm(currentData?.id, jsonPatch);
|
||||||
const response = await patchGlossaryTerm(currentData?.id, jsonPatch);
|
if (!response) {
|
||||||
if (!response) {
|
throw new Error(
|
||||||
throw t('server.entity-updating-error', {
|
t('server.entity-updating-error', {
|
||||||
entity: t('label.glossary-term'),
|
entity: t('label.glossary-term'),
|
||||||
});
|
})
|
||||||
} else {
|
);
|
||||||
updateGlossaryTermInStore({
|
} else {
|
||||||
...response,
|
updateGlossaryTermInStore({
|
||||||
// Since patch didn't respond with childrenCount preserve it from currentData
|
...response,
|
||||||
childrenCount: currentData.childrenCount,
|
// Since patch didn't respond with childrenCount preserve it from currentData
|
||||||
});
|
childrenCount: currentData.childrenCount,
|
||||||
setIsEditModalOpen(false);
|
});
|
||||||
}
|
setIsEditModalOpen(false);
|
||||||
} catch (error) {
|
|
||||||
if (
|
|
||||||
(error as AxiosError).response?.status === HTTP_STATUS_CODE.CONFLICT
|
|
||||||
) {
|
|
||||||
showErrorToast(
|
|
||||||
t('server.entity-already-exist', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
entityPlural: t('label.glossary-term-lowercase-plural'),
|
|
||||||
name: updatedData.name,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
showErrorToast(
|
|
||||||
error as AxiosError,
|
|
||||||
t('server.entity-updating-error', {
|
|
||||||
entity: t('label.glossary-term-lowercase'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -255,36 +235,15 @@ const GlossaryV1 = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleGlossaryTermAdd = async (formData: GlossaryTermForm) => {
|
const handleGlossaryTermAdd = async (formData: GlossaryTermForm) => {
|
||||||
try {
|
const term = await addGlossaryTerm({
|
||||||
const term = await addGlossaryTerm({
|
...formData,
|
||||||
...formData,
|
glossary:
|
||||||
glossary:
|
activeGlossaryTerm?.glossary?.name ||
|
||||||
activeGlossaryTerm?.glossary?.name ||
|
(selectedData.fullyQualifiedName ?? ''),
|
||||||
(selectedData.fullyQualifiedName ?? ''),
|
parent: activeGlossaryTerm?.fullyQualifiedName,
|
||||||
parent: activeGlossaryTerm?.fullyQualifiedName,
|
});
|
||||||
});
|
|
||||||
|
|
||||||
onTermModalSuccess(term);
|
onTermModalSuccess(term);
|
||||||
} catch (error) {
|
|
||||||
if (
|
|
||||||
(error as AxiosError).response?.status === HTTP_STATUS_CODE.CONFLICT
|
|
||||||
) {
|
|
||||||
showErrorToast(
|
|
||||||
t('server.entity-already-exist', {
|
|
||||||
entity: t('label.glossary-term'),
|
|
||||||
entityPlural: t('label.glossary-term-lowercase-plural'),
|
|
||||||
name: formData.name,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
showErrorToast(
|
|
||||||
error as AxiosError,
|
|
||||||
t('server.create-entity-error', {
|
|
||||||
entity: t('label.glossary-term-lowercase'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGlossaryTermSave = async (formData: GlossaryTermForm) => {
|
const handleGlossaryTermSave = async (formData: GlossaryTermForm) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user