diff --git a/packages/grafana-data/src/transformations/transformers/histogram.ts b/packages/grafana-data/src/transformations/transformers/histogram.ts index 3c0e470a89d..b13b1e54633 100644 --- a/packages/grafana-data/src/transformations/transformers/histogram.ts +++ b/packages/grafana-data/src/transformations/transformers/histogram.ts @@ -203,16 +203,17 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform } const bucketMin = { + ...counts[0], name: histogramFrameBucketMinFieldName, values: new ArrayVector(joinedHists[0]), type: FieldType.number, - config: {}, + state: undefined, }; const bucketMax = { + ...bucketMin, name: histogramFrameBucketMaxFieldName, values: new ArrayVector(joinedHists[0].map((v) => v + bucketSize!)), - type: FieldType.number, - config: {}, + state: undefined, }; if (options?.combine) { @@ -227,6 +228,8 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform ...counts[0], name: 'Count', values: new ArrayVector(vals), + type: FieldType.number, + state: undefined, }, ]; } else { diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts index 58ba89d20e0..cadcb42c24e 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts @@ -93,7 +93,7 @@ export class UPlotAxisBuilder extends PlotConfigBuilder { } else if (isTime) { config.values = formatTime; } 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 diff --git a/public/app/plugins/panel/histogram/Histogram.tsx b/public/app/plugins/panel/histogram/Histogram.tsx index 6c3ef7502b4..16bfccc3199 100644 --- a/public/app/plugins/panel/histogram/Histogram.tsx +++ b/public/app/plugins/panel/histogram/Histogram.tsx @@ -2,6 +2,7 @@ import React from 'react'; import uPlot, { AlignedData } from 'uplot'; import { DataFrame, + formattedValueToString, getFieldColorModeForField, getFieldDisplayName, getFieldSeriesColor, @@ -16,6 +17,8 @@ import { AxisPlacement, ScaleDirection, ScaleOrientation, + LegendDisplayMode, + PlotLegend, } from '@grafana/ui'; import { @@ -32,12 +35,7 @@ export interface HistogramProps extends Themeable2 { height: number; structureRev?: number; // a number that will change when the frames[] structure changes legend: VizLegendOptions; - //onLegendClick?: (event: GraphNGLegendEvent) => void; children?: (builder: UPlotConfigBuilder, frame: DataFrame) => React.ReactNode; - - //prepConfig: (frame: DataFrame) => UPlotConfigBuilder; - //propsToDiff?: string[]; - //renderLegend: (config: UPlotConfigBuilder) => React.ReactElement; } const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => { @@ -84,12 +82,18 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => { direction: ScaleDirection.Up, }); + const fmt = frame.fields[0].display!; + const xAxisFormatter = (v: number) => { + return formattedValueToString(fmt(v)); + }; + builder.addAxis({ scaleKey: 'x', isTime: false, placement: AxisPlacement.Bottom, incrs: histogramBucketSizes, 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), //splits: config.xSplits, //values: config.xValues, @@ -138,15 +142,15 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => { colorMode, pathBuilder, //pointsBuilder: config.drawPoints, - show: !customConfig.hideFrom?.graph, + show: !customConfig.hideFrom?.vis, gradientMode: customConfig.gradientMode, thresholds: field.config.thresholds, // The following properties are not used in the uPlot config, but are utilized as transport for legend config - // dataFrameFieldIndex: { - // fieldIndex: i, - // frameIndex: 0, - // }, + dataFrameFieldIndex: { + fieldIndex: i, + frameIndex: 0, + }, fieldName: getFieldDisplayName(field, frame), hideInLegend: customConfig.hideFrom?.legend, }); @@ -178,10 +182,6 @@ const preparePlotData = (frame: DataFrame) => { return data; }; -const renderLegend = (config: UPlotConfigBuilder) => { - return null; -}; - interface State { alignedData: AlignedData; config?: UPlotConfigBuilder; @@ -210,6 +210,15 @@ export class Histogram extends React.Component { return state; } + renderLegend(config: UPlotConfigBuilder) { + const { legend } = this.props; + if (!config || legend.displayMode === LegendDisplayMode.Hidden) { + return null; + } + + return ; + } + componentDidUpdate(prevProps: HistogramProps) { const { structureRev, alignedFrame } = this.props; @@ -241,7 +250,7 @@ export class Histogram extends React.Component { } return ( - + {(vizWidth: number, vizHeight: number) => ( = ({ data, options, width, height } if (!hist) { return undefined; } + return histogramFieldsToFrame(hist); }, [data.series, options]); @@ -41,11 +42,15 @@ export const HistogramPanel: React.FC = ({ data, options, width, height } + > + {(config, alignedFrame) => { + return null; // ; + }} + ); }; diff --git a/public/app/plugins/panel/histogram/models.gen.ts b/public/app/plugins/panel/histogram/models.gen.ts index 4eea7de6f95..5bb4ecc6870 100644 --- a/public/app/plugins/panel/histogram/models.gen.ts +++ b/public/app/plugins/panel/histogram/models.gen.ts @@ -3,11 +3,18 @@ // 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 interface PanelOptions { +export interface PanelOptions extends OptionsWithLegend, OptionsWithTooltip { bucketSize?: number; bucketOffset?: number; combine?: boolean; @@ -15,12 +22,20 @@ export interface PanelOptions { export const defaultPanelOptions: PanelOptions = { bucketOffset: 0, + legend: { + displayMode: LegendDisplayMode.List, + placement: 'bottom', + calcs: [], + }, + tooltip: { + mode: TooltipDisplayMode.Multi, + }, }; /** * @alpha */ -export interface PanelFieldConfig { +export interface PanelFieldConfig extends HideableFieldConfig { lineWidth?: number; // 0 fillOpacity?: number; // 100 gradientMode?: GraphGradientMode; diff --git a/public/app/plugins/panel/histogram/module.tsx b/public/app/plugins/panel/histogram/module.tsx index df38a184bda..da4f9883b14 100644 --- a/public/app/plugins/panel/histogram/module.tsx +++ b/public/app/plugins/panel/histogram/module.tsx @@ -1,6 +1,6 @@ import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data'; import { HistogramPanel } from './HistogramPanel'; -import { graphFieldOptions } from '@grafana/ui'; +import { commonOptionsBuilder, graphFieldOptions } from '@grafana/ui'; import { PanelFieldConfig, PanelOptions, defaultPanelFieldConfig, defaultPanelOptions } from './models.gen'; import { originalDataHasHistogram } from './utils'; @@ -44,6 +44,9 @@ export const plugin = new PanelPlugin(HistogramP defaultValue: defaultPanelOptions.combine, showIf: (opts, data) => !originalDataHasHistogram(data), }); + + // commonOptionsBuilder.addTooltipOptions(builder); + commonOptionsBuilder.addLegendOptions(builder); }) .useFieldConfig({ standardOptions: { @@ -88,5 +91,7 @@ export const plugin = new PanelPlugin(HistogramP options: graphFieldOptions.fillGradient, }, }); + + commonOptionsBuilder.addHideFrom(builder); }, }); diff --git a/public/app/plugins/panel/histogram/plugin.json b/public/app/plugins/panel/histogram/plugin.json index 3aec3df24f4..a62e296bf02 100644 --- a/public/app/plugins/panel/histogram/plugin.json +++ b/public/app/plugins/panel/histogram/plugin.json @@ -3,7 +3,7 @@ "name": "Histogram", "id": "histogram", - "state": "alpha", + "state": "beta", "info": { "author": {