From 6863f49bd0b137696d3405668f0758181a2d6efc Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Fri, 21 Jan 2022 00:27:15 -0800 Subject: [PATCH] [v8.3.x] Cursor sync: Apply the settings without saving the dashboard (#44270) (#44279) * Cursor sync: Apply the settings without saving the dashboard * Remove unnecessary code * Lint god damn (cherry picked from commit 7bf25f62e154886686b436b4201242f4ba7435c3) --- .../grafana-ui/src/components/GraphNG/utils.test.ts | 2 +- .../src/components/PanelChrome/PanelContext.ts | 2 +- .../src/components/TimeSeries/TimeSeries.tsx | 2 +- .../grafana-ui/src/components/TimeSeries/utils.ts | 11 +++++++++-- .../src/components/uPlot/plugins/TooltipPlugin.tsx | 6 +++--- .../app/features/dashboard/dashgrid/PanelChrome.tsx | 11 ++++++----- public/app/plugins/panel/state-timeline/types.ts | 2 +- public/app/plugins/panel/state-timeline/utils.ts | 5 ++++- 8 files changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/grafana-ui/src/components/GraphNG/utils.test.ts b/packages/grafana-ui/src/components/GraphNG/utils.test.ts index 7552cd1974f..0cc6b59533c 100644 --- a/packages/grafana-ui/src/components/GraphNG/utils.test.ts +++ b/packages/grafana-ui/src/components/GraphNG/utils.test.ts @@ -197,7 +197,7 @@ describe('GraphNG utils', () => { timeZone: DefaultTimeZone, getTimeRange: getDefaultTimeRange, eventBus: new EventBusSrv(), - sync: DashboardCursorSync.Tooltip, + sync: () => DashboardCursorSync.Tooltip, allFrames: [frame!], }).getConfig(); expect(result).toMatchSnapshot(); diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts b/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts index b1581a2414f..a83f5fb0cdc 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts +++ b/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts @@ -15,7 +15,7 @@ export interface PanelContext { eventBus: EventBus; /** Dashboard panels sync */ - sync?: DashboardCursorSync; + sync?: () => DashboardCursorSync; /** Information on what the outer container is */ app?: CoreApp | 'string'; diff --git a/packages/grafana-ui/src/components/TimeSeries/TimeSeries.tsx b/packages/grafana-ui/src/components/TimeSeries/TimeSeries.tsx index a62fc1777dd..2b0813d2ee4 100644 --- a/packages/grafana-ui/src/components/TimeSeries/TimeSeries.tsx +++ b/packages/grafana-ui/src/components/TimeSeries/TimeSeries.tsx @@ -18,7 +18,7 @@ export class UnthemedTimeSeries extends React.Component { panelContext: PanelContext = {} as PanelContext; prepConfig = (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => { - const { eventBus, sync } = this.context; + const { eventBus, sync } = this.context as PanelContext; const { theme, timeZone, legend, renderers, tweakAxis, tweakScale } = this.props; return preparePlotConfigBuilder({ diff --git a/packages/grafana-ui/src/components/TimeSeries/utils.ts b/packages/grafana-ui/src/components/TimeSeries/utils.ts index 500c357a5ad..2b0e9bf0da4 100644 --- a/packages/grafana-ui/src/components/TimeSeries/utils.ts +++ b/packages/grafana-ui/src/components/TimeSeries/utils.ts @@ -36,7 +36,10 @@ const defaultConfig: GraphFieldConfig = { axisPlacement: AxisPlacement.Auto, }; -export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursorSync; legend?: VizLegendOptions }> = ({ +export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ + sync?: () => DashboardCursorSync; + legend?: VizLegendOptions; +}> = ({ frame, theme, timeZone, @@ -386,7 +389,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor }, }; - if (sync !== DashboardCursorSync.Off) { + if (sync && sync() !== DashboardCursorSync.Off) { const payload: DataHoverPayload = { point: { [xScaleKey]: null, @@ -399,6 +402,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor key: '__global_', filters: { pub: (type: string, src: uPlot, x: number, y: number, w: number, h: number, dataIdx: number) => { + if (sync && sync() === DashboardCursorSync.Off) { + return false; + } + payload.rowIndex = dataIdx; if (x < 0 && y < 0) { payload.point[xScaleUnit] = null; diff --git a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx index 923708e218d..397abe46ec7 100644 --- a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx +++ b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx @@ -24,7 +24,7 @@ interface TooltipPluginProps { data: DataFrame; config: UPlotConfigBuilder; mode?: TooltipDisplayMode; - sync?: DashboardCursorSync; + sync?: () => DashboardCursorSync; // Allows custom tooltip content rendering. Exposes aligned data frame with relevant indexes for data inspection // Use field.state.origin indexes from alignedData frame field to get access to original data frame and field index. renderTooltip?: (alignedFrame: DataFrame, seriesIdx: number | null, datapointIdx: number | null) => React.ReactNode; @@ -91,7 +91,7 @@ export const TooltipPlugin: React.FC = ({ u.over.addEventListener('mouseleave', plotMouseLeave); u.over.addEventListener('mouseenter', plotMouseEnter); - if (sync === DashboardCursorSync.Crosshair) { + if (sync && sync() === DashboardCursorSync.Crosshair) { u.root.classList.add('shared-crosshair'); } }); @@ -162,7 +162,7 @@ export const TooltipPlugin: React.FC = ({ }; }, [config, setCoords, setIsActive, setFocusedPointIdx, setFocusedPointIdxs]); - if (focusedPointIdx === null || (!isActive && sync === DashboardCursorSync.Crosshair)) { + if (focusedPointIdx === null || (!isActive && sync && sync() === DashboardCursorSync.Crosshair)) { return null; } diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index ccdd4c1a5a2..b4ee69845e6 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -80,8 +80,8 @@ export class PanelChrome extends PureComponent { refreshWhenInView: false, context: { eventBus, - sync: props.isEditing ? DashboardCursorSync.Off : props.dashboard.graphTooltip, app: this.getPanelContextApp(), + sync: this.getSync, onSeriesColorChange: this.onSeriesColorChange, onToggleSeriesVisibility: this.onSeriesVisibilityChange, onAnnotationCreate: this.onAnnotationCreate, @@ -95,6 +95,9 @@ export class PanelChrome extends PureComponent { }; } + // Due to a mutable panel model we get the sync settings via function that proactively reads from the model + getSync = () => (this.props.isEditing ? DashboardCursorSync.Off : this.props.dashboard.graphTooltip); + onInstanceStateChange = (value: any) => { this.props.onInstanceStateChange(value); @@ -218,17 +221,15 @@ export class PanelChrome extends PureComponent { } componentDidUpdate(prevProps: Props) { - const { isInView, isEditing, width } = this.props; + const { isInView, width } = this.props; const { context } = this.state; const app = this.getPanelContextApp(); - const sync = isEditing ? DashboardCursorSync.Off : this.props.dashboard.graphTooltip; - if (context.sync !== sync || context.app !== app) { + if (context.app !== app) { this.setState({ context: { ...context, - sync, app, }, }); diff --git a/public/app/plugins/panel/state-timeline/types.ts b/public/app/plugins/panel/state-timeline/types.ts index c5d672e15dd..1c3a298827e 100644 --- a/public/app/plugins/panel/state-timeline/types.ts +++ b/public/app/plugins/panel/state-timeline/types.ts @@ -17,7 +17,7 @@ export interface TimelineOptions extends OptionsWithLegend, OptionsWithTooltip { // only used in "changes" mode (state-timeline) alignValue?: TimelineValueAlignment; - sync?: DashboardCursorSync; + sync?: () => DashboardCursorSync; } export type TimelineValueAlignment = 'center' | 'left' | 'right'; diff --git a/public/app/plugins/panel/state-timeline/utils.ts b/public/app/plugins/panel/state-timeline/utils.ts index fdd99a988e8..5a316ef9dfb 100644 --- a/public/app/plugins/panel/state-timeline/utils.ts +++ b/public/app/plugins/panel/state-timeline/utils.ts @@ -236,13 +236,16 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({ }); } - if (sync !== DashboardCursorSync.Off) { + if (sync && sync() !== DashboardCursorSync.Off) { let cursor: Partial = {}; cursor.sync = { key: '__global_', filters: { pub: (type: string, src: uPlot, x: number, y: number, w: number, h: number, dataIdx: number) => { + if (sync && sync() === DashboardCursorSync.Off) { + return false; + } payload.rowIndex = dataIdx; if (x < 0 && y < 0) { payload.point[xScaleUnit] = null;