mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-07 08:03:09 +00:00
fix glossary tags missing while edit operation (#14125)
This commit is contained in:
parent
853a83f8b9
commit
ab807164b2
@ -28,6 +28,7 @@ export interface AsyncSelectListProps {
|
|||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
debounceTimeout?: number;
|
debounceTimeout?: number;
|
||||||
defaultValue?: string[];
|
defaultValue?: string[];
|
||||||
|
value?: string[];
|
||||||
initialOptions?: SelectOption[];
|
initialOptions?: SelectOption[];
|
||||||
onChange?: (option: DefaultOptionType | DefaultOptionType[]) => void;
|
onChange?: (option: DefaultOptionType | DefaultOptionType[]) => void;
|
||||||
fetchOptions: (
|
fetchOptions: (
|
||||||
|
@ -236,7 +236,7 @@ const AsyncSelectList: FC<AsyncSelectListProps> = ({
|
|||||||
{...props}>
|
{...props}>
|
||||||
{tagOptions.map(({ label, value, displayName, data }) => (
|
{tagOptions.map(({ label, value, displayName, data }) => (
|
||||||
<Select.Option
|
<Select.Option
|
||||||
className={className}
|
className={`${className} w-full`}
|
||||||
data={data}
|
data={data}
|
||||||
data-testid={`tag-${value}`}
|
data-testid={`tag-${value}`}
|
||||||
key={label}
|
key={label}
|
||||||
|
@ -12,28 +12,24 @@
|
|||||||
*/
|
*/
|
||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import { Button, Col, Form, FormProps, Input, Row, Space } from 'antd';
|
import { Button, Col, Form, FormProps, Input, Row, Space } from 'antd';
|
||||||
|
import { DefaultOptionType } from 'antd/lib/select';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { includes, isEmpty } from 'lodash';
|
import { isEmpty, isString } from 'lodash';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { ReactComponent as DeleteIcon } from '../../../assets/svg/ic-delete.svg';
|
import { ReactComponent as DeleteIcon } from '../../../assets/svg/ic-delete.svg';
|
||||||
import { PAGE_SIZE } from '../../../constants/constants';
|
|
||||||
import {
|
import {
|
||||||
ENTITY_NAME_REGEX,
|
ENTITY_NAME_REGEX,
|
||||||
HEX_COLOR_CODE_REGEX,
|
HEX_COLOR_CODE_REGEX,
|
||||||
} from '../../../constants/regex.constants';
|
} from '../../../constants/regex.constants';
|
||||||
import { SearchIndex } from '../../../enums/search.enum';
|
|
||||||
import { EntityReference } from '../../../generated/entity/type';
|
import { EntityReference } from '../../../generated/entity/type';
|
||||||
import { Paging } from '../../../generated/type/paging';
|
|
||||||
import {
|
import {
|
||||||
FieldProp,
|
FieldProp,
|
||||||
FieldTypes,
|
FieldTypes,
|
||||||
FormItemLayout,
|
FormItemLayout,
|
||||||
} from '../../../interface/FormUtils.interface';
|
} from '../../../interface/FormUtils.interface';
|
||||||
import { searchData } from '../../../rest/miscAPI';
|
|
||||||
import { formatSearchGlossaryTermResponse } from '../../../utils/APIUtils';
|
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
import { getEntityName } from '../../../utils/EntityUtils';
|
||||||
import { generateFormFields, getField } from '../../../utils/formUtils';
|
import { generateFormFields, getField } from '../../../utils/formUtils';
|
||||||
import { getEntityReferenceFromGlossaryTerm } from '../../../utils/GlossaryUtils';
|
import { fetchGlossaryList } from '../../../utils/TagsUtils';
|
||||||
import { useAuthContext } from '../../Auth/AuthProviders/AuthProvider';
|
import { useAuthContext } from '../../Auth/AuthProviders/AuthProvider';
|
||||||
import { UserTag } from '../../common/UserTag/UserTag.component';
|
import { UserTag } from '../../common/UserTag/UserTag.component';
|
||||||
import { UserTagSize } from '../../common/UserTag/UserTag.interface';
|
import { UserTagSize } from '../../common/UserTag/UserTag.interface';
|
||||||
@ -50,52 +46,12 @@ const AddGlossaryTermForm = ({
|
|||||||
formRef: form,
|
formRef: form,
|
||||||
}: AddGlossaryTermFormProps) => {
|
}: AddGlossaryTermFormProps) => {
|
||||||
const { currentUser } = useAuthContext();
|
const { currentUser } = useAuthContext();
|
||||||
const [relatedTermsOptions, setRelatedTermsOptions] = useState<
|
|
||||||
EntityReference[]
|
|
||||||
>([]);
|
|
||||||
const owner = Form.useWatch<EntityReference | undefined>('owner', form);
|
const owner = Form.useWatch<EntityReference | undefined>('owner', form);
|
||||||
const reviewersList =
|
const reviewersList =
|
||||||
Form.useWatch<EntityReference[]>('reviewers', form) ?? [];
|
Form.useWatch<EntityReference[]>('reviewers', form) ?? [];
|
||||||
|
|
||||||
const fetchGlossaryTerms = async (
|
const getRelatedTermFqnList = (relatedTerms: DefaultOptionType[]): string[] =>
|
||||||
searchText = '',
|
relatedTerms.map((tag: DefaultOptionType) => tag.value as string);
|
||||||
page: number
|
|
||||||
): Promise<{
|
|
||||||
data: {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
}[];
|
|
||||||
paging: Paging;
|
|
||||||
}> => {
|
|
||||||
const res = await searchData(
|
|
||||||
searchText,
|
|
||||||
page,
|
|
||||||
PAGE_SIZE,
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
SearchIndex.GLOSSARY
|
|
||||||
);
|
|
||||||
|
|
||||||
let termResult = formatSearchGlossaryTermResponse(res.data.hits.hits);
|
|
||||||
if (editMode && glossaryTerm) {
|
|
||||||
termResult = termResult.filter((item) => {
|
|
||||||
return item.fullyQualifiedName !== glossaryTerm.fullyQualifiedName;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const results = termResult.map(getEntityReferenceFromGlossaryTerm);
|
|
||||||
setRelatedTermsOptions((prev) => [...prev, ...results]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: results.map((item) => ({
|
|
||||||
label: item.fullyQualifiedName ?? '',
|
|
||||||
value: item.fullyQualifiedName ?? '',
|
|
||||||
})),
|
|
||||||
paging: {
|
|
||||||
total: res.data.hits.total.value,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSave: FormProps['onFinish'] = (formObj) => {
|
const handleSave: FormProps['onFinish'] = (formObj) => {
|
||||||
const {
|
const {
|
||||||
@ -127,10 +83,21 @@ const AddGlossaryTermForm = ({
|
|||||||
description: description,
|
description: description,
|
||||||
reviewers: reviewersList,
|
reviewers: reviewersList,
|
||||||
relatedTerms: editMode
|
relatedTerms: editMode
|
||||||
? relatedTermsOptions
|
? relatedTerms.map((term: DefaultOptionType) => {
|
||||||
.filter((item) => includes(relatedTerms, item.fullyQualifiedName))
|
if (isString(term)) {
|
||||||
.map((term) => term.id)
|
return glossaryTerm?.relatedTerms?.find(
|
||||||
: relatedTerms,
|
(r) => r.fullyQualifiedName === term
|
||||||
|
)?.id;
|
||||||
|
}
|
||||||
|
if (term.data) {
|
||||||
|
return term.data.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return glossaryTerm?.relatedTerms?.find(
|
||||||
|
(r) => r.fullyQualifiedName === term.value
|
||||||
|
)?.id;
|
||||||
|
})
|
||||||
|
: getRelatedTermFqnList(relatedTerms),
|
||||||
references: references.length > 0 ? references : undefined,
|
references: references.length > 0 ? references : undefined,
|
||||||
synonyms: synonyms,
|
synonyms: synonyms,
|
||||||
mutuallyExclusive,
|
mutuallyExclusive,
|
||||||
@ -169,7 +136,7 @@ const AddGlossaryTermForm = ({
|
|||||||
tags,
|
tags,
|
||||||
references,
|
references,
|
||||||
mutuallyExclusive,
|
mutuallyExclusive,
|
||||||
relatedTerms: relatedTerms?.map((r) => r.fullyQualifiedName || ''),
|
relatedTerms: relatedTerms?.map((r) => r.fullyQualifiedName ?? ''),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (reviewers) {
|
if (reviewers) {
|
||||||
@ -185,10 +152,6 @@ const AddGlossaryTermForm = ({
|
|||||||
if (owner) {
|
if (owner) {
|
||||||
form.setFieldValue('owner', owner);
|
form.setFieldValue('owner', owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relatedTerms && relatedTerms.length > 0) {
|
|
||||||
setRelatedTermsOptions((prev) => [...prev, ...relatedTerms]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [editMode, glossaryTerm, glossaryReviewers, form]);
|
}, [editMode, glossaryTerm, glossaryReviewers, form]);
|
||||||
|
|
||||||
@ -249,6 +212,11 @@ const AddGlossaryTermForm = ({
|
|||||||
type: FieldTypes.TAG_SUGGESTION,
|
type: FieldTypes.TAG_SUGGESTION,
|
||||||
props: {
|
props: {
|
||||||
'data-testid': 'tags-container',
|
'data-testid': 'tags-container',
|
||||||
|
initialOptions: glossaryTerm?.tags?.map((data) => ({
|
||||||
|
label: data.tagFQN,
|
||||||
|
value: data.tagFQN,
|
||||||
|
data,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -278,7 +246,12 @@ const AddGlossaryTermForm = ({
|
|||||||
placeholder: t('label.add-entity', {
|
placeholder: t('label.add-entity', {
|
||||||
entity: t('label.related-term-plural'),
|
entity: t('label.related-term-plural'),
|
||||||
}),
|
}),
|
||||||
fetchOptions: fetchGlossaryTerms,
|
fetchOptions: fetchGlossaryList,
|
||||||
|
initialOptions: glossaryTerm?.relatedTerms?.map((data) => ({
|
||||||
|
label: data.fullyQualifiedName,
|
||||||
|
value: data.fullyQualifiedName,
|
||||||
|
data,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -71,6 +71,7 @@ import {
|
|||||||
import { getCountBadge, Transi18next } from '../../../../utils/CommonUtils';
|
import { getCountBadge, Transi18next } from '../../../../utils/CommonUtils';
|
||||||
import { getEntityName } from '../../../../utils/EntityUtils';
|
import { getEntityName } from '../../../../utils/EntityUtils';
|
||||||
import { getEntityTypeFromSearchIndex } from '../../../../utils/SearchUtils';
|
import { getEntityTypeFromSearchIndex } from '../../../../utils/SearchUtils';
|
||||||
|
import { getDecodedFqn } from '../../../../utils/StringsUtils';
|
||||||
import { getEntityIcon } from '../../../../utils/TableUtils';
|
import { getEntityIcon } from '../../../../utils/TableUtils';
|
||||||
import { showErrorToast } from '../../../../utils/ToastUtils';
|
import { showErrorToast } from '../../../../utils/ToastUtils';
|
||||||
import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||||
@ -248,7 +249,7 @@ const AssetsTabs = forwardRef(
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case AssetsOfEntity.GLOSSARY:
|
case AssetsOfEntity.GLOSSARY:
|
||||||
data = await getGlossaryTermByFQN(fqn);
|
data = await getGlossaryTermByFQN(getDecodedFqn(fqn));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -83,7 +83,6 @@ const TagSuggestion: React.FC<TagSuggestionProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncSelectList
|
<AsyncSelectList
|
||||||
defaultValue={value?.map((item) => item.tagFQN) || []}
|
|
||||||
fetchOptions={isGlossaryType ? fetchGlossaryList : fetchTagsElasticSearch}
|
fetchOptions={isGlossaryType ? fetchGlossaryList : fetchTagsElasticSearch}
|
||||||
initialOptions={initialOptions}
|
initialOptions={initialOptions}
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
@ -93,6 +92,7 @@ const TagSuggestion: React.FC<TagSuggestionProps> = ({
|
|||||||
field: t('label.tag-plural'),
|
field: t('label.tag-plural'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
value={value?.map((item) => item.tagFQN) ?? []}
|
||||||
onChange={(value) => handleTagSelection(value)}
|
onChange={(value) => handleTagSelection(value)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user