Actions: Fix support in StateTimeline and XYChart (#100543)

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
Adela Almasan
2025-02-12 13:53:32 -06:00
committed by GitHub
parent d1dee968c3
commit 62e06cfac8
9 changed files with 49 additions and 25 deletions

View File

@ -157,8 +157,8 @@ export const BarChartPanel = (props: PanelProps<Options>) => {
hoverMode={
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
}
getDataLinks={(seriesIdx: number, dataIdx: number) =>
vizSeries[0].fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
getDataLinks={(seriesIdx, dataIdx) =>
vizSeries[0].fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
}
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
return (

View File

@ -282,8 +282,8 @@ export const CandlestickPanel = ({
clientZoom={true}
syncMode={cursorSync}
syncScope={eventsScope}
getDataLinks={(seriesIdx: number, dataIdx: number) =>
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
getDataLinks={(seriesIdx, dataIdx) =>
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
}
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange2, viaSync, dataLinks) => {
if (enableAnnotationCreation && timeRange2 != null) {

View File

@ -107,8 +107,8 @@ export const StateTimelinePanel = ({
queryZoom={onChangeTimeRange}
syncMode={cursorSync}
syncScope={eventsScope}
getDataLinks={(seriesIdx: number, dataIdx: number) =>
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
getDataLinks={(seriesIdx, dataIdx) =>
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
}
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
if (enableAnnotationCreation && timeRange2 != null) {

View File

@ -68,12 +68,16 @@ export const StateTimelineTooltip2 = ({
let footer: ReactNode;
if (isPinned && seriesIdx != null) {
if (seriesIdx != null) {
const field = series.fields[seriesIdx];
const dataIdx = dataIdxs[seriesIdx]!;
const actions = getFieldActions(series, field, replaceVariables!, dataIdx);
const hasOneClickLink = dataLinks.some((dataLink) => dataLink.oneClick === true);
footer = <VizTooltipFooter dataLinks={dataLinks} annotate={annotate} actions={actions} />;
if (isPinned || hasOneClickLink) {
const dataIdx = dataIdxs[seriesIdx]!;
const actions = getFieldActions(series, field, replaceVariables!, dataIdx);
footer = <VizTooltipFooter dataLinks={dataLinks} actions={actions} annotate={annotate} />;
}
}
const headerItem: VizTooltipItem = {

View File

@ -119,8 +119,8 @@ export const StatusHistoryPanel = ({
queryZoom={onChangeTimeRange}
syncMode={cursorSync}
syncScope={eventsScope}
getDataLinks={(seriesIdx: number, dataIdx: number) =>
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
getDataLinks={(seriesIdx, dataIdx) =>
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
}
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
if (enableAnnotationCreation && timeRange2 != null) {

View File

@ -106,8 +106,8 @@ export const TimeSeriesPanel = ({
clientZoom={true}
syncMode={cursorSync}
syncScope={eventsScope}
getDataLinks={(seriesIdx: number, dataIdx: number) =>
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
getDataLinks={(seriesIdx, dataIdx) =>
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
}
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange2, viaSync, dataLinks) => {
if (enableAnnotationCreation && timeRange2 != null) {

View File

@ -119,8 +119,8 @@ export const TrendPanel = ({
hoverMode={
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
}
getDataLinks={(seriesIdx: number, dataIdx: number) =>
alignedDataFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
getDataLinks={(seriesIdx, dataIdx) =>
alignedDataFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
}
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange, viaSync, dataLinks) => {
return (

View File

@ -17,6 +17,8 @@ import {
import { TooltipHoverMode } from '@grafana/ui/src/components/uPlot/plugins/TooltipPlugin2';
import { getDisplayValuesForCalcs } from '@grafana/ui/src/components/uPlot/utils';
import { getDataLinks } from '../status-history/utils';
import { XYChartTooltip } from './XYChartTooltip';
import { Options } from './panelcfg.gen';
import { prepConfig } from './scatter';
@ -113,7 +115,11 @@ export const XYChartPanel2 = (props: Props2) => {
<TooltipPlugin2
config={builder!}
hoverMode={TooltipHoverMode.xyOne}
render={(u, dataIdxs, seriesIdx, isPinned, dismiss) => {
getDataLinks={(seriesIdx, dataIdx) => {
const xySeries = series[seriesIdx - 1];
return getDataLinks(xySeries.y.field, dataIdx);
}}
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
return (
<XYChartTooltip
data={props.data.series}
@ -123,6 +129,7 @@ export const XYChartPanel2 = (props: Props2) => {
isPinned={isPinned}
seriesIdx={seriesIdx!}
replaceVariables={props.replaceVariables}
dataLinks={dataLinks}
/>
);
}}

View File

@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { DataFrame, InterpolateFunction } from '@grafana/data';
import { DataFrame, InterpolateFunction, LinkModel } from '@grafana/data';
import { alpha } from '@grafana/data/src/themes/colorManipulator';
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
@ -8,7 +8,7 @@ import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizToolt
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
import { ColorIndicator, VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
import { getDataLinks, getFieldActions } from '../status-history/utils';
import { getFieldActions } from '../status-history/utils';
import { XYSeries } from './types2';
import { fmt } from './utils';
@ -21,6 +21,7 @@ export interface Props {
data: DataFrame[];
xySeries: XYSeries[];
replaceVariables: InterpolateFunction;
dataLinks: LinkModel[];
}
function stripSeriesName(fieldName: string, seriesName: string) {
@ -31,7 +32,16 @@ function stripSeriesName(fieldName: string, seriesName: string) {
return fieldName;
}
export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, xySeries, dismiss, isPinned, replaceVariables }: Props) => {
export const XYChartTooltip = ({
dataIdxs,
seriesIdx,
data,
xySeries,
dismiss,
isPinned,
replaceVariables,
dataLinks,
}: Props) => {
const rowIndex = dataIdxs.find((idx) => idx !== null)!;
const series = xySeries[seriesIdx! - 1];
@ -93,12 +103,15 @@ export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, xySeries, dismiss, i
let footer: ReactNode;
if (isPinned && seriesIdx != null) {
const links = getDataLinks(yField, rowIndex);
const yFieldFrame = data.find((frame) => frame.fields.includes(yField))!;
const actions = getFieldActions(yFieldFrame, yField, replaceVariables, rowIndex);
if (seriesIdx != null) {
const hasOneClickLink = dataLinks?.some((dataLink) => dataLink.oneClick === true);
footer = <VizTooltipFooter dataLinks={links} actions={actions} />;
if (isPinned || hasOneClickLink) {
const yFieldFrame = data.find((frame) => frame.fields.includes(yField))!;
const actions = getFieldActions(yFieldFrame, yField, replaceVariables, rowIndex);
footer = <VizTooltipFooter dataLinks={dataLinks} actions={actions} />;
}
}
return (