diff --git a/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx b/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx index 94660c123e..4dac5c7971 100644 --- a/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx +++ b/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx @@ -36,7 +36,8 @@ const PlatformInfo = styled.div` `; const TitleContainer = styled.div` - margin-bottom: 8px; + margin-bottom: 0px; + line-height: 30px; `; const PreviewImage = styled(Image)` @@ -49,7 +50,7 @@ const PreviewImage = styled(Image)` const EntityTitle = styled(Typography.Text)<{ $titleSizePx?: number }>` &&& { - margin-bottom: 0; + margin-right 8px; font-size: ${(props) => props.$titleSizePx || 16}px; font-weight: 600; vertical-align: middle; @@ -91,7 +92,7 @@ const AvatarContainer = styled.div` const TagContainer = styled.div` display: inline-block; - margin-left: 8px; + margin-left: 0px; margin-top: -2px; `; diff --git a/datahub-web-react/src/app/search/SearchFilterLabel.tsx b/datahub-web-react/src/app/search/SearchFilterLabel.tsx index 34682f2611..d842dd4a2e 100644 --- a/datahub-web-react/src/app/search/SearchFilterLabel.tsx +++ b/datahub-web-react/src/app/search/SearchFilterLabel.tsx @@ -1,8 +1,7 @@ import { BookOutlined } from '@ant-design/icons'; -import { Tag } from 'antd'; +import { Tag, Tooltip } from 'antd'; import * as React from 'react'; import styled from 'styled-components'; - import { AggregationMetadata, Domain, @@ -53,24 +52,27 @@ export const SearchFilterLabel = ({ aggregation, field }: Props) => { if (aggregation.entity?.type === EntityType.Tag) { const tag = aggregation.entity as TagType; + const displayName = entityRegistry.getDisplayName(EntityType.Tag, tag); + const truncatedDisplayName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + - {tag?.name} + {truncatedDisplayName} ({countText}) - + ); } if (aggregation.entity?.type === EntityType.CorpUser) { const user = aggregation.entity as CorpUser; const displayName = entityRegistry.getDisplayName(EntityType.CorpUser, user); + const truncatedDisplayName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + { }} /> {displayName} ({countText}) - + ); } if (aggregation.entity?.type === EntityType.CorpGroup) { const group = aggregation.entity as CorpGroup; + const displayName = entityRegistry.getDisplayName(EntityType.CorpGroup, group); + const truncatedDisplayName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + {entityRegistry.getIcon(EntityType.CorpGroup, 16, IconStyleType.ACCENT)} - {entityRegistry.getDisplayName(EntityType.CorpGroup, group)} ({countText}) - + {truncatedDisplayName} ({countText}) + ); } if (aggregation.entity?.type === EntityType.GlossaryTerm) { const term = aggregation.entity as GlossaryTerm; + const displayName = entityRegistry.getDisplayName(EntityType.GlossaryTerm, term); + const truncatedDisplayName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + - {entityRegistry.getDisplayName(EntityType.GlossaryTerm, term)} + {truncatedDisplayName} ({countText}) - + ); } if (aggregation.entity?.type === EntityType.DataPlatform) { const platform = aggregation.entity as DataPlatform; + const displayName = platform.properties?.displayName || platform.info?.displayName || platform.name; + const truncatedDisplayName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + {!!platform.properties?.logoUrl && ( )} - {platform.properties?.displayName || platform.name} ({countText}) + {truncatedDisplayName} ({countText}) - + ); } if (aggregation.entity?.type === EntityType.Container) { const container = aggregation.entity as Container; + const displayName = entityRegistry.getDisplayName(EntityType.Container, container); + const truncatedDisplayName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + {!!container.platform?.properties?.logoUrl && ( )} - {container.properties?.name} ({countText}) + {truncatedDisplayName} ({countText}) - + ); } if (aggregation.entity?.type === EntityType.Domain) { const domain = aggregation.entity as Domain; + const displayName = entityRegistry.getDisplayName(EntityType.Domain, domain); + const truncatedDomainName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> - ( - {countText}) - + + ({countText}) + ); } // Warning: Special casing for Sub-Types if (field === 'typeNames') { - const subTypeDisplayName = capitalizeFirstLetter(aggregation.value); + const displayName = capitalizeFirstLetter(aggregation.value) || ''; + const truncatedDomainName = displayName.length > 25 ? `${displayName.slice(0, 25)}...` : displayName; return ( - <> + - {subTypeDisplayName} ({countText}) + {truncatedDomainName} ({countText}) - + ); } diff --git a/datahub-web-react/src/app/shared/TagStyleEntity.tsx b/datahub-web-react/src/app/shared/TagStyleEntity.tsx index 69a30a7437..81aa5a3dff 100644 --- a/datahub-web-react/src/app/shared/TagStyleEntity.tsx +++ b/datahub-web-react/src/app/shared/TagStyleEntity.tsx @@ -1,11 +1,11 @@ -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { grey } from '@ant-design/colors'; import { Alert, Button, Divider, message, Typography } from 'antd'; import { useHistory } from 'react-router'; import { ApolloError } from '@apollo/client'; import styled from 'styled-components'; import { ChromePicker } from 'react-color'; - +import ColorHash from 'color-hash'; import { PlusOutlined } from '@ant-design/icons'; import { useGetTagQuery } from '../../graphql/tag.generated'; import { EntityType, FacetMetadata, Maybe, Scalars } from '../../types.generated'; @@ -61,7 +61,6 @@ const TitleText = styled(Typography.Text)` const ColorPicker = styled.div` position: relative; display: inline-block; - margin-top: 1em; `; const ColorPickerButton = styled.div` @@ -141,6 +140,12 @@ const OwnerButtonTitle = styled.span` color: ${grey[10]}; `; +const TagName = styled.div` + display: flex; + align-items: center; + justify-content: left; +`; + const { Paragraph } = Typography; type Props = { @@ -152,6 +157,10 @@ type Props = { }; }; +const generateColor = new ColorHash({ + saturation: 0.9, +}); + /** * Responsible for displaying metadata about a tag */ @@ -166,7 +175,7 @@ export default function TagStyleEntity({ urn, useGetSearchResults = useWrappedSe const description = data?.tag?.properties?.description || ''; const [updatedDescription, setUpdatedDescription] = useState(''); - const hexColor = data?.tag?.properties?.colorHex || ''; + const hexColor = data?.tag?.properties?.colorHex || generateColor.hex(urn); const [displayColorPicker, setDisplayColorPicker] = useState(false); const [colorValue, setColorValue] = useState(''); const ownersEmpty = !data?.tag?.ownership?.owners?.length; @@ -195,9 +204,8 @@ export default function TagStyleEntity({ urn, useGetSearchResults = useWrappedSe const aggregations = facets && facets[0]?.aggregations; // Save Color Change - const saveColor = async () => { + const saveColor = useCallback(async () => { if (displayColorPicker) { - message.loading({ content: 'Saving...' }); try { await setTagColorMutation({ variables: { @@ -206,17 +214,42 @@ export default function TagStyleEntity({ urn, useGetSearchResults = useWrappedSe }, }); message.destroy(); - message.success({ content: 'Color Updated', duration: 2 }); + message.success({ content: 'Color Saved!', duration: 2 }); setDisplayColorPicker(false); } catch (e: unknown) { message.destroy(); if (e instanceof Error) { - message.error({ content: `Failed to update Color: \n ${e.message || ''}`, duration: 2 }); + message.error({ content: `Failed to save tag color: \n ${e.message || ''}`, duration: 2 }); } } refetch?.(); } - }; + }, [urn, colorValue, displayColorPicker, setTagColorMutation, setDisplayColorPicker, refetch]); + + const colorPickerRef = useRef(null); + + useEffect(() => { + /** + * Save Color if Clicked outside of the Color Picker + */ + function handleClickOutsideColorPicker(event) { + if (displayColorPicker) { + const { current }: any = colorPickerRef; + if (current) { + if (!current.contains(event.target)) { + setDisplayColorPicker(false); + saveColor(); + } + } + } + } + // Bind the event listener + document.addEventListener('mousedown', handleClickOutsideColorPicker); + return () => { + // Unbind the event listener on clean up + document.removeEventListener('mousedown', handleClickOutsideColorPicker); + }; + }, [colorPickerRef, displayColorPicker, saveColor]); const handlePickerClick = () => { setDisplayColorPicker(!displayColorPicker); @@ -271,15 +304,17 @@ export default function TagStyleEntity({ urn, useGetSearchResults = useWrappedSe {/* Tag Title */}
Tag - - - + + + + + {data?.tag?.properties?.name} + {displayColorPicker && ( - + )} - {data?.tag?.properties?.name}
{/* Tag Description */} diff --git a/datahub-web-react/src/app/shared/tags/DomainLink.tsx b/datahub-web-react/src/app/shared/tags/DomainLink.tsx index bab0a81714..35d31d363f 100644 --- a/datahub-web-react/src/app/shared/tags/DomainLink.tsx +++ b/datahub-web-react/src/app/shared/tags/DomainLink.tsx @@ -16,13 +16,14 @@ export type Props = { name: string; closable?: boolean; onClose?: (e: any) => void; + tagStyle?: any | undefined; }; -export const DomainLink = ({ urn, name, closable, onClose }: Props): JSX.Element => { +export const DomainLink = ({ urn, name, closable, onClose, tagStyle }: Props): JSX.Element => { const entityRegistry = useEntityRegistry(); return ( - + {entityRegistry.getIcon(EntityType.Domain, 10, IconStyleType.ACCENT)}