Feat: Show description on hover of tags (#1418)

* Feat: Added description popover on hover of tags

* fixed failing test

* add popover changes for DBTmodale pages

* addressing comments

* miner fix for ui

* addressing comments
This commit is contained in:
Shailesh Parmar 2021-12-01 16:05:10 +05:30 committed by GitHub
parent a9e70e6a89
commit 1493cbbb7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 316 additions and 223 deletions

View File

@ -126,7 +126,7 @@ const DBTModelDetails: React.FC<DBTModelDetailsProps> = ({
isLink: owner?.type === 'team',
openInNewTab: false,
},
{ key: 'Tier', value: tier ? tier.split('.')[1] : '' },
{ key: 'Tier', value: tier?.tagFQN ? tier.tagFQN.split('.')[1] : '' },
];
const onDescriptionEdit = (): void => {
@ -280,7 +280,7 @@ const DBTModelDetails: React.FC<DBTModelDetailsProps> = ({
{activeTab === 3 && (
<div className="tw-mt-4">
<ManageTab
currentTier={tier}
currentTier={tier?.tagFQN}
currentUser={owner?.id}
hasEditAccess={hasEditAccess()}
onSave={onSettingsUpdate}

View File

@ -15,6 +15,7 @@ import { EntityTags } from 'Models';
import { Dbtmodel } from '../../generated/entity/data/dbtmodel';
import { EntityReference } from '../../generated/entity/data/table';
import { User } from '../../generated/entity/teams/user';
import { TagLabel } from '../../generated/type/tagLabel';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
export interface DatasetOwner extends EntityReference {
@ -30,7 +31,7 @@ export interface DBTModelDetailsProps {
activeTab: number;
owner: DatasetOwner;
description: string;
tier: string;
tier: TagLabel;
columns: Dbtmodel['columns'];
followers: Array<User>;
dbtModelTags: Array<EntityTags>;

View File

@ -125,7 +125,7 @@ const DashboardDetails = ({
isLink: owner?.type === 'team',
openInNewTab: false,
},
{ key: 'Tier', value: tier ? tier.split('.')[1] : '' },
{ key: 'Tier', value: tier?.tagFQN ? tier.tagFQN.split('.')[1] : '' },
{
key: `${serviceType} Url`,
value: dashboardUrl,
@ -441,7 +441,11 @@ const DashboardDetails = ({
</button>
) : (
<span className="tw-opacity-60 group-hover:tw-opacity-100 tw-text-grey-muted group-hover:tw-text-primary">
<Tags tag="+ Add tag" type="outlined" />
<Tags
startWith="+ "
tag="Add tag"
type="outlined"
/>
</span>
)}
</TagsContainer>
@ -457,7 +461,7 @@ const DashboardDetails = ({
{activeTab === 2 && (
<div className="tw-mt-4">
<ManageTabComponent
currentTier={tier}
currentTier={tier?.tagFQN}
currentUser={owner?.id}
hasEditAccess={hasEditAccess()}
onSave={onSettingsUpdate}

View File

@ -16,6 +16,7 @@ import { EntityTags, TableDetail } from 'Models';
import { Chart } from '../../generated/entity/data/chart';
import { Dashboard } from '../../generated/entity/data/dashboard';
import { User } from '../../generated/entity/teams/user';
import { TagLabel } from '../../generated/type/tagLabel';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
export interface ChartType extends Chart {
@ -33,7 +34,7 @@ export interface DashboardDetailsProps {
activeTab: number;
owner: TableDetail['owner'];
description: string;
tier: string;
tier: TagLabel;
followers: Array<User>;
dashboardTags: Array<EntityTags>;
slashedDashboardName: TitleBreadcrumbProps['titleLinks'];

View File

@ -16,6 +16,7 @@ import { TableDetail } from 'Models';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { Dashboard } from '../../generated/entity/data/dashboard';
import { TagLabel } from '../../generated/type/tagLabel';
import DashboardDetails from './DashboardDetails.component';
const mockUserTeam = [
@ -48,7 +49,7 @@ const DashboardDetailsProps = {
activeTab: 1,
owner: {} as TableDetail['owner'],
description: '',
tier: '',
tier: {} as TagLabel,
followers: [],
dashboardTags: [],
slashedDashboardName: [],

View File

@ -204,7 +204,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
isLink: owner?.type === 'team',
openInNewTab: false,
},
{ key: 'Tier', value: tier ? tier.split('.')[1] : '' },
{ key: 'Tier', value: tier?.tagFQN ? tier.tagFQN.split('.')[1] : '' },
{ key: 'Usage', value: usage },
{ key: 'Queries', value: `${weeklyUsageCount} past week` },
{
@ -338,7 +338,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
followHandler={followTable}
isFollowing={isFollowing}
tags={tableTags}
tier={tier || ''}
tier={tier}
titleLinks={slashedTableName}
version={version}
versionHandler={versionHandler}
@ -411,7 +411,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
{activeTab === 4 && (
<div className="tw-mt-4">
<ManageTab
currentTier={tier}
currentTier={tier?.tagFQN}
currentUser={owner?.id}
hasEditAccess={hasEditAccess()}
onSave={onSettingsUpdate}

View File

@ -21,6 +21,7 @@ import {
} from '../../generated/entity/data/table';
import { User } from '../../generated/entity/teams/user';
import { EntityLineage } from '../../generated/type/entityLineage';
import { TagLabel } from '../../generated/type/tagLabel';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
export interface DatasetOwner extends EntityReference {
@ -42,7 +43,7 @@ export interface DatasetDetailsProps {
description: string;
tableProfile: Table['tableProfile'];
columns: Table['columns'];
tier: string;
tier: TagLabel;
sampleData: TableData;
entityLineage: EntityLineage;
followers: Array<User>;

View File

@ -22,6 +22,7 @@ import {
TypeUsedToReturnUsageDetailsOfAnEntity,
} from '../../generated/entity/data/table';
import { EntityLineage } from '../../generated/type/entityLineage';
import { TagLabel } from '../../generated/type/tagLabel';
import DatasetDetails from './DatasetDetails.component';
import { DatasetOwner } from './DatasetDetails.interface';
@ -65,7 +66,7 @@ const DatasetDetailsProps = {
tableDetails: {} as Table,
tableProfile: [],
tableTags: [],
tier: '',
tier: {} as TagLabel,
unfollowTableHandler: jest.fn(),
usageSummary: {} as TypeUsedToReturnUsageDetailsOfAnEntity,
users: [],

View File

@ -126,8 +126,8 @@ const DatasetVersion: React.FC<DatasetVersionProp> = ({
oldTier?.tagFQN?.split('.')[1] || '',
newTier?.tagFQN?.split('.')[1] || ''
)
: tier
? tier.split('.')[1]
: tier?.tagFQN
? tier?.tagFQN.split('.')[1]
: '',
},
];
@ -343,7 +343,7 @@ const DatasetVersion: React.FC<DatasetVersionProp> = ({
extraInfo={getExtraInfo()}
followersList={[]}
tags={getTableTags(currentVersionData.columns || [])}
tier={tier || ''}
tier={tier}
titleLinks={slashedTableName}
version={version}
versionHandler={backHandler}

View File

@ -13,6 +13,7 @@
import { Table } from '../../generated/entity/data/table';
import { EntityHistory } from '../../generated/type/entityHistory';
import { TagLabel } from '../../generated/type/tagLabel';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
export interface DatasetVersionProp {
@ -20,7 +21,7 @@ export interface DatasetVersionProp {
currentVersionData: Table;
isVersionLoading: boolean;
owner: Table['owner'];
tier: string;
tier: TagLabel;
slashedTableName: TitleBreadcrumbProps['titleLinks'];
datasetFQN: string;
versionList: EntityHistory;

View File

@ -230,7 +230,7 @@ const EntityInfoDrawer = ({
<div className="tw-flex tw-flex-wrap tw-pt-1.5">
{getEntityTags(selectedNode.type, entityDetail).length > 0 ? (
getEntityTags(selectedNode.type, entityDetail).map((t) => {
return <Tags key={t} tag={`#${t}`} />;
return <Tags key={t} startWith="#" tag={t ? t : ''} />;
})
) : (
<p className="tw-text-xs tw-text-grey-muted">No Tags added</p>

View File

@ -531,7 +531,8 @@ const EntityTable = ({
{ 'diff-removed': tag?.removed }
)}
key={i}
tag={`#${tag.tagFQN}`}
startWith="#"
tag={tag}
/>
)
)}
@ -569,7 +570,11 @@ const EntityTable = ({
</button>
) : (
<span className="tw-opacity-60 group-hover:tw-opacity-100 tw-text-grey-muted group-hover:tw-text-primary">
<Tags tag="+ Add tag" type="outlined" />
<Tags
startWith="+ "
tag="Add tag"
type="outlined"
/>
</span>
)}
</TagsContainer>

View File

@ -132,7 +132,7 @@ const PipelineDetails = ({
isLink: owner?.type === 'team',
openInNewTab: false,
},
{ key: 'Tier', value: tier ? tier.split('.')[1] : '' },
{ key: 'Tier', value: tier?.tagFQN ? tier.tagFQN.split('.')[1] : '' },
{
key: `${serviceType} Url`,
value: pipelineUrl,
@ -278,7 +278,7 @@ const PipelineDetails = ({
tagList={tagList}
tags={pipelineTags}
tagsHandler={onTagUpdate}
tier={tier || ''}
tier={tier}
titleLinks={slashedPipelineName}
/>
<div className="tw-mt-1 tw-flex tw-flex-col tw-flex-grow">
@ -386,7 +386,7 @@ const PipelineDetails = ({
{activeTab === 3 && (
<div className="tw-mt-4">
<ManageTabComponent
currentTier={tier}
currentTier={tier?.tagFQN}
currentUser={owner?.id}
hasEditAccess={hasEditAccess()}
onSave={onSettingsUpdate}

View File

@ -25,6 +25,7 @@ import {
EntityLineage,
EntityReference,
} from '../../generated/type/entityLineage';
import { TagLabel } from '../../generated/type/tagLabel';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
export interface PipeLineDetailsProp {
@ -39,7 +40,7 @@ export interface PipeLineDetailsProp {
activeTab: number;
owner: TableDetail['owner'];
description: string;
tier: string;
tier: TagLabel;
followers: Array<User>;
pipelineTags: Array<EntityTags>;
slashedPipelineName: TitleBreadcrumbProps['titleLinks'];

View File

@ -137,7 +137,7 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
isLink: owner?.type === 'team',
openInNewTab: false,
},
{ key: 'Tier', value: tier ? tier.split('.')[1] : '' },
{ key: 'Tier', value: tier?.tagFQN ? tier.tagFQN.split('.')[1] : '' },
...getConfigDetails(),
];
@ -310,7 +310,7 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
{activeTab === 3 && (
<div className="tw-mt-4">
<ManageTabComponent
currentTier={tier}
currentTier={tier?.tagFQN}
currentUser={owner?.id}
hasEditAccess={hasEditAccess()}
onSave={onSettingsUpdate}

View File

@ -14,6 +14,7 @@
import { EntityTags, TableDetail } from 'Models';
import { Topic } from '../../generated/entity/data/topic';
import { User } from '../../generated/entity/teams/user';
import { TagLabel } from '../../generated/type/tagLabel';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
export interface TopicDetailsProps {
@ -31,7 +32,7 @@ export interface TopicDetailsProps {
activeTab: number;
owner: TableDetail['owner'];
description: string;
tier: string;
tier: TagLabel;
followers: Array<User>;
topicTags: Array<EntityTags>;
slashedTopicName: TitleBreadcrumbProps['titleLinks'];

View File

@ -72,7 +72,10 @@ const Description = ({
<div className="tw-px-3 tw-py-2 tw-overflow-y-auto">
<div className="tw-pl-3" data-testid="description" id="description">
{description.trim() ? (
<RichTextEditorPreviewer markdown={description} />
<RichTextEditorPreviewer
className="tw-p-2"
markdown={description}
/>
) : (
<span className="tw-no-description">No description added</span>
)}

View File

@ -17,6 +17,7 @@ import { EntityTags, TableDetail } from 'Models';
import React, { useEffect, useState } from 'react';
import { FOLLOWERS_VIEW_CAP, LIST_SIZE } from '../../../constants/constants';
import { User } from '../../../generated/entity/teams/user';
import { TagLabel } from '../../../generated/type/tagLabel';
import { getHtmlForNonAdminAction } from '../../../utils/CommonUtils';
import SVGIcons from '../../../utils/SvgUtils';
import { getFollowerDetail } from '../../../utils/TableUtils';
@ -42,7 +43,7 @@ type Props = {
isFollowing?: boolean;
followers?: number;
extraInfo: Array<ExtraInfo>;
tier: string;
tier: TagLabel;
tags: Array<EntityTags>;
isTagEditable?: boolean;
tagList?: Array<string>;
@ -86,13 +87,13 @@ const EntityPageInfo = ({
};
const getSelectedTags = () => {
return tier
return tier?.tagFQN
? [
...tags.map((tag) => ({
tagFQN: tag.tagFQN,
isRemovable: true,
})),
{ tagFQN: tier, isRemovable: false },
{ tagFQN: tier.tagFQN, isRemovable: false },
]
: [
...tags.map((tag) => ({
@ -310,8 +311,12 @@ const EntityPageInfo = ({
{(tags.length > 0 || tier) && (
<i className="fas fa-tags tw-px-1 tw-mt-2 tw-text-grey-muted" />
)}
{tier && (
<Tags className="tw-bg-tag" tag={`#${tier.split('.')[1]}`} />
{tier?.tagFQN && (
<Tags
className="tw-bg-tag"
startWith="#"
tag={{ ...tier, tagFQN: tier.tagFQN.split('.')[1] }}
/>
)}
{tags.length > 0 && (
<>
@ -319,7 +324,8 @@ const EntityPageInfo = ({
<Tags
className="tw-bg-tag"
key={index}
tag={`#${tag.tagFQN}`}
startWith="#"
tag={tag}
/>
))}
@ -331,7 +337,8 @@ const EntityPageInfo = ({
<Tags
className="tw-bg-tag tw-px-2"
key={index}
tag={`#${tag.tagFQN}`}
startWith="#"
tag={tag}
/>
))}
</>
@ -381,7 +388,8 @@ const EntityPageInfo = ({
<span className="">
<Tags
className="tw-border-main tw-text-primary"
tag="+ Add tag"
startWith="+ "
tag="Add tag"
type="outlined"
/>
</span>

View File

@ -11,19 +11,26 @@
* limitations under the License.
*/
import classNames from 'classnames';
import React, { useEffect, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import gfm from 'remark-gfm';
/*eslint-disable */
const RichTextEditorPreviewer = ({ markdown }: { markdown: string }) => {
const RichTextEditorPreviewer = ({
markdown,
className = '',
}: {
markdown: string;
className?: string;
}) => {
const [content, setContent] = useState<string>('');
useEffect(() => {
setContent(markdown);
}, [markdown]);
return (
<div className="content-container">
<div className={classNames('content-container', className)}>
<ReactMarkdown
children={content
.replaceAll(/&lt;/g, '<')

View File

@ -11,10 +11,11 @@
* limitations under the License.
*/
import { startCase, uniqueId } from 'lodash';
import { isString, isUndefined, startCase, uniqueId } from 'lodash';
import React, { FunctionComponent } from 'react';
import { Link } from 'react-router-dom';
import { SearchIndex } from '../../../enums/search.enum';
import { TagLabel } from '../../../generated/type/tagLabel';
import { stringToHTML } from '../../../utils/StringsUtils';
import {
getEntityIcon,
@ -28,11 +29,11 @@ type Props = {
owner?: string;
description?: string;
tableType?: string;
tier?: string;
tier?: string | TagLabel;
usage?: number;
serviceType?: string;
fullyQualifiedName: string;
tags?: string[];
tags?: string[] | TagLabel[];
indexType: string;
matches?: {
key: string;
@ -52,6 +53,14 @@ const TableDataCard: FunctionComponent<Props> = ({
indexType,
matches,
}: Props) => {
const getTier = () => {
if (tier) {
return isString(tier) ? tier : tier.tagFQN;
}
return 'No Tier';
};
const OtherDetails = [
{ key: 'Owner', value: owner },
{ key: 'Service', value: serviceType },
@ -62,13 +71,15 @@ const TableDataCard: FunctionComponent<Props> = ({
? getUsagePercentile(usage)
: undefined,
},
{ key: 'Tier', value: tier ? tier : 'No Tier' },
{ key: 'Tier', value: getTier() },
];
const getAssetTags = () => {
const assetTags = [...(tags as Array<string>)];
if (tier) {
assetTags.filter((tag) => !tag.includes(tier)).unshift(tier);
const assetTags = [...(tags as Array<TagLabel>)];
if (tier && !isUndefined(tier)) {
assetTags
// .filter((tag) => !tag.tagFQN.includes((tier as TagLabel).tagFQN))
.unshift(tier as TagLabel);
}
return [...new Set(assetTags)];

View File

@ -11,8 +11,9 @@
* limitations under the License.
*/
import { isNil } from 'lodash';
import { isNil, isString } from 'lodash';
import React, { FunctionComponent } from 'react';
import { TagLabel } from '../../../generated/type/tagLabel';
import Tag from '../../tags/tags';
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
@ -22,7 +23,7 @@ type Props = {
key: string;
value?: string;
}[];
tags?: string[];
tags?: string[] | TagLabel[];
};
const TableDataCardBody: FunctionComponent<Props> = ({
@ -30,6 +31,19 @@ const TableDataCardBody: FunctionComponent<Props> = ({
extraInfo,
tags,
}: Props) => {
const getTagValue = (tag: string | TagLabel): string | TagLabel => {
if (isString(tag)) {
return tag.startsWith('Tier.Tier') ? tag.split('.')[1] : tag;
} else {
return {
...tag,
tagFQN: tag.tagFQN.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN,
};
}
};
return (
<div data-testid="table-body">
<div className="tw-mb-1 description-text">
@ -63,7 +77,8 @@ const TableDataCardBody: FunctionComponent<Props> = ({
<Tag
className="tw-border-none tw-bg-gray-200"
key={index}
tag={`#${tag.startsWith('Tier.Tier') ? tag.split('.')[1] : tag}`}
startWith="#"
tag={getTagValue(tag)}
type="contained"
/>
))}

View File

@ -410,7 +410,8 @@ const SchemaTable: FunctionComponent<Props> = ({
<span className="tw-opacity-0 group-hover:tw-opacity-100">
<Tags
className="tw-border-main"
tag="+ Add tag"
startWith="+ "
tag="Add tag"
type="outlined"
/>
</span>

View File

@ -11,7 +11,8 @@
* limitations under the License.
*/
import { EntityTags, FormatedTableData } from 'Models';
import { isString } from 'lodash';
import { FormatedTableData } from 'Models';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { getDashboardByFqn } from '../../axiosAPIs/dashboardAPI';
import { getPipelineByFqn } from '../../axiosAPIs/pipelineAPI';
@ -23,7 +24,7 @@ import {
getRecentlyViewedData,
setRecentlyViewedData,
} from '../../utils/CommonUtils';
import { getOwnerFromId, getTierFromTableTags } from '../../utils/TableUtils';
import { getOwnerFromId, getTierTags } from '../../utils/TableUtils';
import { getTableTags } from '../../utils/TagsUtils';
import TableDataCard from '../common/table-data-card/TableDataCard';
import Loader from '../Loader/Loader';
@ -69,11 +70,8 @@ const RecentlyViewed: FunctionComponent = () => {
name,
owner: getOwnerFromId(owner?.id)?.name || '--',
serviceType: oData.serviceType,
tags: [
getTierFromTableTags(tags),
...tableTags.map((tag) => tag.tagFQN),
].filter((tag) => tag),
tier: getTierFromTableTags(tags),
tags: [...tableTags].filter((tag) => tag),
tier: getTierTags(tags),
weeklyPercentileRank:
usageSummary?.weeklyStats.percentileRank || 0,
});
@ -93,8 +91,8 @@ const RecentlyViewed: FunctionComponent = () => {
name,
owner: getOwnerFromId(owner?.id)?.name || '--',
serviceType: oData.serviceType,
tags: (tags as Array<EntityTags>).map((tag) => tag.tagFQN),
tier: getTierFromTableTags(tags as Array<EntityTags>),
tags: tags,
tier: getTierTags(tags),
});
break;
@ -121,8 +119,8 @@ const RecentlyViewed: FunctionComponent = () => {
name: displayName,
owner: getOwnerFromId(owner?.id)?.name || '--',
serviceType: oData.serviceType,
tags: (tags as Array<EntityTags>).map((tag) => tag.tagFQN),
tier: getTierFromTableTags(tags as Array<EntityTags>),
tags: tags,
tier: getTierTags(tags),
});
break;
@ -150,8 +148,8 @@ const RecentlyViewed: FunctionComponent = () => {
name: displayName,
owner: getOwnerFromId(owner?.id)?.name || '--',
serviceType: oData.serviceType,
tags: (tags as Array<EntityTags>).map((tag) => tag.tagFQN),
tier: getTierFromTableTags(tags as Array<EntityTags>),
tags: tags,
tier: getTierTags(tags),
});
break;
@ -200,7 +198,9 @@ const RecentlyViewed: FunctionComponent = () => {
serviceType={item.serviceType || '--'}
tableType={item.tableType}
tags={item.tags}
tier={item.tier?.split('.')[1]}
tier={
isString(item.tier) ? item.tier?.split('.')[1] : item.tier
}
usage={item.weeklyPercentileRank}
/>
</div>

View File

@ -12,11 +12,10 @@
*/
import classNames from 'classnames';
import { capitalize, isEmpty, isNull } from 'lodash';
import { isEmpty, isNull } from 'lodash';
import { EntityTags } from 'Models';
import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
import { Button } from '../buttons/Button/Button';
import PopOver from '../common/popover/PopOver';
import DropDownList from '../dropdown/DropDownList';
import Tags from '../tags/tags';
import { TagsContainerProps } from './tags-container.interface';
@ -72,6 +71,7 @@ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
.filter((tag) => {
return !tags.some((selectedTag) => selectedTag.tagFQN === tag);
})
.filter((tag) => !tag.includes('Tier'))
.map((tag) => {
return {
name: tag,
@ -126,8 +126,8 @@ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
onCancel(event);
};
const getTagsContainer = (tag: EntityTags, index: number) => {
return tag.tagFQN ? (
const getTagsElement = (tag: EntityTags, index: number) => {
return (
<Tags
className="tw-bg-gray-200"
editable={editable}
@ -136,26 +136,10 @@ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
removeTag={(_e, removedTag: string) => {
handleTagRemoval(removedTag, index);
}}
tag={`#${tag.tagFQN}`}
startWith="#"
tag={tag}
/>
) : null;
};
const getTagsElement = (tag: EntityTags, index: number) => {
if (tag.labelType) {
return (
<PopOver
key={index}
position="top"
size="small"
title={capitalize(tag.labelType)}
trigger="mouseenter">
{getTagsContainer(tag, index)}
</PopOver>
);
} else {
return getTagsContainer(tag, index);
}
);
};
const handleClick = (e: MouseEvent) => {
if (node?.current?.contains(e.target as Node)) {

View File

@ -11,10 +11,13 @@
* limitations under the License.
*/
import { TagLabel } from '../../generated/type/tagLabel';
export type TagProps = {
className?: string;
editable?: boolean;
tag: string;
startWith?: '#' | '+ ';
tag: string | TagLabel;
type?: 'contained' | 'outlined';
isRemovable?: boolean;
removeTag?: (

View File

@ -20,7 +20,7 @@ const mockCallback = jest.fn();
describe('Test tags Component', () => {
it('Component should render', () => {
const { container } = render(
<Tags editable removeTag={mockCallback} tag="test" />
<Tags editable removeTag={mockCallback} startWith="#" tag="test" />
);
const tags = getByTestId(container, 'tags');
const remove = getByTestId(container, 'remove');
@ -31,7 +31,7 @@ describe('Test tags Component', () => {
it('onClick of X callback function should call', () => {
const { container } = render(
<Tags editable removeTag={mockCallback} tag="test" />
<Tags editable removeTag={mockCallback} startWith="#" tag="test" />
);
const remove = getByTestId(container, 'remove');
fireEvent.click(

View File

@ -12,7 +12,10 @@
*/
import classNames from 'classnames';
import { isString } from 'lodash';
import React, { FunctionComponent } from 'react';
import PopOver from '../common/popover/PopOver';
import RichTextEditorPreviewer from '../common/rich-text-editor/RichTextEditorPreviewer';
import { TagProps } from './tags.interface';
import { tagStyles } from './tags.styles';
@ -20,6 +23,7 @@ const Tags: FunctionComponent<TagProps> = ({
className,
editable,
tag,
startWith,
type = 'contained',
removeTag,
isRemovable = true,
@ -31,24 +35,67 @@ const Tags: FunctionComponent<TagProps> = ({
? tagStyles.text.editable
: tagStyles.text.default;
return (
<span
className={classNames(baseStyle, layoutStyles, className)}
data-testid="tags">
<span className={classNames(textBaseStyle, textLayoutStyles)}>{tag}</span>
{editable && isRemovable && (
<span
className="tw-py-1 tw-px-2 tw-rounded tw-cursor-pointer"
data-testid="remove"
onClick={(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
e.preventDefault();
e.stopPropagation();
removeTag && removeTag(e, tag.startsWith('#') ? tag.slice(1) : tag);
}}>
<i aria-hidden="true" className="fa fa-times tw-text-grey-300" />
const getTagString = (tag: string) => {
return tag.startsWith('#') ? tag.slice(1) : tag;
};
const getTag = (tag: string, startWith = '') => {
return (
<span
className={classNames(baseStyle, layoutStyles, className)}
data-testid="tags">
<span className={classNames(textBaseStyle, textLayoutStyles)}>
{`${startWith}${tag}`}
</span>
{editable && isRemovable && (
<span
className="tw-py-1 tw-px-2 tw-rounded tw-cursor-pointer"
data-testid="remove"
onClick={(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
e.preventDefault();
e.stopPropagation();
removeTag && removeTag(e, getTagString(tag));
}}>
<i aria-hidden="true" className="fa fa-times tw-text-grey-300" />
</span>
)}
</span>
);
};
return (
<>
{isString(tag) ? (
getTag(tag, startWith)
) : (
<>
{tag.description || tag.labelType ? (
<PopOver
html={
<div className="tw-text-left tw-p-1">
{tag.description && (
<div className="tw-mb-3">
<RichTextEditorPreviewer
className="tw-p-2"
markdown={tag.description}
/>
</div>
)}
<p>Set as {tag.labelType}</p>
</div>
}
position="top"
size="small"
title=""
trigger="mouseenter">
{getTag(tag.tagFQN, startWith)}
</PopOver>
) : (
getTag(tag.tagFQN, startWith)
)}
</>
)}
</span>
</>
);
};

View File

@ -190,14 +190,14 @@ declare module 'Models' {
fullyQualifiedName: string;
owner: string;
tableType?: string;
tags: string[];
tags: string[] | TagLabel[];
dailyStats?: number;
dailyPercentileRank?: number;
weeklyStats?: number;
weeklyPercentileRank?: number;
service?: string;
serviceType?: string;
tier: string;
tier: string | TagLabel;
highlight?: {
description: string[];
table_name: string[];

View File

@ -38,13 +38,14 @@ import { EntityType } from '../../enums/entity.enum';
import { ServiceCategory } from '../../enums/service.enum';
import { Dbtmodel } from '../../generated/entity/data/dbtmodel';
import { User } from '../../generated/entity/teams/user';
import { TagLabel } from '../../generated/type/tagLabel';
import { addToRecentViewed, getCurrentUserId } from '../../utils/CommonUtils';
import {
dbtModelTabs,
getCurrentDBTModelTab,
} from '../../utils/DBTModelDetailsUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import { getOwnerFromId, getTierFromTableTags } from '../../utils/TableUtils';
import { getOwnerFromId, getTierTags } from '../../utils/TableUtils';
import { getTableTags } from '../../utils/TagsUtils';
const DBTModelDetailsPage: FunctionComponent = () => {
@ -65,7 +66,7 @@ const DBTModelDetailsPage: FunctionComponent = () => {
const [, setCurrentVersion] = useState<string>();
const [dbtModelId, setDbtModelId] = useState('');
const [tier, setTier] = useState<string>();
const [tier, setTier] = useState<TagLabel>();
const [name, setName] = useState('');
const [followers, setFollowers] = useState<Array<User>>([]);
const [slashedDBTModelName, setSlashedDBTModelName] = useState<
@ -131,7 +132,7 @@ const DBTModelDetailsPage: FunctionComponent = () => {
setCurrentVersion(version);
setDbtModelDetails(res.data);
setOwner(getOwnerFromId(owner?.id));
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
resolve();
})
.catch(() => reject());
@ -185,7 +186,7 @@ const DBTModelDetailsPage: FunctionComponent = () => {
setDbtModelId(id);
setCurrentVersion(version);
setOwner(getOwnerFromId(owner?.id));
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setFollowers(followers);
getDatabase(database.id, 'service').then((resDB: AxiosResponse) => {
getServiceById('databaseServices', resDB.data.service?.id).then(
@ -259,7 +260,7 @@ const DBTModelDetailsPage: FunctionComponent = () => {
setActiveTabHandler={activeTabHandler}
settingsUpdateHandler={settingsUpdateHandler}
slashedDBTModelName={slashedDBTModelName}
tier={tier as string}
tier={tier as TagLabel}
unfollowDBTModelHandler={unfollowDBTModel}
users={AppState.users}
viewDefinition={dbtViewDefinition}

View File

@ -37,6 +37,7 @@ import { ServiceCategory } from '../../enums/service.enum';
import { Chart } from '../../generated/entity/data/chart';
import { Dashboard } from '../../generated/entity/data/dashboard';
import { User } from '../../generated/entity/teams/user';
import { TagLabel } from '../../generated/type/tagLabel';
import { addToRecentViewed, getCurrentUserId } from '../../utils/CommonUtils';
import {
dashboardDetailsTabs,
@ -46,7 +47,7 @@ import { serviceTypeLogo } from '../../utils/ServiceUtils';
import {
getOwnerFromId,
getTagsWithoutTier,
getTierFromTableTags,
getTierTags,
} from '../../utils/TableUtils';
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
type ChartType = {
@ -67,7 +68,7 @@ const DashboardDetailsPage = () => {
const [description, setDescription] = useState<string>('');
const [followers, setFollowers] = useState<Array<User>>([]);
const [owner, setOwner] = useState<TableDetail['owner']>();
const [tier, setTier] = useState<string>();
const [tier, setTier] = useState<TagLabel>();
const [tags, setTags] = useState<Array<EntityTags>>([]);
const [activeTab, setActiveTab] = useState<number>(
getCurrentDashboardTab(tab)
@ -172,7 +173,7 @@ const DashboardDetailsPage = () => {
setDescription(description ?? '');
setFollowers(followers);
setOwner(getOwnerFromId(owner?.id));
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setTags(getTagsWithoutTier(tags));
getServiceById('dashboardServices', service?.id).then(
(serviceRes: AxiosResponse) => {
@ -239,7 +240,7 @@ const DashboardDetailsPage = () => {
const onTagUpdate = (updatedDashboard: Dashboard) => {
saveUpdatedDashboardData(updatedDashboard).then((res: AxiosResponse) => {
setTier(getTierFromTableTags(res.data.tags));
setTier(getTierTags(res.data.tags));
setTags(getTagsWithoutTier(res.data.tags));
});
};
@ -252,7 +253,7 @@ const DashboardDetailsPage = () => {
.then((res) => {
setDashboardDetails(res.data);
setOwner(getOwnerFromId(res.data.owner?.id));
setTier(getTierFromTableTags(res.data.tags));
setTier(getTierTags(res.data.tags));
resolve();
})
.catch(() => reject());
@ -326,7 +327,7 @@ const DashboardDetailsPage = () => {
slashedDashboardName={slashedDashboardName}
tagList={tagList}
tagUpdateHandler={onTagUpdate}
tier={tier as string}
tier={tier as TagLabel}
unfollowDashboardHandler={unfollowDashboard}
users={AppState.users}
/>

View File

@ -47,6 +47,7 @@ import {
} from '../../generated/entity/data/table';
import { User } from '../../generated/entity/teams/user';
import { EntityLineage } from '../../generated/type/entityLineage';
import { TagLabel } from '../../generated/type/tagLabel';
import {
addToRecentViewed,
getCurrentUserId,
@ -58,7 +59,7 @@ import {
} from '../../utils/DatasetDetailsUtils';
import { getEntityLineage } from '../../utils/EntityUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import { getOwnerFromId, getTierFromTableTags } from '../../utils/TableUtils';
import { getOwnerFromId, getTierTags } from '../../utils/TableUtils';
import { getTableTags } from '../../utils/TagsUtils';
const DatasetDetailsPage: FunctionComponent = () => {
@ -67,7 +68,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(true);
const USERId = getCurrentUserId();
const [tableId, setTableId] = useState('');
const [tier, setTier] = useState<string>();
const [tier, setTier] = useState<TagLabel>();
const [name, setName] = useState('');
const [followers, setFollowers] = useState<Array<User>>([]);
const [slashedTableName, setSlashedTableName] = useState<
@ -167,7 +168,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
setPreviousVersion(changeDescription.previousVersion);
setTableDetails(res.data);
setOwner(getOwnerFromId(owner?.id));
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
resolve();
})
.catch(() => reject());
@ -249,7 +250,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
setTableId(id);
setCurrentVersion(version);
setPreviousVersion(changeDescription?.previousVersion);
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setOwner(getOwnerFromId(owner?.id));
setFollowers(followers);
getDatabase(database.id, 'service').then((resDB: AxiosResponse) => {
@ -341,7 +342,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
tableDetails={tableDetails}
tableProfile={tableProfile}
tableTags={tableTags}
tier={tier as string}
tier={tier as TagLabel}
unfollowTableHandler={unfollowTable}
usageSummary={usageSummary}
users={AppState.users}

View File

@ -33,14 +33,15 @@ import {
import { ServiceCategory } from '../../enums/service.enum';
import { Table } from '../../generated/entity/data/table';
import { EntityHistory } from '../../generated/type/entityHistory';
import { TagLabel } from '../../generated/type/tagLabel';
import useToastContext from '../../hooks/useToastContext';
import { getPartialNameFromFQN } from '../../utils/CommonUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import { getOwnerFromId, getTierFromTableTags } from '../../utils/TableUtils';
import { getOwnerFromId, getTierTags } from '../../utils/TableUtils';
const EntityVersionPage: FunctionComponent = () => {
const history = useHistory();
const showToast = useToastContext();
const [tier, setTier] = useState<string>();
const [tier, setTier] = useState<TagLabel>();
const [owner, setOwner] = useState<
Table['owner'] & { displayName?: string }
>();
@ -74,7 +75,7 @@ const EntityVersionPage: FunctionComponent = () => {
)
.then((res: AxiosResponse) => {
const { id, owner, tags, name, database } = res.data;
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setOwner(getOwnerFromId(owner?.id));
setCurrentVersionData(res.data);
getDatabase(database.id, 'service').then((resDB: AxiosResponse) => {
@ -171,7 +172,7 @@ const EntityVersionPage: FunctionComponent = () => {
getTableVersion(id, version)
.then((vRes: AxiosResponse) => {
const { owner, tags } = vRes.data;
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setOwner(getOwnerFromId(owner?.id));
setCurrentVersionData(vRes.data);
setIsVersionLoading(false);
@ -214,7 +215,7 @@ const EntityVersionPage: FunctionComponent = () => {
isVersionLoading={isVersionLoading}
owner={owner}
slashedTableName={slashedTableName}
tier={tier as string}
tier={tier as TagLabel}
version={version}
versionHandler={versionHandler}
versionList={versionList}

View File

@ -48,6 +48,7 @@ import {
} from '../../generated/entity/data/pipeline';
import { User } from '../../generated/entity/teams/user';
import { EntityLineage } from '../../generated/type/entityLineage';
import { TagLabel } from '../../generated/type/tagLabel';
import { addToRecentViewed, getCurrentUserId } from '../../utils/CommonUtils';
import { getEntityLineage } from '../../utils/EntityUtils';
import {
@ -58,7 +59,7 @@ import { serviceTypeLogo } from '../../utils/ServiceUtils';
import {
getOwnerFromId,
getTagsWithoutTier,
getTierFromTableTags,
getTierTags,
} from '../../utils/TableUtils';
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
@ -77,7 +78,7 @@ const PipelineDetailsPage = () => {
const [description, setDescription] = useState<string>('');
const [followers, setFollowers] = useState<Array<User>>([]);
const [owner, setOwner] = useState<TableDetail['owner']>();
const [tier, setTier] = useState<string>();
const [tier, setTier] = useState<TagLabel>();
const [tags, setTags] = useState<Array<EntityTags>>([]);
const [activeTab, setActiveTab] = useState<number>(
getCurrentPipelineTab(tab)
@ -166,7 +167,7 @@ const PipelineDetailsPage = () => {
setDescription(description ?? '');
setFollowers(followers);
setOwner(getOwnerFromId(owner?.id));
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setTags(getTagsWithoutTier(tags));
getServiceById('pipelineServices', service?.id).then(
(serviceRes: AxiosResponse) => {
@ -237,7 +238,7 @@ const PipelineDetailsPage = () => {
.then((res) => {
setPipelineDetails(res.data);
setOwner(getOwnerFromId(res.data.owner?.id));
setTier(getTierFromTableTags(res.data.tags));
setTier(getTierTags(res.data.tags));
resolve();
})
.catch(() => reject());
@ -246,7 +247,7 @@ const PipelineDetailsPage = () => {
const onTagUpdate = (updatedPipeline: Pipeline) => {
saveUpdatedPipelineData(updatedPipeline).then((res: AxiosResponse) => {
setTier(getTierFromTableTags(res.data.tags));
setTier(getTierTags(res.data.tags));
setTags(getTagsWithoutTier(res.data.tags));
});
};
@ -327,7 +328,7 @@ const PipelineDetailsPage = () => {
tagUpdateHandler={onTagUpdate}
tasks={tasks}
taskUpdateHandler={onTaskUpdate}
tier={tier as string}
tier={tier as TagLabel}
unfollowPipelineHandler={unfollowPipeline}
users={AppState.users}
/>

View File

@ -36,13 +36,14 @@ import { EntityType } from '../../enums/entity.enum';
import { ServiceCategory } from '../../enums/service.enum';
import { Topic } from '../../generated/entity/data/topic';
import { User } from '../../generated/entity/teams/user';
import { TagLabel } from '../../generated/type/tagLabel';
import useToastContext from '../../hooks/useToastContext';
import { addToRecentViewed, getCurrentUserId } from '../../utils/CommonUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import {
getOwnerFromId,
getTagsWithoutTier,
getTierFromTableTags,
getTierTags,
} from '../../utils/TableUtils';
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
import {
@ -63,7 +64,7 @@ const TopicDetailsPage: FunctionComponent = () => {
const [description, setDescription] = useState<string>('');
const [followers, setFollowers] = useState<Array<User>>([]);
const [owner, setOwner] = useState<TableDetail['owner']>();
const [tier, setTier] = useState<string>();
const [tier, setTier] = useState<TagLabel>();
const [schemaType, setSchemaType] = useState<string>('');
const [tags, setTags] = useState<Array<EntityTags>>([]);
const [activeTab, setActiveTab] = useState<number>(getCurrentTopicTab(tab));
@ -141,7 +142,7 @@ const TopicDetailsPage: FunctionComponent = () => {
setSchemaType(schemaType);
setFollowers(followers);
setOwner(getOwnerFromId(owner?.id));
setTier(getTierFromTableTags(tags));
setTier(getTierTags(tags));
setTags(getTagsWithoutTier(tags));
setSchemaText(schemaText);
setPartitions(partitions);
@ -230,7 +231,7 @@ const TopicDetailsPage: FunctionComponent = () => {
.then((res) => {
setTopicDetails(res.data);
setOwner(getOwnerFromId(res.data.owner?.id));
setTier(getTierFromTableTags(res.data.tags));
setTier(getTierTags(res.data.tags));
resolve();
})
.catch(() => reject());
@ -239,7 +240,7 @@ const TopicDetailsPage: FunctionComponent = () => {
const onTagUpdate = (updatedTopic: Topic) => {
saveUpdatedTopicData(updatedTopic).then((res: AxiosResponse) => {
setTier(getTierFromTableTags(res.data.tags));
setTier(getTierTags(res.data.tags));
setTags(getTagsWithoutTier(res.data.tags));
});
};
@ -277,7 +278,7 @@ const TopicDetailsPage: FunctionComponent = () => {
slashedTopicName={slashedTopicName}
tagList={tagList}
tagUpdateHandler={onTagUpdate}
tier={tier as string}
tier={tier as TagLabel}
topicDetails={topicDetails}
topicTags={tags}
unfollowTopicHandler={unfollowTopic}

View File

@ -30,7 +30,6 @@ import { getServiceById } from '../../axiosAPIs/serviceAPI';
import { getDatabaseTables } from '../../axiosAPIs/tableAPI';
import NextPrevious from '../../components/common/next-previous/NextPrevious';
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
import PopOver from '../../components/common/popover/PopOver';
import RichTextEditorPreviewer from '../../components/common/rich-text-editor/RichTextEditorPreviewer';
import TabsPane from '../../components/common/TabsPane/TabsPane';
import TitleBreadcrumb from '../../components/common/title-breadcrumb/title-breadcrumb.component';
@ -460,35 +459,28 @@ const DatabaseDetails: FunctionComponent = () => {
</td>
<td className="tableBody-cell">
{table.tags?.map((tag, tagIndex) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
tag.tagFQN?.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
startWith="#"
tag={{
...tag,
tagFQN: tag.tagFQN?.startsWith(
'Tier.Tier'
)
? tag.tagFQN.split('.')[1]
: tag.tagFQN,
}}
/>
))}
{getTableTags(table.columns).map(
(tag, tagIdx) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIdx}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${tag.tagFQN}`}
/>
</PopOver>
startWith="#"
tag={tag}
/>
)
)}
</td>
@ -585,35 +577,28 @@ const DatabaseDetails: FunctionComponent = () => {
</td>
<td className="tableBody-cell">
{dbtModel.tags?.map((tag, tagIndex) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
tag.tagFQN?.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
startWith="#"
tag={{
...tag,
tagFQN: tag.tagFQN?.startsWith(
'Tier.Tier'
)
? tag.tagFQN.split('.')[1]
: tag.tagFQN,
}}
/>
))}
{getTableTags(dbtModel.columns).map(
(tag, tagIdx) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIdx}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${tag.tagFQN}`}
/>
</PopOver>
startWith="#"
tag={tag}
/>
)
)}
</td>

View File

@ -497,21 +497,19 @@ const ServicePage: FunctionComponent = () => {
<td className="tableBody-cell">
{topic.tags && topic.tags?.length > 0
? topic.tags.map((tag, tagIndex) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
startWith="#"
tag={{
...tag,
tagFQN: `${
tag.tagFQN?.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
}`,
}}
/>
))
: '--'}
</td>
@ -524,21 +522,19 @@ const ServicePage: FunctionComponent = () => {
<td className="tableBody-cell">
{dashboard.tags && dashboard.tags?.length > 0
? dashboard.tags.map((tag, tagIndex) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
startWith="#"
tag={{
...tag,
tagFQN: `${
tag.tagFQN?.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
}`,
}}
/>
))
: '--'}
</td>
@ -551,21 +547,19 @@ const ServicePage: FunctionComponent = () => {
<td className="tableBody-cell">
{pipeline.tags && pipeline.tags?.length > 0
? pipeline.tags.map((tag, tagIndex) => (
<PopOver
<Tags
className="tw-bg-gray-200"
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
startWith="#"
tag={{
...tag,
tagFQN: `${
tag.tagFQN?.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
}`,
}}
/>
))
: '--'}
</td>

View File

@ -428,7 +428,8 @@ const TagsPage = () => {
<span className="tw-opacity-0 group-hover:tw-opacity-100">
<Tags
className="tw-border-main"
tag="+ Add tag"
startWith="+ "
tag="Add tag"
type="outlined"
/>
</span>

View File

@ -26,6 +26,7 @@ import { EntityType } from '../enums/entity.enum';
import { SearchIndex } from '../enums/search.enum';
import { ConstraintTypes } from '../enums/table.enum';
import { Column, Table } from '../generated/entity/data/table';
import { TagLabel } from '../generated/type/tagLabel';
import { ordinalize } from './StringsUtils';
import SVGIcons from './SvgUtils';
@ -71,6 +72,16 @@ export const getTierFromTableTags = (
return tierTag?.tagFQN || '';
};
export const getTierTags = (tags: Array<TagLabel>) => {
const tierTag = tags.find(
(item) =>
item.tagFQN.startsWith('Tier.Tier') &&
!isNaN(parseInt(item.tagFQN.substring(9).trim()))
);
return tierTag;
};
export const getTagsWithoutTier = (
tags: Array<EntityTags>
): Array<EntityTags> => {