mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-15 10:48:31 +00:00
fix(ui):supported separate tags for glossary and tags (#12068)
* supported separate tags for glossary and tags * fix cypress issue * fix cypress issue
This commit is contained in:
parent
5197682921
commit
10ba297961
@ -640,7 +640,7 @@ export const addNewTagToEntity = (entityObj, term) => {
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get('[data-testid="entity-tags"]')
|
||||
cy.get('[data-testid="tags-container"] [data-testid="entity-tags"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.contains(term);
|
||||
|
@ -38,8 +38,9 @@ const addTags = (tag, parent) => {
|
||||
const checkTags = (tag, checkForParentEntity) => {
|
||||
if (checkForParentEntity) {
|
||||
cy.get(
|
||||
'[data-testid="entity-right-panel"] [data-testid="tag-container"] [data-testid="entity-tags"] '
|
||||
'[data-testid="entity-right-panel"] [data-testid="tags-container"] [data-testid="entity-tags"] '
|
||||
)
|
||||
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.contains(tag);
|
||||
@ -48,9 +49,9 @@ const checkTags = (tag, checkForParentEntity) => {
|
||||
}
|
||||
};
|
||||
|
||||
const removeTags = (checkForParentEntity, separate) => {
|
||||
const removeTags = (checkForParentEntity) => {
|
||||
if (checkForParentEntity) {
|
||||
cy.get('[data-testid="entity-right-panel"] [data-testid="edit-button"] ')
|
||||
cy.get('[data-testid="entity-right-panel"] [data-testid="edit-button"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
@ -86,7 +87,9 @@ describe('Check if tags addition and removal flow working properly from tables',
|
||||
entityDetails.entity
|
||||
);
|
||||
|
||||
cy.get('[data-testid="entity-right-panel"] [data-testid="add-tag"]')
|
||||
cy.get(
|
||||
'[data-testid="entity-right-panel"] [data-testid="tags-container"] [data-testid="add-tag"]'
|
||||
)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
|
@ -281,7 +281,7 @@ describe('Tags page should work', () => {
|
||||
cy.get('[data-testid="tag-selector"] > .ant-select-selector').contains(tag);
|
||||
cy.get('[data-testid="saveAssociatedTag"]').scrollIntoView().click();
|
||||
verifyResponseStatusCode('@addTags', 200);
|
||||
cy.get('[data-testid="entity-tags"]')
|
||||
cy.get('[data-testid="tag-container"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.contains(tag);
|
||||
|
@ -36,7 +36,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { restoreDashboard } from 'rest/dashboardAPI';
|
||||
import { getEntityName } from 'utils/EntityUtils';
|
||||
import { getEntityName, getEntityThreadLink } from 'utils/EntityUtils';
|
||||
import { getFilterTags } from 'utils/TableTags/TableTags.utils';
|
||||
import { ReactComponent as ExternalLinkIcon } from '../../assets/svg/external-links.svg';
|
||||
import { EntityField } from '../../constants/Feeds.constants';
|
||||
@ -645,20 +645,35 @@ const DashboardDetails = ({
|
||||
className="entity-tag-right-panel-container"
|
||||
data-testid="entity-right-panel"
|
||||
flex="320px">
|
||||
<TagsContainerV1
|
||||
editable={
|
||||
dashboardPermissions.EditAll || dashboardPermissions.EditTags
|
||||
}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={dashboardDetails.fullyQualifiedName}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
selectedTags={dashboardTags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={dashboardDetails.fullyQualifiedName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
permission={
|
||||
dashboardPermissions.EditAll ||
|
||||
dashboardPermissions.EditTags
|
||||
}
|
||||
selectedTags={dashboardTags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<TagsContainerV1
|
||||
entityFqn={dashboardDetails.fullyQualifiedName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
permission={
|
||||
dashboardPermissions.EditAll ||
|
||||
dashboardPermissions.EditTags
|
||||
}
|
||||
selectedTags={dashboardTags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
|
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Card, Col, Row, Tabs } from 'antd';
|
||||
import { Card, Col, Row, Space, Tabs } from 'antd';
|
||||
import ActivityFeedProvider, {
|
||||
useActivityFeedProvider,
|
||||
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||
@ -29,13 +29,13 @@ import { getDataModelDetailsPath, getVersionPath } from 'constants/constants';
|
||||
import { EntityField } from 'constants/Feeds.constants';
|
||||
import { CSMode } from 'enums/codemirror.enum';
|
||||
import { EntityTabs, EntityType } from 'enums/entity.enum';
|
||||
import { LabelType, State, TagLabel } from 'generated/type/tagLabel';
|
||||
import { LabelType, State, TagLabel, TagSource } from 'generated/type/tagLabel';
|
||||
import { isUndefined, toString } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { getEntityName } from 'utils/EntityUtils';
|
||||
import { getEntityName, getEntityThreadLink } from 'utils/EntityUtils';
|
||||
import { getEntityFieldThreadCounts } from 'utils/FeedUtils';
|
||||
import { getTagsWithoutTier } from 'utils/TableUtils';
|
||||
import { DataModelDetailsProps } from './DataModelDetails.interface';
|
||||
@ -176,18 +176,28 @@ const DataModelDetails = ({
|
||||
className="entity-tag-right-panel-container"
|
||||
data-testid="entity-right-panel"
|
||||
flex="320px">
|
||||
<TagsContainerV1
|
||||
editable={hasEditTagsPermission}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={dashboardDataModelFQN}
|
||||
entityType={EntityType.DASHBOARD_DATA_MODEL}
|
||||
selectedTags={tags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={dashboardDataModelFQN}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.DASHBOARD_DATA_MODEL}
|
||||
permission={hasEditTagsPermission}
|
||||
selectedTags={tags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<TagsContainerV1
|
||||
entityFqn={dashboardDataModelFQN}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.DASHBOARD_DATA_MODEL}
|
||||
permission={hasEditTagsPermission}
|
||||
selectedTags={tags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Card, Col, Row, Table, Tabs, Typography } from 'antd';
|
||||
import { Card, Col, Row, Space, Table, Tabs, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { AxiosError } from 'axios';
|
||||
import ActivityFeedProvider, {
|
||||
@ -24,14 +24,14 @@ import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAss
|
||||
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import { TagLabel } from 'generated/type/schema';
|
||||
import { TagLabel, TagSource } from 'generated/type/schema';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { restoreMlmodel } from 'rest/mlModelAPI';
|
||||
import { getEntityName } from 'utils/EntityUtils';
|
||||
import { getEntityName, getEntityThreadLink } from 'utils/EntityUtils';
|
||||
import AppState from '../../AppState';
|
||||
import { getMlModelDetailsPath } from '../../constants/constants';
|
||||
import { EntityField } from '../../constants/Feeds.constants';
|
||||
@ -392,20 +392,33 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
|
||||
className="entity-tag-right-panel-container"
|
||||
data-testid="entity-right-panel"
|
||||
flex="320px">
|
||||
<TagsContainerV1
|
||||
editable={
|
||||
mlModelPermissions.EditAll || mlModelPermissions.EditTags
|
||||
}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={mlModelDetail.fullyQualifiedName}
|
||||
entityType={EntityType.MLMODEL}
|
||||
selectedTags={mlModelTags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={handleThreadLinkSelect}
|
||||
/>
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={mlModelDetail.fullyQualifiedName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.MLMODEL}
|
||||
permission={
|
||||
mlModelPermissions.EditAll || mlModelPermissions.EditTags
|
||||
}
|
||||
selectedTags={mlModelTags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={handleThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<TagsContainerV1
|
||||
entityFqn={mlModelDetail.fullyQualifiedName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.MLMODEL}
|
||||
permission={
|
||||
mlModelPermissions.EditAll || mlModelPermissions.EditTags
|
||||
}
|
||||
selectedTags={mlModelTags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={handleThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
|
@ -65,7 +65,7 @@ import {
|
||||
getFeedCounts,
|
||||
refreshPage,
|
||||
} from '../../utils/CommonUtils';
|
||||
import { getEntityName } from '../../utils/EntityUtils';
|
||||
import { getEntityName, getEntityThreadLink } from '../../utils/EntityUtils';
|
||||
import { getEntityFieldThreadCounts } from '../../utils/FeedUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
||||
@ -651,20 +651,33 @@ const PipelineDetails = ({
|
||||
className="entity-tag-right-panel-container"
|
||||
data-testid="entity-right-panel"
|
||||
flex="320px">
|
||||
<TagsContainerV1
|
||||
editable={
|
||||
pipelinePermissions.EditAll || pipelinePermissions.EditTags
|
||||
}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={pipelineFQN}
|
||||
entityType={EntityType.TOPIC}
|
||||
selectedTags={tags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={pipelineFQN}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.PIPELINE}
|
||||
permission={
|
||||
pipelinePermissions.EditAll || pipelinePermissions.EditTags
|
||||
}
|
||||
selectedTags={tags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<TagsContainerV1
|
||||
entityFqn={pipelineFQN}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.PIPELINE}
|
||||
permission={
|
||||
pipelinePermissions.EditAll || pipelinePermissions.EditTags
|
||||
}
|
||||
selectedTags={tags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
|
@ -15,7 +15,6 @@ import { ThreadType } from 'generated/api/feed/createThread';
|
||||
import { Tag } from 'generated/entity/classification/tag';
|
||||
import { GlossaryTerm } from 'generated/entity/data/glossaryTerm';
|
||||
import { TagSource } from 'generated/type/tagLabel';
|
||||
import { EntityFieldThreads } from 'interface/feed.interface';
|
||||
import { EntityTags } from 'Models';
|
||||
|
||||
interface TagsTreeProps {
|
||||
@ -29,10 +28,6 @@ export interface HierarchyTagsProps extends TagsTreeProps {
|
||||
children: TagsTreeProps[];
|
||||
}
|
||||
|
||||
export interface GlossaryTermNodeProps extends TagsTreeProps {
|
||||
children: TagsTreeProps[] | undefined;
|
||||
}
|
||||
|
||||
export type TagDetailsProps = {
|
||||
isLoading: boolean;
|
||||
options: {
|
||||
@ -60,13 +55,19 @@ export type GlossaryTermDetailsProps = {
|
||||
};
|
||||
|
||||
export type TagsContainerV1Props = {
|
||||
editable: boolean;
|
||||
permission: boolean;
|
||||
selectedTags: Array<EntityTags>;
|
||||
onSelectionChange: (selectedTags: Array<EntityTags>) => void;
|
||||
placeholder?: string;
|
||||
showLimited?: boolean;
|
||||
onThreadLinkSelect?: (value: string, threadType?: ThreadType) => void;
|
||||
onThreadLinkSelect: (value: string, threadType?: ThreadType) => void;
|
||||
entityType?: string;
|
||||
entityFieldThreads?: EntityFieldThreads[];
|
||||
entityThreadLink?: string;
|
||||
entityFqn?: string;
|
||||
tagType: TagSource;
|
||||
};
|
||||
|
||||
export type TagsTreeComponentProps = {
|
||||
placeholder: string;
|
||||
treeData: HierarchyTagsProps[];
|
||||
defaultValue: string[];
|
||||
onChange?: (value: string[]) => void;
|
||||
};
|
||||
|
@ -20,40 +20,37 @@ import {
|
||||
Popover,
|
||||
Row,
|
||||
Space,
|
||||
TreeSelect,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { ReactComponent as EditIcon } from 'assets/svg/edit-new.svg';
|
||||
import classNames from 'classnames';
|
||||
import Loader from 'components/Loader/Loader';
|
||||
import { TableTagsProps } from 'components/TableTags/TableTags.interface';
|
||||
import Tags from 'components/Tag/Tags/tags';
|
||||
import {
|
||||
API_RES_MAX_SIZE,
|
||||
DE_ACTIVE_COLOR,
|
||||
NO_DATA_PLACEHOLDER,
|
||||
PAGE_SIZE_LARGE,
|
||||
} from 'constants/constants';
|
||||
import { TAG_CONSTANT, TAG_START_WITH } from 'constants/Tag.constants';
|
||||
import { EntityType } from 'enums/entity.enum';
|
||||
import { TagSource } from 'generated/type/tagLabel';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { getGlossariesList, getGlossaryTerms } from 'rest/glossaryAPI';
|
||||
import { getEntityFeedLink } from 'utils/EntityUtils';
|
||||
import { getGlossaryTermHierarchy } from 'utils/GlossaryUtils';
|
||||
import { getFilterTags } from 'utils/TableTags/TableTags.utils';
|
||||
import { getAllTagsForOptions, getTagsHierarchy } from 'utils/TagsUtils';
|
||||
import {
|
||||
getRequestTagsPath,
|
||||
getUpdateTagsPath,
|
||||
TASK_ENTITIES,
|
||||
} from 'utils/TasksUtils';
|
||||
import { ReactComponent as IconCommentPlus } from '../../../assets/svg/add-chat.svg';
|
||||
import { ReactComponent as IconComments } from '../../../assets/svg/comment.svg';
|
||||
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
|
||||
import TagsV1 from '../TagsV1/TagsV1.component';
|
||||
import TagsViewer from '../TagsViewer/tags-viewer';
|
||||
import {
|
||||
GlossaryDetailsProps,
|
||||
@ -61,17 +58,17 @@ import {
|
||||
TagDetailsProps,
|
||||
TagsContainerV1Props,
|
||||
} from './TagsContainerV1.interface';
|
||||
import TagTree from './TagsTree.component';
|
||||
|
||||
const TagsContainerV1 = ({
|
||||
editable,
|
||||
permission,
|
||||
selectedTags,
|
||||
onSelectionChange,
|
||||
placeholder,
|
||||
showLimited,
|
||||
onThreadLinkSelect,
|
||||
entityType,
|
||||
entityFieldThreads,
|
||||
entityThreadLink,
|
||||
entityFqn,
|
||||
tagType,
|
||||
onSelectionChange,
|
||||
onThreadLinkSelect,
|
||||
}: TagsContainerV1Props) => {
|
||||
const history = useHistory();
|
||||
const [form] = Form.useForm();
|
||||
@ -90,19 +87,41 @@ const TagsContainerV1 = ({
|
||||
options: [],
|
||||
});
|
||||
|
||||
const tagThread = entityFieldThreads?.[0];
|
||||
const [tags, setTags] = useState<TableTagsProps>();
|
||||
|
||||
const showAddTagButton = useMemo(
|
||||
() => editable && isEmpty(selectedTags),
|
||||
[editable, selectedTags]
|
||||
const isGlossaryType = useMemo(
|
||||
() => tagType === TagSource.Glossary,
|
||||
[tagType]
|
||||
);
|
||||
|
||||
const handleRequestTags = () => {
|
||||
history.push(getRequestTagsPath(entityType as string, entityFqn as string));
|
||||
};
|
||||
const handleUpdateTags = () => {
|
||||
history.push(getUpdateTagsPath(entityType as string, entityFqn as string));
|
||||
};
|
||||
const searchPlaceholder = useMemo(
|
||||
() =>
|
||||
isGlossaryType
|
||||
? t('label.search-entity', {
|
||||
entity: t('label.glossary-term-plural'),
|
||||
})
|
||||
: t('label.search-entity', {
|
||||
entity: t('label.tag-plural'),
|
||||
}),
|
||||
[isGlossaryType]
|
||||
);
|
||||
|
||||
const showAddTagButton = useMemo(
|
||||
() => permission && isEmpty(tags?.[tagType]),
|
||||
[permission, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const selectedTagsInternal = useMemo(
|
||||
() => tags?.[tagType].map(({ tagFQN }) => tagFQN as string),
|
||||
[tags, tagType]
|
||||
);
|
||||
|
||||
const getTreeData = useMemo(() => {
|
||||
const tags = getTagsHierarchy(tagDetails.options);
|
||||
const glossary = getGlossaryTermHierarchy(glossaryDetails.options);
|
||||
|
||||
return [...tags, ...glossary];
|
||||
}, [tagDetails.options, glossaryDetails.options]);
|
||||
|
||||
const fetchTags = async () => {
|
||||
if (isEmpty(tagDetails.options) || tagDetails.isError) {
|
||||
@ -172,8 +191,8 @@ const TagsContainerV1 = ({
|
||||
};
|
||||
|
||||
const showNoDataPlaceholder = useMemo(
|
||||
() => !showAddTagButton && selectedTags.length === 0,
|
||||
[showAddTagButton, selectedTags]
|
||||
() => !showAddTagButton && isEmpty(tags?.[tagType]),
|
||||
[showAddTagButton, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const getUpdatedTags = (selectedTag: string[]): EntityTags[] => {
|
||||
@ -188,8 +207,13 @@ const TagsContainerV1 = ({
|
||||
};
|
||||
|
||||
const handleSave: FormProps['onFinish'] = (data) => {
|
||||
const tags = getUpdatedTags(data.tags);
|
||||
onSelectionChange(tags);
|
||||
const updatedTags = getUpdatedTags(data.tags);
|
||||
onSelectionChange([
|
||||
...updatedTags,
|
||||
...((isGlossaryType
|
||||
? tags?.[TagSource.Classification]
|
||||
: tags?.[TagSource.Glossary]) ?? []),
|
||||
]);
|
||||
form.resetFields();
|
||||
setIsEditTags(false);
|
||||
};
|
||||
@ -199,15 +223,14 @@ const TagsContainerV1 = ({
|
||||
form.resetFields();
|
||||
}, [form]);
|
||||
|
||||
const handleAddClick = () => {
|
||||
fetchTags();
|
||||
fetchGlossaryList();
|
||||
const handleAddClick = useCallback(() => {
|
||||
if (isGlossaryType) {
|
||||
fetchGlossaryList();
|
||||
} else {
|
||||
fetchTags();
|
||||
}
|
||||
setIsEditTags(true);
|
||||
};
|
||||
|
||||
const getTagsElement = (tag: EntityTags) => (
|
||||
<TagsV1 key={tag.tagFQN} tag={tag} />
|
||||
);
|
||||
}, [isGlossaryType, fetchGlossaryList, fetchTags]);
|
||||
|
||||
const addTagButton = useMemo(
|
||||
() =>
|
||||
@ -225,47 +248,19 @@ const TagsContainerV1 = ({
|
||||
);
|
||||
|
||||
const renderTags = useMemo(
|
||||
() =>
|
||||
showLimited ? (
|
||||
<TagsViewer
|
||||
isTextPlaceholder
|
||||
showNoDataPlaceholder={showNoDataPlaceholder}
|
||||
tags={selectedTags}
|
||||
type="border"
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{!showAddTagButton && isEmpty(selectedTags) ? (
|
||||
<Typography.Text data-testid="no-tags">
|
||||
{NO_DATA_PLACEHOLDER}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
{selectedTags.map(getTagsElement)}
|
||||
</>
|
||||
),
|
||||
[
|
||||
showLimited,
|
||||
showNoDataPlaceholder,
|
||||
selectedTags,
|
||||
getTagsElement,
|
||||
showAddTagButton,
|
||||
]
|
||||
() => (
|
||||
<TagsViewer
|
||||
isTextPlaceholder
|
||||
showNoDataPlaceholder={showNoDataPlaceholder}
|
||||
tags={tags?.[tagType] ?? []}
|
||||
type="border"
|
||||
/>
|
||||
),
|
||||
[showNoDataPlaceholder, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const selectedTagsInternal = useMemo(
|
||||
() => selectedTags.map(({ tagFQN }) => tagFQN as string),
|
||||
[selectedTags]
|
||||
);
|
||||
|
||||
const getTreeData = useMemo(() => {
|
||||
const tags = getTagsHierarchy(tagDetails.options);
|
||||
const glossary = getGlossaryTermHierarchy(glossaryDetails.options);
|
||||
|
||||
return [...tags, ...glossary];
|
||||
}, [tagDetails.options, glossaryDetails.options]);
|
||||
|
||||
const tagsSelectContainer = useMemo(() => {
|
||||
return tagDetails.isLoading && glossaryDetails.isLoading ? (
|
||||
return tagDetails.isLoading || glossaryDetails.isLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<Form form={form} name="tagsForm" onFinish={handleSave}>
|
||||
@ -292,32 +287,10 @@ const TagsContainerV1 = ({
|
||||
|
||||
<Col className="gutter-row" span={24}>
|
||||
<Form.Item noStyle name="tags">
|
||||
<TreeSelect
|
||||
autoFocus
|
||||
multiple
|
||||
showSearch
|
||||
treeDefaultExpandAll
|
||||
treeLine
|
||||
className={classNames('w-full')}
|
||||
data-testid="tag-selector"
|
||||
defaultValue={selectedTagsInternal}
|
||||
placeholder={
|
||||
placeholder
|
||||
? placeholder
|
||||
: t('label.select-field', {
|
||||
field: t('label.tag-plural'),
|
||||
})
|
||||
}
|
||||
removeIcon={
|
||||
<CloseOutlined
|
||||
data-testid="remove-tags"
|
||||
height={8}
|
||||
width={8}
|
||||
/>
|
||||
}
|
||||
showCheckedStrategy={TreeSelect.SHOW_ALL}
|
||||
<TagTree
|
||||
defaultValue={selectedTagsInternal ?? []}
|
||||
placeholder={searchPlaceholder}
|
||||
treeData={getTreeData}
|
||||
treeNodeFilterProp="title"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
@ -325,23 +298,26 @@ const TagsContainerV1 = ({
|
||||
</Form>
|
||||
);
|
||||
}, [
|
||||
searchPlaceholder,
|
||||
selectedTagsInternal,
|
||||
handleCancel,
|
||||
handleSave,
|
||||
placeholder,
|
||||
glossaryDetails,
|
||||
tagDetails,
|
||||
getTreeData,
|
||||
handleCancel,
|
||||
handleSave,
|
||||
]);
|
||||
|
||||
const getRequestTagsElements = useCallback(() => {
|
||||
const hasTags = !isEmpty(selectedTags);
|
||||
const text = hasTags
|
||||
? t('label.update-request-tag-plural')
|
||||
: t('label.request-tag-plural');
|
||||
const handleRequestTags = () => {
|
||||
history.push(getRequestTagsPath(entityType as string, entityFqn as string));
|
||||
};
|
||||
const handleUpdateTags = () => {
|
||||
history.push(getUpdateTagsPath(entityType as string, entityFqn as string));
|
||||
};
|
||||
|
||||
return onThreadLinkSelect &&
|
||||
TASK_ENTITIES.includes(entityType as EntityType) ? (
|
||||
const requestTagElement = useMemo(() => {
|
||||
const hasTags = !isEmpty(tags?.[tagType]);
|
||||
|
||||
return TASK_ENTITIES.includes(entityType as EntityType) ? (
|
||||
<Col>
|
||||
<Button
|
||||
className="p-0 flex-center"
|
||||
@ -351,7 +327,11 @@ const TagsContainerV1 = ({
|
||||
onClick={hasTags ? handleUpdateTags : handleRequestTags}>
|
||||
<Popover
|
||||
destroyTooltipOnHide
|
||||
content={text}
|
||||
content={
|
||||
hasTags
|
||||
? t('label.update-request-tag-plural')
|
||||
: t('label.request-tag-plural')
|
||||
}
|
||||
overlayClassName="ant-popover-request-description"
|
||||
placement="topLeft"
|
||||
trigger="hover"
|
||||
@ -366,57 +346,53 @@ const TagsContainerV1 = ({
|
||||
</Button>
|
||||
</Col>
|
||||
) : null;
|
||||
}, [tags?.[tagType], handleUpdateTags, handleRequestTags]);
|
||||
|
||||
const conversationThreadElement = useMemo(
|
||||
() => (
|
||||
<Col>
|
||||
<Button
|
||||
className="p-0 flex-center"
|
||||
data-testid="tag-thread"
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() =>
|
||||
onThreadLinkSelect(
|
||||
entityThreadLink ??
|
||||
getEntityFeedLink(entityType, entityFqn, 'tags')
|
||||
)
|
||||
}>
|
||||
<Space align="center" className="w-full h-full" size={2}>
|
||||
<IconComments height={16} name="comments" width={16} />
|
||||
</Space>
|
||||
</Button>
|
||||
</Col>
|
||||
),
|
||||
[
|
||||
entityType,
|
||||
entityFqn,
|
||||
entityThreadLink,
|
||||
getEntityFeedLink,
|
||||
onThreadLinkSelect,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setTags(getFilterTags(selectedTags));
|
||||
}, [selectedTags]);
|
||||
|
||||
const getThreadElements = () => {
|
||||
if (!isUndefined(entityFieldThreads)) {
|
||||
return !isUndefined(tagThread) ? (
|
||||
<Col>
|
||||
<Button
|
||||
className="p-0 flex-center"
|
||||
data-testid="tag-thread"
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() => onThreadLinkSelect?.(tagThread.entityLink)}>
|
||||
<Space align="center" className="w-full h-full" size={2}>
|
||||
<IconComments height={16} name="comments" width={16} />
|
||||
<span data-testid="tag-thread-count">{tagThread.count}</span>
|
||||
</Space>
|
||||
</Button>
|
||||
</Col>
|
||||
) : (
|
||||
<Col>
|
||||
<Button
|
||||
className="p-0 flex-center"
|
||||
data-testid="start-tag-thread"
|
||||
icon={<IconCommentPlus height={16} name="comments" width={16} />}
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() =>
|
||||
onThreadLinkSelect?.(
|
||||
getEntityFeedLink(entityType, entityFqn, 'tags')
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div data-testid="tag-container">
|
||||
<div data-testid={isGlossaryType ? 'glossary-container' : 'tags-container'}>
|
||||
<div className="d-flex justify-between m-b-xs">
|
||||
<div className="d-flex items-center">
|
||||
<Typography.Text className="right-panel-label">
|
||||
{t('label.tag-plural')}
|
||||
{isGlossaryType ? t('label.glossary-term') : t('label.tag-plural')}
|
||||
</Typography.Text>
|
||||
{editable && selectedTags.length > 0 && (
|
||||
{permission && !isEmpty(tags?.[tagType]) && (
|
||||
<Button
|
||||
className="cursor-pointer flex-center m-l-xss"
|
||||
data-testid="edit-button"
|
||||
disabled={!editable}
|
||||
disabled={!permission}
|
||||
icon={<EditIcon color={DE_ACTIVE_COLOR} width="14px" />}
|
||||
size="small"
|
||||
type="text"
|
||||
@ -425,8 +401,8 @@ const TagsContainerV1 = ({
|
||||
)}
|
||||
</div>
|
||||
<Row gutter={8}>
|
||||
{getRequestTagsElements()}
|
||||
{getThreadElements()}
|
||||
{requestTagElement}
|
||||
{conversationThreadElement}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 { CloseOutlined } from '@ant-design/icons';
|
||||
import { TreeSelect } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import { TagsTreeComponentProps } from './TagsContainerV1.interface';
|
||||
|
||||
const TagTree = ({
|
||||
defaultValue,
|
||||
placeholder,
|
||||
treeData,
|
||||
onChange,
|
||||
}: TagsTreeComponentProps) => {
|
||||
return (
|
||||
<TreeSelect
|
||||
autoFocus
|
||||
multiple
|
||||
showSearch
|
||||
treeDefaultExpandAll
|
||||
treeLine
|
||||
className={classNames('w-full')}
|
||||
data-testid="tag-selector"
|
||||
defaultValue={defaultValue}
|
||||
placeholder={placeholder}
|
||||
removeIcon={
|
||||
<CloseOutlined data-testid="remove-tags" height={8} width={8} />
|
||||
}
|
||||
showCheckedStrategy={TreeSelect.SHOW_ALL}
|
||||
treeData={treeData}
|
||||
treeNodeFilterProp="title"
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagTree;
|
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Card, Col, Row, Tabs } from 'antd';
|
||||
import { Card, Col, Row, Space, Tabs } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import ActivityFeedProvider, {
|
||||
useActivityFeedProvider,
|
||||
@ -30,12 +30,12 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { restoreTopic } from 'rest/topicsAPI';
|
||||
import { getEntityName } from 'utils/EntityUtils';
|
||||
import { getEntityName, getEntityThreadLink } from 'utils/EntityUtils';
|
||||
import { EntityField } from '../../constants/Feeds.constants';
|
||||
import { EntityTabs, EntityType } from '../../enums/entity.enum';
|
||||
import { Topic } from '../../generated/entity/data/topic';
|
||||
import { ThreadType } from '../../generated/entity/feed/thread';
|
||||
import { LabelType, State } from '../../generated/type/tagLabel';
|
||||
import { LabelType, State, TagSource } from '../../generated/type/tagLabel';
|
||||
import { getCurrentUserId, refreshPage } from '../../utils/CommonUtils';
|
||||
import { getEntityFieldThreadCounts } from '../../utils/FeedUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||
@ -307,18 +307,33 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
|
||||
className="entity-tag-right-panel-container"
|
||||
data-testid="entity-right-panel"
|
||||
flex="320px">
|
||||
<TagsContainerV1
|
||||
editable={topicPermissions.EditAll || topicPermissions.EditTags}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={topicDetails.fullyQualifiedName}
|
||||
entityType={EntityType.TOPIC}
|
||||
selectedTags={topicTags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={topicDetails.fullyQualifiedName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.TOPIC}
|
||||
permission={
|
||||
topicPermissions.EditAll || topicPermissions.EditTags
|
||||
}
|
||||
selectedTags={topicTags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<TagsContainerV1
|
||||
entityFqn={topicDetails.fullyQualifiedName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.TOPIC}
|
||||
permission={
|
||||
topicPermissions.EditAll || topicPermissions.EditTags
|
||||
}
|
||||
selectedTags={topicTags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Card, Col, Row, Tabs } from 'antd';
|
||||
import { Card, Col, Row, Space, Tabs } from 'antd';
|
||||
import AppState from 'AppState';
|
||||
import { AxiosError } from 'axios';
|
||||
import ActivityFeedProvider, {
|
||||
@ -77,7 +77,11 @@ import {
|
||||
refreshPage,
|
||||
sortTagsCaseInsensitive,
|
||||
} from 'utils/CommonUtils';
|
||||
import { getEntityLineage, getEntityName } from 'utils/EntityUtils';
|
||||
import {
|
||||
getEntityLineage,
|
||||
getEntityName,
|
||||
getEntityThreadLink,
|
||||
} from 'utils/EntityUtils';
|
||||
import { getEntityFieldThreadCounts } from 'utils/FeedUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils';
|
||||
import { getLineageViewPath } from 'utils/RouterUtils';
|
||||
@ -623,18 +627,28 @@ const ContainerPage = () => {
|
||||
className="entity-tag-right-panel-container"
|
||||
data-testid="entity-right-panel"
|
||||
flex="320px">
|
||||
<TagsContainerV1
|
||||
editable={hasEditDescriptionPermission}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={containerName}
|
||||
entityType={EntityType.CONTAINER}
|
||||
selectedTags={tags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={containerName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.CONTAINER}
|
||||
permission={hasEditDescriptionPermission}
|
||||
selectedTags={tags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<TagsContainerV1
|
||||
entityFqn={containerName}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.CONTAINER}
|
||||
permission={hasEditDescriptionPermission}
|
||||
selectedTags={tags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Card, Col, Divider, Row, Tabs } from 'antd';
|
||||
import { Card, Col, Divider, Row, Space, Tabs } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import ActivityFeedProvider, {
|
||||
useActivityFeedProvider,
|
||||
@ -46,7 +46,7 @@ import { compare } from 'fast-json-patch';
|
||||
import { CreateThread } from 'generated/api/feed/createThread';
|
||||
import { JoinedWith, Table } from 'generated/entity/data/table';
|
||||
import { ThreadType } from 'generated/entity/feed/thread';
|
||||
import { LabelType, State, TagLabel } from 'generated/type/tagLabel';
|
||||
import { LabelType, State, TagLabel, TagSource } from 'generated/type/tagLabel';
|
||||
import { EntityFieldThreadCount } from 'interface/feed.interface';
|
||||
import { isEmpty, isEqual } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
@ -71,7 +71,7 @@ import {
|
||||
sortTagsCaseInsensitive,
|
||||
} from 'utils/CommonUtils';
|
||||
import { defaultFields } from 'utils/DatasetDetailsUtils';
|
||||
import { getEntityName } from 'utils/EntityUtils';
|
||||
import { getEntityName, getEntityThreadLink } from 'utils/EntityUtils';
|
||||
import { getEntityFieldThreadCounts } from 'utils/FeedUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils';
|
||||
import { createQueryFilter } from 'utils/Query/QueryUtils';
|
||||
@ -448,19 +448,30 @@ const TableDetailsPageV1 = () => {
|
||||
<Divider className="m-y-sm" />
|
||||
</>
|
||||
) : null}
|
||||
<TagsContainerV1
|
||||
showLimited
|
||||
editable={tablePermissions.EditAll || tablePermissions.EditTags}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={datasetFQN}
|
||||
entityType={EntityType.TABLE}
|
||||
selectedTags={tableTags}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
<TagsContainerV1
|
||||
entityFqn={datasetFQN}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.TABLE}
|
||||
permission={tablePermissions.EditAll || tablePermissions.EditTags}
|
||||
selectedTags={tableTags}
|
||||
tagType={TagSource.Classification}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<TagsContainerV1
|
||||
entityFqn={datasetFQN}
|
||||
entityThreadLink={getEntityThreadLink(entityFieldThreadCount)}
|
||||
entityType={EntityType.TABLE}
|
||||
permission={tablePermissions.EditAll || tablePermissions.EditTags}
|
||||
selectedTags={tableTags}
|
||||
tagType={TagSource.Glossary}
|
||||
onSelectionChange={handleTagSelection}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
SearchedDataProps,
|
||||
SourceType,
|
||||
} from 'components/searched-data/SearchedData.interface';
|
||||
import { EntityField } from 'constants/Feeds.constants';
|
||||
import { ExplorePageTabs } from 'enums/Explore.enum';
|
||||
import { Container } from 'generated/entity/data/container';
|
||||
import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel';
|
||||
@ -34,6 +35,7 @@ import { GlossaryTerm } from 'generated/entity/data/glossaryTerm';
|
||||
import { Mlmodel } from 'generated/entity/data/mlmodel';
|
||||
import { Topic } from 'generated/entity/data/topic';
|
||||
import i18next from 'i18next';
|
||||
import { EntityFieldThreadCount } from 'interface/feed.interface';
|
||||
import { get, isEmpty, isNil, isUndefined, lowerCase, startCase } from 'lodash';
|
||||
import { Bucket, EntityDetailUnion } from 'Models';
|
||||
import React, { Fragment } from 'react';
|
||||
@ -74,6 +76,7 @@ import {
|
||||
getPartialNameFromTableFQN,
|
||||
getTableFQNFromColumnFQN,
|
||||
} from './CommonUtils';
|
||||
import { getEntityFieldThreadCounts } from './FeedUtils';
|
||||
import Fqn from './Fqn';
|
||||
import { getGlossaryPath } from './RouterUtils';
|
||||
import {
|
||||
@ -1064,3 +1067,14 @@ export const getEntityLinkFromType = (
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
export const getEntityThreadLink = (
|
||||
entityFieldThreadCount: EntityFieldThreadCount[]
|
||||
) => {
|
||||
const thread = getEntityFieldThreadCounts(
|
||||
EntityField.TAGS,
|
||||
entityFieldThreadCount
|
||||
);
|
||||
|
||||
return thread[0]?.entityLink;
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ import { AxiosError } from 'axios';
|
||||
import { ModifiedGlossaryTerm } from 'components/Glossary/GlossaryTermTab/GlossaryTermTab.interface';
|
||||
import {
|
||||
GlossaryTermDetailsProps,
|
||||
GlossaryTermNodeProps,
|
||||
HierarchyTagsProps,
|
||||
} from 'components/Tag/TagsContainerV1/TagsContainerV1.interface';
|
||||
import { isUndefined, omit } from 'lodash';
|
||||
import { ListGlossaryTermsParams } from 'rest/glossaryAPI';
|
||||
@ -224,9 +224,9 @@ export const formatRelatedTermOptions = (
|
||||
|
||||
export const getGlossaryTermHierarchy = (
|
||||
data: GlossaryTermDetailsProps[]
|
||||
): GlossaryTermNodeProps[] => {
|
||||
const nodes: Record<string, GlossaryTermNodeProps> = {};
|
||||
const tree: GlossaryTermNodeProps[] = [];
|
||||
): HierarchyTagsProps[] => {
|
||||
const nodes: Record<string, HierarchyTagsProps> = {};
|
||||
const tree: HierarchyTagsProps[] = [];
|
||||
|
||||
data.forEach((obj) => {
|
||||
if (obj.fqn) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user