mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Histogram: move histogram from alpha to beta panel (#34246)
* add legend * tooltip off-by-one * units in x axis * update function call * remove tooltip
This commit is contained in:
@@ -203,16 +203,17 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bucketMin = {
|
const bucketMin = {
|
||||||
|
...counts[0],
|
||||||
name: histogramFrameBucketMinFieldName,
|
name: histogramFrameBucketMinFieldName,
|
||||||
values: new ArrayVector(joinedHists[0]),
|
values: new ArrayVector(joinedHists[0]),
|
||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
config: {},
|
state: undefined,
|
||||||
};
|
};
|
||||||
const bucketMax = {
|
const bucketMax = {
|
||||||
|
...bucketMin,
|
||||||
name: histogramFrameBucketMaxFieldName,
|
name: histogramFrameBucketMaxFieldName,
|
||||||
values: new ArrayVector(joinedHists[0].map((v) => v + bucketSize!)),
|
values: new ArrayVector(joinedHists[0].map((v) => v + bucketSize!)),
|
||||||
type: FieldType.number,
|
state: undefined,
|
||||||
config: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options?.combine) {
|
if (options?.combine) {
|
||||||
@@ -227,6 +228,8 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
|
|||||||
...counts[0],
|
...counts[0],
|
||||||
name: 'Count',
|
name: 'Count',
|
||||||
values: new ArrayVector(vals),
|
values: new ArrayVector(vals),
|
||||||
|
type: FieldType.number,
|
||||||
|
state: undefined,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
|
|||||||
} else if (isTime) {
|
} else if (isTime) {
|
||||||
config.values = formatTime;
|
config.values = formatTime;
|
||||||
} else if (formatValue) {
|
} else if (formatValue) {
|
||||||
config.values = (u: uPlot, vals: any[]) => vals.map((v) => formatValue!(v));
|
config.values = (u: uPlot, vals: any[]) => vals.map(formatValue!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store timezone
|
// store timezone
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import uPlot, { AlignedData } from 'uplot';
|
import uPlot, { AlignedData } from 'uplot';
|
||||||
import {
|
import {
|
||||||
DataFrame,
|
DataFrame,
|
||||||
|
formattedValueToString,
|
||||||
getFieldColorModeForField,
|
getFieldColorModeForField,
|
||||||
getFieldDisplayName,
|
getFieldDisplayName,
|
||||||
getFieldSeriesColor,
|
getFieldSeriesColor,
|
||||||
@@ -16,6 +17,8 @@ import {
|
|||||||
AxisPlacement,
|
AxisPlacement,
|
||||||
ScaleDirection,
|
ScaleDirection,
|
||||||
ScaleOrientation,
|
ScaleOrientation,
|
||||||
|
LegendDisplayMode,
|
||||||
|
PlotLegend,
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -32,12 +35,7 @@ export interface HistogramProps extends Themeable2 {
|
|||||||
height: number;
|
height: number;
|
||||||
structureRev?: number; // a number that will change when the frames[] structure changes
|
structureRev?: number; // a number that will change when the frames[] structure changes
|
||||||
legend: VizLegendOptions;
|
legend: VizLegendOptions;
|
||||||
//onLegendClick?: (event: GraphNGLegendEvent) => void;
|
|
||||||
children?: (builder: UPlotConfigBuilder, frame: DataFrame) => React.ReactNode;
|
children?: (builder: UPlotConfigBuilder, frame: DataFrame) => React.ReactNode;
|
||||||
|
|
||||||
//prepConfig: (frame: DataFrame) => UPlotConfigBuilder;
|
|
||||||
//propsToDiff?: string[];
|
|
||||||
//renderLegend: (config: UPlotConfigBuilder) => React.ReactElement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||||
@@ -84,12 +82,18 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
|||||||
direction: ScaleDirection.Up,
|
direction: ScaleDirection.Up,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fmt = frame.fields[0].display!;
|
||||||
|
const xAxisFormatter = (v: number) => {
|
||||||
|
return formattedValueToString(fmt(v));
|
||||||
|
};
|
||||||
|
|
||||||
builder.addAxis({
|
builder.addAxis({
|
||||||
scaleKey: 'x',
|
scaleKey: 'x',
|
||||||
isTime: false,
|
isTime: false,
|
||||||
placement: AxisPlacement.Bottom,
|
placement: AxisPlacement.Bottom,
|
||||||
incrs: histogramBucketSizes,
|
incrs: histogramBucketSizes,
|
||||||
splits: xSplits,
|
splits: xSplits,
|
||||||
|
values: (u: uPlot, vals: any[]) => vals.map(xAxisFormatter),
|
||||||
//incrs: () => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((mult) => mult * bucketSize),
|
//incrs: () => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((mult) => mult * bucketSize),
|
||||||
//splits: config.xSplits,
|
//splits: config.xSplits,
|
||||||
//values: config.xValues,
|
//values: config.xValues,
|
||||||
@@ -138,15 +142,15 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
|||||||
colorMode,
|
colorMode,
|
||||||
pathBuilder,
|
pathBuilder,
|
||||||
//pointsBuilder: config.drawPoints,
|
//pointsBuilder: config.drawPoints,
|
||||||
show: !customConfig.hideFrom?.graph,
|
show: !customConfig.hideFrom?.vis,
|
||||||
gradientMode: customConfig.gradientMode,
|
gradientMode: customConfig.gradientMode,
|
||||||
thresholds: field.config.thresholds,
|
thresholds: field.config.thresholds,
|
||||||
|
|
||||||
// The following properties are not used in the uPlot config, but are utilized as transport for legend config
|
// The following properties are not used in the uPlot config, but are utilized as transport for legend config
|
||||||
// dataFrameFieldIndex: {
|
dataFrameFieldIndex: {
|
||||||
// fieldIndex: i,
|
fieldIndex: i,
|
||||||
// frameIndex: 0,
|
frameIndex: 0,
|
||||||
// },
|
},
|
||||||
fieldName: getFieldDisplayName(field, frame),
|
fieldName: getFieldDisplayName(field, frame),
|
||||||
hideInLegend: customConfig.hideFrom?.legend,
|
hideInLegend: customConfig.hideFrom?.legend,
|
||||||
});
|
});
|
||||||
@@ -178,10 +182,6 @@ const preparePlotData = (frame: DataFrame) => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderLegend = (config: UPlotConfigBuilder) => {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
alignedData: AlignedData;
|
alignedData: AlignedData;
|
||||||
config?: UPlotConfigBuilder;
|
config?: UPlotConfigBuilder;
|
||||||
@@ -210,6 +210,15 @@ export class Histogram extends React.Component<HistogramProps, State> {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderLegend(config: UPlotConfigBuilder) {
|
||||||
|
const { legend } = this.props;
|
||||||
|
if (!config || legend.displayMode === LegendDisplayMode.Hidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <PlotLegend data={[this.props.alignedFrame]} config={config} maxHeight="35%" maxWidth="60%" {...legend} />;
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: HistogramProps) {
|
componentDidUpdate(prevProps: HistogramProps) {
|
||||||
const { structureRev, alignedFrame } = this.props;
|
const { structureRev, alignedFrame } = this.props;
|
||||||
|
|
||||||
@@ -241,7 +250,7 @@ export class Histogram extends React.Component<HistogramProps, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VizLayout width={width} height={height} legend={renderLegend(config) as any}>
|
<VizLayout width={width} height={height} legend={this.renderLegend(config)}>
|
||||||
{(vizWidth: number, vizHeight: number) => (
|
{(vizWidth: number, vizHeight: number) => (
|
||||||
<UPlotChart
|
<UPlotChart
|
||||||
config={this.state.config!}
|
config={this.state.config!}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export const HistogramPanel: React.FC<Props> = ({ data, options, width, height }
|
|||||||
if (!hist) {
|
if (!hist) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return histogramFieldsToFrame(hist);
|
return histogramFieldsToFrame(hist);
|
||||||
}, [data.series, options]);
|
}, [data.series, options]);
|
||||||
|
|
||||||
@@ -41,11 +42,15 @@ export const HistogramPanel: React.FC<Props> = ({ data, options, width, height }
|
|||||||
<Histogram
|
<Histogram
|
||||||
options={options}
|
options={options}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
legend={null as any} // TODO!
|
legend={options.legend}
|
||||||
structureRev={data.structureRev}
|
structureRev={data.structureRev}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
alignedFrame={histogram}
|
alignedFrame={histogram}
|
||||||
/>
|
>
|
||||||
|
{(config, alignedFrame) => {
|
||||||
|
return null; // <TooltipPlugin data={alignedFrame} config={config} mode={options.tooltip.mode} timeZone={timeZone} />;
|
||||||
|
}}
|
||||||
|
</Histogram>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,11 +3,18 @@
|
|||||||
// It is currenty hand written but will serve as the target for cuetsy
|
// It is currenty hand written but will serve as the target for cuetsy
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
import { GraphGradientMode } from '@grafana/ui';
|
import {
|
||||||
|
GraphGradientMode,
|
||||||
|
HideableFieldConfig,
|
||||||
|
LegendDisplayMode,
|
||||||
|
OptionsWithLegend,
|
||||||
|
OptionsWithTooltip,
|
||||||
|
TooltipDisplayMode,
|
||||||
|
} from '@grafana/ui';
|
||||||
|
|
||||||
export const modelVersion = Object.freeze([1, 0]);
|
export const modelVersion = Object.freeze([1, 0]);
|
||||||
|
|
||||||
export interface PanelOptions {
|
export interface PanelOptions extends OptionsWithLegend, OptionsWithTooltip {
|
||||||
bucketSize?: number;
|
bucketSize?: number;
|
||||||
bucketOffset?: number;
|
bucketOffset?: number;
|
||||||
combine?: boolean;
|
combine?: boolean;
|
||||||
@@ -15,12 +22,20 @@ export interface PanelOptions {
|
|||||||
|
|
||||||
export const defaultPanelOptions: PanelOptions = {
|
export const defaultPanelOptions: PanelOptions = {
|
||||||
bucketOffset: 0,
|
bucketOffset: 0,
|
||||||
|
legend: {
|
||||||
|
displayMode: LegendDisplayMode.List,
|
||||||
|
placement: 'bottom',
|
||||||
|
calcs: [],
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
mode: TooltipDisplayMode.Multi,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
export interface PanelFieldConfig {
|
export interface PanelFieldConfig extends HideableFieldConfig {
|
||||||
lineWidth?: number; // 0
|
lineWidth?: number; // 0
|
||||||
fillOpacity?: number; // 100
|
fillOpacity?: number; // 100
|
||||||
gradientMode?: GraphGradientMode;
|
gradientMode?: GraphGradientMode;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data';
|
import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data';
|
||||||
import { HistogramPanel } from './HistogramPanel';
|
import { HistogramPanel } from './HistogramPanel';
|
||||||
import { graphFieldOptions } from '@grafana/ui';
|
import { commonOptionsBuilder, graphFieldOptions } from '@grafana/ui';
|
||||||
import { PanelFieldConfig, PanelOptions, defaultPanelFieldConfig, defaultPanelOptions } from './models.gen';
|
import { PanelFieldConfig, PanelOptions, defaultPanelFieldConfig, defaultPanelOptions } from './models.gen';
|
||||||
import { originalDataHasHistogram } from './utils';
|
import { originalDataHasHistogram } from './utils';
|
||||||
|
|
||||||
@@ -44,6 +44,9 @@ export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(HistogramP
|
|||||||
defaultValue: defaultPanelOptions.combine,
|
defaultValue: defaultPanelOptions.combine,
|
||||||
showIf: (opts, data) => !originalDataHasHistogram(data),
|
showIf: (opts, data) => !originalDataHasHistogram(data),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// commonOptionsBuilder.addTooltipOptions(builder);
|
||||||
|
commonOptionsBuilder.addLegendOptions(builder);
|
||||||
})
|
})
|
||||||
.useFieldConfig({
|
.useFieldConfig({
|
||||||
standardOptions: {
|
standardOptions: {
|
||||||
@@ -88,5 +91,7 @@ export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(HistogramP
|
|||||||
options: graphFieldOptions.fillGradient,
|
options: graphFieldOptions.fillGradient,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
commonOptionsBuilder.addHideFrom(builder);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Histogram",
|
"name": "Histogram",
|
||||||
"id": "histogram",
|
"id": "histogram",
|
||||||
|
|
||||||
"state": "alpha",
|
"state": "beta",
|
||||||
|
|
||||||
"info": {
|
"info": {
|
||||||
"author": {
|
"author": {
|
||||||
|
|||||||
Reference in New Issue
Block a user