mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* kindsys: Adapt to new PanelCfg schema interface * building locally * Remove Panel prefix in cue files * Regenerate * Update imports * fixup! Merge branch 'remove-panel-prefix' into sdboyer/redundant-panelcfg-prefixes * Fix formatting --------- Co-authored-by: Ryan McKinley <ryantxu@gmail.com> Co-authored-by: Tania B <yalyna.ts@gmail.com>
178 lines
5.3 KiB
TypeScript
178 lines
5.3 KiB
TypeScript
import { FieldConfigSource, PanelModel, PanelTypeChangedHandler } from '@grafana/data';
|
|
import {
|
|
AxisPlacement,
|
|
ScaleDistribution,
|
|
VisibilityMode,
|
|
HeatmapCellLayout,
|
|
HeatmapCalculationMode,
|
|
HeatmapCalculationOptions,
|
|
} from '@grafana/schema';
|
|
|
|
import { colorSchemes } from './palettes';
|
|
import { Options, defaultOptions, HeatmapColorMode } from './types';
|
|
|
|
/** Called when the version number changes */
|
|
export const heatmapMigrationHandler = (panel: PanelModel): Partial<Options> => {
|
|
// Migrating from angular
|
|
if (Object.keys(panel.options).length === 0) {
|
|
return heatmapChangedHandler(panel, 'heatmap', { angular: panel }, panel.fieldConfig);
|
|
}
|
|
return panel.options;
|
|
};
|
|
|
|
/**
|
|
* This is called when the panel changes from another panel
|
|
*/
|
|
export const heatmapChangedHandler: PanelTypeChangedHandler = (panel, prevPluginId, prevOptions, prevFieldConfig) => {
|
|
if (prevPluginId === 'heatmap' && prevOptions.angular) {
|
|
const { fieldConfig, options } = angularToReactHeatmap({
|
|
...prevOptions.angular,
|
|
fieldConfig: prevFieldConfig,
|
|
});
|
|
panel.fieldConfig = fieldConfig; // Mutates the incoming panel
|
|
return options;
|
|
}
|
|
// alpha for 8.5+, then beta at 9.0.1
|
|
if (prevPluginId === 'heatmap-new') {
|
|
const { bucketFrame, ...options } = panel.options;
|
|
if (bucketFrame) {
|
|
return { ...options, rowsFrame: bucketFrame };
|
|
}
|
|
return panel.options;
|
|
}
|
|
return {};
|
|
};
|
|
|
|
export function angularToReactHeatmap(angular: any): { fieldConfig: FieldConfigSource; options: Options } {
|
|
const fieldConfig: FieldConfigSource = {
|
|
defaults: {},
|
|
overrides: [],
|
|
};
|
|
|
|
const calculate = angular.dataFormat === 'tsbuckets' ? false : true;
|
|
const calculation: HeatmapCalculationOptions = {
|
|
...defaultOptions.calculation,
|
|
};
|
|
|
|
const oldYAxis = { logBase: 1, ...angular.yAxis };
|
|
|
|
if (calculate) {
|
|
if (angular.xBucketSize) {
|
|
calculation.xBuckets = { mode: HeatmapCalculationMode.Size, value: `${angular.xBucketSize}` };
|
|
} else if (angular.xBucketNumber) {
|
|
calculation.xBuckets = { mode: HeatmapCalculationMode.Count, value: `${angular.xBucketNumber}` };
|
|
}
|
|
|
|
if (angular.yBucketSize) {
|
|
calculation.yBuckets = { mode: HeatmapCalculationMode.Size, value: `${angular.yBucketSize}` };
|
|
} else if (angular.xBucketNumber) {
|
|
calculation.yBuckets = { mode: HeatmapCalculationMode.Count, value: `${angular.yBucketNumber}` };
|
|
}
|
|
|
|
if (oldYAxis.logBase > 1) {
|
|
calculation.yBuckets = {
|
|
mode: HeatmapCalculationMode.Count,
|
|
value: +oldYAxis.splitFactor > 0 ? `${oldYAxis.splitFactor}` : undefined,
|
|
scale: {
|
|
type: ScaleDistribution.Log,
|
|
log: oldYAxis.logBase,
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
const cellGap = asNumber(angular.cards?.cardPadding, 2);
|
|
const options: Options = {
|
|
calculate,
|
|
calculation,
|
|
color: {
|
|
...defaultOptions.color,
|
|
steps: 128, // best match with existing colors
|
|
},
|
|
cellGap: cellGap ? cellGap : 1, // default to size 1
|
|
cellRadius: asNumber(angular.cards?.cardRound), // just to keep it
|
|
yAxis: {
|
|
axisPlacement: oldYAxis.show === false ? AxisPlacement.Hidden : AxisPlacement.Left,
|
|
reverse: Boolean(angular.reverseYBuckets),
|
|
axisWidth: asNumber(oldYAxis.width),
|
|
min: oldYAxis.min,
|
|
max: oldYAxis.max,
|
|
unit: oldYAxis.format,
|
|
decimals: oldYAxis.decimals,
|
|
},
|
|
cellValues: {
|
|
decimals: asNumber(angular.tooltipDecimals),
|
|
},
|
|
rowsFrame: {
|
|
layout: getHeatmapCellLayout(angular.yBucketBound),
|
|
},
|
|
legend: {
|
|
show: Boolean(angular.legend?.show),
|
|
},
|
|
showValue: VisibilityMode.Never,
|
|
tooltip: {
|
|
show: Boolean(angular.tooltip?.show),
|
|
yHistogram: Boolean(angular.tooltip?.showHistogram),
|
|
},
|
|
exemplars: {
|
|
...defaultOptions.exemplars,
|
|
},
|
|
};
|
|
|
|
if (angular.hideZeroBuckets) {
|
|
options.filterValues = { ...defaultOptions.filterValues }; // min: 1e-9
|
|
}
|
|
|
|
// Migrate color options
|
|
const color = angular.color ?? {};
|
|
switch (color?.mode) {
|
|
case 'spectrum': {
|
|
options.color.mode = HeatmapColorMode.Scheme;
|
|
|
|
const current = color.colorScheme as string;
|
|
let scheme = colorSchemes.find((v) => v.name === current);
|
|
if (!scheme) {
|
|
scheme = colorSchemes.find((v) => current.indexOf(v.name) >= 0);
|
|
}
|
|
options.color.scheme = scheme ? scheme.name : defaultOptions.color.scheme;
|
|
break;
|
|
}
|
|
case 'opacity': {
|
|
options.color.mode = HeatmapColorMode.Opacity;
|
|
options.color.scale = color.scale;
|
|
break;
|
|
}
|
|
}
|
|
options.color.fill = color.cardColor;
|
|
options.color.min = color.min;
|
|
options.color.max = color.max;
|
|
|
|
if (typeof color.min === 'number' && typeof color.max === 'number' && color.min > color.max) {
|
|
options.color.min = color.max;
|
|
options.color.max = color.min;
|
|
options.color.reverse = true;
|
|
}
|
|
|
|
return { fieldConfig, options };
|
|
}
|
|
|
|
function getHeatmapCellLayout(v?: string): HeatmapCellLayout {
|
|
switch (v) {
|
|
case 'upper':
|
|
return HeatmapCellLayout.ge;
|
|
case 'lower':
|
|
return HeatmapCellLayout.le;
|
|
case 'middle':
|
|
return HeatmapCellLayout.unknown;
|
|
}
|
|
return HeatmapCellLayout.auto;
|
|
}
|
|
|
|
function asNumber(v: any, defaultValue?: number): number | undefined {
|
|
if (v == null || v === '') {
|
|
return defaultValue;
|
|
}
|
|
const num = +v;
|
|
return isNaN(num) ? defaultValue : num;
|
|
}
|