Skip to content

Commit

Permalink
Minor: add base class for tags (open-metadata#14218)
Browse files Browse the repository at this point in the history
* Minor: exclude knowledge center classification tags from tag suggestion

* add base class for tags

* add unit test

* clean up constants
  • Loading branch information
Sachin-chaurasiya authored and Shiyang Xiao committed Dec 12, 2023
1 parent bc81ff5 commit 0d2e883
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export type TagsContainerV2Props = {
children?: ReactElement;
displayType?: DisplayType;
layoutType?: LayoutType;
filterClassifications?: string[];
onSelectionChange?: (selectedTags: EntityTags[]) => Promise<void>;
onThreadLinkSelect?: (value: string, threadType?: ThreadType) => void;
};
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -62,7 +56,6 @@ const TagsContainerV2 = ({
onSelectionChange,
onThreadLinkSelect,
children,
filterClassifications = [KNOWLEDGE_CENTER_CLASSIFICATION],
}: TagsContainerV2Props) => {
const history = useHistory();
const [form] = Form.useForm();
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -818,5 +818,3 @@ export const ICON_DIMENSION = {
export const COMMON_ICON_STYLES: CSSProperties = {
verticalAlign: 'middle',
};

export const KNOWLEDGE_CENTER_CLASSIFICATION = 'KnowledgeCenter';
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -83,7 +81,7 @@ const TagSuggestion: React.FC<TagSuggestionProps> = ({

return (
<AsyncSelectList
fetchOptions={isGlossaryType ? fetchGlossaryList : fetchTagsElasticSearch}
fetchOptions={isGlossaryType ? fetchGlossaryList : tagClassBase.getTags}
initialOptions={initialOptions}
mode="multiple"
placeholder={
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
},
});
});
});
44 changes: 44 additions & 0 deletions openmetadata-ui/src/main/resources/ui/src/utils/TagClassBase.ts
Original file line number Diff line number Diff line change
@@ -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 };
42 changes: 2 additions & 40 deletions openmetadata-ui/src/main/resources/ui/src/utils/TagsUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 0d2e883

Please sign in to comment.