MINOR: filter out glossary term option of same term in the related term (#17213)

* filter out glossary term option of same term in the related term

* fix sonar
This commit is contained in:
Ashish Gupta 2024-07-28 17:38:49 +05:30 committed by GitHub
parent e93bf7024f
commit 464d6cab72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 127 additions and 11 deletions

View File

@ -269,6 +269,7 @@ const RelatedTerms = ({
defaultValue={selectedOption.map(
(item) => item.fullyQualifiedName ?? ''
)}
filterOptions={[glossaryTerm?.fullyQualifiedName ?? '']}
placeholder={t('label.add-entity', {
entity: t('label.related-term-plural'),
})}

View File

@ -28,6 +28,7 @@ const TagSelectForm = ({
onCancel,
tagData,
tagType,
filterOptions,
}: TagsSelectFormProps) => {
const [form] = useForm();
const [isSubmitLoading, setIsSubmitLoading] = useState(false);
@ -52,6 +53,7 @@ const TagSelectForm = ({
<AsyncSelectList
open
fetchOptions={fetchApi}
filterOptions={filterOptions}
initialOptions={tagData}
isSubmitLoading={isSubmitLoading}
mode="multiple"
@ -62,6 +64,7 @@ const TagSelectForm = ({
/>
) : (
<TreeAsyncSelectList
filterOptions={filterOptions}
initialOptions={tagData}
isSubmitLoading={isSubmitLoading}
optionClassName="tag-select-box"

View File

@ -20,6 +20,7 @@ export type TagsSelectFormProps = {
placeholder: string;
defaultValue: string[];
tagData?: SelectOption[];
filterOptions?: string[]; // array of fqn
onChange?: (value: string[]) => void;
onSubmit: (option: DefaultOptionType | DefaultOptionType[]) => Promise<void>;
onCancel: () => void;

View File

@ -32,6 +32,7 @@ jest.mock('../../../utils/GlossaryUtils', () => ({
]),
convertGlossaryTermsToTreeOptions: jest.fn(),
findGlossaryTermByFqn: jest.fn(),
filterTreeNodeOptions: jest.fn().mockReturnValue([]),
}));
describe('TreeAsyncSelectList', () => {

View File

@ -41,6 +41,7 @@ import {
import { getEntityName } from '../../../utils/EntityUtils';
import {
convertGlossaryTermsToTreeOptions,
filterTreeNodeOptions,
findGlossaryTermByFqn,
} from '../../../utils/GlossaryUtils';
import {
@ -63,6 +64,7 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
initialOptions,
tagType,
isSubmitLoading,
filterOptions = [],
onCancel,
...props
}) => {
@ -82,7 +84,9 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
const { data } = await getGlossariesList({
limit: PAGE_SIZE_LARGE,
});
setGlossaries((prev) => [...prev, ...data]);
setGlossaries((prev) =>
filterTreeNodeOptions([...prev, ...data], filterOptions)
);
} catch (error) {
showErrorToast(error as AxiosError);
} finally {
@ -229,6 +233,7 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
const activeGlossary = results[0];
setGlossaries((prev) =>
filterTreeNodeOptions(
prev.map((glossary) => ({
...glossary,
children: get(
@ -236,7 +241,9 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
'children',
[]
),
}))
})),
filterOptions
)
);
} catch (error) {
showErrorToast(error as AxiosError);
@ -248,7 +255,7 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
const encodedValue = getEncodedFqn(escapeESReservedCharacters(value));
const results: Glossary[] = await searchGlossaryTerms(encodedValue);
setSearchOptions(results);
setSearchOptions(filterTreeNodeOptions(results, filterOptions));
setExpandedRowKeys(
results.map((result) => result.fullyQualifiedName as string)
);

View File

@ -12,6 +12,7 @@
*/
import { ModifiedGlossaryTerm } from '../components/Glossary/GlossaryTermTab/GlossaryTermTab.interface';
import { EntityType } from '../enums/entity.enum';
import { Glossary } from '../generated/entity/data/glossary';
import {
MOCKED_GLOSSARY_TERMS,
MOCKED_GLOSSARY_TERMS_1,
@ -20,6 +21,7 @@ import {
} from '../mocks/Glossary.mock';
import {
buildTree,
filterTreeNodeOptions,
findExpandableKeys,
findExpandableKeysForArray,
getQueryFilterToExcludeTerm,
@ -159,4 +161,61 @@ describe('Glossary Utils', () => {
expect(expandableKeys).toEqual(['example1', 'example2']);
});
it('Should return same Glossary when no filterOption is provided', () => {
const glossary = [
{
fullyQualifiedName: 'example1',
children: [
{
fullyQualifiedName: 'child1',
},
],
},
{
fullyQualifiedName: 'example2',
childrenCount: 2,
},
{
fullyQualifiedName: 'example3',
},
];
const filteredOptions = filterTreeNodeOptions(glossary as Glossary[], []);
expect(filteredOptions).toEqual(glossary);
});
it('Should return filtered Glossary when filterOption is provided', () => {
const glossary = [
{
fullyQualifiedName: 'example1',
children: [
{
fullyQualifiedName: 'child1',
},
],
},
{
fullyQualifiedName: 'example3',
},
];
const expected_glossary = [
{
fullyQualifiedName: 'example1',
children: [],
},
{
fullyQualifiedName: 'example3',
children: [],
},
];
const filteredOptions = filterTreeNodeOptions(glossary as Glossary[], [
'child1',
]);
expect(filteredOptions).toEqual(expected_glossary);
});
});

View File

@ -13,7 +13,7 @@
import { Typography } from 'antd';
import { DefaultOptionType } from 'antd/lib/select';
import { isEmpty } from 'lodash';
import { isEmpty, isUndefined } from 'lodash';
import React from 'react';
import { StatusType } from '../components/common/StatusBadge/StatusBadge.interface';
import { ModifiedGlossaryTerm } from '../components/Glossary/GlossaryTermTab/GlossaryTermTab.interface';
@ -265,3 +265,47 @@ export const findExpandableKeysForArray = (
return expandableKeys;
};
/**
* Filter out the tree node options based on the filter options.
*
* @param options - An array of Glossary objects.
* @param filterOptions - An array of FQN string to filter.
* @returns An array of filtered Glossary
*/
export const filterTreeNodeOptions = (
options: Glossary[],
filterOptions: string[]
): Glossary[] => {
if (isEmpty(filterOptions)) {
return options;
}
const filterNodes = (
nodes: ModifiedGlossaryTerm[]
): ModifiedGlossaryTerm[] => {
return nodes.reduce(
(acc: ModifiedGlossaryTerm[], node: ModifiedGlossaryTerm) => {
const isMatching = filterOptions.includes(
node.fullyQualifiedName ?? ''
);
const filteredChildren = !isUndefined(node.children)
? filterNodes(node.children as unknown as ModifiedGlossaryTerm[])
: [];
if (!isMatching) {
acc.push({
...node,
children: filteredChildren as GlossaryTerm[],
});
}
return acc;
},
[]
);
};
return filterNodes(options as ModifiedGlossaryTerm[]);
};