mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-29 17:49:14 +00:00
fix(ui): tree dropdown for glossary terms inside form (#21173)
* fix: add tree dropdown for glossary terms inside form * fix: add domain form
This commit is contained in:
parent
2f4355bd4e
commit
c185862e40
@ -117,6 +117,9 @@ const AddDomainForm = ({
|
||||
selectProps: {
|
||||
'data-testid': 'glossary-terms-container',
|
||||
},
|
||||
open: false,
|
||||
hasNoActionButtons: true,
|
||||
isTreeSelect: true,
|
||||
tagType: TagSource.Glossary,
|
||||
placeholder: t('label.select-field', {
|
||||
field: t('label.glossary-term-plural'),
|
||||
@ -248,7 +251,7 @@ const AddDomainForm = ({
|
||||
style,
|
||||
experts: expertsList.map((item) => item.name ?? ''),
|
||||
owners: ownersList ?? [],
|
||||
tags: [...(formData.tags || []), ...(formData.glossaryTerms || [])],
|
||||
tags: [...(formData.tags ?? []), ...(formData.glossaryTerms ?? [])],
|
||||
} as CreateDomain | CreateDataProduct;
|
||||
|
||||
onSubmit(data);
|
||||
|
||||
@ -248,7 +248,7 @@ const AddGlossaryTermForm = ({
|
||||
required: false,
|
||||
label: t('label.related-term-plural'),
|
||||
id: 'root/relatedTerms',
|
||||
type: FieldTypes.ASYNC_SELECT_LIST,
|
||||
type: FieldTypes.TREE_ASYNC_SELECT_LIST,
|
||||
props: {
|
||||
className: 'glossary-select',
|
||||
'data-testid': 'related-terms',
|
||||
@ -256,6 +256,8 @@ const AddGlossaryTermForm = ({
|
||||
placeholder: t('label.add-entity', {
|
||||
entity: t('label.related-term-plural'),
|
||||
}),
|
||||
open: false,
|
||||
hasNoActionButtons: true,
|
||||
fetchOptions: fetchGlossaryList,
|
||||
initialOptions: glossaryTerm?.relatedTerms?.map((data) => ({
|
||||
label: data.fullyQualifiedName,
|
||||
|
||||
@ -40,4 +40,6 @@ export interface AsyncSelectListProps {
|
||||
search: string,
|
||||
page: number
|
||||
) => Promise<PagingResponse<SelectOption[]>>;
|
||||
open?: boolean;
|
||||
hasNoActionButtons?: boolean;
|
||||
}
|
||||
|
||||
@ -25,7 +25,14 @@ import { Key } from 'antd/lib/table/interface';
|
||||
import { AxiosError } from 'axios';
|
||||
import { debounce, get, isEmpty, isNull, isUndefined, pick } from 'lodash';
|
||||
import { CustomTagProps } from 'rc-select/lib/BaseSelect';
|
||||
import React, { FC, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, {
|
||||
FC,
|
||||
ReactElement,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as ArrowIcon } from '../../../assets/svg/ic-arrow-down.svg';
|
||||
import { PAGE_SIZE_LARGE, TEXT_BODY_COLOR } from '../../../constants/constants';
|
||||
@ -67,6 +74,8 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
|
||||
isSubmitLoading,
|
||||
filterOptions = [],
|
||||
onCancel,
|
||||
open: openProp = true,
|
||||
hasNoActionButtons,
|
||||
...props
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -76,9 +85,14 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
|
||||
const expandableKeys = useRef<string[]>([]);
|
||||
const [expandedRowKeys, setExpandedRowKeys] = useState<Key[]>([]);
|
||||
const [searchOptions, setSearchOptions] = useState<Glossary[] | null>(null);
|
||||
const [open, setOpen] = useState(openProp); // state for controlling dropdown visibility
|
||||
|
||||
const form = Form.useFormInstance();
|
||||
|
||||
const handleDropdownVisibleChange = (visible: boolean) => {
|
||||
setOpen(visible);
|
||||
};
|
||||
|
||||
const fetchGlossaryListInternal = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
@ -286,14 +300,15 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
|
||||
|
||||
return (
|
||||
<TreeSelect
|
||||
autoFocus
|
||||
open
|
||||
showSearch
|
||||
treeCheckStrictly
|
||||
treeCheckable
|
||||
autoFocus={open}
|
||||
className="async-select-list"
|
||||
data-testid="tag-selector"
|
||||
dropdownRender={dropdownRender}
|
||||
dropdownRender={
|
||||
hasNoActionButtons ? (menu: ReactElement) => menu : dropdownRender
|
||||
}
|
||||
dropdownStyle={{ width: 300 }}
|
||||
filterTreeNode={false}
|
||||
loadData={({ id, name }) => {
|
||||
@ -315,6 +330,7 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
|
||||
/>
|
||||
)
|
||||
}
|
||||
open={open}
|
||||
showCheckedStrategy={TreeSelect.SHOW_ALL}
|
||||
style={{ width: '100%' }}
|
||||
switcherIcon={
|
||||
@ -328,6 +344,7 @@ const TreeAsyncSelectList: FC<Omit<AsyncSelectListProps, 'fetchOptions'>> = ({
|
||||
treeData={treeData}
|
||||
treeExpandedKeys={isEmpty(searchOptions) ? undefined : expandedRowKeys}
|
||||
onChange={handleChange}
|
||||
onDropdownVisibleChange={handleDropdownVisibleChange}
|
||||
onSearch={onSearch}
|
||||
onTreeExpand={setExpandedRowKeys}
|
||||
{...props}
|
||||
|
||||
@ -42,6 +42,7 @@ export enum FieldTypes {
|
||||
COLOR_PICKER = 'color_picker',
|
||||
DOMAIN_SELECT = 'domain_select',
|
||||
CRON_EDITOR = 'cron_editor',
|
||||
TREE_ASYNC_SELECT_LIST = 'tree_async_select_list',
|
||||
}
|
||||
|
||||
export enum HelperTextType {
|
||||
|
||||
@ -18,6 +18,7 @@ import { EntityTags } from 'Models';
|
||||
import React, { useMemo } from 'react';
|
||||
import AsyncSelectList from '../../../components/common/AsyncSelectList/AsyncSelectList';
|
||||
import { SelectOption } from '../../../components/common/AsyncSelectList/AsyncSelectList.interface';
|
||||
import TreeAsyncSelectList from '../../../components/common/AsyncSelectList/TreeAsyncSelectList';
|
||||
import { TagSource } from '../../../generated/entity/data/container';
|
||||
import { TagLabel } from '../../../generated/type/tagLabel';
|
||||
import tagClassBase from '../../../utils/TagClassBase';
|
||||
@ -30,6 +31,9 @@ export interface TagSuggestionProps {
|
||||
initialOptions?: SelectOption[];
|
||||
onChange?: (newTags: TagLabel[]) => void;
|
||||
selectProps?: SelectProps;
|
||||
isTreeSelect?: boolean;
|
||||
hasNoActionButtons?: boolean;
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
const TagSuggestion: React.FC<TagSuggestionProps> = ({
|
||||
@ -39,6 +43,9 @@ const TagSuggestion: React.FC<TagSuggestionProps> = ({
|
||||
initialOptions,
|
||||
tagType = TagSource.Classification,
|
||||
selectProps,
|
||||
isTreeSelect = false,
|
||||
hasNoActionButtons = false,
|
||||
open = true,
|
||||
}) => {
|
||||
const isGlossaryType = useMemo(
|
||||
() => tagType === TagSource.Glossary,
|
||||
@ -81,21 +88,28 @@ const TagSuggestion: React.FC<TagSuggestionProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<AsyncSelectList
|
||||
fetchOptions={isGlossaryType ? fetchGlossaryList : tagClassBase.getTags}
|
||||
initialOptions={initialOptions}
|
||||
{...selectProps}
|
||||
mode="multiple"
|
||||
placeholder={
|
||||
placeholder ??
|
||||
t('label.select-field', {
|
||||
field: t('label.tag-plural'),
|
||||
})
|
||||
}
|
||||
value={value?.map((item) => item.tagFQN) ?? []}
|
||||
onChange={handleTagSelection}
|
||||
const commonProps = {
|
||||
fetchOptions: isGlossaryType ? fetchGlossaryList : tagClassBase.getTags,
|
||||
initialOptions,
|
||||
...selectProps,
|
||||
mode: 'multiple' as const,
|
||||
placeholder:
|
||||
placeholder ??
|
||||
t('label.select-field', {
|
||||
field: t('label.tag-plural'),
|
||||
}),
|
||||
value: value?.map((item) => item.tagFQN) ?? [],
|
||||
onChange: handleTagSelection,
|
||||
};
|
||||
|
||||
return isTreeSelect ? (
|
||||
<TreeAsyncSelectList
|
||||
{...commonProps}
|
||||
hasNoActionButtons={hasNoActionButtons}
|
||||
open={open}
|
||||
/>
|
||||
) : (
|
||||
<AsyncSelectList {...commonProps} />
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ import { compact, startCase, toString } from 'lodash';
|
||||
import React, { Fragment, ReactNode } from 'react';
|
||||
import AsyncSelectList from '../components/common/AsyncSelectList/AsyncSelectList';
|
||||
import { AsyncSelectListProps } from '../components/common/AsyncSelectList/AsyncSelectList.interface';
|
||||
import TreeAsyncSelectList from '../components/common/AsyncSelectList/TreeAsyncSelectList';
|
||||
import ColorPicker from '../components/common/ColorPicker/ColorPicker.component';
|
||||
import DomainSelectableList from '../components/common/DomainSelectableList/DomainSelectableList.component';
|
||||
import { DomainSelectableListProps } from '../components/common/DomainSelectableList/DomainSelectableList.interface';
|
||||
@ -172,6 +173,15 @@ export const getField = (field: FieldProp) => {
|
||||
|
||||
break;
|
||||
|
||||
case FieldTypes.TREE_ASYNC_SELECT_LIST:
|
||||
fieldElement = (
|
||||
<TreeAsyncSelectList
|
||||
{...(props as unknown as Omit<AsyncSelectListProps, 'fetchOptions'>)}
|
||||
/>
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case FieldTypes.ASYNC_SELECT_LIST:
|
||||
fieldElement = (
|
||||
<AsyncSelectList {...(props as unknown as AsyncSelectListProps)} />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user