HeatmapNG: support y min/max config (#50900)

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Leon Sorokin 2022-06-15 17:24:51 -05:00 committed by GitHub
parent c1550d1f07
commit 7c175e019c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 6 deletions

View File

@ -1,14 +1,16 @@
import React from 'react';
import { FieldConfigProperty, FieldType, identityOverrideProcessor, PanelPlugin } from '@grafana/data';
import { FieldConfigProperty, FieldType, identityOverrideProcessor, PanelData, PanelPlugin } from '@grafana/data';
import { config } from '@grafana/runtime';
import { AxisPlacement, GraphFieldConfig, ScaleDistribution, ScaleDistributionConfig } from '@grafana/schema';
import { addHideFrom, ScaleDistributionEditor } from '@grafana/ui/src/options/builder';
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
import { addHeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/editor/helper';
import { readHeatmapScanlinesCustomMeta } from 'app/features/transformers/calculateHeatmap/heatmap';
import { HeatmapCellLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
import { HeatmapPanel } from './HeatmapPanel';
import { prepareHeatmapData } from './fields';
import { heatmapChangedHandler, heatmapMigrationHandler } from './migrations';
import { PanelOptions, defaultPanelOptions, HeatmapColorMode, HeatmapColorScale } from './models.gen';
import { colorSchemes, quantizeScheme } from './palettes';
@ -46,6 +48,13 @@ export const plugin = new PanelPlugin<PanelOptions, GraphFieldConfig>(HeatmapPan
.setPanelOptions((builder, context) => {
const opts = context.options ?? defaultPanelOptions;
let isOrdinalY = false;
try {
const v = prepareHeatmapData({ series: context.data } as PanelData, opts, config.theme2);
isOrdinalY = readHeatmapScanlinesCustomMeta(v.heatmap).yOrdinalDisplay != null;
} catch {}
let category = ['Heatmap'];
builder.addRadio({
@ -81,8 +90,8 @@ export const plugin = new PanelPlugin<PanelOptions, GraphFieldConfig>(HeatmapPan
},
});
// TODO: support clamping the min/max range when there is a real axis
if (false && opts.calculate) {
if (!isOrdinalY) {
// if undefined, then show the min+max
builder
.addNumberInput({
path: 'yAxis.min',

View File

@ -260,6 +260,7 @@ export function prepConfig(opts: PrepConfigOpts) {
const yScale = yFieldConfig?.scaleDistribution ?? { type: ScaleDistribution.Linear };
const yAxisReverse = Boolean(yAxisConfig.reverse);
const shouldUseLogScale = yScale.type !== ScaleDistribution.Linear || heatmapType === DataFrameType.HeatmapSparse;
const isOrdianalY = readHeatmapScanlinesCustomMeta(dataRef.current?.heatmap).yOrdinalDisplay != null;
// random to prevent syncing y in other heatmaps
// TODO: try to match TimeSeries y keygen algo to sync with TimeSeries panels (when not isOrdianalY)
@ -275,11 +276,34 @@ export function prepConfig(opts: PrepConfigOpts) {
distribution: shouldUseLogScale ? ScaleDistribution.Log : ScaleDistribution.Linear,
log: yScale.log ?? 2,
range:
// sparse already accounts for le/ge by explicit yMin & yMax cell bounds, so use default log ranging
// sparse already accounts for le/ge by explicit yMin & yMax cell bounds, so no need to expand y range
heatmapType === DataFrameType.HeatmapSparse
? undefined
? (u, dataMin, dataMax) => {
let scaleMin: number | null, scaleMax: number | null;
[scaleMin, scaleMax] = shouldUseLogScale
? uPlot.rangeLog(dataMin, dataMax, (yScale.log ?? 2) as unknown as uPlot.Scale.LogBase, true)
: [dataMin, dataMax];
if (shouldUseLogScale && !isOrdianalY) {
let { min: explicitMin, max: explicitMax } = yAxisConfig;
// guard against <= 0
if (explicitMin != null && explicitMin > 0) {
scaleMin = explicitMin;
}
if (explicitMax != null && explicitMax > 0) {
scaleMax = explicitMax;
}
}
return [scaleMin, scaleMax];
}
: // dense and ordinal only have one of yMin|yMax|y, so expand range by one cell in the direction of le/ge/unknown
(u, dataMin, dataMax) => {
let { min: explicitMin, max: explicitMax } = yAxisConfig;
// logarithmic expansion
if (shouldUseLogScale) {
let yExp = u.scales[yScaleKey].log!;
@ -316,6 +340,17 @@ export function prepConfig(opts: PrepConfigOpts) {
dataMin /= yExp / 2;
dataMax *= yExp / 2;
}
if (!isOrdianalY) {
// guard against <= 0
if (explicitMin != null && explicitMin > 0) {
dataMin = explicitMin;
}
if (explicitMax != null && explicitMax > 0) {
dataMax = explicitMax;
}
}
}
// linear expansion
else {
@ -337,12 +372,17 @@ export function prepConfig(opts: PrepConfigOpts) {
} else {
// how to expand scale range if inferred non-regular or log buckets?
}
if (!isOrdianalY) {
dataMin = explicitMin ?? dataMin;
dataMax = explicitMax ?? dataMax;
}
}
return [dataMin, dataMax];
},
});
const isOrdianalY = readHeatmapScanlinesCustomMeta(dataRef.current?.heatmap).yOrdinalDisplay != null;
const disp = dataRef.current?.heatmap?.fields[1].display ?? getValueFormat('short');
builder.addAxis({