fix(histogram): remove CUE config, use pure TypeScript interface
This commit is contained in:
@@ -25,7 +25,7 @@ import {
|
||||
preparePlotData2,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import { defaultFieldConfig, FieldConfig, Options } from './panelcfg.gen';
|
||||
import { HistogramOptions, HistogramFieldConfig, defaultHistogramFieldConfig } from './types';
|
||||
|
||||
function incrRoundDn(num: number, incr: number) {
|
||||
return Math.floor(num / incr) * incr;
|
||||
@@ -36,36 +36,36 @@ function incrRoundUp(num: number, incr: number) {
|
||||
}
|
||||
|
||||
export interface HistogramProps extends Themeable2 {
|
||||
options: Options; // used for diff
|
||||
alignedFrame: DataFrame; // This could take HistogramFields
|
||||
options: HistogramOptions;
|
||||
alignedFrame: DataFrame;
|
||||
bucketCount?: number;
|
||||
bucketSize: number;
|
||||
width: number;
|
||||
height: number;
|
||||
structureRev?: number; // a number that will change when the frames[] structure changes
|
||||
structureRev?: number;
|
||||
legend: VizLegendOptions;
|
||||
rawSeries?: DataFrame[];
|
||||
children?: (builder: UPlotConfigBuilder, frame: DataFrame, xMinOnlyFrame: DataFrame) => React.ReactNode;
|
||||
}
|
||||
|
||||
export function getBucketSize(frame: DataFrame) {
|
||||
// assumes BucketMin is fields[0] and BucktMax is fields[1]
|
||||
// NOTE: Assumes BucketMin is fields[0] and BucktMax is fields[1]
|
||||
return frame.fields[0].type === FieldType.string
|
||||
? 1
|
||||
: roundDecimals(frame.fields[1].values[0] - frame.fields[0].values[0], 9);
|
||||
}
|
||||
|
||||
export function getBucketSize1(frame: DataFrame) {
|
||||
// assumes BucketMin is fields[0] and BucktMax is fields[1]
|
||||
// NOTE: Assumes BucketMin is fields[0] and BucktMax is fields[1]
|
||||
return frame.fields[0].type === FieldType.string
|
||||
? 1
|
||||
: roundDecimals(frame.fields[1].values[1] - frame.fields[0].values[1], 9);
|
||||
}
|
||||
|
||||
const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
// todo: scan all values in BucketMin and BucketMax fields to assert if uniform bucketSize
|
||||
// TODO: scan all values in BucketMin and BucketMax fields to assert if uniform bucketSize
|
||||
|
||||
// since this is x axis range, this should ideally come from xMin or xMax fields, not a count field
|
||||
// NOTE: Since this is x axis range, this should ideally come from xMin or xMax fields, not a count field
|
||||
// though both methods are probably hacks, and we should just accept explicit opts into this prepConfig
|
||||
let { min: xScaleMin, max: xScaleMax } = frame.fields[2].config;
|
||||
|
||||
@@ -73,7 +73,7 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
|
||||
let isOrdinalX = frame.fields[0].type === FieldType.string;
|
||||
|
||||
// assumes BucketMin is fields[0] and BucktMax is fields[1]
|
||||
// NOTE: Assumes BucketMin is fields[0] and BucktMax is fields[1]
|
||||
let bucketSize = getBucketSize(frame);
|
||||
let bucketSize1 = getBucketSize1(frame);
|
||||
|
||||
@@ -81,7 +81,7 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
|
||||
let useLogScale = bucketSize1 !== bucketSize; // (imperfect floats)
|
||||
|
||||
// splits shifter, to ensure splits always start at first bucket
|
||||
// Splits shifter to ensure splits always start at first bucket
|
||||
let xSplits: uPlot.Axis.Splits = (u, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace) => {
|
||||
/** @ts-ignore */
|
||||
let minSpace = u.axes[axisIdx]._space;
|
||||
@@ -101,7 +101,7 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
};
|
||||
|
||||
builder.addScale({
|
||||
scaleKey: 'x', // bukkits
|
||||
scaleKey: 'x', // Buckets
|
||||
isTime: false,
|
||||
distribution: isOrdinalX
|
||||
? ScaleDistribution.Ordinal
|
||||
@@ -116,7 +116,7 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
return uPlot.rangeLog(wantedMin, wantedMax * bucketFactor, 2, true);
|
||||
}
|
||||
: (u, wantedMin, wantedMax) => {
|
||||
// these settings will prevent zooming, probably okay?
|
||||
// TODO: These settings will prevent zooming, probably okay?
|
||||
if (xScaleMin != null) {
|
||||
wantedMin = xScaleMin;
|
||||
}
|
||||
@@ -126,8 +126,10 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
|
||||
let fullRangeMax = u.data[0][u.data[0].length - 1];
|
||||
|
||||
// isOrdinalX is when we have classic histograms, which are LE, ordinal X, and already have 0 dummy bucket prepended
|
||||
// else we have calculated histograms which are GE and cardinal+linear X, and have no next dummy bucket appended
|
||||
// NOTE: isOrdinalX is when we have classic histograms, which are LE,
|
||||
// ordinal X, and already have 0 dummy bucket prepended
|
||||
// else we have calculated histograms which are GE and cardinal+linear X,
|
||||
// and have no next dummy bucket appended.
|
||||
wantedMin = incrRoundUp(wantedMin, bucketSize);
|
||||
wantedMax =
|
||||
!isOrdinalX && wantedMax === fullRangeMax ? wantedMax + bucketSize : incrRoundDn(wantedMax, bucketSize);
|
||||
@@ -137,7 +139,7 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
});
|
||||
|
||||
builder.addScale({
|
||||
scaleKey: 'y', // counts
|
||||
scaleKey: 'y', // Counts
|
||||
isTime: false,
|
||||
distribution: ScaleDistribution.Linear,
|
||||
orientation: ScaleOrientation.Vertical,
|
||||
@@ -227,7 +229,7 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
field.state = field.state ?? {};
|
||||
field.state.seriesIndex = seriesIndex++;
|
||||
|
||||
const customConfig: FieldConfig = { ...defaultFieldConfig, ...field.config.custom };
|
||||
const customConfig: HistogramFieldConfig = { ...defaultHistogramFieldConfig, ...field.config.custom };
|
||||
|
||||
const scaleKey = 'y';
|
||||
const colorMode = getFieldColorModeForField(field);
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
histogramFieldsToFrame,
|
||||
joinHistograms,
|
||||
DataFrameType,
|
||||
PanelProps,
|
||||
buildHistogram,
|
||||
cacheFieldDisplayNames,
|
||||
getHistogramFields,
|
||||
@@ -14,11 +13,11 @@ import { TooltipDisplayMode, TooltipPlugin2, useTheme2, TooltipHoverMode } from
|
||||
|
||||
import { Histogram, getBucketSize } from './Histogram';
|
||||
import { HistogramTooltip } from './HistogramTooltip';
|
||||
import { Options } from './panelcfg.gen';
|
||||
import { HistogramPanelProps } from './types';
|
||||
|
||||
type Props = PanelProps<Options>;
|
||||
type Props = HistogramPanelProps;
|
||||
|
||||
export const HistogramPanel = ({ data, options, width, height }: Props) => {
|
||||
export const HistogramPanel = ({ data, options, fieldConfig, width, height }: Props) => {
|
||||
const theme = useTheme2();
|
||||
|
||||
const histogram = useMemo(() => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { StackingMode } from '@grafana/schema';
|
||||
|
||||
import { FieldConfig } from './panelcfg.gen';
|
||||
import { HistogramFieldConfig } from './types';
|
||||
|
||||
export const defaultHistogramConfig: FieldConfig = {
|
||||
export const defaultHistogramConfig: HistogramFieldConfig = {
|
||||
stacking: {
|
||||
mode: StackingMode.None,
|
||||
group: 'A',
|
||||
|
||||
@@ -4,4 +4,10 @@ export { HistogramTooltip, type HistogramTooltipProps } from './HistogramTooltip
|
||||
export { changeToHistogramPanelMigrationHandler } from './migrations';
|
||||
export { defaultHistogramConfig } from './config';
|
||||
export { originalDataHasHistogram } from './utils';
|
||||
export { type Options, type FieldConfig, defaultOptions, defaultFieldConfig } from './panelcfg.gen';
|
||||
export {
|
||||
type HistogramOptions,
|
||||
type HistogramFieldConfig,
|
||||
type HistogramPanelProps,
|
||||
defaultHistogramOptions,
|
||||
defaultHistogramFieldConfig,
|
||||
} from './types';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FieldConfigSource, PanelTypeChangedHandler } from '@grafana/data';
|
||||
import { LegendDisplayMode, SortOrder, StackingMode, TooltipDisplayMode } from '@grafana/schema';
|
||||
|
||||
import { defaultHistogramConfig } from './config';
|
||||
import { FieldConfig as HistogramFieldConfig, Options } from './panelcfg.gen';
|
||||
import { HistogramFieldConfig, HistogramOptions } from './types';
|
||||
|
||||
/*
|
||||
* This is called when the panel changes from another panel
|
||||
@@ -35,10 +35,10 @@ export const changeToHistogramPanelMigrationHandler: PanelTypeChangedHandler = (
|
||||
|
||||
function graphToHistogramOptions(graphOptions: GraphOptions): {
|
||||
fieldConfig: FieldConfigSource;
|
||||
options: Options;
|
||||
options: HistogramOptions;
|
||||
} {
|
||||
let histogramFieldConfig: HistogramFieldConfig = {};
|
||||
const options: Options = {
|
||||
const options: HistogramOptions = {
|
||||
legend: {
|
||||
displayMode: LegendDisplayMode.List,
|
||||
showLegend: true,
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
//
|
||||
// Generated by:
|
||||
// public/app/plugins/gen.go
|
||||
// Using jennies:
|
||||
// TSTypesJenny
|
||||
// PluginTsTypesJenny
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export interface Options extends common.OptionsWithLegend, common.OptionsWithTooltip {
|
||||
/**
|
||||
* Bucket count (approx)
|
||||
*/
|
||||
bucketCount?: number;
|
||||
/**
|
||||
* Offset buckets by this amount
|
||||
*/
|
||||
bucketOffset?: number;
|
||||
/**
|
||||
* Size of each bucket
|
||||
*/
|
||||
bucketSize?: number;
|
||||
/**
|
||||
* Combines multiple series into a single histogram
|
||||
*/
|
||||
combine?: boolean;
|
||||
}
|
||||
|
||||
export const defaultOptions: Partial<Options> = {
|
||||
bucketCount: 30,
|
||||
bucketOffset: 0,
|
||||
};
|
||||
|
||||
export interface FieldConfig extends common.AxisConfig, common.HideableFieldConfig, common.StackableFieldConfig {
|
||||
/**
|
||||
* Controls the fill opacity of the bars.
|
||||
*/
|
||||
fillOpacity?: number;
|
||||
/**
|
||||
* Set the mode of the gradient fill. Fill gradient is based on the line color. To change the color, use the standard color scheme field option.
|
||||
* Gradient appearance is influenced by the Fill opacity setting.
|
||||
*/
|
||||
gradientMode?: common.GraphGradientMode;
|
||||
/**
|
||||
* Controls line width of the bars.
|
||||
*/
|
||||
lineWidth?: number;
|
||||
}
|
||||
|
||||
export const defaultFieldConfig: Partial<FieldConfig> = {
|
||||
fillOpacity: 80,
|
||||
gradientMode: common.GraphGradientMode.None,
|
||||
lineWidth: 1,
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
import { PanelData } from '@grafana/data';
|
||||
import {
|
||||
VizLegendOptions,
|
||||
VizTooltipOptions,
|
||||
GraphGradientMode,
|
||||
StackingConfig,
|
||||
AxisConfig,
|
||||
HideableFieldConfig,
|
||||
} from '@grafana/schema';
|
||||
|
||||
export interface HistogramOptions {
|
||||
/**
|
||||
* Bucket count (approx)
|
||||
*/
|
||||
bucketCount?: number;
|
||||
/**
|
||||
* Size of each bucket
|
||||
*/
|
||||
bucketSize?: number;
|
||||
/**
|
||||
* Offset buckets by this amount
|
||||
*/
|
||||
bucketOffset?: number;
|
||||
/**
|
||||
* Combines multiple series into a single histogram
|
||||
*/
|
||||
combine?: boolean;
|
||||
/**
|
||||
* Legend configuration
|
||||
*/
|
||||
legend: VizLegendOptions;
|
||||
/**
|
||||
* Tooltip configuration
|
||||
*/
|
||||
tooltip: VizTooltipOptions;
|
||||
}
|
||||
|
||||
export interface HistogramFieldConfig extends AxisConfig, HideableFieldConfig {
|
||||
/**
|
||||
* Controls line width of the bars.
|
||||
*/
|
||||
lineWidth?: number;
|
||||
/**
|
||||
* Controls the fill opacity of the bars.
|
||||
*/
|
||||
fillOpacity?: number;
|
||||
/**
|
||||
* Set the mode of the gradient fill.
|
||||
*/
|
||||
gradientMode?: GraphGradientMode;
|
||||
/**
|
||||
* Stacking configuration
|
||||
*/
|
||||
stacking?: StackingConfig;
|
||||
}
|
||||
|
||||
export interface HistogramPanelProps {
|
||||
data: PanelData;
|
||||
options: HistogramOptions;
|
||||
fieldConfig: HistogramFieldConfig;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
// Default values
|
||||
export const defaultHistogramOptions: Partial<HistogramOptions> = {
|
||||
bucketCount: 30,
|
||||
bucketOffset: 0,
|
||||
combine: false,
|
||||
};
|
||||
|
||||
export const defaultHistogramFieldConfig: Partial<HistogramFieldConfig> = {
|
||||
fillOpacity: 80,
|
||||
gradientMode: GraphGradientMode.None,
|
||||
lineWidth: 1,
|
||||
};
|
||||
@@ -1,10 +1,47 @@
|
||||
import { PanelProps } from '@grafana/data';
|
||||
import { HistogramPanel as HistogramPanelComponent } from '@grafana/histogram';
|
||||
import { HistogramPanel as HistogramPanelComponent, HistogramOptions, HistogramFieldConfig } from '@grafana/histogram';
|
||||
|
||||
import { Options } from './panelcfg.gen';
|
||||
import { Options, FieldConfig } from './panelcfg.gen';
|
||||
|
||||
type Props = PanelProps<Options>;
|
||||
|
||||
// Adapter function: Transform Grafana's CUE-generated config to clean histogram config
|
||||
function adaptGrafanaToHistogram(
|
||||
grafanaOptions: Options,
|
||||
grafanaFieldConfig: FieldConfig
|
||||
): { options: HistogramOptions; fieldConfig: HistogramFieldConfig } {
|
||||
return {
|
||||
options: {
|
||||
bucketCount: grafanaOptions.bucketCount,
|
||||
bucketSize: grafanaOptions.bucketSize,
|
||||
bucketOffset: grafanaOptions.bucketOffset,
|
||||
combine: grafanaOptions.combine ?? false,
|
||||
legend: grafanaOptions.legend,
|
||||
tooltip: grafanaOptions.tooltip,
|
||||
},
|
||||
fieldConfig: {
|
||||
lineWidth: grafanaFieldConfig.lineWidth,
|
||||
fillOpacity: grafanaFieldConfig.fillOpacity,
|
||||
gradientMode: grafanaFieldConfig.gradientMode,
|
||||
stacking: grafanaFieldConfig.stacking,
|
||||
// Include extended properties from AxisConfig and HideableFieldConfig
|
||||
hideFrom: grafanaFieldConfig.hideFrom,
|
||||
axisSoftMin: grafanaFieldConfig.axisSoftMin,
|
||||
axisSoftMax: grafanaFieldConfig.axisSoftMax,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const HistogramPanel = (props: Props) => {
|
||||
return <HistogramPanelComponent {...props} />;
|
||||
const { options, fieldConfig } = adaptGrafanaToHistogram(props.options, props.fieldConfig?.defaults?.custom || {});
|
||||
|
||||
return (
|
||||
<HistogramPanelComponent
|
||||
data={props.data}
|
||||
options={options}
|
||||
fieldConfig={fieldConfig}
|
||||
width={props.width}
|
||||
height={props.height}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user