mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-22 15:32:48 +00:00
chore(ui): remove unused tags files and minor ui fixes (#12264)
* remove unused tags files and minor ui fixes * no tags shown as per global styling * fix unit test
This commit is contained in:
parent
cf2aafa770
commit
8635fd7a28
@ -19,7 +19,7 @@ import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import { getVersionPathWithTab } from 'constants/constants';
|
||||
import { EntityField } from 'constants/Feeds.constants';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
@ -153,9 +153,7 @@ const ContainerVersion: React.FC<ContainerVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
isVersionView
|
||||
showLimited
|
||||
<TagsContainerV2
|
||||
entityFqn={containerFQN}
|
||||
entityType={EntityType.CONTAINER}
|
||||
key={tagType}
|
||||
|
@ -21,7 +21,7 @@ import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import { getVersionPathWithTab } from 'constants/constants';
|
||||
import { EntityField } from 'constants/Feeds.constants';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
@ -195,9 +195,7 @@ const DashboardVersion: FC<DashboardVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
isVersionView
|
||||
showLimited
|
||||
<TagsContainerV2
|
||||
entityFqn={currentVersionData.fullyQualifiedName}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
key={tagType}
|
||||
|
@ -17,7 +17,7 @@ import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import VersionTable from 'components/VersionTable/VersionTable.component';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
import { EntityTabs, EntityType, FqnPart } from 'enums/entity.enum';
|
||||
@ -301,9 +301,7 @@ const DataModelVersion: FC<DataModelVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
isVersionView
|
||||
showLimited
|
||||
<TagsContainerV2
|
||||
entityFqn={currentVersionData.fullyQualifiedName}
|
||||
entityType={EntityType.DASHBOARD_DATA_MODEL}
|
||||
key={tagType}
|
||||
|
@ -19,7 +19,7 @@ import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import { getVersionPathWithTab } from 'constants/constants';
|
||||
import { EntityField } from 'constants/Feeds.constants';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
@ -173,9 +173,7 @@ const DatasetVersion: React.FC<DatasetVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
isVersionView
|
||||
showLimited
|
||||
<TagsContainerV2
|
||||
entityFqn={datasetFQN}
|
||||
entityType={EntityType.TABLE}
|
||||
key={tagType}
|
||||
|
@ -30,7 +30,7 @@ import RichTextEditorPreviewer from 'components/common/rich-text-editor/RichText
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import SourceList from 'components/MlModelDetail/SourceList.component';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import TagsViewer from 'components/Tag/TagsViewer/tags-viewer';
|
||||
import { getVersionPathWithTab } from 'constants/constants';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
@ -272,7 +272,7 @@ const MlModelVersion: FC<MlModelVersionProp> = ({
|
||||
</Col>
|
||||
<Col className="m-b-xs" span={24}>
|
||||
<Row gutter={8} wrap={false}>
|
||||
<Col flex="120px">
|
||||
<Col flex="130px">
|
||||
<Typography.Text className="text-grey-muted">
|
||||
{`${t('label.glossary-term-plural')} :`}
|
||||
</Typography.Text>
|
||||
@ -293,7 +293,7 @@ const MlModelVersion: FC<MlModelVersionProp> = ({
|
||||
|
||||
<Col className="m-b-xs" span={24}>
|
||||
<Row gutter={8} wrap={false}>
|
||||
<Col flex="120px">
|
||||
<Col flex="130px">
|
||||
<Typography.Text className="text-grey-muted">
|
||||
{`${t('label.tag-plural')} :`}
|
||||
</Typography.Text>
|
||||
@ -358,9 +358,7 @@ const MlModelVersion: FC<MlModelVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
isVersionView
|
||||
showLimited
|
||||
<TagsContainerV2
|
||||
entityFqn={currentVersionData.fullyQualifiedName}
|
||||
entityType={EntityType.MLMODEL}
|
||||
key={tagType}
|
||||
|
@ -21,7 +21,7 @@ import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import TagsViewer from 'components/Tag/TagsViewer/tags-viewer';
|
||||
import { getVersionPathWithTab } from 'constants/constants';
|
||||
import { TABLE_SCROLL_VALUE } from 'constants/Table.constants';
|
||||
@ -379,9 +379,7 @@ const PipelineVersion: FC<PipelineVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
isVersionView
|
||||
showLimited
|
||||
<TagsContainerV2
|
||||
entityFqn={currentVersionData.fullyQualifiedName}
|
||||
entityType={EntityType.PIPELINE}
|
||||
key={tagType}
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
import { OperationPermission } from 'components/PermissionProvider/PermissionProvider.interface';
|
||||
import { TagsDetailsProps } from 'components/Tag/TagsContainerV1/TagsContainerV1.interface';
|
||||
import { Query } from 'generated/entity/data/query';
|
||||
|
||||
export interface TableQueryRightPanelProps {
|
||||
@ -21,9 +20,3 @@ export interface TableQueryRightPanelProps {
|
||||
permission: OperationPermission;
|
||||
onQueryUpdate: (updatedQuery: Query, key: keyof Query) => Promise<void>;
|
||||
}
|
||||
|
||||
export type TagDetails = {
|
||||
isLoading: boolean;
|
||||
options: TagsDetailsProps[];
|
||||
isError: boolean;
|
||||
};
|
||||
|
@ -204,7 +204,6 @@ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
|
||||
() =>
|
||||
showLimited ? (
|
||||
<TagsViewer
|
||||
isTextPlaceholder
|
||||
showNoDataPlaceholder={showNoDataPlaceholder}
|
||||
tags={selectedTags}
|
||||
type="border"
|
||||
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Button, Space } from 'antd';
|
||||
import { ReactComponent as IconEdit } from 'assets/svg/edit-new.svg';
|
||||
import Loader from 'components/Loader/Loader';
|
||||
import { TableTagsProps } from 'components/TableTags/TableTags.interface';
|
||||
import Tags from 'components/Tag/Tags/tags';
|
||||
import { TAG_CONSTANT, TAG_START_WITH } from 'constants/Tag.constants';
|
||||
import { TagSource } from 'generated/type/tagLabel';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { getFilterTags } from 'utils/TableTags/TableTags.utils';
|
||||
import { getTagPlaceholder } from 'utils/TagsUtils';
|
||||
import TagTree from '../TagsTree/TagsTreeForm.component';
|
||||
import TagsViewer from '../TagsViewer/tags-viewer';
|
||||
import { TagsContainerEntityTableProps } from './TagsContainerEntityTable.interface';
|
||||
|
||||
const TagsContainerEntityTable = ({
|
||||
isLoading,
|
||||
isEditing,
|
||||
permission,
|
||||
selectedTags,
|
||||
showEditButton,
|
||||
tagType,
|
||||
treeData,
|
||||
onCancel,
|
||||
onSelectionChange,
|
||||
onAddButtonClick,
|
||||
}: TagsContainerEntityTableProps) => {
|
||||
const [tags, setTags] = useState<TableTagsProps>();
|
||||
|
||||
const isGlossaryType = useMemo(
|
||||
() => tagType === TagSource.Glossary,
|
||||
[tagType]
|
||||
);
|
||||
|
||||
const showAddTagButton = useMemo(
|
||||
() => permission && isEmpty(tags?.[tagType]),
|
||||
[permission, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const selectedTagsInternal = useMemo(
|
||||
() => tags?.[tagType].map(({ tagFQN }) => tagFQN as string),
|
||||
[tags, tagType]
|
||||
);
|
||||
|
||||
const showNoDataPlaceholder = useMemo(
|
||||
() => !showAddTagButton && isEmpty(tags?.[tagType]),
|
||||
[showAddTagButton, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const getUpdatedTags = (selectedTag: string[]): EntityTags[] => {
|
||||
const updatedTags = selectedTag.map((t) => ({
|
||||
tagFQN: t,
|
||||
source: isGlossaryType ? TagSource.Glossary : TagSource.Classification,
|
||||
}));
|
||||
|
||||
return updatedTags;
|
||||
};
|
||||
|
||||
const handleSave = useCallback(
|
||||
(selectedTag: string[]) => {
|
||||
const updatedTags = getUpdatedTags(selectedTag);
|
||||
onSelectionChange([
|
||||
...updatedTags,
|
||||
...((isGlossaryType
|
||||
? tags?.[TagSource.Classification]
|
||||
: tags?.[TagSource.Glossary]) ?? []),
|
||||
]);
|
||||
},
|
||||
[isGlossaryType, tags, getUpdatedTags]
|
||||
);
|
||||
|
||||
const editTagButton = useMemo(
|
||||
() =>
|
||||
!isEmpty(tags?.[tagType]) && showEditButton ? (
|
||||
<Button
|
||||
className="p-0 flex-center text-primary"
|
||||
data-testid="edit-button"
|
||||
icon={<IconEdit className="anticon" height={16} width={16} />}
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={onAddButtonClick}
|
||||
/>
|
||||
) : null,
|
||||
[selectedTags, showEditButton, onAddButtonClick]
|
||||
);
|
||||
|
||||
const addTagButton = useMemo(
|
||||
() =>
|
||||
showAddTagButton ? (
|
||||
<span onClick={onAddButtonClick}>
|
||||
<Tags
|
||||
className="tw-font-semibold tw-text-primary"
|
||||
startWith={TAG_START_WITH.PLUS}
|
||||
tag={TAG_CONSTANT}
|
||||
type="border"
|
||||
/>
|
||||
</span>
|
||||
) : null,
|
||||
[showAddTagButton]
|
||||
);
|
||||
|
||||
const renderTags = useMemo(
|
||||
() => (
|
||||
<TagsViewer
|
||||
isTextPlaceholder
|
||||
showNoDataPlaceholder={showNoDataPlaceholder}
|
||||
tags={tags?.[tagType] ?? []}
|
||||
type="border"
|
||||
/>
|
||||
),
|
||||
[showNoDataPlaceholder, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const tagsSelectContainer = useMemo(() => {
|
||||
return isLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<TagTree
|
||||
defaultValue={selectedTagsInternal ?? []}
|
||||
placeholder={getTagPlaceholder(isGlossaryType)}
|
||||
treeData={treeData}
|
||||
onCancel={onCancel}
|
||||
onSubmit={handleSave}
|
||||
/>
|
||||
);
|
||||
}, [isGlossaryType, selectedTagsInternal, treeData, onCancel, handleSave]);
|
||||
|
||||
useEffect(() => {
|
||||
setTags(getFilterTags(selectedTags));
|
||||
}, [selectedTags]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-full"
|
||||
data-testid={isGlossaryType ? 'glossary-container' : 'tags-container'}>
|
||||
{!isEditing && (
|
||||
<Space wrap align="center" data-testid="entity-tags" size={4}>
|
||||
{addTagButton}
|
||||
{renderTags}
|
||||
{editTagButton}
|
||||
</Space>
|
||||
)}
|
||||
{isEditing && tagsSelectContainer}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagsContainerEntityTable;
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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 { TagSource } from 'generated/type/tagLabel';
|
||||
import { EntityTags } from 'Models';
|
||||
import { HierarchyTagsProps } from '../TagsContainerV1/TagsContainerV1.interface';
|
||||
|
||||
export type TagsContainerEntityTableProps = {
|
||||
isEditing: boolean;
|
||||
isLoading: boolean;
|
||||
permission: boolean;
|
||||
selectedTags: EntityTags;
|
||||
tagType: TagSource;
|
||||
treeData: HierarchyTagsProps[];
|
||||
showEditButton?: boolean;
|
||||
onCancel: () => void;
|
||||
onAddButtonClick: () => void;
|
||||
onSelectionChange: (selectedTags: EntityTags[]) => void;
|
||||
};
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* 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 { 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 { EntityTags } from 'Models';
|
||||
|
||||
interface TagsTreeProps {
|
||||
title: string;
|
||||
value: string;
|
||||
key: string;
|
||||
selectable: boolean;
|
||||
}
|
||||
|
||||
export interface HierarchyTagsProps extends TagsTreeProps {
|
||||
children: TagsTreeProps[];
|
||||
}
|
||||
|
||||
export interface TagsDetailsProps {
|
||||
name: string;
|
||||
fqn: string;
|
||||
classification: Tag['classification'];
|
||||
source: TagSource;
|
||||
}
|
||||
|
||||
export type TagDetailsProps = {
|
||||
isLoading: boolean;
|
||||
options: TagsDetailsProps[];
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
export type GlossaryDetailsProps = {
|
||||
isLoading: boolean;
|
||||
options: GlossaryTermDetailsProps[];
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
export type GlossaryTermDetailsProps = {
|
||||
name: string;
|
||||
fqn: string;
|
||||
children: GlossaryTerm['children'];
|
||||
parent: GlossaryTerm['parent'];
|
||||
glossary: GlossaryTerm['glossary'];
|
||||
source: TagSource;
|
||||
};
|
||||
|
||||
export type TagsContainerV1Props = {
|
||||
isVersionView?: boolean;
|
||||
permission: boolean;
|
||||
selectedTags: Array<EntityTags>;
|
||||
onSelectionChange?: (selectedTags: Array<EntityTags>) => void;
|
||||
placeholder?: string;
|
||||
showLimited?: boolean;
|
||||
onThreadLinkSelect?: (value: string, threadType?: ThreadType) => void;
|
||||
entityType?: string;
|
||||
entityThreadLink?: string;
|
||||
entityFqn?: string;
|
||||
tagType: TagSource;
|
||||
};
|
||||
|
||||
export type TagsTreeComponentProps = {
|
||||
placeholder: string;
|
||||
treeData: HierarchyTagsProps[];
|
||||
defaultValue: string[];
|
||||
onChange?: (value: string[]) => void;
|
||||
onSubmit: (tags: string[]) => void;
|
||||
onCancel: () => void;
|
||||
};
|
@ -1,388 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Button, Col, Form, Row, Space, Tooltip, Typography } from 'antd';
|
||||
import { ReactComponent as EditIcon } from 'assets/svg/edit-new.svg';
|
||||
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,
|
||||
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 } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
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,
|
||||
getTagPlaceholder,
|
||||
getTagsHierarchy,
|
||||
} from 'utils/TagsUtils';
|
||||
import {
|
||||
getRequestTagsPath,
|
||||
getUpdateTagsPath,
|
||||
TASK_ENTITIES,
|
||||
} from 'utils/TasksUtils';
|
||||
import { ReactComponent as IconComments } from '../../../assets/svg/comment.svg';
|
||||
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
|
||||
import TagTree from '../TagsTree/TagsTreeForm.component';
|
||||
import TagsViewer from '../TagsViewer/tags-viewer';
|
||||
import {
|
||||
GlossaryDetailsProps,
|
||||
GlossaryTermDetailsProps,
|
||||
TagDetailsProps,
|
||||
TagsContainerV1Props,
|
||||
} from './TagsContainerV1.interface';
|
||||
|
||||
const TagsContainerV1 = ({
|
||||
permission,
|
||||
selectedTags,
|
||||
entityType,
|
||||
entityThreadLink,
|
||||
entityFqn,
|
||||
tagType,
|
||||
onSelectionChange,
|
||||
onThreadLinkSelect,
|
||||
isVersionView,
|
||||
}: TagsContainerV1Props) => {
|
||||
const history = useHistory();
|
||||
const [form] = Form.useForm();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [isEditTags, setIsEditTags] = useState(false);
|
||||
const [tagDetails, setTagDetails] = useState<TagDetailsProps>({
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
options: [],
|
||||
});
|
||||
|
||||
const [glossaryDetails, setGlossaryDetails] = useState<GlossaryDetailsProps>({
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
options: [],
|
||||
});
|
||||
|
||||
const [tags, setTags] = useState<TableTagsProps>();
|
||||
|
||||
const isGlossaryType = useMemo(
|
||||
() => tagType === TagSource.Glossary,
|
||||
[tagType]
|
||||
);
|
||||
|
||||
const showAddTagButton = useMemo(
|
||||
() => permission && isEmpty(tags?.[tagType]),
|
||||
[permission, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const selectedTagsInternal = useMemo(
|
||||
() => tags?.[tagType].map(({ tagFQN }) => tagFQN as string),
|
||||
[tags, tagType]
|
||||
);
|
||||
|
||||
const treeData = 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) {
|
||||
setTagDetails((pre) => ({ ...pre, isLoading: true }));
|
||||
try {
|
||||
const tags = await getAllTagsForOptions();
|
||||
setTagDetails((pre) => ({
|
||||
...pre,
|
||||
options: tags.map((tag) => {
|
||||
return {
|
||||
name: tag.name,
|
||||
fqn: tag.fullyQualifiedName ?? '',
|
||||
classification: tag.classification,
|
||||
source: TagSource.Classification,
|
||||
};
|
||||
}),
|
||||
}));
|
||||
setIsEditTags(true);
|
||||
} catch (_error) {
|
||||
setTagDetails((pre) => ({ ...pre, isError: true, options: [] }));
|
||||
} finally {
|
||||
setTagDetails((pre) => ({ ...pre, isLoading: false }));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const fetchGlossaryList = async () => {
|
||||
if (isEmpty(glossaryDetails.options) || glossaryDetails.isError) {
|
||||
setGlossaryDetails((pre) => ({ ...pre, isLoading: true }));
|
||||
try {
|
||||
const glossaryTermList: GlossaryTermDetailsProps[] = [];
|
||||
const { data } = await getGlossariesList({
|
||||
limit: PAGE_SIZE_LARGE,
|
||||
});
|
||||
|
||||
const promises = data.map((item) =>
|
||||
getGlossaryTerms({
|
||||
glossary: item.id,
|
||||
limit: API_RES_MAX_SIZE,
|
||||
fields: 'children,parent',
|
||||
})
|
||||
);
|
||||
const response = await Promise.allSettled(promises);
|
||||
|
||||
response.forEach((res) => {
|
||||
if (res.status === 'fulfilled') {
|
||||
glossaryTermList.push(
|
||||
...res.value.data.map((data) => ({
|
||||
name: data.name,
|
||||
fqn: data.fullyQualifiedName ?? '',
|
||||
children: data.children,
|
||||
parent: data.parent,
|
||||
glossary: data.glossary,
|
||||
source: TagSource.Glossary,
|
||||
}))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
setGlossaryDetails((pre) => ({ ...pre, options: glossaryTermList }));
|
||||
} catch (error) {
|
||||
setGlossaryDetails((pre) => ({ ...pre, isError: true, options: [] }));
|
||||
} finally {
|
||||
setGlossaryDetails((pre) => ({ ...pre, isLoading: false }));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const showNoDataPlaceholder = useMemo(
|
||||
() => !showAddTagButton && isEmpty(tags?.[tagType]),
|
||||
[showAddTagButton, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const getUpdatedTags = (selectedTag: string[]): EntityTags[] => {
|
||||
const updatedTags = selectedTag.map((t) => ({
|
||||
tagFQN: t,
|
||||
source: [...tagDetails.options, ...glossaryDetails.options].find(
|
||||
(tag) => tag.fqn === t
|
||||
)?.source,
|
||||
}));
|
||||
|
||||
return updatedTags;
|
||||
};
|
||||
|
||||
const handleSave = (data: string[]) => {
|
||||
const updatedTags = getUpdatedTags(data);
|
||||
if (onSelectionChange) {
|
||||
onSelectionChange([
|
||||
...updatedTags,
|
||||
...((isGlossaryType
|
||||
? tags?.[TagSource.Classification]
|
||||
: tags?.[TagSource.Glossary]) ?? []),
|
||||
]);
|
||||
}
|
||||
form.resetFields();
|
||||
setIsEditTags(false);
|
||||
};
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
setIsEditTags(false);
|
||||
form.resetFields();
|
||||
}, [form]);
|
||||
|
||||
const handleAddClick = useCallback(() => {
|
||||
if (isGlossaryType) {
|
||||
fetchGlossaryList();
|
||||
} else {
|
||||
fetchTags();
|
||||
}
|
||||
setIsEditTags(true);
|
||||
}, [isGlossaryType, fetchGlossaryList, fetchTags]);
|
||||
|
||||
const addTagButton = useMemo(
|
||||
() =>
|
||||
showAddTagButton ? (
|
||||
<span onClick={handleAddClick}>
|
||||
<Tags
|
||||
className="tw-font-semibold tw-text-primary"
|
||||
startWith={TAG_START_WITH.PLUS}
|
||||
tag={TAG_CONSTANT}
|
||||
type="border"
|
||||
/>
|
||||
</span>
|
||||
) : null,
|
||||
[showAddTagButton, fetchTags, fetchGlossaryList]
|
||||
);
|
||||
|
||||
const renderTags = useMemo(
|
||||
() => (
|
||||
<TagsViewer
|
||||
isTextPlaceholder
|
||||
showNoDataPlaceholder={showNoDataPlaceholder}
|
||||
tags={tags?.[tagType] ?? []}
|
||||
type="border"
|
||||
/>
|
||||
),
|
||||
[showNoDataPlaceholder, tags?.[tagType]]
|
||||
);
|
||||
|
||||
const tagsSelectContainer = useMemo(() => {
|
||||
return tagDetails.isLoading || glossaryDetails.isLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<TagTree
|
||||
defaultValue={selectedTagsInternal ?? []}
|
||||
placeholder={getTagPlaceholder(isGlossaryType)}
|
||||
treeData={treeData}
|
||||
onCancel={handleCancel}
|
||||
onSubmit={handleSave}
|
||||
/>
|
||||
);
|
||||
}, [
|
||||
isGlossaryType,
|
||||
selectedTagsInternal,
|
||||
glossaryDetails,
|
||||
tagDetails,
|
||||
treeData,
|
||||
handleCancel,
|
||||
handleSave,
|
||||
]);
|
||||
|
||||
const handleRequestTags = () => {
|
||||
history.push(getRequestTagsPath(entityType as string, entityFqn as string));
|
||||
};
|
||||
const handleUpdateTags = () => {
|
||||
history.push(getUpdateTagsPath(entityType as string, entityFqn as string));
|
||||
};
|
||||
|
||||
const requestTagElement = useMemo(() => {
|
||||
const hasTags = !isEmpty(tags?.[tagType]);
|
||||
|
||||
return TASK_ENTITIES.includes(entityType as EntityType) ? (
|
||||
<Col>
|
||||
<Button
|
||||
className="p-0 flex-center"
|
||||
data-testid="request-entity-tags"
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={hasTags ? handleUpdateTags : handleRequestTags}>
|
||||
<Tooltip
|
||||
placement="left"
|
||||
title={
|
||||
hasTags
|
||||
? t('label.update-request-tag-plural')
|
||||
: t('label.request-tag-plural')
|
||||
}>
|
||||
<IconRequest
|
||||
className="anticon"
|
||||
height={14}
|
||||
name="request-tags"
|
||||
style={{ color: DE_ACTIVE_COLOR }}
|
||||
width={14}
|
||||
/>
|
||||
</Tooltip>
|
||||
</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={() => {
|
||||
if (onThreadLinkSelect) {
|
||||
onThreadLinkSelect(
|
||||
entityThreadLink ??
|
||||
getEntityFeedLink(entityType, entityFqn, 'tags')
|
||||
);
|
||||
}
|
||||
}}>
|
||||
<Tooltip
|
||||
placement="left"
|
||||
title={t('label.list-entity', {
|
||||
entity: t('label.conversation'),
|
||||
})}>
|
||||
<IconComments
|
||||
height={14}
|
||||
name="comments"
|
||||
style={{ color: DE_ACTIVE_COLOR }}
|
||||
width={14}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Button>
|
||||
</Col>
|
||||
),
|
||||
[
|
||||
entityType,
|
||||
entityFqn,
|
||||
entityThreadLink,
|
||||
getEntityFeedLink,
|
||||
onThreadLinkSelect,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setTags(getFilterTags(selectedTags));
|
||||
}, [selectedTags]);
|
||||
|
||||
return (
|
||||
<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">
|
||||
{isGlossaryType ? t('label.glossary-term') : t('label.tag-plural')}
|
||||
</Typography.Text>
|
||||
{permission && !isEmpty(tags?.[tagType]) && (
|
||||
<Button
|
||||
className="cursor-pointer flex-center m-l-xss"
|
||||
data-testid="edit-button"
|
||||
icon={<EditIcon color={DE_ACTIVE_COLOR} width="14px" />}
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={handleAddClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{permission && !isVersionView && (
|
||||
<Row gutter={8}>
|
||||
{tagType === TagSource.Classification && requestTagElement}
|
||||
{conversationThreadElement}
|
||||
</Row>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isEditTags && (
|
||||
<Space wrap align="center" data-testid="entity-tags" size={4}>
|
||||
{addTagButton}
|
||||
{renderTags}
|
||||
</Space>
|
||||
)}
|
||||
{isEditTags && tagsSelectContainer}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagsContainerV1;
|
@ -18,6 +18,7 @@ import { ReactElement } from 'react';
|
||||
|
||||
export type TagsContainerV2Props = {
|
||||
permission: boolean;
|
||||
isVersionView?: boolean;
|
||||
selectedTags: EntityTags[];
|
||||
entityType?: string;
|
||||
entityThreadLink?: string;
|
||||
@ -27,6 +28,6 @@ export type TagsContainerV2Props = {
|
||||
showBottomEditButton?: boolean;
|
||||
showInlineEditButton?: boolean;
|
||||
children?: ReactElement;
|
||||
onSelectionChange: (selectedTags: EntityTags[]) => Promise<void>;
|
||||
onSelectionChange?: (selectedTags: EntityTags[]) => Promise<void>;
|
||||
onThreadLinkSelect?: (value: string, threadType?: ThreadType) => void;
|
||||
};
|
||||
|
@ -44,6 +44,7 @@ import { TagsContainerV2Props } from './TagsContainerV2.interface';
|
||||
|
||||
const TagsContainerV2 = ({
|
||||
permission,
|
||||
isVersionView,
|
||||
selectedTags,
|
||||
entityType,
|
||||
entityThreadLink,
|
||||
@ -134,12 +135,15 @@ const TagsContainerV2 = ({
|
||||
source: tagType,
|
||||
}));
|
||||
|
||||
if (onSelectionChange) {
|
||||
await onSelectionChange([
|
||||
...updatedTags,
|
||||
...((isGlossaryType
|
||||
? tags?.[TagSource.Classification]
|
||||
: tags?.[TagSource.Glossary]) ?? []),
|
||||
]);
|
||||
}
|
||||
|
||||
form.resetFields();
|
||||
setIsEditTags(false);
|
||||
};
|
||||
@ -166,7 +170,6 @@ const TagsContainerV2 = ({
|
||||
const renderTags = useMemo(
|
||||
() => (
|
||||
<TagsViewer
|
||||
isTextPlaceholder
|
||||
showNoDataPlaceholder={showNoDataPlaceholder}
|
||||
tags={tags?.[tagType] ?? []}
|
||||
type="border"
|
||||
@ -289,10 +292,14 @@ const TagsContainerV2 = ({
|
||||
onClick={handleAddClick}
|
||||
/>
|
||||
)}
|
||||
{permission && !isVersionView && (
|
||||
<Row gutter={8}>
|
||||
{tagType === TagSource.Classification && requestTagElement}
|
||||
{onThreadLinkSelect && conversationThreadElement}
|
||||
</Row>
|
||||
)}
|
||||
</Row>
|
||||
)}
|
||||
</Space>
|
||||
)
|
||||
);
|
||||
@ -302,6 +309,7 @@ const TagsContainerV2 = ({
|
||||
showHeader,
|
||||
isEditTags,
|
||||
permission,
|
||||
isVersionView,
|
||||
isGlossaryType,
|
||||
requestTagElement,
|
||||
conversationThreadElement,
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { Button, Col, Form, Row, Space, TreeSelect } from 'antd';
|
||||
import { useForm } from 'antd/lib/form/Form';
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import { TagsTreeComponentProps } from '../TagsContainerV1/TagsContainerV1.interface';
|
||||
|
||||
const TagTree = ({
|
||||
defaultValue,
|
||||
placeholder,
|
||||
treeData,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}: TagsTreeComponentProps) => {
|
||||
const [form] = useForm();
|
||||
|
||||
return (
|
||||
<Form form={form} name="tagsForm" onFinish={(data) => onSubmit(data.tags)}>
|
||||
<Row gutter={[0, 8]}>
|
||||
<Col className="gutter-row d-flex justify-end" span={24}>
|
||||
<Space align="center">
|
||||
<Button
|
||||
className="p-x-05"
|
||||
data-testid="cancelAssociatedTag"
|
||||
icon={<CloseOutlined size={12} />}
|
||||
size="small"
|
||||
onClick={onCancel}
|
||||
/>
|
||||
<Button
|
||||
className="p-x-05"
|
||||
data-testid="saveAssociatedTag"
|
||||
htmlType="submit"
|
||||
icon={<CheckOutlined size={12} />}
|
||||
size="small"
|
||||
type="primary"
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
<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={defaultValue}
|
||||
placeholder={placeholder}
|
||||
removeIcon={
|
||||
<CloseOutlined data-testid="remove-tags" height={8} width={8} />
|
||||
}
|
||||
showCheckedStrategy={TreeSelect.SHOW_ALL}
|
||||
treeData={treeData}
|
||||
treeNodeFilterProp="title"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagTree;
|
@ -17,6 +17,5 @@ export interface TagsViewerProps {
|
||||
tags: Array<EntityTags>;
|
||||
sizeCap?: number;
|
||||
type?: 'label' | 'contained' | 'outlined' | 'border';
|
||||
isTextPlaceholder?: boolean;
|
||||
showNoDataPlaceholder?: boolean;
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import { TAG_START_WITH } from 'constants/Tag.constants';
|
||||
import { isEmpty, sortBy, uniqBy } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { FunctionComponent, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LIST_SIZE, NO_DATA_PLACEHOLDER } from '../../../constants/constants';
|
||||
import { TagSource } from '../../../generated/type/tagLabel';
|
||||
import { TagsViewerProps } from './tags-viewer.interface';
|
||||
@ -28,10 +27,8 @@ const TagsViewer: FunctionComponent<TagsViewerProps> = ({
|
||||
tags,
|
||||
sizeCap = LIST_SIZE,
|
||||
type = 'label',
|
||||
isTextPlaceholder,
|
||||
showNoDataPlaceholder = true,
|
||||
}: TagsViewerProps) => {
|
||||
const { t } = useTranslation();
|
||||
const tagChipStye = {
|
||||
margin: '0 0 8px 0',
|
||||
justifyContent: 'start',
|
||||
@ -65,11 +62,7 @@ const TagsViewer: FunctionComponent<TagsViewerProps> = ({
|
||||
<Space wrap size={4}>
|
||||
{isEmpty(sortedTagsBySource) && showNoDataPlaceholder ? (
|
||||
<Typography.Text className="text-grey-muted m-r-xss">
|
||||
{isTextPlaceholder
|
||||
? t('label.no-entity', {
|
||||
entity: t('label.tag-plural'),
|
||||
})
|
||||
: NO_DATA_PLACEHOLDER}
|
||||
{NO_DATA_PLACEHOLDER}
|
||||
</Typography.Text>
|
||||
) : sizeCap > -1 ? (
|
||||
<>
|
||||
|
@ -90,8 +90,8 @@ jest.mock('../common/rich-text-editor/RichTextEditorPreviewer', () => {
|
||||
return jest.fn().mockReturnValue(<p>RichTextEditorPreviwer</p>);
|
||||
});
|
||||
|
||||
jest.mock('components/Tag/TagsContainerV1/TagsContainerV1', () => {
|
||||
return jest.fn().mockReturnValue(<p>TagsContainerV1</p>);
|
||||
jest.mock('components/Tag/TagsContainerV2/TagsContainerV2', () => {
|
||||
return jest.fn().mockReturnValue(<p>TagsContainerV2</p>);
|
||||
});
|
||||
|
||||
jest.mock('components/Tag/Tags/tags', () => {
|
||||
|
@ -19,7 +19,7 @@ import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import TopicSchemaFields from 'components/TopicDetails/TopicSchema/TopicSchema';
|
||||
import { getVersionPathWithTab } from 'constants/constants';
|
||||
import { EntityField } from 'constants/Feeds.constants';
|
||||
@ -142,9 +142,8 @@ const TopicVersion: FC<TopicVersionProp> = ({
|
||||
flex="220px">
|
||||
<Space className="w-full" direction="vertical" size="large">
|
||||
{Object.keys(TagSource).map((tagType) => (
|
||||
<TagsContainerV1
|
||||
<TagsContainerV2
|
||||
isVersionView
|
||||
showLimited
|
||||
entityFqn={currentVersionData.fullyQualifiedName}
|
||||
entityType={EntityType.TOPIC}
|
||||
key={tagType}
|
||||
|
@ -60,10 +60,10 @@ jest.mock('components/common/description/Description', () => {
|
||||
.mockReturnValue(<div data-testid="description">Description</div>);
|
||||
});
|
||||
|
||||
jest.mock('components/Tag/TagsContainerV1/TagsContainerV1', () => {
|
||||
jest.mock('components/Tag/TagsContainerV2/TagsContainerV2', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-testid="entity-page-info">TagsContainerV1</div>);
|
||||
.mockReturnValue(<div data-testid="entity-page-info">TagsContainerV2</div>);
|
||||
});
|
||||
|
||||
jest.mock('components/FeedEditor/FeedEditor', () => {
|
||||
|
@ -13,18 +13,8 @@
|
||||
|
||||
import { AxiosError } from 'axios';
|
||||
import { ModifiedGlossaryTerm } from 'components/Glossary/GlossaryTermTab/GlossaryTermTab.interface';
|
||||
import {
|
||||
GlossaryTermDetailsProps,
|
||||
HierarchyTagsProps,
|
||||
} from 'components/Tag/TagsContainerV1/TagsContainerV1.interface';
|
||||
import { API_RES_MAX_SIZE, PAGE_SIZE_LARGE } from 'constants/constants';
|
||||
import { TagSource } from 'generated/type/tagLabel';
|
||||
import { isUndefined, omit } from 'lodash';
|
||||
import {
|
||||
getGlossariesList,
|
||||
getGlossaryTerms,
|
||||
ListGlossaryTermsParams,
|
||||
} from 'rest/glossaryAPI';
|
||||
import { ListGlossaryTermsParams } from 'rest/glossaryAPI';
|
||||
import { searchData } from 'rest/miscAPI';
|
||||
import { WILD_CARD_CHAR } from '../constants/char.constants';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
@ -237,86 +227,3 @@ export const formatRelatedTermOptions = (
|
||||
}))
|
||||
: [];
|
||||
};
|
||||
|
||||
export const getGlossaryTermHierarchy = (
|
||||
data: GlossaryTermDetailsProps[]
|
||||
): HierarchyTagsProps[] => {
|
||||
const nodes: Record<string, HierarchyTagsProps> = {};
|
||||
const tree: HierarchyTagsProps[] = [];
|
||||
|
||||
data.forEach((obj) => {
|
||||
if (obj.fqn) {
|
||||
nodes[obj.fqn] = {
|
||||
title: obj.name,
|
||||
value: obj.fqn,
|
||||
key: obj.fqn,
|
||||
selectable: true,
|
||||
children: [],
|
||||
};
|
||||
const parentNode =
|
||||
obj.parent &&
|
||||
obj.parent.fullyQualifiedName &&
|
||||
nodes[obj.parent.fullyQualifiedName];
|
||||
parentNode && nodes[obj.fqn] && parentNode.children?.push(nodes[obj.fqn]);
|
||||
|
||||
if (!parentNode) {
|
||||
const glossaryName = obj.glossary.name ?? '';
|
||||
const existInTree = tree.find((item) => item.title === glossaryName);
|
||||
|
||||
if (existInTree) {
|
||||
nodes[glossaryName].children?.push(nodes[obj.fqn]);
|
||||
} else {
|
||||
nodes[glossaryName] = {
|
||||
title: glossaryName,
|
||||
value: obj.glossary.fullyQualifiedName ?? '',
|
||||
key: obj.glossary.fullyQualifiedName ?? '',
|
||||
selectable: false,
|
||||
children: [],
|
||||
};
|
||||
|
||||
nodes[glossaryName].children?.push(nodes[obj.fqn]);
|
||||
tree.push(nodes[glossaryName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
};
|
||||
|
||||
export const getGlossaryTermsList = async () => {
|
||||
try {
|
||||
const glossaryTermList: GlossaryTermDetailsProps[] = [];
|
||||
const { data } = await getGlossariesList({
|
||||
limit: PAGE_SIZE_LARGE,
|
||||
});
|
||||
|
||||
const promises = data.map((item) =>
|
||||
getGlossaryTerms({
|
||||
glossary: item.id,
|
||||
limit: API_RES_MAX_SIZE,
|
||||
fields: 'children,parent',
|
||||
})
|
||||
);
|
||||
const response = await Promise.allSettled(promises);
|
||||
|
||||
response.forEach((res) => {
|
||||
if (res.status === 'fulfilled') {
|
||||
glossaryTermList.push(
|
||||
...res.value.data.map((data) => ({
|
||||
name: data.name,
|
||||
fqn: data.fullyQualifiedName ?? '',
|
||||
children: data.children,
|
||||
parent: data.parent,
|
||||
glossary: data.glossary,
|
||||
source: TagSource.Glossary,
|
||||
}))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.resolve(glossaryTermList);
|
||||
} catch (error) {
|
||||
return Promise.reject({ data: (error as AxiosError).response });
|
||||
}
|
||||
};
|
||||
|
@ -18,10 +18,6 @@ import { ReactComponent as DeleteIcon } from 'assets/svg/ic-delete.svg';
|
||||
import { AxiosError } from 'axios';
|
||||
import RichTextEditorPreviewer from 'components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||
import Loader from 'components/Loader/Loader';
|
||||
import {
|
||||
HierarchyTagsProps,
|
||||
TagsDetailsProps,
|
||||
} from 'components/Tag/TagsContainerV1/TagsContainerV1.interface';
|
||||
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
||||
import { getExplorePath, PAGE_SIZE } from 'constants/constants';
|
||||
import { delimiterRegex } from 'constants/regex.constants';
|
||||
@ -329,77 +325,6 @@ export const getUsageCountLink = (tagFQN: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getTagsHierarchy = (
|
||||
tags: TagsDetailsProps[]
|
||||
): HierarchyTagsProps[] => {
|
||||
const filteredTags = tags.filter(
|
||||
(tag) => !tag.fqn?.startsWith(`Tier${FQN_SEPARATOR_CHAR}Tier`)
|
||||
);
|
||||
|
||||
let hierarchyTags: HierarchyTagsProps[] = [];
|
||||
|
||||
filteredTags.forEach((tags) => {
|
||||
const haveParent = hierarchyTags.find(
|
||||
(h) => h.title === tags?.classification?.name
|
||||
);
|
||||
|
||||
if (haveParent) {
|
||||
hierarchyTags = hierarchyTags.map((h) => {
|
||||
if (h.title === tags?.classification?.name) {
|
||||
return {
|
||||
...h,
|
||||
children: [
|
||||
...h.children,
|
||||
{
|
||||
title: tags.name,
|
||||
value: tags.fqn,
|
||||
key: tags.fqn,
|
||||
selectable: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
return h;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
hierarchyTags.push({
|
||||
title: tags.classification?.name ?? '',
|
||||
value: tags.classification?.name ?? '',
|
||||
children: [
|
||||
{
|
||||
title: tags.name,
|
||||
value: tags.fqn,
|
||||
key: tags.fqn,
|
||||
selectable: true,
|
||||
},
|
||||
],
|
||||
key: tags.classification?.name ?? '',
|
||||
selectable: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return hierarchyTags;
|
||||
};
|
||||
|
||||
export const getAllTagsList = async () => {
|
||||
try {
|
||||
const tags = await getAllTagsForOptions();
|
||||
|
||||
return Promise.resolve(
|
||||
tags.map((tag) => ({
|
||||
name: tag.name,
|
||||
fqn: tag.fullyQualifiedName ?? '',
|
||||
classification: tag.classification,
|
||||
source: TagSource.Classification,
|
||||
}))
|
||||
);
|
||||
} catch (error) {
|
||||
return Promise.reject({ data: (error as AxiosError).response });
|
||||
}
|
||||
};
|
||||
|
||||
export const getTagPlaceholder = (isGlossaryType: boolean): string =>
|
||||
isGlossaryType
|
||||
? i18next.t('label.search-entity', {
|
||||
|
Loading…
x
Reference in New Issue
Block a user