mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-04 22:52:54 +00:00
feat(ui/lineageV2): Show version pill in lineage sidebar and node (#12599)
This commit is contained in:
parent
6531f0df04
commit
a1a20b2f9d
@ -45,6 +45,7 @@ export function Pill({
|
|||||||
onPillClick,
|
onPillClick,
|
||||||
customStyle,
|
customStyle,
|
||||||
customIconRenderer,
|
customIconRenderer,
|
||||||
|
className,
|
||||||
}: PillProps) {
|
}: PillProps) {
|
||||||
if (!SUPPORTED_CONFIGURATIONS[variant].includes(color)) {
|
if (!SUPPORTED_CONFIGURATIONS[variant].includes(color)) {
|
||||||
console.debug(`Unsupported configuration for Pill: variant=${variant}, color=${color}`);
|
console.debug(`Unsupported configuration for Pill: variant=${variant}, color=${color}`);
|
||||||
@ -62,6 +63,7 @@ export function Pill({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: customStyle?.backgroundColor,
|
backgroundColor: customStyle?.backgroundColor,
|
||||||
}}
|
}}
|
||||||
|
className={className}
|
||||||
>
|
>
|
||||||
{customIconRenderer
|
{customIconRenderer
|
||||||
? customIconRenderer()
|
? customIconRenderer()
|
||||||
|
|||||||
@ -30,6 +30,4 @@ export const PillText = styled.span({
|
|||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
fontSize: '12px',
|
|
||||||
fontWeight: 400,
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export interface PillProps extends Partial<PillPropsDefaults>, Omit<HTMLAttribut
|
|||||||
onClickRightIcon?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
onClickRightIcon?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||||
onClickLeftIcon?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
onClickLeftIcon?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||||
onPillClick?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
onPillClick?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PillStyleProps = PillPropsDefaults & Pick<PillProps, 'color'>;
|
export type PillStyleProps = PillPropsDefaults & Pick<PillProps, 'color'>;
|
||||||
|
|||||||
@ -79,6 +79,7 @@ const getPillFontStyles = (variant: PillVariantOptions, size: SizeOptions): CSSO
|
|||||||
md: { fontSize: getFontSize(size), lineHeight: '24px' },
|
md: { fontSize: getFontSize(size), lineHeight: '24px' },
|
||||||
lg: { fontSize: getFontSize(size), lineHeight: '30px' },
|
lg: { fontSize: getFontSize(size), lineHeight: '30px' },
|
||||||
xl: { fontSize: getFontSize(size), lineHeight: '34px' },
|
xl: { fontSize: getFontSize(size), lineHeight: '34px' },
|
||||||
|
inherit: { fontSize: 'inherit', lineHeight: 'inherit' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const variantOverrides: Partial<Record<PillVariantOptions, CSSObject>> = {
|
const variantOverrides: Partial<Record<PillVariantOptions, CSSObject>> = {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export enum SizeValues {
|
|||||||
md = 'md',
|
md = 'md',
|
||||||
lg = 'lg',
|
lg = 'lg',
|
||||||
xl = 'xl',
|
xl = 'xl',
|
||||||
|
inherit = 'inherit',
|
||||||
}
|
}
|
||||||
export type SizeOptions = keyof typeof SizeValues;
|
export type SizeOptions = keyof typeof SizeValues;
|
||||||
export function getSizeName(size: SizeOptions): string {
|
export function getSizeName(size: SizeOptions): string {
|
||||||
@ -73,8 +74,9 @@ export enum FontSizeValues {
|
|||||||
'2xl' = '2xl',
|
'2xl' = '2xl',
|
||||||
'3xl' = '3xl',
|
'3xl' = '3xl',
|
||||||
'4xl' = '4xl',
|
'4xl' = '4xl',
|
||||||
|
inherit = 'inherit',
|
||||||
}
|
}
|
||||||
export type FontSizeOptions = keyof typeof FontSizeValues;
|
export type FontSizeOptions = keyof typeof SizeValues | keyof typeof FontSizeValues;
|
||||||
export type FontWeightOptions = 'normal' | 'medium' | 'semiBold' | 'bold';
|
export type FontWeightOptions = 'normal' | 'medium' | 'semiBold' | 'bold';
|
||||||
export type FontColorOptions = MiscColorOptions | ColorOptions;
|
export type FontColorOptions = MiscColorOptions | ColorOptions;
|
||||||
|
|
||||||
|
|||||||
@ -27,9 +27,8 @@ export const getColor = (color?: MiscColorOptions | ColorOptions, value: number
|
|||||||
@param size - the size of the font
|
@param size - the size of the font
|
||||||
*/
|
*/
|
||||||
export const getFontSize = (size?: FontSizeOptions) => {
|
export const getFontSize = (size?: FontSizeOptions) => {
|
||||||
let sizeValue = size || '';
|
if (size === 'inherit') return 'inherit';
|
||||||
if (!size) sizeValue = 'md';
|
return typography.fontSizes[size || 'md'];
|
||||||
return typography.fontSizes[sizeValue];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -251,6 +251,7 @@ export default class EntityRegistry {
|
|||||||
canEditLineage: genericEntityProperties.privileges?.canEditLineage ?? undefined,
|
canEditLineage: genericEntityProperties.privileges?.canEditLineage ?? undefined,
|
||||||
lineageSiblingIcon: genericEntityProperties?.lineageSiblingIcon,
|
lineageSiblingIcon: genericEntityProperties?.lineageSiblingIcon,
|
||||||
structuredProperties: genericEntityProperties.structuredProperties ?? undefined,
|
structuredProperties: genericEntityProperties.structuredProperties ?? undefined,
|
||||||
|
versionProperties: genericEntityProperties.versionProperties ?? undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import VersioningBadge from '@app/entityV2/shared/versioning/VersioningBadge';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { useEntityData, useRefetch } from '../../../../../entity/shared/EntityContext';
|
import { useEntityData, useRefetch } from '../../../../../entity/shared/EntityContext';
|
||||||
@ -91,6 +92,10 @@ const SidebarEntityHeader = () => {
|
|||||||
)}
|
)}
|
||||||
{entityData?.health && <HealthIcon urn={urn} health={entityData.health} baseUrl={entityUrl} />}
|
{entityData?.health && <HealthIcon urn={urn} health={entityData.health} baseUrl={entityUrl} />}
|
||||||
<StructuredPropertyBadge structuredProperties={entityData?.structuredProperties} />
|
<StructuredPropertyBadge structuredProperties={entityData?.structuredProperties} />
|
||||||
|
<VersioningBadge
|
||||||
|
versionProperties={entityData?.versionProperties ?? undefined}
|
||||||
|
showPopover={false}
|
||||||
|
/>
|
||||||
</NameWrapper>
|
</NameWrapper>
|
||||||
<ContextPath
|
<ContextPath
|
||||||
instanceId={entityData?.dataPlatformInstance?.instanceId}
|
instanceId={entityData?.dataPlatformInstance?.instanceId}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { VersionPill } from '@app/entityV2/shared/versioning/common';
|
import { VersionPill } from '@app/entityV2/shared/versioning/common';
|
||||||
import VersionsPreview from '@app/entityV2/shared/versioning/VersionsPreview';
|
import VersionsPreview from '@app/entityV2/shared/versioning/VersionsPreview';
|
||||||
import { Popover } from '@components';
|
import { Popover } from '@components';
|
||||||
|
import { PillStyleProps } from '@components/components/Pills/types';
|
||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { VersionProperties } from '@types';
|
import { VersionProperties } from '@types';
|
||||||
@ -8,9 +9,15 @@ import { VersionProperties } from '@types';
|
|||||||
interface Props {
|
interface Props {
|
||||||
versionProperties?: VersionProperties;
|
versionProperties?: VersionProperties;
|
||||||
showPopover: boolean;
|
showPopover: boolean;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function VersioningBadge({ showPopover, versionProperties }: Props) {
|
export default function VersioningBadge({
|
||||||
|
showPopover,
|
||||||
|
versionProperties,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Props & Partial<PillStyleProps>) {
|
||||||
if (!versionProperties?.version.versionTag) {
|
if (!versionProperties?.version.versionTag) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -19,9 +26,11 @@ export default function VersioningBadge({ showPopover, versionProperties }: Prop
|
|||||||
<Popover content={showPopover && <VersionsPreview versionSet={versionProperties.versionSet ?? undefined} />}>
|
<Popover content={showPopover && <VersionsPreview versionSet={versionProperties.versionSet ?? undefined} />}>
|
||||||
<Space>
|
<Space>
|
||||||
<VersionPill
|
<VersionPill
|
||||||
|
{...props}
|
||||||
label={versionProperties?.version.versionTag}
|
label={versionProperties?.version.versionTag}
|
||||||
isLatest={versionProperties.isLatest}
|
isLatest={versionProperties.isLatest}
|
||||||
clickable
|
clickable={showPopover}
|
||||||
|
className={className}
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { LoadingOutlined } from '@ant-design/icons';
|
import { LoadingOutlined } from '@ant-design/icons';
|
||||||
|
import VersioningBadge from '@app/entityV2/shared/versioning/VersioningBadge';
|
||||||
import ContainerPath from '@app/lineageV2/LineageEntityNode/ContainerPath';
|
import ContainerPath from '@app/lineageV2/LineageEntityNode/ContainerPath';
|
||||||
import GhostEntityMenu from '@app/lineageV2/LineageEntityNode/GhostEntityMenu';
|
import GhostEntityMenu from '@app/lineageV2/LineageEntityNode/GhostEntityMenu';
|
||||||
import SchemaFieldNodeContents from '@app/lineageV2/LineageEntityNode/SchemaFieldNodeContents';
|
import SchemaFieldNodeContents from '@app/lineageV2/LineageEntityNode/SchemaFieldNodeContents';
|
||||||
@ -222,6 +223,12 @@ const PropertyBadgeWrapper = styled.div`
|
|||||||
top: -16px;
|
top: -16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledVersioningBadge = styled(VersioningBadge)`
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 1;
|
||||||
|
max-width: 100px;
|
||||||
|
`;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
urn: string;
|
urn: string;
|
||||||
type: EntityType;
|
type: EntityType;
|
||||||
@ -441,6 +448,15 @@ function NodeContents(props: Props & LineageEntity & DisplayedColumns) {
|
|||||||
title={entity?.name}
|
title={entity?.name}
|
||||||
highlightText={searchQuery}
|
highlightText={searchQuery}
|
||||||
highlightColor={highlightColor}
|
highlightColor={highlightColor}
|
||||||
|
extra={
|
||||||
|
entity?.versionProperties && (
|
||||||
|
<StyledVersioningBadge
|
||||||
|
showPopover={false}
|
||||||
|
versionProperties={entity.versionProperties}
|
||||||
|
size="inherit"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{entity?.deprecation?.deprecated && (
|
{entity?.deprecation?.deprecated && (
|
||||||
<DeprecationIcon
|
<DeprecationIcon
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import useShouldHideTransformations from '@app/lineageV2/useShouldHideTransformations';
|
import useShouldHideTransformations from '@app/lineageV2/useShouldHideTransformations';
|
||||||
|
import useShouldShowDataProcessInstances from '@app/lineageV2/useShouldShowDataProcessInstances';
|
||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { ReactFlowProvider } from 'reactflow';
|
import { ReactFlowProvider } from 'reactflow';
|
||||||
import { EntityType, LineageDirection } from '../../types.generated';
|
import { EntityType, LineageDirection } from '../../types.generated';
|
||||||
@ -36,7 +37,7 @@ export default function LineageExplorer(props: Props) {
|
|||||||
const [columnEdgeVersion, setColumnEdgeVersion] = useState(0);
|
const [columnEdgeVersion, setColumnEdgeVersion] = useState(0);
|
||||||
const [displayVersion, setDisplayVersion] = useState<[number, string[]]>([0, []]);
|
const [displayVersion, setDisplayVersion] = useState<[number, string[]]>([0, []]);
|
||||||
const [hideTransformations, setHideTransformations] = useShouldHideTransformations();
|
const [hideTransformations, setHideTransformations] = useShouldHideTransformations();
|
||||||
const [showDataProcessInstances, setShowDataProcessInstances] = useState(false);
|
const [showDataProcessInstances, setShowDataProcessInstances] = useShouldShowDataProcessInstances();
|
||||||
|
|
||||||
const [showGhostEntities, setShowGhostEntities] = useState(false);
|
const [showGhostEntities, setShowGhostEntities] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { DBT_URN } from '@app/ingest/source/builder/constants';
|
|
||||||
import { useGetLineageTimeParams } from '@app/lineage/utils/useGetLineageTimeParams';
|
import { useGetLineageTimeParams } from '@app/lineage/utils/useGetLineageTimeParams';
|
||||||
import { LineageNodesContext } from '@app/lineageV2/common';
|
import { LineageNodesContext } from '@app/lineageV2/common';
|
||||||
import computeOrFilters from '@app/lineageV2/LineageFilterNode/computeOrFilters';
|
import computeOrFilters from '@app/lineageV2/LineageFilterNode/computeOrFilters';
|
||||||
|
import { DEFAULT_IGNORE_AS_HOPS, DEFAULT_SEARCH_FLAGS } from '@app/lineageV2/useSearchAcrossLineage';
|
||||||
import { DEGREE_FILTER_NAME } from '@app/search/utils/constants';
|
import { DEGREE_FILTER_NAME } from '@app/search/utils/constants';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { PlatformFieldsFragment } from '../../../graphql/fragments.generated';
|
import { PlatformFieldsFragment } from '../../../graphql/fragments.generated';
|
||||||
import { useAggregateAcrossLineageQuery } from '../../../graphql/search.generated';
|
import { useAggregateAcrossLineageQuery } from '../../../graphql/search.generated';
|
||||||
import { AggregationMetadata, EntityType, LineageDirection } from '../../../types.generated';
|
import { AggregationMetadata, LineageDirection } from '../../../types.generated';
|
||||||
import { ENTITY_SUB_TYPE_FILTER_NAME, FILTER_DELIMITER, PLATFORM_FILTER_NAME } from '../../searchV2/utils/constants';
|
import { ENTITY_SUB_TYPE_FILTER_NAME, FILTER_DELIMITER, PLATFORM_FILTER_NAME } from '../../searchV2/utils/constants';
|
||||||
|
|
||||||
export type PlatformAggregate = readonly [string, number, PlatformFieldsFragment];
|
export type PlatformAggregate = readonly [string, number, PlatformFieldsFragment];
|
||||||
@ -25,7 +25,7 @@ export default function useFetchFilterNodeContents(parent: string, direction: Li
|
|||||||
const orFilters = computeOrFilters(
|
const orFilters = computeOrFilters(
|
||||||
[{ field: DEGREE_FILTER_NAME, values: ['1'] }],
|
[{ field: DEGREE_FILTER_NAME, values: ['1'] }],
|
||||||
hideTransformations,
|
hideTransformations,
|
||||||
showDataProcessInstances,
|
!showDataProcessInstances,
|
||||||
);
|
);
|
||||||
const { data } = useAggregateAcrossLineageQuery({
|
const { data } = useAggregateAcrossLineageQuery({
|
||||||
skip,
|
skip,
|
||||||
@ -39,15 +39,10 @@ export default function useFetchFilterNodeContents(parent: string, direction: Li
|
|||||||
lineageFlags: {
|
lineageFlags: {
|
||||||
startTimeMillis,
|
startTimeMillis,
|
||||||
endTimeMillis,
|
endTimeMillis,
|
||||||
ignoreAsHops: [
|
ignoreAsHops: DEFAULT_IGNORE_AS_HOPS,
|
||||||
{
|
|
||||||
entityType: EntityType.Dataset,
|
|
||||||
platforms: [DBT_URN],
|
|
||||||
},
|
|
||||||
{ entityType: EntityType.DataJob },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
searchFlags: {
|
searchFlags: {
|
||||||
|
...DEFAULT_SEARCH_FLAGS,
|
||||||
skipCache: true, // TODO: Figure how to get around not needing this
|
skipCache: true, // TODO: Figure how to get around not needing this
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
SchemaMetadata,
|
SchemaMetadata,
|
||||||
Status,
|
Status,
|
||||||
StructuredProperties,
|
StructuredProperties,
|
||||||
|
VersionProperties,
|
||||||
} from '@types';
|
} from '@types';
|
||||||
|
|
||||||
export enum LineageAssetType {
|
export enum LineageAssetType {
|
||||||
@ -67,6 +68,7 @@ export interface FetchedEntityV2 {
|
|||||||
inputFields?: InputFields;
|
inputFields?: InputFields;
|
||||||
canEditLineage?: boolean;
|
canEditLineage?: boolean;
|
||||||
health?: Health[];
|
health?: Health[];
|
||||||
|
versionProperties?: VersionProperties;
|
||||||
lineageAssets?: Map<string, LineageAsset>;
|
lineageAssets?: Map<string, LineageAsset>;
|
||||||
lineageSiblingIcon?: string;
|
lineageSiblingIcon?: string;
|
||||||
containers?: GenericEntityProperties[];
|
containers?: GenericEntityProperties[];
|
||||||
|
|||||||
@ -22,6 +22,24 @@ import {
|
|||||||
|
|
||||||
const PER_HOP_LIMIT = 2;
|
const PER_HOP_LIMIT = 2;
|
||||||
|
|
||||||
|
export const DEFAULT_IGNORE_AS_HOPS = [
|
||||||
|
{
|
||||||
|
entityType: EntityType.Dataset,
|
||||||
|
platforms: [DBT_URN],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entityType: EntityType.SchemaField,
|
||||||
|
platforms: [DBT_URN],
|
||||||
|
},
|
||||||
|
{ entityType: EntityType.DataJob },
|
||||||
|
{ entityType: EntityType.DataProcessInstance },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const DEFAULT_SEARCH_FLAGS = {
|
||||||
|
groupingSpec: { groupingCriteria: [] },
|
||||||
|
filterNonLatestVersions: false,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the lineage structure for a given urn and direction, and updates the nodes map with the results.
|
* Fetches the lineage structure for a given urn and direction, and updates the nodes map with the results.
|
||||||
* @param urn Urn for which to fetch lineage
|
* @param urn Urn for which to fetch lineage
|
||||||
@ -68,22 +86,11 @@ export default function useSearchAcrossLineage(
|
|||||||
startTimeMillis,
|
startTimeMillis,
|
||||||
endTimeMillis,
|
endTimeMillis,
|
||||||
entitiesExploredPerHopLimit: PER_HOP_LIMIT,
|
entitiesExploredPerHopLimit: PER_HOP_LIMIT,
|
||||||
ignoreAsHops: [
|
ignoreAsHops: DEFAULT_IGNORE_AS_HOPS,
|
||||||
{
|
|
||||||
entityType: EntityType.Dataset,
|
|
||||||
platforms: [DBT_URN],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
entityType: EntityType.SchemaField,
|
|
||||||
platforms: [DBT_URN],
|
|
||||||
},
|
|
||||||
{ entityType: EntityType.DataJob },
|
|
||||||
{ entityType: EntityType.DataProcessInstance },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
searchFlags: {
|
searchFlags: {
|
||||||
|
...DEFAULT_SEARCH_FLAGS,
|
||||||
skipCache: !!skipCache,
|
skipCache: !!skipCache,
|
||||||
groupingSpec: { groupingCriteria: [] },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
export default function useShouldShowDataProcessInstances(): [boolean, (value: boolean) => void] {
|
||||||
|
const defaultValue = inLocalStorage() ? loadFromLocalStorage() : true;
|
||||||
|
const [showInstances, setShowInstances] = useState(defaultValue);
|
||||||
|
const setter = useCallback((value: boolean) => {
|
||||||
|
setShowInstances(value);
|
||||||
|
saveToLocalStorage(value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return [showInstances, setter];
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHOW_DATA_PROCESS_INSTANCES_KEY = 'lineageV2__showDataProcessInstances';
|
||||||
|
|
||||||
|
function inLocalStorage(): boolean {
|
||||||
|
return localStorage.getItem(SHOW_DATA_PROCESS_INSTANCES_KEY) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadFromLocalStorage(): boolean {
|
||||||
|
return localStorage.getItem(SHOW_DATA_PROCESS_INSTANCES_KEY) === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveToLocalStorage(showInstances: boolean) {
|
||||||
|
localStorage.setItem(SHOW_DATA_PROCESS_INSTANCES_KEY, String(showInstances));
|
||||||
|
}
|
||||||
@ -23,6 +23,10 @@ const Wrapper = styled.div<{ scale: number; computedRatio: boolean }>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ExtraWrapper = styled.span`
|
||||||
|
margin-left: 0.4em;
|
||||||
|
`;
|
||||||
|
|
||||||
const MIN_SCALE = 2 / 3;
|
const MIN_SCALE = 2 / 3;
|
||||||
const TOOLTIP_THRESHOLD = 0.8; // Show tooltip if text is smaller than TOOLTIP_THRESHOLD em
|
const TOOLTIP_THRESHOLD = 0.8; // Show tooltip if text is smaller than TOOLTIP_THRESHOLD em
|
||||||
|
|
||||||
@ -30,11 +34,19 @@ interface Props {
|
|||||||
title?: string;
|
title?: string;
|
||||||
highlightText?: string;
|
highlightText?: string;
|
||||||
highlightColor?: string;
|
highlightColor?: string;
|
||||||
|
extra?: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
placement?: TooltipProps['placement'];
|
placement?: TooltipProps['placement'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function OverflowTitle({ title, highlightText, highlightColor, className, placement = 'top' }: Props) {
|
export default function OverflowTitle({
|
||||||
|
title,
|
||||||
|
highlightText,
|
||||||
|
highlightColor,
|
||||||
|
extra,
|
||||||
|
className,
|
||||||
|
placement = 'top',
|
||||||
|
}: Props) {
|
||||||
const [scale, setScale] = React.useState<number>(1);
|
const [scale, setScale] = React.useState<number>(1);
|
||||||
const [ratio, setRatio] = React.useState<number | undefined>(undefined);
|
const [ratio, setRatio] = React.useState<number | undefined>(undefined);
|
||||||
|
|
||||||
@ -59,6 +71,7 @@ export default function OverflowTitle({ title, highlightText, highlightColor, cl
|
|||||||
<Wrapper className={className} ref={ref} scale={scale} computedRatio={!!ratio}>
|
<Wrapper className={className} ref={ref} scale={scale} computedRatio={!!ratio}>
|
||||||
<Highlight search={highlightText} matchStyle={{ backgroundColor: highlightColor }}>
|
<Highlight search={highlightText} matchStyle={{ backgroundColor: highlightColor }}>
|
||||||
{title}
|
{title}
|
||||||
|
{!!extra && <ExtraWrapper>{extra}</ExtraWrapper>}
|
||||||
</Highlight>
|
</Highlight>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
</OptionalTooltip>
|
</OptionalTooltip>
|
||||||
|
|||||||
@ -694,6 +694,11 @@ fragment entityLineageV2 on Entity {
|
|||||||
...lineageV2Result
|
...lineageV2Result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
... on SupportsVersions {
|
||||||
|
versionProperties {
|
||||||
|
...versionProperties
|
||||||
|
}
|
||||||
|
}
|
||||||
... on SchemaFieldEntity {
|
... on SchemaFieldEntity {
|
||||||
fieldPath
|
fieldPath
|
||||||
parent {
|
parent {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user