From 0d2e883195d8392568a751ba8a4ada1d3e0a969b Mon Sep 17 00:00:00 2001 From: Sachin Chaurasiya Date: Mon, 4 Dec 2023 18:00:54 +0530 Subject: [PATCH] Minor: add base class for tags (#14218) * Minor: exclude knowledge center classification tags from tag suggestion * add base class for tags * add unit test * clean up constants --- .../TagsContainerV2.interface.ts | 1 - .../Tag/TagsContainerV2/TagsContainerV2.tsx | 17 +--- .../resources/ui/src/constants/constants.ts | 2 - .../pages/TasksPage/shared/TagSuggestion.tsx | 8 +- .../ui/src/utils/TagClassBase.test.ts | 97 +++++++++++++++++++ .../resources/ui/src/utils/TagClassBase.ts | 44 +++++++++ .../main/resources/ui/src/utils/TagsUtils.tsx | 42 +------- 7 files changed, 151 insertions(+), 60 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.test.ts 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/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'; 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..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 @@ -20,10 +20,8 @@ import AsyncSelectList from '../../../components/AsyncSelectList/AsyncSelectList import { SelectOption } from '../../../components/AsyncSelectList/AsyncSelectList.interface'; 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; @@ -83,7 +81,7 @@ const TagSuggestion: React.FC = ({ return ( { + 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, + }, + }); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.ts new file mode 100644 index 000000000000..f8cdf0d45b6c --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.ts @@ -0,0 +1,44 @@ +/* + * 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 { PAGE_SIZE } from '../constants/constants'; +import { SearchIndex } from '../enums/search.enum'; +import { searchQuery } from '../rest/searchAPI'; + +class TagClassBase { + public async getTags(searchText: string, page: number) { + const res = await searchQuery({ + query: `*${searchText}*`, + filters: 'disabled:false', + pageNumber: page, + pageSize: PAGE_SIZE, + queryFilter: {}, + searchIndex: SearchIndex.TAG, + }); + + return { + data: res.hits.hits.map(({ _source }) => ({ + 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