From 23f61868e0758b07949d2c34c55e6a472366089b Mon Sep 17 00:00:00 2001 From: Sachin Chaurasiya Date: Mon, 4 Dec 2023 15:18:42 +0530 Subject: [PATCH 1/4] Minor: exclude knowledge center classification tags from tag suggestion --- .../ui/src/pages/TasksPage/shared/TagSuggestion.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx index 99507dfc6577..26ac125b6642 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx @@ -18,6 +18,7 @@ import { EntityTags } from 'Models'; import React, { useMemo } from 'react'; import AsyncSelectList from '../../../components/AsyncSelectList/AsyncSelectList'; import { SelectOption } from '../../../components/AsyncSelectList/AsyncSelectList.interface'; +import { KNOWLEDGE_CENTER_CLASSIFICATION } from '../../../constants/constants'; import { TagSource } from '../../../generated/entity/data/container'; import { TagLabel } from '../../../generated/type/tagLabel'; import { @@ -30,6 +31,7 @@ export interface TagSuggestionProps { tagType?: TagSource; value?: TagLabel[]; initialOptions?: SelectOption[]; + filterClassifications?: string[]; onChange?: (newTags: TagLabel[]) => void; } @@ -39,6 +41,7 @@ const TagSuggestion: React.FC = ({ placeholder, initialOptions, tagType = TagSource.Classification, + filterClassifications = [KNOWLEDGE_CENTER_CLASSIFICATION], }) => { const isGlossaryType = useMemo( () => tagType === TagSource.Glossary, @@ -81,9 +84,17 @@ const TagSuggestion: React.FC = ({ } }; + const handleFetchOptions = async (search: string, page: number) => { + if (isGlossaryType) { + return fetchGlossaryList(search, page); + } + + return fetchTagsElasticSearch(search, page, filterClassifications); + }; + return ( Date: Mon, 4 Dec 2023 16:27:37 +0530 Subject: [PATCH 2/4] add base class for tags --- .../TagsContainerV2.interface.ts | 1 - .../Tag/TagsContainerV2/TagsContainerV2.tsx | 17 +++---- .../pages/TasksPage/shared/TagSuggestion.tsx | 19 ++------ .../resources/ui/src/utils/TagClassBase.ts | 44 +++++++++++++++++++ .../main/resources/ui/src/utils/TagsUtils.tsx | 42 +----------------- 5 files changed, 54 insertions(+), 69 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.ts diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.interface.ts index a5fbfcc285f1..c5fe002c7aad 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.interface.ts @@ -30,7 +30,6 @@ export type TagsContainerV2Props = { children?: ReactElement; displayType?: DisplayType; layoutType?: LayoutType; - filterClassifications?: string[]; onSelectionChange?: (selectedTags: EntityTags[]) => Promise; onThreadLinkSelect?: (value: string, threadType?: ThreadType) => void; }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx index c794f1753075..f8058bdc7443 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsContainerV2/TagsContainerV2.tsx @@ -22,19 +22,13 @@ import { ReactComponent as IconComments } from '../../../assets/svg/comment.svg' import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg'; import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg'; import { TableTagsProps } from '../../../components/TableTags/TableTags.interface'; -import { - DE_ACTIVE_COLOR, - KNOWLEDGE_CENTER_CLASSIFICATION, -} from '../../../constants/constants'; +import { DE_ACTIVE_COLOR } from '../../../constants/constants'; import { TAG_CONSTANT, TAG_START_WITH } from '../../../constants/Tag.constants'; import { TagSource } from '../../../generated/type/tagLabel'; import { getEntityFeedLink } from '../../../utils/EntityUtils'; import { getFilterTags } from '../../../utils/TableTags/TableTags.utils'; -import { - fetchGlossaryList, - fetchTagsElasticSearch, - getTagPlaceholder, -} from '../../../utils/TagsUtils'; +import tagClassBase from '../../../utils/TagClassBase'; +import { fetchGlossaryList, getTagPlaceholder } from '../../../utils/TagsUtils'; import { getRequestTagsPath, getUpdateTagsPath, @@ -62,7 +56,6 @@ const TagsContainerV2 = ({ onSelectionChange, onThreadLinkSelect, children, - filterClassifications = [KNOWLEDGE_CENTER_CLASSIFICATION], }: TagsContainerV2Props) => { const history = useHistory(); const [form] = Form.useForm(); @@ -95,12 +88,12 @@ const TagsContainerV2 = ({ const fetchAPI = useCallback( (searchValue: string, page: number) => { if (tagType === TagSource.Classification) { - return fetchTagsElasticSearch(searchValue, page, filterClassifications); + return tagClassBase.getTags(searchValue, page); } else { return fetchGlossaryList(searchValue, page); } }, - [tagType, filterClassifications] + [tagType] ); const showNoDataPlaceholder = useMemo( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx index 26ac125b6642..7e434c288222 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/shared/TagSuggestion.tsx @@ -18,20 +18,16 @@ import { EntityTags } from 'Models'; import React, { useMemo } from 'react'; import AsyncSelectList from '../../../components/AsyncSelectList/AsyncSelectList'; import { SelectOption } from '../../../components/AsyncSelectList/AsyncSelectList.interface'; -import { KNOWLEDGE_CENTER_CLASSIFICATION } from '../../../constants/constants'; import { TagSource } from '../../../generated/entity/data/container'; import { TagLabel } from '../../../generated/type/tagLabel'; -import { - fetchGlossaryList, - fetchTagsElasticSearch, -} from '../../../utils/TagsUtils'; +import tagClassBase from '../../../utils/TagClassBase'; +import { fetchGlossaryList } from '../../../utils/TagsUtils'; export interface TagSuggestionProps { placeholder?: string; tagType?: TagSource; value?: TagLabel[]; initialOptions?: SelectOption[]; - filterClassifications?: string[]; onChange?: (newTags: TagLabel[]) => void; } @@ -41,7 +37,6 @@ const TagSuggestion: React.FC = ({ placeholder, initialOptions, tagType = TagSource.Classification, - filterClassifications = [KNOWLEDGE_CENTER_CLASSIFICATION], }) => { const isGlossaryType = useMemo( () => tagType === TagSource.Glossary, @@ -84,17 +79,9 @@ const TagSuggestion: React.FC = ({ } }; - const handleFetchOptions = async (search: string, page: number) => { - if (isGlossaryType) { - return fetchGlossaryList(search, page); - } - - return fetchTagsElasticSearch(search, page, filterClassifications); - }; - return ( ({ + label: _source.fullyQualifiedName ?? '', + value: _source.fullyQualifiedName ?? '', + data: _source, + })), + paging: { + total: res.hits.total.value, + }, + }; + } +} + +const tagClassBase = new TagClassBase(); + +export default tagClassBase; +export { TagClassBase }; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TagsUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TagsUtils.tsx index edcc6ab9a21b..4384bb099c56 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TagsUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TagsUtils.tsx @@ -23,7 +23,7 @@ import { ReactComponent as DeleteIcon } from '../assets/svg/ic-delete.svg'; import RichTextEditorPreviewer from '../components/common/RichTextEditor/RichTextEditorPreviewer'; import Loader from '../components/Loader/Loader'; import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; -import { getExplorePath, PAGE_SIZE } from '../constants/constants'; +import { getExplorePath } from '../constants/constants'; import { SettledStatus } from '../enums/axios.enum'; import { ExplorePageTabs } from '../enums/Explore.enum'; import { SearchIndex } from '../enums/search.enum'; @@ -296,50 +296,12 @@ export const tagRender = (customTagProps: CustomTagProps) => { ); }; -type ResultType = { +export type ResultType = { label: string; value: string; data: Tag; }; -export const fetchTagsElasticSearch = async ( - searchText: string, - page: number, - filterClassifications?: string[] -): Promise<{ - data: ResultType[]; - paging: Paging; -}> => { - const res = await searchQuery({ - query: `*${searchText}*`, - filters: 'disabled:false', - pageNumber: page, - pageSize: PAGE_SIZE, - queryFilter: {}, - searchIndex: SearchIndex.TAG, - }); - - return { - data: res.hits.hits.reduce((result: ResultType[], { _source }) => { - const classificationName = - _source.classification?.fullyQualifiedName ?? ''; - - if (!filterClassifications?.includes(classificationName)) { - result.push({ - label: _source.fullyQualifiedName ?? '', - value: _source.fullyQualifiedName ?? '', - data: _source, - }); - } - - return result; - }, []), - paging: { - total: res.hits.total.value, - }, - }; -}; - export const fetchGlossaryList = async ( searchQueryParam: string, page: number From af80a098274d8c789b96b10a9b4c6f8ec4935526 Mon Sep 17 00:00:00 2001 From: Sachin Chaurasiya Date: Mon, 4 Dec 2023 16:34:12 +0530 Subject: [PATCH 3/4] add unit test --- .../ui/src/utils/TagClassBase.test.ts | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.test.ts diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.test.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.test.ts new file mode 100644 index 000000000000..61efade41071 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { SearchIndex } from '../enums/search.enum'; +import { searchQuery } from '../rest/searchAPI'; +import tagClassBase, { TagClassBase } from './TagClassBase'; + +jest.mock('../rest/searchAPI'); + +describe('TagClassBase', () => { + beforeEach(() => { + (searchQuery as jest.Mock).mockClear(); + }); + + it('should create an instance of TagClassBase', () => { + expect(tagClassBase).toBeInstanceOf(TagClassBase); + }); + + it('should call searchQuery with correct parameters', async () => { + const searchText = 'test'; + const page = 1; + + const mockResponse = { + hits: { + hits: [ + { + _source: { + fullyQualifiedName: 'test', + }, + }, + ], + total: { + value: 1, + }, + }, + }; + + (searchQuery as jest.Mock).mockResolvedValue(mockResponse); + await tagClassBase.getTags(searchText, page); + + expect(searchQuery).toHaveBeenCalledWith({ + query: `*${searchText}*`, + filters: 'disabled:false', + pageNumber: page, + pageSize: 10, // Assuming PAGE_SIZE is 10 + queryFilter: {}, + searchIndex: SearchIndex.TAG, + }); + }); + + it('should return correct data structure', async () => { + const searchText = 'test'; + const page = 1; + const mockResponse = { + hits: { + hits: [ + { + _source: { + fullyQualifiedName: 'test', + }, + }, + ], + total: { + value: 1, + }, + }, + }; + + (searchQuery as jest.Mock).mockResolvedValue(mockResponse); + + const result = await tagClassBase.getTags(searchText, page); + + expect(result).toEqual({ + data: [ + { + label: 'test', + value: 'test', + data: { + fullyQualifiedName: 'test', + }, + }, + ], + paging: { + total: 1, + }, + }); + }); +}); From ad2edc5b784d614b26dea745f35e45899f1061e3 Mon Sep 17 00:00:00 2001 From: Sachin Chaurasiya Date: Mon, 4 Dec 2023 16:53:13 +0530 Subject: [PATCH 4/4] clean up constants --- .../src/main/resources/ui/src/constants/constants.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts index ed7bbb7c19a6..410c2ed9bcea 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts @@ -818,5 +818,3 @@ export const ICON_DIMENSION = { export const COMMON_ICON_STYLES: CSSProperties = { verticalAlign: 'middle', }; - -export const KNOWLEDGE_CENTER_CLASSIFICATION = 'KnowledgeCenter';