mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Heatmap: consolidate naming conventions (#50272)
This commit is contained in:
parent
d8d3a9c561
commit
1902357693
@ -13,17 +13,19 @@ export enum DataFrameType {
|
|||||||
DirectoryListing = 'directory-listing',
|
DirectoryListing = 'directory-listing',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First field is X, the rest are bucket values
|
* First field is X, the rest are ordinal values used as rows in the heatmap
|
||||||
*/
|
*/
|
||||||
HeatmapBuckets = 'heatmap-buckets',
|
HeatmapRows = 'heatmap-rows',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Explicit fields for:
|
* Explicit fields for:
|
||||||
* xMin, yMin, count, ...
|
* xMin, yMin, count, ...
|
||||||
*
|
*
|
||||||
* All values in the grid exist and have regular spacing
|
* All values in the grid exist and have regular spacing
|
||||||
|
*
|
||||||
|
* If the y value is actually ordinal, use `meta.custom` to specify the bucket lookup values
|
||||||
*/
|
*/
|
||||||
HeatmapScanlines = 'heatmap-scanlines',
|
HeatmapCells = 'heatmap-cells',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WIP sparse heatmap support
|
* WIP sparse heatmap support
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FieldType } from '@grafana/data';
|
import { FieldType } from '@grafana/data';
|
||||||
import { toDataFrame } from '@grafana/data/src/dataframe/processDataFrame';
|
import { toDataFrame } from '@grafana/data/src/dataframe/processDataFrame';
|
||||||
|
|
||||||
import { bucketsToScanlines, calculateHeatmapFromData } from './heatmap';
|
import { rowsToCellsHeatmap, calculateHeatmapFromData } from './heatmap';
|
||||||
import { HeatmapCalculationOptions } from './models.gen';
|
import { HeatmapCalculationOptions } from './models.gen';
|
||||||
|
|
||||||
describe('Heatmap transformer', () => {
|
describe('Heatmap transformer', () => {
|
||||||
@ -58,7 +58,7 @@ describe('Heatmap transformer', () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const heatmap = bucketsToScanlines({ frame, value: 'Speed' });
|
const heatmap = rowsToCellsHeatmap({ frame, value: 'Speed' });
|
||||||
expect(heatmap.fields.map((f) => ({ name: f.name, type: f.type, config: f.config }))).toMatchInlineSnapshot(`
|
expect(heatmap.fields.map((f) => ({ name: f.name, type: f.type, config: f.config }))).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
Object {
|
Object {
|
||||||
@ -92,7 +92,7 @@ describe('Heatmap transformer', () => {
|
|||||||
"C",
|
"C",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"type": "heatmap-scanlines",
|
"type": "heatmap-cells",
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
expect(heatmap.fields[1].values.toArray()).toMatchInlineSnapshot(`
|
expect(heatmap.fields[1].values.toArray()).toMatchInlineSnapshot(`
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { ScaleDistribution } from '@grafana/schema';
|
import { ScaleDistribution } from '@grafana/schema';
|
||||||
|
|
||||||
import { HeatmapBucketLayout, HeatmapCalculationMode, HeatmapCalculationOptions } from './models.gen';
|
import { HeatmapCellLayout, HeatmapCalculationMode, HeatmapCalculationOptions } from './models.gen';
|
||||||
import { niceLinearIncrs, niceTimeIncrs } from './utils';
|
import { niceLinearIncrs, niceTimeIncrs } from './utils';
|
||||||
|
|
||||||
export interface HeatmapTransformerOptions extends HeatmapCalculationOptions {
|
export interface HeatmapTransformerOptions extends HeatmapCalculationOptions {
|
||||||
@ -61,15 +61,15 @@ export function readHeatmapScanlinesCustomMeta(frame?: DataFrame): HeatmapScanli
|
|||||||
return (frame?.meta?.custom ?? {}) as HeatmapScanlinesCustomMeta;
|
return (frame?.meta?.custom ?? {}) as HeatmapScanlinesCustomMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BucketsOptions {
|
export interface RowsHeatmapOptions {
|
||||||
frame: DataFrame;
|
frame: DataFrame;
|
||||||
value?: string; // the field value name
|
value?: string; // the field value name
|
||||||
layout?: HeatmapBucketLayout;
|
layout?: HeatmapCellLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Given existing buckets, create a values style frame */
|
/** Given existing buckets, create a values style frame */
|
||||||
// Assumes frames have already been sorted ASC and de-accumulated.
|
// Assumes frames have already been sorted ASC and de-accumulated.
|
||||||
export function bucketsToScanlines(opts: BucketsOptions): DataFrame {
|
export function rowsToCellsHeatmap(opts: RowsHeatmapOptions): DataFrame {
|
||||||
// TODO: handle null-filling w/ fields[0].config.interval?
|
// TODO: handle null-filling w/ fields[0].config.interval?
|
||||||
const xField = opts.frame.fields[0];
|
const xField = opts.frame.fields[0];
|
||||||
const xValues = xField.values.toArray();
|
const xValues = xField.values.toArray();
|
||||||
@ -106,13 +106,13 @@ export function bucketsToScanlines(opts: BucketsOptions): DataFrame {
|
|||||||
// this name determines whether cells are drawn above, below, or centered on the values
|
// this name determines whether cells are drawn above, below, or centered on the values
|
||||||
let ordinalFieldName = yFields[0].labels?.le != null ? 'yMax' : 'y';
|
let ordinalFieldName = yFields[0].labels?.le != null ? 'yMax' : 'y';
|
||||||
switch (opts.layout) {
|
switch (opts.layout) {
|
||||||
case HeatmapBucketLayout.le:
|
case HeatmapCellLayout.le:
|
||||||
ordinalFieldName = 'yMax';
|
ordinalFieldName = 'yMax';
|
||||||
break;
|
break;
|
||||||
case HeatmapBucketLayout.ge:
|
case HeatmapCellLayout.ge:
|
||||||
ordinalFieldName = 'yMin';
|
ordinalFieldName = 'yMin';
|
||||||
break;
|
break;
|
||||||
case HeatmapBucketLayout.unknown:
|
case HeatmapCellLayout.unknown:
|
||||||
ordinalFieldName = 'y';
|
ordinalFieldName = 'y';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ export function bucketsToScanlines(opts: BucketsOptions): DataFrame {
|
|||||||
length: xs.length,
|
length: xs.length,
|
||||||
refId: opts.frame.refId,
|
refId: opts.frame.refId,
|
||||||
meta: {
|
meta: {
|
||||||
type: DataFrameType.HeatmapScanlines,
|
type: DataFrameType.HeatmapCells,
|
||||||
custom,
|
custom,
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
@ -261,7 +261,7 @@ export function calculateHeatmapFromData(frames: DataFrame[], options: HeatmapCa
|
|||||||
length: heat2d.x.length,
|
length: heat2d.x.length,
|
||||||
name: getFieldDisplayName(yField),
|
name: getFieldDisplayName(yField),
|
||||||
meta: {
|
meta: {
|
||||||
type: DataFrameType.HeatmapScanlines,
|
type: DataFrameType.HeatmapCells,
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ export enum HeatmapCalculationMode {
|
|||||||
Count = 'count',
|
Count = 'count',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum HeatmapBucketLayout {
|
export const enum HeatmapCellLayout {
|
||||||
le = 'le',
|
le = 'le',
|
||||||
ge = 'ge',
|
ge = 'ge',
|
||||||
unknown = 'unknown', // unknown
|
unknown = 'unknown', // unknown
|
||||||
|
@ -558,7 +558,7 @@ function mergeHeatmapFrames(frames: DataFrame[]): DataFrame[] {
|
|||||||
...frames[0],
|
...frames[0],
|
||||||
meta: {
|
meta: {
|
||||||
...frames[0].meta,
|
...frames[0].meta,
|
||||||
type: DataFrameType.HeatmapBuckets,
|
type: DataFrameType.HeatmapRows,
|
||||||
},
|
},
|
||||||
fields: [timeField!, ...countFields],
|
fields: [timeField!, ...countFields],
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,7 @@ import { DataFrameType, Field, FieldType, formattedValueToString, getFieldDispla
|
|||||||
import { LinkButton, VerticalGroup } from '@grafana/ui';
|
import { LinkButton, VerticalGroup } from '@grafana/ui';
|
||||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
import { readHeatmapScanlinesCustomMeta } from 'app/features/transformers/calculateHeatmap/heatmap';
|
import { readHeatmapScanlinesCustomMeta } from 'app/features/transformers/calculateHeatmap/heatmap';
|
||||||
import { HeatmapBucketLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
import { HeatmapCellLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
||||||
|
|
||||||
import { DataHoverView } from '../geomap/components/DataHoverView';
|
import { DataHoverView } from '../geomap/components/DataHoverView';
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ const HeatmapHoverCell = ({ data, hover, showHistogram }: Props) => {
|
|||||||
|
|
||||||
const yValueIdx = index % data.yBucketCount! ?? 0;
|
const yValueIdx = index % data.yBucketCount! ?? 0;
|
||||||
|
|
||||||
const yMinIdx = data.yLayout === HeatmapBucketLayout.le ? yValueIdx - 1 : yValueIdx;
|
const yMinIdx = data.yLayout === HeatmapCellLayout.le ? yValueIdx - 1 : yValueIdx;
|
||||||
const yMaxIdx = data.yLayout === HeatmapBucketLayout.le ? yValueIdx : yValueIdx + 1;
|
const yMaxIdx = data.yLayout === HeatmapCellLayout.le ? yValueIdx : yValueIdx + 1;
|
||||||
|
|
||||||
const yBucketMin = yDispSrc?.[yMinIdx];
|
const yBucketMin = yDispSrc?.[yMinIdx];
|
||||||
const yBucketMax = yDispSrc?.[yMaxIdx];
|
const yBucketMax = yDispSrc?.[yMaxIdx];
|
||||||
@ -164,7 +164,7 @@ const HeatmapHoverCell = ({ data, hover, showHistogram }: Props) => {
|
|||||||
|
|
||||||
const renderYBuckets = () => {
|
const renderYBuckets = () => {
|
||||||
switch (data.yLayout) {
|
switch (data.yLayout) {
|
||||||
case HeatmapBucketLayout.unknown:
|
case HeatmapCellLayout.unknown:
|
||||||
return <div>{yDisp(yBucketMin)}</div>;
|
return <div>{yDisp(yBucketMin)}</div>;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -143,7 +143,7 @@ export const HeatmapPanel: React.FC<HeatmapPanelProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let heatmapType = dataRef.current?.heatmap?.meta?.type;
|
let heatmapType = dataRef.current?.heatmap?.meta?.type;
|
||||||
let countFieldIdx = heatmapType === DataFrameType.HeatmapScanlines ? 2 : 3;
|
let countFieldIdx = heatmapType === DataFrameType.HeatmapCells ? 2 : 3;
|
||||||
const countField = info.heatmap.fields[countFieldIdx];
|
const countField = info.heatmap.fields[countFieldIdx];
|
||||||
|
|
||||||
// TODO -- better would be to get the range from the real color scale!
|
// TODO -- better would be to get the range from the real color scale!
|
||||||
|
@ -8,8 +8,8 @@ import {
|
|||||||
outerJoinDataFrames,
|
outerJoinDataFrames,
|
||||||
PanelData,
|
PanelData,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { calculateHeatmapFromData, bucketsToScanlines } from 'app/features/transformers/calculateHeatmap/heatmap';
|
import { calculateHeatmapFromData, rowsToCellsHeatmap } from 'app/features/transformers/calculateHeatmap/heatmap';
|
||||||
import { HeatmapBucketLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
import { HeatmapCellLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
||||||
|
|
||||||
import { PanelOptions } from './models.gen';
|
import { PanelOptions } from './models.gen';
|
||||||
|
|
||||||
@ -24,8 +24,8 @@ export interface HeatmapData {
|
|||||||
xBucketCount?: number;
|
xBucketCount?: number;
|
||||||
yBucketCount?: number;
|
yBucketCount?: number;
|
||||||
|
|
||||||
xLayout?: HeatmapBucketLayout;
|
xLayout?: HeatmapCellLayout;
|
||||||
yLayout?: HeatmapBucketLayout;
|
yLayout?: HeatmapCellLayout;
|
||||||
|
|
||||||
// Print a heatmap cell value
|
// Print a heatmap cell value
|
||||||
display?: (v: number) => string;
|
display?: (v: number) => string;
|
||||||
@ -48,34 +48,34 @@ export function prepareHeatmapData(data: PanelData, options: PanelOptions, theme
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for known heatmap types
|
// Check for known heatmap types
|
||||||
let bucketHeatmap: DataFrame | undefined = undefined;
|
let rowsHeatmap: DataFrame | undefined = undefined;
|
||||||
for (const frame of frames) {
|
for (const frame of frames) {
|
||||||
switch (frame.meta?.type) {
|
switch (frame.meta?.type) {
|
||||||
case DataFrameType.HeatmapSparse:
|
case DataFrameType.HeatmapSparse:
|
||||||
return getSparseHeatmapData(frame, exemplars, theme);
|
return getSparseHeatmapData(frame, exemplars, theme);
|
||||||
|
|
||||||
case DataFrameType.HeatmapScanlines:
|
case DataFrameType.HeatmapCells:
|
||||||
return getHeatmapData(frame, exemplars, theme);
|
return getHeatmapData(frame, exemplars, theme);
|
||||||
|
|
||||||
case DataFrameType.HeatmapBuckets:
|
case DataFrameType.HeatmapRows:
|
||||||
bucketHeatmap = frame; // the default format
|
rowsHeatmap = frame; // the default format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything past here assumes a field for each row in the heatmap (buckets)
|
// Everything past here assumes a field for each row in the heatmap (buckets)
|
||||||
if (!bucketHeatmap) {
|
if (!rowsHeatmap) {
|
||||||
if (frames.length > 1) {
|
if (frames.length > 1) {
|
||||||
bucketHeatmap = [
|
rowsHeatmap = [
|
||||||
outerJoinDataFrames({
|
outerJoinDataFrames({
|
||||||
frames,
|
frames,
|
||||||
})!,
|
})!,
|
||||||
][0];
|
][0];
|
||||||
} else {
|
} else {
|
||||||
bucketHeatmap = frames[0];
|
rowsHeatmap = frames[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return getHeatmapData(bucketsToScanlines({ ...options.bucketFrame, frame: bucketHeatmap }), exemplars, theme);
|
return getHeatmapData(rowsToCellsHeatmap({ ...options.rowsFrame, frame: rowsHeatmap }), exemplars, theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSparseHeatmapData = (
|
const getSparseHeatmapData = (
|
||||||
@ -99,7 +99,7 @@ const getSparseHeatmapData = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getHeatmapData = (frame: DataFrame, exemplars: DataFrame | undefined, theme: GrafanaTheme2): HeatmapData => {
|
const getHeatmapData = (frame: DataFrame, exemplars: DataFrame | undefined, theme: GrafanaTheme2): HeatmapData => {
|
||||||
if (frame.meta?.type !== DataFrameType.HeatmapScanlines) {
|
if (frame.meta?.type !== DataFrameType.HeatmapCells) {
|
||||||
return {
|
return {
|
||||||
warning: 'Expected heatmap scanlines format',
|
warning: 'Expected heatmap scanlines format',
|
||||||
heatmap: frame,
|
heatmap: frame,
|
||||||
@ -147,17 +147,9 @@ const getHeatmapData = (frame: DataFrame, exemplars: DataFrame | undefined, them
|
|||||||
|
|
||||||
// TODO: improve heuristic
|
// TODO: improve heuristic
|
||||||
xLayout:
|
xLayout:
|
||||||
xName === 'xMax'
|
xName === 'xMax' ? HeatmapCellLayout.le : xName === 'xMin' ? HeatmapCellLayout.ge : HeatmapCellLayout.unknown,
|
||||||
? HeatmapBucketLayout.le
|
|
||||||
: xName === 'xMin'
|
|
||||||
? HeatmapBucketLayout.ge
|
|
||||||
: HeatmapBucketLayout.unknown,
|
|
||||||
yLayout:
|
yLayout:
|
||||||
yName === 'yMax'
|
yName === 'yMax' ? HeatmapCellLayout.le : yName === 'yMin' ? HeatmapCellLayout.ge : HeatmapCellLayout.unknown,
|
||||||
? HeatmapBucketLayout.le
|
|
||||||
: yName === 'yMin'
|
|
||||||
? HeatmapBucketLayout.ge
|
|
||||||
: HeatmapBucketLayout.unknown,
|
|
||||||
|
|
||||||
display: (v) => formattedValueToString(disp(v)),
|
display: (v) => formattedValueToString(disp(v)),
|
||||||
};
|
};
|
||||||
|
@ -28,9 +28,6 @@ describe('Heatmap Migrations', () => {
|
|||||||
"overrides": Array [],
|
"overrides": Array [],
|
||||||
},
|
},
|
||||||
"options": Object {
|
"options": Object {
|
||||||
"bucketFrame": Object {
|
|
||||||
"layout": "auto",
|
|
||||||
},
|
|
||||||
"calculate": true,
|
"calculate": true,
|
||||||
"calculation": Object {
|
"calculation": Object {
|
||||||
"xBuckets": Object {
|
"xBuckets": Object {
|
||||||
@ -67,6 +64,9 @@ describe('Heatmap Migrations', () => {
|
|||||||
"legend": Object {
|
"legend": Object {
|
||||||
"show": true,
|
"show": true,
|
||||||
},
|
},
|
||||||
|
"rowsFrame": Object {
|
||||||
|
"layout": "auto",
|
||||||
|
},
|
||||||
"showValue": "never",
|
"showValue": "never",
|
||||||
"tooltip": Object {
|
"tooltip": Object {
|
||||||
"show": true,
|
"show": true,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FieldConfigSource, PanelModel, PanelTypeChangedHandler } from '@grafana/data';
|
import { FieldConfigSource, PanelModel, PanelTypeChangedHandler } from '@grafana/data';
|
||||||
import { AxisPlacement, ScaleDistribution, VisibilityMode } from '@grafana/schema';
|
import { AxisPlacement, ScaleDistribution, VisibilityMode } from '@grafana/schema';
|
||||||
import {
|
import {
|
||||||
HeatmapBucketLayout,
|
HeatmapCellLayout,
|
||||||
HeatmapCalculationMode,
|
HeatmapCalculationMode,
|
||||||
HeatmapCalculationOptions,
|
HeatmapCalculationOptions,
|
||||||
} from 'app/features/transformers/calculateHeatmap/models.gen';
|
} from 'app/features/transformers/calculateHeatmap/models.gen';
|
||||||
@ -81,8 +81,8 @@ export function angularToReactHeatmap(angular: any): { fieldConfig: FieldConfigS
|
|||||||
min: oldYAxis.min,
|
min: oldYAxis.min,
|
||||||
max: oldYAxis.max,
|
max: oldYAxis.max,
|
||||||
},
|
},
|
||||||
bucketFrame: {
|
rowsFrame: {
|
||||||
layout: getHeatmapBucketLayout(angular.yBucketBound),
|
layout: getHeatmapCellLayout(angular.yBucketBound),
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
show: Boolean(angular.legend.show),
|
show: Boolean(angular.legend.show),
|
||||||
@ -127,16 +127,16 @@ export function angularToReactHeatmap(angular: any): { fieldConfig: FieldConfigS
|
|||||||
return { fieldConfig, options };
|
return { fieldConfig, options };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHeatmapBucketLayout(v?: string): HeatmapBucketLayout {
|
function getHeatmapCellLayout(v?: string): HeatmapCellLayout {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 'upper':
|
case 'upper':
|
||||||
return HeatmapBucketLayout.ge;
|
return HeatmapCellLayout.ge;
|
||||||
case 'lower':
|
case 'lower':
|
||||||
return HeatmapBucketLayout.le;
|
return HeatmapCellLayout.le;
|
||||||
case 'middle':
|
case 'middle':
|
||||||
return HeatmapBucketLayout.unknown;
|
return HeatmapCellLayout.unknown;
|
||||||
}
|
}
|
||||||
return HeatmapBucketLayout.auto;
|
return HeatmapCellLayout.auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
function asNumber(v: any, defaultValue?: number): number | undefined {
|
function asNumber(v: any, defaultValue?: number): number | undefined {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
import { AxisConfig, AxisPlacement, HideableFieldConfig, ScaleDistributionConfig, VisibilityMode } from '@grafana/schema';
|
import { AxisConfig, AxisPlacement, HideableFieldConfig, ScaleDistributionConfig, VisibilityMode } from '@grafana/schema';
|
||||||
import { HeatmapBucketLayout, HeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/models.gen';
|
import { HeatmapCellLayout, HeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/models.gen';
|
||||||
|
|
||||||
export const modelVersion = Object.freeze([1, 0]);
|
export const modelVersion = Object.freeze([1, 0]);
|
||||||
|
|
||||||
@ -56,9 +56,9 @@ export interface ExemplarConfig {
|
|||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BucketFrameOptions {
|
export interface RowsHeatmapOptions {
|
||||||
value?: string; // value field name
|
value?: string; // value field name
|
||||||
layout?: HeatmapBucketLayout;
|
layout?: HeatmapCellLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanelOptions {
|
export interface PanelOptions {
|
||||||
@ -67,7 +67,7 @@ export interface PanelOptions {
|
|||||||
|
|
||||||
color: HeatmapColorOptions;
|
color: HeatmapColorOptions;
|
||||||
filterValues?: FilterValueRange; // was hideZeroBuckets
|
filterValues?: FilterValueRange; // was hideZeroBuckets
|
||||||
bucketFrame?: BucketFrameOptions;
|
rowsFrame?: RowsHeatmapOptions;
|
||||||
showValue: VisibilityMode;
|
showValue: VisibilityMode;
|
||||||
|
|
||||||
cellGap?: number; // was cardPadding
|
cellGap?: number; // was cardPadding
|
||||||
@ -90,8 +90,8 @@ export const defaultPanelOptions: PanelOptions = {
|
|||||||
exponent: 0.5,
|
exponent: 0.5,
|
||||||
steps: 64,
|
steps: 64,
|
||||||
},
|
},
|
||||||
bucketFrame: {
|
rowsFrame: {
|
||||||
layout: HeatmapBucketLayout.auto,
|
layout: HeatmapCellLayout.auto,
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
axisPlacement: AxisPlacement.Left,
|
axisPlacement: AxisPlacement.Left,
|
||||||
|
@ -6,7 +6,7 @@ import { AxisPlacement, GraphFieldConfig, ScaleDistribution, ScaleDistributionCo
|
|||||||
import { addHideFrom, ScaleDistributionEditor } from '@grafana/ui/src/options/builder';
|
import { addHideFrom, ScaleDistributionEditor } from '@grafana/ui/src/options/builder';
|
||||||
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
|
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
|
||||||
import { addHeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/editor/helper';
|
import { addHeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/editor/helper';
|
||||||
import { HeatmapBucketLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
import { HeatmapCellLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
||||||
|
|
||||||
import { HeatmapPanel } from './HeatmapPanel';
|
import { HeatmapPanel } from './HeatmapPanel';
|
||||||
import { heatmapChangedHandler, heatmapMigrationHandler } from './migrations';
|
import { heatmapChangedHandler, heatmapMigrationHandler } from './migrations';
|
||||||
@ -125,16 +125,16 @@ export const plugin = new PanelPlugin<PanelOptions, GraphFieldConfig>(HeatmapPan
|
|||||||
|
|
||||||
if (!opts.calculate) {
|
if (!opts.calculate) {
|
||||||
builder.addRadio({
|
builder.addRadio({
|
||||||
path: 'bucketFrame.layout',
|
path: 'rowsFrame.layout',
|
||||||
name: 'Tick alignment',
|
name: 'Tick alignment',
|
||||||
defaultValue: defaultPanelOptions.bucketFrame?.layout ?? HeatmapBucketLayout.auto,
|
defaultValue: defaultPanelOptions.rowsFrame?.layout ?? HeatmapCellLayout.auto,
|
||||||
category,
|
category,
|
||||||
settings: {
|
settings: {
|
||||||
options: [
|
options: [
|
||||||
{ label: 'Auto', value: HeatmapBucketLayout.auto },
|
{ label: 'Auto', value: HeatmapCellLayout.auto },
|
||||||
{ label: 'Top (LE)', value: HeatmapBucketLayout.le },
|
{ label: 'Top (LE)', value: HeatmapCellLayout.le },
|
||||||
{ label: 'Middle', value: HeatmapBucketLayout.unknown },
|
{ label: 'Middle', value: HeatmapCellLayout.unknown },
|
||||||
{ label: 'Bottom (GE)', value: HeatmapBucketLayout.ge },
|
{ label: 'Bottom (GE)', value: HeatmapCellLayout.ge },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -326,9 +326,9 @@ export const plugin = new PanelPlugin<PanelOptions, GraphFieldConfig>(HeatmapPan
|
|||||||
|
|
||||||
if (!opts.calculate) {
|
if (!opts.calculate) {
|
||||||
builder.addTextInput({
|
builder.addTextInput({
|
||||||
path: 'bucketFrame.value',
|
path: 'rowsFrame.value',
|
||||||
name: 'Cell value name',
|
name: 'Cell value name',
|
||||||
defaultValue: defaultPanelOptions.bucketFrame?.value,
|
defaultValue: defaultPanelOptions.rowsFrame?.value,
|
||||||
settings: {
|
settings: {
|
||||||
placeholder: 'Value',
|
placeholder: 'Value',
|
||||||
},
|
},
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
import { AxisPlacement, ScaleDirection, ScaleDistribution, ScaleOrientation } from '@grafana/schema';
|
import { AxisPlacement, ScaleDirection, ScaleDistribution, ScaleOrientation } from '@grafana/schema';
|
||||||
import { UPlotConfigBuilder } from '@grafana/ui';
|
import { UPlotConfigBuilder } from '@grafana/ui';
|
||||||
import { readHeatmapScanlinesCustomMeta } from 'app/features/transformers/calculateHeatmap/heatmap';
|
import { readHeatmapScanlinesCustomMeta } from 'app/features/transformers/calculateHeatmap/heatmap';
|
||||||
import { HeatmapBucketLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
import { HeatmapCellLayout } from 'app/features/transformers/calculateHeatmap/models.gen';
|
||||||
|
|
||||||
import { pointWithin, Quadtree, Rect } from '../barchart/quadtree';
|
import { pointWithin, Quadtree, Rect } from '../barchart/quadtree';
|
||||||
|
|
||||||
@ -270,11 +270,11 @@ export function prepConfig(opts: PrepConfigOpts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataRef.current?.yLayout === HeatmapBucketLayout.le) {
|
if (dataRef.current?.yLayout === HeatmapCellLayout.le) {
|
||||||
if (!minExpanded) {
|
if (!minExpanded) {
|
||||||
dataMin /= yExp;
|
dataMin /= yExp;
|
||||||
}
|
}
|
||||||
} else if (dataRef.current?.yLayout === HeatmapBucketLayout.ge) {
|
} else if (dataRef.current?.yLayout === HeatmapCellLayout.ge) {
|
||||||
if (!maxExpanded) {
|
if (!maxExpanded) {
|
||||||
dataMax *= yExp;
|
dataMax *= yExp;
|
||||||
}
|
}
|
||||||
@ -292,9 +292,9 @@ export function prepConfig(opts: PrepConfigOpts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bucketSize) {
|
if (bucketSize) {
|
||||||
if (dataRef.current?.yLayout === HeatmapBucketLayout.le) {
|
if (dataRef.current?.yLayout === HeatmapCellLayout.le) {
|
||||||
dataMin -= bucketSize!;
|
dataMin -= bucketSize!;
|
||||||
} else if (dataRef.current?.yLayout === HeatmapBucketLayout.ge) {
|
} else if (dataRef.current?.yLayout === HeatmapCellLayout.ge) {
|
||||||
dataMax += bucketSize!;
|
dataMax += bucketSize!;
|
||||||
} else {
|
} else {
|
||||||
dataMin -= bucketSize! / 2;
|
dataMin -= bucketSize! / 2;
|
||||||
@ -328,10 +328,10 @@ export function prepConfig(opts: PrepConfigOpts) {
|
|||||||
let splits = meta.yOrdinalDisplay.map((v, idx) => idx);
|
let splits = meta.yOrdinalDisplay.map((v, idx) => idx);
|
||||||
|
|
||||||
switch (dataRef.current?.yLayout) {
|
switch (dataRef.current?.yLayout) {
|
||||||
case HeatmapBucketLayout.le:
|
case HeatmapCellLayout.le:
|
||||||
splits.unshift(-1);
|
splits.unshift(-1);
|
||||||
break;
|
break;
|
||||||
case HeatmapBucketLayout.ge:
|
case HeatmapCellLayout.ge:
|
||||||
splits.push(splits.length);
|
splits.push(splits.length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -367,7 +367,7 @@ export function prepConfig(opts: PrepConfigOpts) {
|
|||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const pathBuilder = heatmapType === DataFrameType.HeatmapScanlines ? heatmapPathsDense : heatmapPathsSparse;
|
const pathBuilder = heatmapType === DataFrameType.HeatmapCells ? heatmapPathsDense : heatmapPathsSparse;
|
||||||
|
|
||||||
// heatmap layer
|
// heatmap layer
|
||||||
builder.addSeries({
|
builder.addSeries({
|
||||||
@ -397,21 +397,21 @@ export function prepConfig(opts: PrepConfigOpts) {
|
|||||||
hideLE,
|
hideLE,
|
||||||
hideGE,
|
hideGE,
|
||||||
xAlign:
|
xAlign:
|
||||||
dataRef.current?.xLayout === HeatmapBucketLayout.le
|
dataRef.current?.xLayout === HeatmapCellLayout.le
|
||||||
? -1
|
? -1
|
||||||
: dataRef.current?.xLayout === HeatmapBucketLayout.ge
|
: dataRef.current?.xLayout === HeatmapCellLayout.ge
|
||||||
? 1
|
? 1
|
||||||
: 0,
|
: 0,
|
||||||
yAlign: ((dataRef.current?.yLayout === HeatmapBucketLayout.le
|
yAlign: ((dataRef.current?.yLayout === HeatmapCellLayout.le
|
||||||
? -1
|
? -1
|
||||||
: dataRef.current?.yLayout === HeatmapBucketLayout.ge
|
: dataRef.current?.yLayout === HeatmapCellLayout.ge
|
||||||
? 1
|
? 1
|
||||||
: 0) * (yAxisReverse ? -1 : 1)) as -1 | 0 | 1,
|
: 0) * (yAxisReverse ? -1 : 1)) as -1 | 0 | 1,
|
||||||
ySizeDivisor,
|
ySizeDivisor,
|
||||||
disp: {
|
disp: {
|
||||||
fill: {
|
fill: {
|
||||||
values: (u, seriesIdx) => {
|
values: (u, seriesIdx) => {
|
||||||
let countFacetIdx = heatmapType === DataFrameType.HeatmapScanlines ? 2 : 3;
|
let countFacetIdx = heatmapType === DataFrameType.HeatmapCells ? 2 : 3;
|
||||||
return valuesToFills(u.data[seriesIdx][countFacetIdx] as unknown as number[], palette, valueMin, valueMax);
|
return valuesToFills(u.data[seriesIdx][countFacetIdx] as unknown as number[], palette, valueMin, valueMax);
|
||||||
},
|
},
|
||||||
index: palette,
|
index: palette,
|
||||||
|
Loading…
Reference in New Issue
Block a user