diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js index 1097d7d72df4..c491a5b921ae 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js @@ -39,10 +39,12 @@ import { SEARCH_ENTITY_TABLE, } from '../../constants/constants'; +const name = `test_dataconsumer${uuid()}`; + const CREDENTIALS = { firstName: 'Cypress', lastName: 'UserDC', - email: `test_dataconsumer${uuid()}@openmetadata.org`, + email: `${name}@openmetadata.org`, password: 'User@OMD123', username: 'CypressUserDC', }; @@ -278,9 +280,7 @@ const updateTags = (inTerm) => { '/api/v1/search/query?q=*&index=tag_search_index&from=0&size=*&query_filter=*', 'tags' ); - cy.get( - '[data-testid="tags-input-container"] [data-testid="add-tag"]' - ).click(); + cy.get('[data-testid="tags-container"] [data-testid="add-tag"]').click(); verifyResponseStatusCode('@tags', 200); @@ -294,7 +294,7 @@ const updateTags = (inTerm) => { cy.get('[data-testid="saveAssociatedTag"]').scrollIntoView().click(); const container = inTerm - ? '[data-testid="tags-input-container"]' + ? '[data-testid="tags-container"]' : '[data-testid="glossary-details"]'; cy.wait(1000); cy.get(container).scrollIntoView().contains('Personal').should('be.visible'); @@ -636,7 +636,7 @@ describe('Glossary page should work properly', () => { // Remove Tag cy.get( - '[data-testid="tags-input-container"] [data-testid="edit-button"]' + '[data-testid="tags-container"] [data-testid="edit-button"]' ).click(); cy.get('[data-testid="remove-tags"]').should('be.visible').click(); @@ -768,6 +768,64 @@ describe('Glossary page should work properly', () => { voteGlossary(); }); + it('Request Tags workflow for Glossary', function () { + cy.get('[data-testid="glossary-left-panel"]') + .contains(NEW_GLOSSARY_1.name) + .click(); + + interceptURL( + 'GET', + `/api/v1/search/query?q=*%20AND%20disabled:false&index=tag_search_index*`, + 'suggestTag' + ); + interceptURL('POST', '/api/v1/feed', 'taskCreated'); + interceptURL('PUT', '/api/v1/feed/tasks/*/resolve', 'taskResolve'); + + cy.get('[data-testid="request-entity-tags"]').should('exist').click(); + + // set assignees for task + cy.get( + '[data-testid="select-assignee"] > .ant-select-selector > .ant-select-selection-overflow' + ) + .click() + .type(name); + cy.get(`[data-testid="assignee-option-${name}"]`).click(); + cy.clickOutside(); + + cy.get('[data-testid="tag-selector"]') + .click() + .type('{backspace}') + .type('{backspace}') + .type('Personal'); + + verifyResponseStatusCode('@suggestTag', 200); + cy.get( + '.ant-select-dropdown [data-testid="tag-PersonalData.Personal"]' + ).click(); + cy.clickOutside(); + + cy.get('[data-testid="submit-tag-request"]').click(); + verifyResponseStatusCode('@taskCreated', 201); + + // Accept the tag suggestion which is created + cy.get('.ant-btn-compact-first-item').contains('Accept Suggestion').click(); + + verifyResponseStatusCode('@taskResolve', 200); + + cy.reload(); + + cy.get('[data-testid="glossary-left-panel"]') + .contains(NEW_GLOSSARY_1.name) + .click(); + + checkDisplayName(NEW_GLOSSARY_1.name); + + // Verify Tags which is added at the time of creating glossary + cy.get('[data-testid="tags-container"]') + .contains('Personal') + .should('be.visible'); + }); + it('Assets Tab should work properly', () => { selectActiveGlossary(NEW_GLOSSARY.name); const glossary = NEW_GLOSSARY.name; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.component.tsx index 9450f6d2dd75..c668132847a4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.component.tsx @@ -46,6 +46,7 @@ const GlossaryDetails = ({ onAddGlossaryTerm, onEditGlossaryTerm, isVersionView, + onThreadLinkSelect, }: GlossaryDetailsProps) => { const { t } = useTranslation(); const history = useHistory(); @@ -131,15 +132,19 @@ const GlossaryDetails = ({ setIsDescriptionEditable(false)} onDescriptionEdit={() => setIsDescriptionEditable(true)} onDescriptionUpdate={onDescriptionUpdate} + onThreadLinkSelect={onThreadLinkSelect} /> + diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts index f79d24151aa0..c9ffb55067e1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts @@ -33,4 +33,5 @@ export type GlossaryDetailsProps = { refreshGlossaryTerms: () => void; onAddGlossaryTerm: (glossaryTerm: GlossaryTerm | undefined) => void; onEditGlossaryTerm: (glossaryTerm: GlossaryTerm) => void; + onThreadLinkSelect: (value: string) => void; }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.test.tsx index 4eba4a5b30e0..441212f5e6b6 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.test.tsx @@ -65,6 +65,7 @@ const mockProps = { onAddGlossaryTerm: jest.fn(), onEditGlossaryTerm: jest.fn(), updateVote: jest.fn(), + onThreadLinkSelect: jest.fn(), }; describe('Test Glossary-details component', () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.component.tsx index e9c64eaaff36..b6c6ad725d21 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.component.tsx @@ -22,7 +22,6 @@ import { UserSelectableList } from '../../../components/common/UserSelectableLis import { UserTeamSelectableList } from '../../../components/common/UserTeamSelectableList/UserTeamSelectableList.component'; import { OperationPermission } from '../../../components/PermissionProvider/PermissionProvider.interface'; import TagButton from '../../../components/TagButton/TagButton.component'; -import TagsInput from '../../../components/TagsInput/TagsInput.component'; import { DE_ACTIVE_COLOR, getTeamAndUserDetailsPath, @@ -31,7 +30,7 @@ import { } from '../../../constants/constants'; import { EntityField } from '../../../constants/Feeds.constants'; import { EntityType } from '../../../enums/entity.enum'; -import { Glossary } from '../../../generated/entity/data/glossary'; +import { Glossary, TagSource } from '../../../generated/entity/data/glossary'; import { GlossaryTerm, TagLabel, @@ -47,6 +46,8 @@ import { getEntityVersionTags, } from '../../../utils/EntityVersionUtils'; import { DomainLabel } from '../../common/DomainLabel/DomainLabel.component'; +import TagsContainerV2 from '../../Tag/TagsContainerV2/TagsContainerV2'; +import { DisplayType } from '../../Tag/TagsViewer/TagsViewer.interface'; import GlossaryReviewers from './GlossaryReviewers'; type Props = { @@ -55,6 +56,7 @@ type Props = { selectedData: Glossary | GlossaryTerm; isGlossary: boolean; onUpdate: (data: GlossaryTerm | Glossary) => void; + onThreadLinkSelect: (value: string) => void; }; const GlossaryDetailsRightPanel = ({ @@ -63,6 +65,7 @@ const GlossaryDetailsRightPanel = ({ isGlossary, onUpdate, isVersionView, + onThreadLinkSelect, }: Props) => { const hasEditReviewerAccess = useMemo(() => { return permissions.EditAll || permissions.EditReviewers; @@ -307,11 +310,15 @@ const GlossaryDetailsRightPanel = ({
{isGlossary && ( - )}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.test.tsx index dfc567c8e4da..c9db49c24f54 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.test.tsx @@ -48,6 +48,7 @@ describe('GlossaryDetailsRightPanel', () => { isGlossary permissions={mockPermissions} selectedData={mockedGlossaries[0]} + onThreadLinkSelect={jest.fn()} onUpdate={jest.fn()} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx index dd420b940f5b..f3e43fca3c2e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx @@ -63,6 +63,7 @@ const GlossaryTermsV1 = ({ updateVote, refreshActiveGlossaryTerm, isVersionView, + onThreadLinkSelect, }: GlossaryTermsV1Props) => { const { fqn: glossaryFqn, @@ -130,6 +131,7 @@ const GlossaryTermsV1 = ({ isVersionView={isVersionView} permissions={permissions} selectedData={glossaryTerm} + onThreadLinkSelect={onThreadLinkSelect} onUpdate={(data) => handleGlossaryTermUpdate(data as GlossaryTerm)} /> ), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts index a653b3d7ea3e..6bcb02186cc8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts @@ -30,4 +30,5 @@ export interface GlossaryTermsV1Props { onEditGlossaryTerm: (glossaryTerm: GlossaryTerm) => void; updateVote?: (data: VotingDataProps) => Promise; refreshActiveGlossaryTerm?: () => void; + onThreadLinkSelect: (value: string) => void; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.test.tsx index da64b2c299a3..21a6ad52bd55 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.test.tsx @@ -83,6 +83,7 @@ const mockProps = { refreshActiveGlossaryTerm: jest.fn(), onAddGlossaryTerm: jest.fn(), onEditGlossaryTerm: jest.fn(), + onThreadLinkSelect: jest.fn(), }; describe('Test Glossary-term component', () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.component.tsx index 004538048529..30a0336e9527 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.component.tsx @@ -17,7 +17,7 @@ import { EntityType } from '../../../../enums/entity.enum'; import { Glossary } from '../../../../generated/entity/data/glossary'; import { GlossaryTerm } from '../../../../generated/entity/data/glossaryTerm'; import { ChangeDescription } from '../../../../generated/entity/type'; -import { TagLabel } from '../../../../generated/type/tagLabel'; +import { TagLabel, TagSource } from '../../../../generated/type/tagLabel'; import { getEntityName } from '../../../../utils/EntityUtils'; import { getEntityVersionByField, @@ -25,7 +25,8 @@ import { } from '../../../../utils/EntityVersionUtils'; import DescriptionV1 from '../../../common/EntityDescription/DescriptionV1'; import { OperationPermission } from '../../../PermissionProvider/PermissionProvider.interface'; -import TagsInput from '../../../TagsInput/TagsInput.component'; +import TagsContainerV2 from '../../../Tag/TagsContainerV2/TagsContainerV2'; +import { DisplayType } from '../../../Tag/TagsViewer/TagsViewer.interface'; import GlossaryDetailsRightPanel from '../../GlossaryDetailsRightPanel/GlossaryDetailsRightPanel.component'; import GlossaryTermReferences from './GlossaryTermReferences'; import GlossaryTermSynonyms from './GlossaryTermSynonyms'; @@ -37,6 +38,7 @@ type Props = { onUpdate: (data: GlossaryTerm | Glossary) => Promise; isGlossary: boolean; isVersionView?: boolean; + onThreadLinkSelect: (value: string) => void; }; const GlossaryOverviewTab = ({ @@ -45,6 +47,7 @@ const GlossaryOverviewTab = ({ onUpdate, isGlossary, isVersionView, + onThreadLinkSelect, }: Props) => { const [isDescriptionEditable, setIsDescriptionEditable] = useState(false); @@ -110,14 +113,17 @@ const GlossaryOverviewTab = ({ setIsDescriptionEditable(false)} onDescriptionEdit={() => setIsDescriptionEditable(true)} onDescriptionUpdate={onDescriptionUpdate} + onThreadLinkSelect={onThreadLinkSelect} /> @@ -153,11 +159,15 @@ const GlossaryOverviewTab = ({ - @@ -171,6 +181,7 @@ const GlossaryOverviewTab = ({ isVersionView={isVersionView} permissions={permissions} selectedData={selectedData} + onThreadLinkSelect={onThreadLinkSelect} onUpdate={onUpdate} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.test.tsx index 6a6a8c19cb5a..300077f9ede2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryOverviewTab.test.tsx @@ -50,6 +50,7 @@ describe('GlossaryOverviewTab', () => { isGlossary={isGlossary} permissions={permissions} selectedData={selectedData} + onThreadLinkSelect={jest.fn()} onUpdate={onUpdate} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx index 7955d6233108..0e441bcd446b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx @@ -25,9 +25,14 @@ import { getGlossaryTermDetailsPath, } from '../../constants/constants'; import { EntityAction } from '../../enums/entity.enum'; +import { + CreateThread, + ThreadType, +} from '../../generated/api/feed/createThread'; import { Glossary } from '../../generated/entity/data/glossary'; import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm'; import { VERSION_VIEW_GLOSSARY_PERMISSION } from '../../mocks/Glossary.mock'; +import { postThread } from '../../rest/feedsAPI'; import { addGlossaryTerm, getGlossaryTerms, @@ -37,6 +42,8 @@ import { import { getEntityDeleteMessage } from '../../utils/CommonUtils'; import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils'; import { showErrorToast } from '../../utils/ToastUtils'; +import { useActivityFeedProvider } from '../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider'; +import ActivityThreadPanel from '../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel'; import EntityDeleteModal from '../Modals/EntityDeleteModal/EntityDeleteModal'; import { usePermissionProvider } from '../PermissionProvider/PermissionProvider'; import { @@ -69,6 +76,11 @@ const GlossaryV1 = ({ const { action, tab } = useParams<{ action: EntityAction; glossaryName: string; tab: string }>(); const history = useHistory(); + const [threadLink, setThreadLink] = useState(''); + const [threadType, setThreadType] = useState( + ThreadType.Conversation + ); + const { postFeed, deleteFeed, updateFeed } = useActivityFeedProvider(); const { getEntityPermission } = usePermissionProvider(); const [isLoading, setIsLoading] = useState(true); @@ -96,6 +108,17 @@ const GlossaryV1 = ({ [action] ); + const onThreadPanelClose = () => { + setThreadLink(''); + }; + + const onThreadLinkSelect = (link: string, threadType?: ThreadType) => { + setThreadLink(link); + if (threadType) { + setThreadType(threadType); + } + }; + const fetchGlossaryTerm = async ( params?: ListGlossaryTermsParams, refresh?: boolean @@ -139,6 +162,19 @@ const GlossaryV1 = ({ } }; + const createThread = async (data: CreateThread) => { + try { + await postThread(data); + } catch (error) { + showErrorToast( + error as AxiosError, + t('server.create-entity-error', { + entity: t('label.conversation'), + }) + ); + } + }; + const handleDelete = () => { const { id } = selectedData; if (isGlossaryActive) { @@ -329,6 +365,7 @@ const GlossaryV1 = ({ onEditGlossaryTerm={(term) => handleGlossaryTermModalAction(true, term) } + onThreadLinkSelect={onThreadLinkSelect} /> ) : ( handleGlossaryTermModalAction(true, term) } + onThreadLinkSelect={onThreadLinkSelect} /> ))} @@ -376,6 +414,19 @@ const GlossaryV1 = ({ onSave={handleGlossaryTermSave} /> )} + + {threadLink ? ( + + ) : null} ); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Task/TaskTab/TaskTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Task/TaskTab/TaskTab.component.tsx index a5e481602a81..1548c199f66b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Task/TaskTab/TaskTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Task/TaskTab/TaskTab.component.tsx @@ -342,6 +342,7 @@ export const TaskTab = ({ ) : ( } menu={{ items: TASK_ACTION_LIST, diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts index 0fc43a30a3aa..7ba42936193d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts @@ -16,6 +16,8 @@ import { Dashboard } from '../../generated/entity/data/dashboard'; import { DashboardDataModel } from '../../generated/entity/data/dashboardDataModel'; import { Database } from '../../generated/entity/data/database'; import { DatabaseSchema } from '../../generated/entity/data/databaseSchema'; +import { Glossary } from '../../generated/entity/data/glossary'; +import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm'; import { Mlmodel } from '../../generated/entity/data/mlmodel'; import { Pipeline } from '../../generated/entity/data/pipeline'; import { SearchIndex } from '../../generated/entity/data/searchIndex'; @@ -34,7 +36,9 @@ export type EntityData = | Database | DatabaseSchema | DashboardDataModel - | SearchIndex; + | SearchIndex + | Glossary + | GlossaryTerm; export interface Option { label: string; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts index 59481045250d..31b438c3ef28 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts @@ -15,7 +15,10 @@ import { AxiosError } from 'axios'; import { isUndefined, omit } from 'lodash'; import { StatusType } from '../components/common/StatusBadge/StatusBadge.interface'; import { ModifiedGlossaryTerm } from '../components/Glossary/GlossaryTermTab/GlossaryTermTab.interface'; -import { WILD_CARD_CHAR } from '../constants/char.constants'; +import { + FQN_SEPARATOR_CHAR, + WILD_CARD_CHAR, +} from '../constants/char.constants'; import { SearchIndex } from '../enums/search.enum'; import { Glossary } from '../generated/entity/data/glossary'; import { GlossaryTerm, Status } from '../generated/entity/data/glossaryTerm'; @@ -24,6 +27,8 @@ import { SearchResponse } from '../interface/search.interface'; import { ListGlossaryTermsParams } from '../rest/glossaryAPI'; import { searchData } from '../rest/miscAPI'; import { formatSearchGlossaryTermResponse } from './APIUtils'; +import Fqn from './Fqn'; +import { getGlossaryPath } from './RouterUtils'; export interface GlossaryTermTreeNode { children?: GlossaryTermTreeNode[]; @@ -234,3 +239,26 @@ export const StatusFilters = Object.values(Status) text: status, value: status, })); + +export const getGlossaryBreadcrumbs = (fqn: string) => { + const arr = Fqn.split(fqn); + const dataFQN: Array = []; + const breadcrumbList = [ + { + name: 'Glossaries', + url: getGlossaryPath(''), + activeTitle: false, + }, + ...arr.map((d) => { + dataFQN.push(d); + + return { + name: d, + url: getGlossaryPath(dataFQN.join(FQN_SEPARATOR_CHAR)), + activeTitle: false, + }; + }), + ]; + + return breadcrumbList; +}; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts index e504e5d4a5f8..bdc7f1bb4c1e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts @@ -53,6 +53,7 @@ import { getDatabaseSchemaDetailsByFQN, } from '../rest/databaseAPI'; import { getDataModelDetailsByFQN } from '../rest/dataModelsAPI'; +import { getGlossariesByName, getGlossaryTermByFQN } from '../rest/glossaryAPI'; import { getUserSuggestions } from '../rest/miscAPI'; import { getMlModelByFQN } from '../rest/mlModelAPI'; import { getPipelineByFqn } from '../rest/pipelineAPI'; @@ -73,11 +74,12 @@ import { defaultFields as DataModelFields } from './DataModelsUtils'; import { defaultFields as TableFields } from './DatasetDetailsUtils'; import { getEntityName } from './EntityUtils'; import { getEntityFQN, getEntityType } from './FeedUtils'; +import { getGlossaryBreadcrumbs } from './GlossaryUtils'; import { defaultFields as MlModelFields } from './MlModelDetailsUtils'; import { defaultFields as PipelineFields } from './PipelineDetailsUtils'; import serviceUtilClassBase from './ServiceUtilClassBase'; import { STORED_PROCEDURE_DEFAULT_FIELDS } from './StoredProceduresUtils'; -import { getEncodedFqn } from './StringsUtils'; +import { getDecodedFqn, getEncodedFqn } from './StringsUtils'; import { getEntityLink } from './TableUtils'; import { showErrorToast } from './ToastUtils'; @@ -275,6 +277,8 @@ export const TASK_ENTITIES = [ EntityType.DASHBOARD_DATA_MODEL, EntityType.STORED_PROCEDURE, EntityType.SEARCH_INDEX, + EntityType.GLOSSARY, + EntityType.GLOSSARY_TERM, ]; export const getBreadCrumbList = ( @@ -308,12 +312,17 @@ export const getBreadCrumbList = ( const service = (serviceCategory: ServiceCategory) => { return { - name: getEntityName(entityData.service), - url: getEntityName(entityData.service) - ? getServiceDetailsPath(entityData.service?.name || '', serviceCategory) + name: getEntityName((entityData as Table).service), + url: getEntityName((entityData as Table).service) + ? getServiceDetailsPath( + (entityData as Table).service?.name ?? '', + serviceCategory + ) : '', - imgSrc: entityData.serviceType - ? serviceUtilClassBase.getServiceTypeLogo(entityData.serviceType) + imgSrc: (entityData as Table).serviceType + ? serviceUtilClassBase.getServiceTypeLogo( + (entityData as Table).serviceType as string + ) : undefined, }; }; @@ -372,6 +381,11 @@ export const getBreadCrumbList = ( ]; } + case EntityType.GLOSSARY: + case EntityType.GLOSSARY_TERM: { + return getGlossaryBreadcrumbs(entityData.fullyQualifiedName ?? ''); + } + default: return []; } @@ -485,6 +499,22 @@ export const fetchEntityDetail = ( .catch((err: AxiosError) => showErrorToast(err)); break; + case EntityType.GLOSSARY: + getGlossariesByName(entityFQN, TabSpecificField.TAGS) + .then((res) => { + setEntityData(res); + }) + .catch((err: AxiosError) => showErrorToast(err)); + + break; + case EntityType.GLOSSARY_TERM: + getGlossaryTermByFQN(getDecodedFqn(entityFQN), TabSpecificField.TAGS) + .then((res) => { + setEntityData(res); + }) + .catch((err: AxiosError) => showErrorToast(err)); + + break; default: break;