mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 20:59:35 +08:00
Actions: Fix support in StateTimeline
and XYChart
(#100543)
Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
@ -157,8 +157,8 @@ export const BarChartPanel = (props: PanelProps<Options>) => {
|
|||||||
hoverMode={
|
hoverMode={
|
||||||
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
|
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
|
||||||
}
|
}
|
||||||
getDataLinks={(seriesIdx: number, dataIdx: number) =>
|
getDataLinks={(seriesIdx, dataIdx) =>
|
||||||
vizSeries[0].fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
vizSeries[0].fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
||||||
}
|
}
|
||||||
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
|
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
|
||||||
return (
|
return (
|
||||||
|
@ -282,8 +282,8 @@ export const CandlestickPanel = ({
|
|||||||
clientZoom={true}
|
clientZoom={true}
|
||||||
syncMode={cursorSync}
|
syncMode={cursorSync}
|
||||||
syncScope={eventsScope}
|
syncScope={eventsScope}
|
||||||
getDataLinks={(seriesIdx: number, dataIdx: number) =>
|
getDataLinks={(seriesIdx, dataIdx) =>
|
||||||
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
||||||
}
|
}
|
||||||
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange2, viaSync, dataLinks) => {
|
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange2, viaSync, dataLinks) => {
|
||||||
if (enableAnnotationCreation && timeRange2 != null) {
|
if (enableAnnotationCreation && timeRange2 != null) {
|
||||||
|
@ -107,8 +107,8 @@ export const StateTimelinePanel = ({
|
|||||||
queryZoom={onChangeTimeRange}
|
queryZoom={onChangeTimeRange}
|
||||||
syncMode={cursorSync}
|
syncMode={cursorSync}
|
||||||
syncScope={eventsScope}
|
syncScope={eventsScope}
|
||||||
getDataLinks={(seriesIdx: number, dataIdx: number) =>
|
getDataLinks={(seriesIdx, dataIdx) =>
|
||||||
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
||||||
}
|
}
|
||||||
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
|
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
|
||||||
if (enableAnnotationCreation && timeRange2 != null) {
|
if (enableAnnotationCreation && timeRange2 != null) {
|
||||||
|
@ -68,12 +68,16 @@ export const StateTimelineTooltip2 = ({
|
|||||||
|
|
||||||
let footer: ReactNode;
|
let footer: ReactNode;
|
||||||
|
|
||||||
if (isPinned && seriesIdx != null) {
|
if (seriesIdx != null) {
|
||||||
const field = series.fields[seriesIdx];
|
const field = series.fields[seriesIdx];
|
||||||
const dataIdx = dataIdxs[seriesIdx]!;
|
const hasOneClickLink = dataLinks.some((dataLink) => dataLink.oneClick === true);
|
||||||
const actions = getFieldActions(series, field, replaceVariables!, dataIdx);
|
|
||||||
|
|
||||||
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 = {
|
const headerItem: VizTooltipItem = {
|
||||||
|
@ -119,8 +119,8 @@ export const StatusHistoryPanel = ({
|
|||||||
queryZoom={onChangeTimeRange}
|
queryZoom={onChangeTimeRange}
|
||||||
syncMode={cursorSync}
|
syncMode={cursorSync}
|
||||||
syncScope={eventsScope}
|
syncScope={eventsScope}
|
||||||
getDataLinks={(seriesIdx: number, dataIdx: number) =>
|
getDataLinks={(seriesIdx, dataIdx) =>
|
||||||
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
||||||
}
|
}
|
||||||
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
|
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => {
|
||||||
if (enableAnnotationCreation && timeRange2 != null) {
|
if (enableAnnotationCreation && timeRange2 != null) {
|
||||||
|
@ -106,8 +106,8 @@ export const TimeSeriesPanel = ({
|
|||||||
clientZoom={true}
|
clientZoom={true}
|
||||||
syncMode={cursorSync}
|
syncMode={cursorSync}
|
||||||
syncScope={eventsScope}
|
syncScope={eventsScope}
|
||||||
getDataLinks={(seriesIdx: number, dataIdx: number) =>
|
getDataLinks={(seriesIdx, dataIdx) =>
|
||||||
alignedFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
||||||
}
|
}
|
||||||
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange2, viaSync, dataLinks) => {
|
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange2, viaSync, dataLinks) => {
|
||||||
if (enableAnnotationCreation && timeRange2 != null) {
|
if (enableAnnotationCreation && timeRange2 != null) {
|
||||||
|
@ -119,8 +119,8 @@ export const TrendPanel = ({
|
|||||||
hoverMode={
|
hoverMode={
|
||||||
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
|
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
|
||||||
}
|
}
|
||||||
getDataLinks={(seriesIdx: number, dataIdx: number) =>
|
getDataLinks={(seriesIdx, dataIdx) =>
|
||||||
alignedDataFrame.fields[seriesIdx]!.getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
alignedDataFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? []
|
||||||
}
|
}
|
||||||
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange, viaSync, dataLinks) => {
|
render={(u, dataIdxs, seriesIdx, isPinned = false, dismiss, timeRange, viaSync, dataLinks) => {
|
||||||
return (
|
return (
|
||||||
|
@ -17,6 +17,8 @@ import {
|
|||||||
import { TooltipHoverMode } from '@grafana/ui/src/components/uPlot/plugins/TooltipPlugin2';
|
import { TooltipHoverMode } from '@grafana/ui/src/components/uPlot/plugins/TooltipPlugin2';
|
||||||
import { getDisplayValuesForCalcs } from '@grafana/ui/src/components/uPlot/utils';
|
import { getDisplayValuesForCalcs } from '@grafana/ui/src/components/uPlot/utils';
|
||||||
|
|
||||||
|
import { getDataLinks } from '../status-history/utils';
|
||||||
|
|
||||||
import { XYChartTooltip } from './XYChartTooltip';
|
import { XYChartTooltip } from './XYChartTooltip';
|
||||||
import { Options } from './panelcfg.gen';
|
import { Options } from './panelcfg.gen';
|
||||||
import { prepConfig } from './scatter';
|
import { prepConfig } from './scatter';
|
||||||
@ -113,7 +115,11 @@ export const XYChartPanel2 = (props: Props2) => {
|
|||||||
<TooltipPlugin2
|
<TooltipPlugin2
|
||||||
config={builder!}
|
config={builder!}
|
||||||
hoverMode={TooltipHoverMode.xyOne}
|
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 (
|
return (
|
||||||
<XYChartTooltip
|
<XYChartTooltip
|
||||||
data={props.data.series}
|
data={props.data.series}
|
||||||
@ -123,6 +129,7 @@ export const XYChartPanel2 = (props: Props2) => {
|
|||||||
isPinned={isPinned}
|
isPinned={isPinned}
|
||||||
seriesIdx={seriesIdx!}
|
seriesIdx={seriesIdx!}
|
||||||
replaceVariables={props.replaceVariables}
|
replaceVariables={props.replaceVariables}
|
||||||
|
dataLinks={dataLinks}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ReactNode } from 'react';
|
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 { alpha } from '@grafana/data/src/themes/colorManipulator';
|
||||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
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 { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||||
import { ColorIndicator, VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
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 { XYSeries } from './types2';
|
||||||
import { fmt } from './utils';
|
import { fmt } from './utils';
|
||||||
@ -21,6 +21,7 @@ export interface Props {
|
|||||||
data: DataFrame[];
|
data: DataFrame[];
|
||||||
xySeries: XYSeries[];
|
xySeries: XYSeries[];
|
||||||
replaceVariables: InterpolateFunction;
|
replaceVariables: InterpolateFunction;
|
||||||
|
dataLinks: LinkModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripSeriesName(fieldName: string, seriesName: string) {
|
function stripSeriesName(fieldName: string, seriesName: string) {
|
||||||
@ -31,7 +32,16 @@ function stripSeriesName(fieldName: string, seriesName: string) {
|
|||||||
return fieldName;
|
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 rowIndex = dataIdxs.find((idx) => idx !== null)!;
|
||||||
|
|
||||||
const series = xySeries[seriesIdx! - 1];
|
const series = xySeries[seriesIdx! - 1];
|
||||||
@ -93,12 +103,15 @@ export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, xySeries, dismiss, i
|
|||||||
|
|
||||||
let footer: ReactNode;
|
let footer: ReactNode;
|
||||||
|
|
||||||
if (isPinned && seriesIdx != null) {
|
if (seriesIdx != null) {
|
||||||
const links = getDataLinks(yField, rowIndex);
|
const hasOneClickLink = dataLinks?.some((dataLink) => dataLink.oneClick === true);
|
||||||
const yFieldFrame = data.find((frame) => frame.fields.includes(yField))!;
|
|
||||||
const actions = getFieldActions(yFieldFrame, yField, replaceVariables, rowIndex);
|
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
|
Reference in New Issue
Block a user