diff --git a/packages/grafana-ui/src/components/TimeSeries/utils.ts b/packages/grafana-ui/src/components/TimeSeries/utils.ts index f6568a3ee87..ac66bbc39d6 100644 --- a/packages/grafana-ui/src/components/TimeSeries/utils.ts +++ b/packages/grafana-ui/src/components/TimeSeries/utils.ts @@ -236,6 +236,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor show: !customConfig.hideFrom?.viz, gradientMode: customConfig.gradientMode, thresholds: config.thresholds, + hardMin: field.config.min, + hardMax: field.config.max, + softMin: customConfig.axisSoftMin, + softMax: customConfig.axisSoftMax, // The following properties are not used in the uPlot config, but are utilized as transport for legend config dataFrameFieldIndex: field.state?.origin, }); @@ -249,6 +253,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor thresholds: config.thresholds, scaleKey, theme, + hardMin: field.config.min, + hardMax: field.config.max, + softMin: customConfig.axisSoftMin, + softMax: customConfig.axisSoftMax, }); } } diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts index fea3256a6a2..c7cd5356d8f 100755 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts @@ -26,10 +26,15 @@ export interface SeriesProps extends LineConfig, BarConfig, FillConfig, PointsCo scaleKey: string; pxAlign?: boolean; gradientMode?: GraphGradientMode; + /** Used when gradientMode is set to Scheme */ thresholds?: ThresholdsConfig; - /** Used when gradientMode is set to Scheme */ colorMode?: FieldColorMode; + hardMin?: number | null; + hardMax?: number | null; + softMin?: number | null; + softMax?: number | null; + drawStyle?: GraphDrawStyle; pathBuilder?: Series.PathBuilder; pointsFilter?: Series.Points.Filter; @@ -138,17 +143,29 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder { } private getLineColor(): Series.Stroke { - const { lineColor, gradientMode, colorMode, thresholds, theme } = this.props; + const { lineColor, gradientMode, colorMode, thresholds, theme, hardMin, hardMax, softMin, softMax } = this.props; if (gradientMode === GraphGradientMode.Scheme && colorMode?.id !== FieldColorModeId.Fixed) { - return getScaleGradientFn(1, theme, colorMode, thresholds); + return getScaleGradientFn(1, theme, colorMode, thresholds, hardMin, hardMax, softMin, softMax); } return lineColor ?? FALLBACK_COLOR; } private getFill(): Series.Fill | undefined { - const { lineColor, fillColor, gradientMode, fillOpacity, colorMode, thresholds, theme } = this.props; + const { + lineColor, + fillColor, + gradientMode, + fillOpacity, + colorMode, + thresholds, + theme, + hardMin, + hardMax, + softMin, + softMax, + } = this.props; if (fillColor) { return fillColor; @@ -164,7 +181,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder { return getHueGradientFn((fillColor ?? lineColor)!, opacityPercent, theme); case GraphGradientMode.Scheme: if (colorMode?.id !== FieldColorModeId.Fixed) { - return getScaleGradientFn(opacityPercent, theme, colorMode, thresholds); + return getScaleGradientFn(opacityPercent, theme, colorMode, thresholds, hardMin, hardMax, softMin, softMax); } // intentional fall-through to handle Scheme with Fixed color default: diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts index d3921790555..d431c91976a 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts @@ -1,6 +1,6 @@ import { GrafanaTheme2, ThresholdsConfig, ThresholdsMode } from '@grafana/data'; import { GraphThresholdsStyleConfig, GraphTresholdsStyleMode } from '@grafana/schema'; -import { getDataRange, GradientDirection, scaleGradient } from './gradientFills'; +import { getThresholdRange, GradientDirection, scaleGradient } from './gradientFills'; import tinycolor from 'tinycolor2'; export interface UPlotThresholdOptions { @@ -8,23 +8,27 @@ export interface UPlotThresholdOptions { thresholds: ThresholdsConfig; config: GraphThresholdsStyleConfig; theme: GrafanaTheme2; + hardMin?: number | null; + hardMax?: number | null; + softMin?: number | null; + softMax?: number | null; } export function getThresholdsDrawHook(options: UPlotThresholdOptions) { return (u: uPlot) => { const ctx = u.ctx; - const { scaleKey, thresholds, theme, config } = options; + const { scaleKey, thresholds, theme, config, hardMin, hardMax, softMin, softMax } = options; const { min: xMin, max: xMax } = u.scales.x; const { min: yMin, max: yMax } = u.scales[scaleKey]; - if (xMin === undefined || xMax === undefined || yMin === undefined || yMax === undefined) { + if (xMin == null || xMax == null || yMin == null || yMax == null) { return; } let { steps, mode } = thresholds; if (mode === ThresholdsMode.Percentage) { - let [min, max] = getDataRange(u, scaleKey); + let [min, max] = getThresholdRange(u, scaleKey, hardMin, hardMax, softMin, softMax); let range = max - min; steps = steps.map((step) => ({ diff --git a/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts b/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts index de1c43e8ff7..88bd1d617a0 100644 --- a/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts +++ b/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts @@ -172,11 +172,36 @@ export function getDataRange(plot: uPlot, scaleKey: string) { return [min, max]; } +export function getThresholdRange( + u: uPlot, + scaleKey: string, + hardMin?: number | null, + hardMax?: number | null, + softMin?: number | null, + softMax?: number | null +) { + let min = hardMin ?? softMin ?? null; + let max = hardMax ?? softMax ?? null; + + if (min == null || max == null) { + let [dataMin, dataMax] = getDataRange(u, scaleKey); + + min = min ?? dataMin ?? 0; + max = max ?? dataMax ?? 100; + } + + return [min, max]; +} + export function getScaleGradientFn( opacity: number, theme: GrafanaTheme2, colorMode?: FieldColorMode, - thresholds?: ThresholdsConfig + thresholds?: ThresholdsConfig, + hardMin?: number | null, + hardMax?: number | null, + softMin?: number | null, + softMax?: number | null ): (self: uPlot, seriesIdx: number) => CanvasGradient | string { if (!colorMode) { throw Error('Missing colorMode required for color scheme gradients'); @@ -199,7 +224,7 @@ export function getScaleGradientFn( ); gradient = scaleGradient(plot, scaleKey, GradientDirection.Up, valueStops, true); } else { - const [min, max] = getDataRange(plot, scaleKey); + const [min, max] = getThresholdRange(plot, scaleKey, hardMin, hardMax, softMin, softMax); const range = max - min; const valueStops = thresholds.steps.map( (step) => @@ -212,7 +237,7 @@ export function getScaleGradientFn( } } else if (colorMode.getColors) { const colors = colorMode.getColors(theme); - const [min, max] = getDataRange(plot, scaleKey); + const [min, max] = getThresholdRange(plot, scaleKey, hardMin, hardMax, softMin, softMax); const range = max - min; const valueStops = colors.map( (color, i) => diff --git a/public/app/plugins/panel/barchart/module.tsx b/public/app/plugins/panel/barchart/module.tsx index 583878c5dbf..3baf5f4a813 100755 --- a/public/app/plugins/panel/barchart/module.tsx +++ b/public/app/plugins/panel/barchart/module.tsx @@ -17,7 +17,7 @@ export const plugin = new PanelPlugin(BarC standardOptions: { [FieldConfigProperty.Color]: { settings: { - byValueSupport: false, + byValueSupport: true, }, defaultValue: { mode: FieldColorModeId.PaletteClassic, diff --git a/public/app/plugins/panel/barchart/utils.ts b/public/app/plugins/panel/barchart/utils.ts index 2215e23ba78..de8f19793a6 100644 --- a/public/app/plugins/panel/barchart/utils.ts +++ b/public/app/plugins/panel/barchart/utils.ts @@ -134,6 +134,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({ show: !customConfig.hideFrom?.viz, gradientMode: customConfig.gradientMode, thresholds: field.config.thresholds, + hardMin: field.config.min, + hardMax: field.config.max, + softMin: customConfig.axisSoftMin, + softMax: customConfig.axisSoftMax, // The following properties are not used in the uPlot config, but are utilized as transport for legend config dataFrameFieldIndex: { diff --git a/public/app/plugins/panel/histogram/Histogram.tsx b/public/app/plugins/panel/histogram/Histogram.tsx index d74ce4d7878..a4b21980c2f 100644 --- a/public/app/plugins/panel/histogram/Histogram.tsx +++ b/public/app/plugins/panel/histogram/Histogram.tsx @@ -182,6 +182,11 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => { gradientMode: customConfig.gradientMode, thresholds: field.config.thresholds, + hardMin: field.config.min, + hardMax: field.config.max, + softMin: customConfig.axisSoftMin, + softMax: customConfig.axisSoftMax, + // The following properties are not used in the uPlot config, but are utilized as transport for legend config dataFrameFieldIndex: { fieldIndex: i, diff --git a/public/app/plugins/panel/histogram/module.tsx b/public/app/plugins/panel/histogram/module.tsx index da4f9883b14..80f198aeea9 100644 --- a/public/app/plugins/panel/histogram/module.tsx +++ b/public/app/plugins/panel/histogram/module.tsx @@ -52,7 +52,7 @@ export const plugin = new PanelPlugin(HistogramP standardOptions: { [FieldConfigProperty.Color]: { settings: { - byValueSupport: false, + byValueSupport: true, }, defaultValue: { mode: FieldColorModeId.PaletteClassic,