diff --git a/packages/grafana-ui/src/components/VizTooltip/utils.ts b/packages/grafana-ui/src/components/VizTooltip/utils.ts index d14d636caa5..36541a0b82d 100644 --- a/packages/grafana-ui/src/components/VizTooltip/utils.ts +++ b/packages/grafana-ui/src/components/VizTooltip/utils.ts @@ -148,18 +148,26 @@ export const getContentItems = ( _restFields?.forEach((field) => { if (!field.config.custom?.hideFrom?.tooltip) { - const { colorIndicator, colorPlacement } = getIndicatorAndPlacement(field); - const display = field.display!(field.values[dataIdxs[0]!]); + const valueIdx = dataIdxs[seriesIdx ?? 0]; - rows.push({ - label: field.state?.displayName ?? field.name, - value: formattedValueToString(display), - color: FALLBACK_COLOR, - colorIndicator, - colorPlacement, - lineStyle: field.config.custom?.lineStyle, - isHiddenFromViz: true, - }); + if (valueIdx != null) { + const value = field.values[valueIdx]; + + if (value != null) { + const display = field.display!(value); + const { colorIndicator, colorPlacement } = getIndicatorAndPlacement(field); + + rows.push({ + label: field.state?.displayName ?? field.name, + value: formattedValueToString(display), + color: FALLBACK_COLOR, + colorIndicator, + colorPlacement, + lineStyle: field.config.custom?.lineStyle, + isHiddenFromViz: true, + }); + } + } } }); diff --git a/public/app/core/components/GraphNG/GraphNG.tsx b/public/app/core/components/GraphNG/GraphNG.tsx index 3babaa7ac63..49dc1552864 100644 --- a/public/app/core/components/GraphNG/GraphNG.tsx +++ b/public/app/core/components/GraphNG/GraphNG.tsx @@ -48,14 +48,6 @@ export interface GraphNGProps extends Themeable2 { dataLinkPostProcessor?: DataLinkPostProcessor; cursorSync?: DashboardCursorSync; - // Remove fields that are hidden from the visualization before rendering - // The fields will still be available for other things like data links - // this is a temporary hack that only works when: - // 1. renderLegend (above) does not render - // 2. does not have legend series toggle - // 3. passes through all fields required for link/action gen (including those with hideFrom.viz) - omitHideFromViz?: boolean; - /** * needed for propsToDiff to re-init the plot & config * this is a generic approach to plot re-init, without having to specify which panel-level options @@ -179,15 +171,6 @@ export class GraphNG extends Component { }; } - if (props.omitHideFromViz) { - const nonHiddenFields = alignedFrameFinal.fields.filter((field) => field.config.custom?.hideFrom?.viz !== true); - alignedFrameFinal = { - ...alignedFrameFinal, - fields: nonHiddenFields, - length: nonHiddenFields.length, - }; - } - let config = this.state?.config; if (withConfig) { diff --git a/public/app/core/components/TimelineChart/TimelineChart.tsx b/public/app/core/components/TimelineChart/TimelineChart.tsx index ce6e4a1f4c1..e0dcf054802 100644 --- a/public/app/core/components/TimelineChart/TimelineChart.tsx +++ b/public/app/core/components/TimelineChart/TimelineChart.tsx @@ -6,7 +6,7 @@ import { UPlotConfigBuilder, VizLayout, VizLegend, VizLegendItem } from '@grafan import { GraphNG, GraphNGProps } from '../GraphNG/GraphNG'; -import { preparePlotConfigBuilder, TimelineMode } from './utils'; +import { getSeriesAndRest, preparePlotConfigBuilder, TimelineMode } from './utils'; /** * @alpha @@ -46,8 +46,11 @@ export const TimelineChart = (props: TimelineProps) => { const prepConfig = useCallback( (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => { + + const { seriesFrame } = getSeriesAndRest(alignedFrame); + return preparePlotConfigBuilder({ - frame: alignedFrame, + frame: seriesFrame, getTimeRange, allFrames: frames, ...props, @@ -56,7 +59,7 @@ export const TimelineChart = (props: TimelineProps) => { timeZones: Array.isArray(timeZone) ? timeZone : [timeZone], // When there is only one row, use the full space - rowHeight: alignedFrame.fields.length > 2 ? rowHeight : 1, + rowHeight: seriesFrame.fields.length > 2 ? rowHeight : 1, getValueColor: getValueColor, hoverMulti: tooltip?.mode === TooltipDisplayMode.Multi, @@ -94,7 +97,6 @@ export const TimelineChart = (props: TimelineProps) => { prepConfig={prepConfig} propsToDiff={propsToDiff} renderLegend={renderLegend} - omitHideFromViz={true} /> ); }; diff --git a/public/app/core/components/TimelineChart/utils.ts b/public/app/core/components/TimelineChart/utils.ts index 78f7cd4ef69..e3e4dea1dbf 100644 --- a/public/app/core/components/TimelineChart/utils.ts +++ b/public/app/core/components/TimelineChart/utils.ts @@ -731,3 +731,26 @@ export function fmtDuration(milliSeconds: number): string { : '0' ).trim(); } + +export function getSeriesAndRest(alignedFrame: DataFrame) { + const seriesFields: Field[] = []; + const restFields: Field[] = []; + + alignedFrame.fields.forEach((field) => { + if (field.config.custom?.hideFrom?.viz) { + restFields.push(field); + } else { + seriesFields.push(field); + } + }); + + const seriesFrame: DataFrame = { + ...alignedFrame, + fields: seriesFields, + }; + + return { + seriesFrame: seriesFrame, + restFields: restFields, + }; +} diff --git a/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx b/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx index 59883b946c4..1202e2c790d 100644 --- a/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx +++ b/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx @@ -13,6 +13,7 @@ import { import { TimeRange2, TooltipHoverMode } from '@grafana/ui/internal'; import { TimelineChart } from 'app/core/components/TimelineChart/TimelineChart'; import { + getSeriesAndRest, prepareTimelineFields, prepareTimelineLegendItems, TimelineMode, @@ -94,10 +95,13 @@ export const StateTimelinePanel = ({ cursorSync={cursorSync} > {(builder, alignedFrame) => { + // TODO: refactor frame prep not to do this here, should be memod at panel level once GraphNG is dissolved + const { seriesFrame, restFields } = getSeriesAndRest(alignedFrame); + return ( <> {cursorSync !== DashboardCursorSync.Off && ( - + )} {options.tooltip.mode !== TooltipDisplayMode.None && ( - alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? [] + seriesFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? [] } render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => { if (enableAnnotationCreation && timeRange2 != null) { @@ -127,7 +131,7 @@ export const StateTimelinePanel = ({ return ( ); }} maxWidth={options.tooltip.maxWidth} /> )} - {alignedFrame.fields[0].config.custom?.axisPlacement !== AxisPlacement.Hidden && ( + {seriesFrame.fields[0].config.custom?.axisPlacement !== AxisPlacement.Hidden && ( { const pluginContext = usePluginContext(); const xField = series.fields[0]; @@ -45,7 +46,17 @@ export const StateTimelineTooltip = ({ mode = isPinned ? TooltipDisplayMode.Single : mode; - const contentItems = getContentItems(series.fields, xField, dataIdxs, seriesIdx, mode, sortOrder); + const contentItems = getContentItems( + series.fields, + xField, + dataIdxs, + seriesIdx, + mode, + sortOrder, + undefined, + undefined, + _rest + ); let endTime = null; // append duration in single mode diff --git a/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx b/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx index cb0ca2633ea..87ce2597946 100644 --- a/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx +++ b/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx @@ -14,6 +14,7 @@ import { import { TimeRange2, TooltipHoverMode } from '@grafana/ui/internal'; import { TimelineChart } from 'app/core/components/TimelineChart/TimelineChart'; import { + getSeriesAndRest, prepareTimelineFields, prepareTimelineLegendItems, TimelineMode, @@ -110,10 +111,13 @@ export const StatusHistoryPanel = ({ cursorSync={cursorSync} > {(builder, alignedFrame) => { + // TODO: refactor frame prep not to do this here, should be memod at panel level once GraphNG is dissolved + const { seriesFrame, restFields } = getSeriesAndRest(alignedFrame); + return ( <> {cursorSync !== DashboardCursorSync.Off && ( - + )} {options.tooltip.mode !== TooltipDisplayMode.None && ( - alignedFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? [] + seriesFrame.fields[seriesIdx].getLinks?.({ valueRowIndex: dataIdx }) ?? [] } render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2, viaSync, dataLinks) => { if (enableAnnotationCreation && timeRange2 != null) { @@ -143,7 +147,7 @@ export const StatusHistoryPanel = ({ return ( ); }} maxWidth={options.tooltip.maxWidth} /> )} - {alignedFrame.fields[0].config.custom?.axisPlacement !== AxisPlacement.Hidden && ( + {seriesFrame.fields[0].config.custom?.axisPlacement !== AxisPlacement.Hidden && (