mirror of
https://github.com/grafana/grafana.git
synced 2025-02-09 06:56:07 -06:00
Canvas: Improved tooltip (#90162)
Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
parent
bb187ce4b1
commit
8989ac4a0c
@ -108,6 +108,7 @@ export const cloudItem: CanvasElementItem = {
|
||||
|
||||
const data: CanvasElementData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -114,6 +114,7 @@ export const ellipseItem: CanvasElementItem<CanvasElementConfig, CanvasElementDa
|
||||
|
||||
const data: CanvasElementData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -183,6 +183,7 @@ export const metricValueItem: CanvasElementItem<TextConfig, TextData> = {
|
||||
|
||||
const data: TextData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -108,6 +108,7 @@ export const parallelogramItem: CanvasElementItem = {
|
||||
|
||||
const data: CanvasElementData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -81,6 +81,7 @@ export const rectangleItem: CanvasElementItem<TextConfig, TextData> = {
|
||||
|
||||
const data: TextData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -156,6 +156,7 @@ export const textItem: CanvasElementItem<TextConfig, TextData> = {
|
||||
|
||||
const data: TextData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -109,6 +109,7 @@ export const triangleItem: CanvasElementItem = {
|
||||
|
||||
const data: CanvasElementData = {
|
||||
text: textConfig?.text ? dimensionContext.getText(textConfig.text).value() : '',
|
||||
field: textConfig?.text?.field,
|
||||
align: textConfig?.align ?? Align.Center,
|
||||
valign: textConfig?.valign ?? VAlign.Middle,
|
||||
size: textConfig?.size,
|
||||
|
@ -281,7 +281,7 @@ export class Scene {
|
||||
};
|
||||
|
||||
render() {
|
||||
const isTooltipValid = (this.tooltip?.element?.data?.links?.length ?? 0) > 0;
|
||||
const isTooltipValid = (this.tooltip?.element?.data?.links?.length ?? 0) > 0 || this.tooltip?.element?.data?.field;
|
||||
const canShowElementTooltip = !this.isEditingEnabled && isTooltipValid;
|
||||
|
||||
const sceneDiv = (
|
||||
|
@ -30,6 +30,7 @@ export interface TextData {
|
||||
align: Align;
|
||||
valign: VAlign;
|
||||
links?: LinkModel[];
|
||||
field?: string;
|
||||
}
|
||||
|
||||
export interface TextConfig {
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { useDialog } from '@react-aria/dialog';
|
||||
import { useOverlay } from '@react-aria/overlays';
|
||||
import { createRef } from 'react';
|
||||
|
||||
import { GrafanaTheme2, LinkModel } from '@grafana/data/src';
|
||||
import { LinkButton, Portal, Stack, useStyles2, VizTooltipContainer } from '@grafana/ui';
|
||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||
import { FieldType, GrafanaTheme2, formattedValueToString, getFieldDisplayName } from '@grafana/data/src';
|
||||
import { Portal, useStyles2, VizTooltipContainer } from '@grafana/ui';
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
import { CloseButton } from '@grafana/ui/src/components/uPlot/plugins/CloseButton';
|
||||
import { Scene } from 'app/features/canvas/runtime/scene';
|
||||
|
||||
interface Props {
|
||||
@ -13,7 +17,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export const CanvasTooltip = ({ scene }: Props) => {
|
||||
const style = useStyles2(getStyles);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const onClose = () => {
|
||||
if (scene?.tooltipCallback && scene.tooltip) {
|
||||
@ -30,40 +34,47 @@ export const CanvasTooltip = ({ scene }: Props) => {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const renderDataLinks = () =>
|
||||
element.data?.links &&
|
||||
element.data?.links.length > 0 && (
|
||||
<div>
|
||||
<Stack direction={'column'}>
|
||||
{element.data?.links?.map((link: LinkModel, i: number) => (
|
||||
<LinkButton
|
||||
key={i}
|
||||
icon={'external-link-alt'}
|
||||
target={link.target}
|
||||
href={link.href}
|
||||
onClick={link.onClick}
|
||||
fill="text"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{link.title}
|
||||
</LinkButton>
|
||||
))}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
// Retrieve timestamp of the last data point if available
|
||||
const timeField = scene.data?.series[0].fields?.find((field) => field.type === FieldType.time);
|
||||
const lastTimeValue = timeField?.values[timeField.values.length - 1];
|
||||
const shouldDisplayTimeContentItem =
|
||||
timeField && lastTimeValue && element.data.field && getFieldDisplayName(timeField) !== element.data.field;
|
||||
|
||||
const headerItem: VizTooltipItem | null = {
|
||||
label: element.getName(),
|
||||
value: '',
|
||||
};
|
||||
|
||||
const contentItems: VizTooltipItem[] = [
|
||||
{
|
||||
label: element.data.field ?? 'Fixed',
|
||||
value: element.data.text,
|
||||
},
|
||||
...(shouldDisplayTimeContentItem
|
||||
? [
|
||||
{
|
||||
label: 'Time',
|
||||
value: formattedValueToString(timeField?.display!(lastTimeValue)),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
{scene.tooltip?.element && scene.tooltip.anchorPoint && (
|
||||
<Portal>
|
||||
<VizTooltipContainer
|
||||
className={cx(styles.tooltipWrapper, scene.tooltip.isOpen && styles.pinned)}
|
||||
position={{ x: scene.tooltip.anchorPoint.x, y: scene.tooltip.anchorPoint.y }}
|
||||
offset={{ x: 5, y: 0 }}
|
||||
allowPointerEvents={scene.tooltip.isOpen}
|
||||
>
|
||||
<section ref={ref} {...overlayProps} {...dialogProps}>
|
||||
{scene.tooltip.isOpen && <CloseButton style={{ zIndex: 1 }} onClick={onClose} />}
|
||||
<div className={style.wrapper}>{renderDataLinks()}</div>
|
||||
<VizTooltipHeader item={headerItem} isPinned={scene.tooltip.isOpen!} />
|
||||
{element.data.text && <VizTooltipContent items={contentItems} isPinned={scene.tooltip.isOpen!} />}
|
||||
<VizTooltipFooter dataLinks={element.data?.links} />
|
||||
</section>
|
||||
</VizTooltipContainer>
|
||||
</Portal>
|
||||
@ -77,4 +88,20 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
marginTop: '20px',
|
||||
background: theme.colors.background.primary,
|
||||
}),
|
||||
tooltipWrapper: css({
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: theme.zIndex.portal,
|
||||
whiteSpace: 'pre',
|
||||
borderRadius: theme.shape.radius.default,
|
||||
position: 'fixed',
|
||||
background: theme.colors.background.primary,
|
||||
border: `1px solid ${theme.colors.border.weak}`,
|
||||
boxShadow: theme.shadows.z2,
|
||||
userSelect: 'text',
|
||||
padding: 0,
|
||||
}),
|
||||
pinned: css({
|
||||
boxShadow: theme.shadows.z3,
|
||||
}),
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user