2020-12-15 03:53:04 -06:00
|
|
|
import React from 'react';
|
2020-01-17 08:52:08 -06:00
|
|
|
import { ContextMenu, ContextMenuProps } from '../ContextMenu/ContextMenu';
|
|
|
|
import { GraphDimensions } from './GraphTooltip/types';
|
|
|
|
import {
|
|
|
|
FlotDataPoint,
|
|
|
|
getValueFromDimension,
|
|
|
|
getDisplayProcessor,
|
|
|
|
Dimensions,
|
2020-04-27 08:28:06 -05:00
|
|
|
dateTimeFormat,
|
|
|
|
TimeZone,
|
2020-12-15 03:53:04 -06:00
|
|
|
FormattedValue,
|
2020-01-17 08:52:08 -06:00
|
|
|
} from '@grafana/data';
|
2020-12-15 03:53:04 -06:00
|
|
|
import { useTheme } from '../../themes';
|
|
|
|
import { HorizontalGroup } from '../Layout/Layout';
|
|
|
|
import { FormattedValueDisplay } from '../FormattedValueDisplay/FormattedValueDisplay';
|
2021-01-12 08:58:46 -06:00
|
|
|
import { SeriesIcon } from '../VizLegend/SeriesIcon';
|
2020-01-17 08:52:08 -06:00
|
|
|
import { css } from 'emotion';
|
|
|
|
|
|
|
|
export type ContextDimensions<T extends Dimensions = any> = { [key in keyof T]: [number, number | undefined] | null };
|
|
|
|
|
|
|
|
export type GraphContextMenuProps = ContextMenuProps & {
|
|
|
|
getContextMenuSource: () => FlotDataPoint | null;
|
2020-04-27 08:28:06 -05:00
|
|
|
timeZone?: TimeZone;
|
2020-01-17 08:52:08 -06:00
|
|
|
dimensions?: GraphDimensions;
|
|
|
|
contextDimensions?: ContextDimensions;
|
|
|
|
};
|
|
|
|
|
2020-12-15 03:53:04 -06:00
|
|
|
/** @internal */
|
2020-01-17 08:52:08 -06:00
|
|
|
export const GraphContextMenu: React.FC<GraphContextMenuProps> = ({
|
|
|
|
getContextMenuSource,
|
2020-04-27 08:28:06 -05:00
|
|
|
timeZone,
|
2020-01-17 08:52:08 -06:00
|
|
|
items,
|
|
|
|
dimensions,
|
|
|
|
contextDimensions,
|
|
|
|
...otherProps
|
|
|
|
}) => {
|
|
|
|
const source = getContextMenuSource();
|
|
|
|
|
|
|
|
// Do not render items that do not have label specified
|
|
|
|
const itemsToRender = items
|
2021-01-20 00:59:48 -06:00
|
|
|
? items.map((group) => ({
|
2020-01-17 08:52:08 -06:00
|
|
|
...group,
|
2021-01-20 00:59:48 -06:00
|
|
|
items: group.items.filter((item) => item.label),
|
2020-01-17 08:52:08 -06:00
|
|
|
}))
|
|
|
|
: [];
|
|
|
|
|
|
|
|
const renderHeader = () => {
|
|
|
|
if (!source) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If dimensions supplied, we can calculate and display value
|
|
|
|
let value;
|
|
|
|
if (dimensions?.yAxis && contextDimensions?.yAxis?.[1]) {
|
|
|
|
const valueFromDimensions = getValueFromDimension(
|
|
|
|
dimensions.yAxis,
|
|
|
|
contextDimensions.yAxis[0],
|
|
|
|
contextDimensions.yAxis[1]
|
|
|
|
);
|
2020-04-27 08:28:06 -05:00
|
|
|
const display =
|
|
|
|
source.series.valueField.display ??
|
|
|
|
getDisplayProcessor({
|
|
|
|
field: source.series.valueField,
|
|
|
|
timeZone,
|
|
|
|
});
|
2020-01-17 08:52:08 -06:00
|
|
|
value = display(valueFromDimensions);
|
|
|
|
}
|
|
|
|
|
2020-04-27 08:28:06 -05:00
|
|
|
const formattedValue = dateTimeFormat(source.datapoint[0], {
|
|
|
|
defaultWithMS: source.series.hasMsResolution,
|
|
|
|
timeZone,
|
|
|
|
});
|
|
|
|
|
2020-01-17 08:52:08 -06:00
|
|
|
return (
|
2020-12-15 03:53:04 -06:00
|
|
|
<GraphContextMenuHeader
|
|
|
|
timestamp={formattedValue}
|
|
|
|
seriesColor={source.series.color}
|
|
|
|
displayName={source.series.alias || source.series.label}
|
|
|
|
displayValue={value}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
return <ContextMenu {...otherProps} items={itemsToRender} renderHeader={renderHeader} />;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
export const GraphContextMenuHeader = ({
|
|
|
|
timestamp,
|
|
|
|
seriesColor,
|
|
|
|
displayName,
|
|
|
|
displayValue,
|
|
|
|
}: {
|
|
|
|
timestamp: string;
|
|
|
|
seriesColor: string;
|
|
|
|
displayName: string;
|
|
|
|
displayValue: FormattedValue;
|
|
|
|
}) => {
|
|
|
|
const theme = useTheme();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={css`
|
|
|
|
padding: ${theme.spacing.xs} ${theme.spacing.sm};
|
|
|
|
font-size: ${theme.typography.size.sm};
|
|
|
|
z-index: ${theme.zIndex.tooltip};
|
|
|
|
`}
|
|
|
|
>
|
|
|
|
<strong>{timestamp}</strong>
|
|
|
|
<HorizontalGroup>
|
2020-01-17 08:52:08 -06:00
|
|
|
<div>
|
2020-12-15 03:53:04 -06:00
|
|
|
<SeriesIcon color={seriesColor} />
|
2020-01-17 08:52:08 -06:00
|
|
|
<span
|
|
|
|
className={css`
|
|
|
|
white-space: nowrap;
|
|
|
|
padding-left: ${theme.spacing.xs};
|
|
|
|
`}
|
|
|
|
>
|
2020-12-15 03:53:04 -06:00
|
|
|
{displayName}
|
2020-01-17 08:52:08 -06:00
|
|
|
</span>
|
|
|
|
</div>
|
2020-12-15 03:53:04 -06:00
|
|
|
{displayValue && <FormattedValueDisplay value={displayValue} />}
|
|
|
|
</HorizontalGroup>
|
|
|
|
</div>
|
|
|
|
);
|
2020-01-17 08:52:08 -06:00
|
|
|
};
|