mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
GraphNG: add bar alignment option (#30499)
* GraphNG: add bar alignment option * Fix builders
This commit is contained in:
parent
2f394a219b
commit
820866e425
@ -242,6 +242,7 @@ export const GraphNG: React.FC<GraphNGProps> = ({
|
|||||||
lineWidth: customConfig.lineWidth,
|
lineWidth: customConfig.lineWidth,
|
||||||
lineInterpolation: customConfig.lineInterpolation,
|
lineInterpolation: customConfig.lineInterpolation,
|
||||||
lineStyle: customConfig.lineStyle,
|
lineStyle: customConfig.lineStyle,
|
||||||
|
barAlignment: customConfig.barAlignment,
|
||||||
pointSize: customConfig.pointSize,
|
pointSize: customConfig.pointSize,
|
||||||
pointColor: customConfig.pointColor ?? seriesColor,
|
pointColor: customConfig.pointColor ?? seriesColor,
|
||||||
spanNulls: customConfig.spanNulls || false,
|
spanNulls: customConfig.spanNulls || false,
|
||||||
|
@ -81,11 +81,67 @@ const IconNotFound: FC<SvgProps> = ({ size, ...rest }) => {
|
|||||||
return <svg width={size} height={size} {...rest} />;
|
return <svg width={size} height={size} {...rest} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BarAlignmentAfter: FC<SvgProps> = ({ size, ...rest }) => {
|
||||||
|
return (
|
||||||
|
<svg width={'16px'} height={size} viewBox="0 0 16 19" version="1.1" xmlns="http://www.w3.org/2000/svg" {...rest}>
|
||||||
|
<g id="Page-1">
|
||||||
|
<g id="Group" transform="translate(0.500000, 0.000000)">
|
||||||
|
<circle id="Oval" cx="2.67" cy="2.67" r="2.67" />
|
||||||
|
<polygon id="Path" points="13.42 18.08 13.42 3.42 3.06 3.42 3.06 1.92 14.92 1.92 14.92 18.08" />
|
||||||
|
<polygon id="Path" points="1.92 18.08 1.92 16.58 1.92 2.67 3.42 2.67 3.42 18.08" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BarAlignmentBefore: FC<SvgProps> = ({ size, ...rest }) => {
|
||||||
|
return (
|
||||||
|
<svg width={'16px'} height={size} viewBox="0 0 16 19" version="1.1" xmlns="http://www.w3.org/2000/svg" {...rest}>
|
||||||
|
<g id="Page-1">
|
||||||
|
<g
|
||||||
|
id="Group"
|
||||||
|
transform="translate(8.000000, 9.500000) scale(-1, 1) translate(-8.000000, -9.500000) translate(0.500000, 0.000000)"
|
||||||
|
>
|
||||||
|
<circle id="Oval" cx="2.67" cy="2.67" r="2.67" />
|
||||||
|
<polygon id="Path" points="13.42 18.08 13.42 3.42 3.06 3.42 3.06 1.92 14.92 1.92 14.92 18.08" />
|
||||||
|
<polygon id="Path" points="1.92 18.08 1.92 16.58 1.92 2.67 3.42 2.67 3.42 18.08" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BarAlignmentCenter: FC<SvgProps> = ({ size, ...rest }) => {
|
||||||
|
return (
|
||||||
|
<svg width="16px" height={size} viewBox="0 0 16 19" version="1.1" xmlns="http://www.w3.org/2000/svg" {...rest}>
|
||||||
|
<g id="Page-1">
|
||||||
|
<g id="Group" transform="translate(2.500000, 0.000000)">
|
||||||
|
<circle id="Oval" cx="6.67" cy="2.67" r="2.67" />
|
||||||
|
<g id="Group-2" transform="translate(0.000000, 2.000000)">
|
||||||
|
<polygon
|
||||||
|
id="Path"
|
||||||
|
points="11.5 16.16 11.5 1.5 1.84741111e-13 1.5 1.84741111e-13 1.77635684e-14 13 1.77635684e-14 13 16.16"
|
||||||
|
/>
|
||||||
|
<polygon
|
||||||
|
id="Path"
|
||||||
|
points="2.27373675e-13 16.16 2.27373675e-13 14.66 2.32286412e-13 0.75 1.5 0.75 1.5 16.16"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const customIcons: Record<string, ComponentType<SvgProps>> = {
|
export const customIcons: Record<string, ComponentType<SvgProps>> = {
|
||||||
'gf-interpolation-linear': InterpolationLinear,
|
'gf-interpolation-linear': InterpolationLinear,
|
||||||
'gf-interpolation-smooth': InterpolationSmooth,
|
'gf-interpolation-smooth': InterpolationSmooth,
|
||||||
'gf-interpolation-step-before': InterpolationStepBefore,
|
'gf-interpolation-step-before': InterpolationStepBefore,
|
||||||
'gf-interpolation-step-after': InterpolationStepAfter,
|
'gf-interpolation-step-after': InterpolationStepAfter,
|
||||||
'gf-logs': Logs,
|
'gf-logs': Logs,
|
||||||
|
'gf-bar-alignment-after': BarAlignmentAfter,
|
||||||
|
'gf-bar-alignment-before': BarAlignmentBefore,
|
||||||
|
'gf-bar-alignment-center': BarAlignmentCenter,
|
||||||
notFoundDummy: IconNotFound,
|
notFoundDummy: IconNotFound,
|
||||||
};
|
};
|
||||||
|
@ -40,6 +40,15 @@ export enum LineInterpolation {
|
|||||||
StepAfter = 'stepAfter',
|
StepAfter = 'stepAfter',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @alpha
|
||||||
|
*/
|
||||||
|
export enum BarAlignment {
|
||||||
|
Before = -1,
|
||||||
|
Center = 0,
|
||||||
|
After = 1,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
@ -87,6 +96,13 @@ export interface LineConfig {
|
|||||||
spanNulls?: boolean;
|
spanNulls?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @alpha
|
||||||
|
*/
|
||||||
|
export interface BarConfig {
|
||||||
|
barAlignment?: BarAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
@ -156,7 +172,13 @@ export interface HideableFieldConfig {
|
|||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
export interface GraphFieldConfig extends LineConfig, FillConfig, PointsConfig, AxisConfig, HideableFieldConfig {
|
export interface GraphFieldConfig
|
||||||
|
extends LineConfig,
|
||||||
|
FillConfig,
|
||||||
|
PointsConfig,
|
||||||
|
AxisConfig,
|
||||||
|
BarConfig,
|
||||||
|
HideableFieldConfig {
|
||||||
drawStyle?: DrawStyle;
|
drawStyle?: DrawStyle;
|
||||||
gradientMode?: GraphGradientMode;
|
gradientMode?: GraphGradientMode;
|
||||||
}
|
}
|
||||||
@ -178,6 +200,12 @@ export const graphFieldOptions = {
|
|||||||
{ description: 'Step after', value: LineInterpolation.StepAfter, icon: 'gf-interpolation-step-after' },
|
{ description: 'Step after', value: LineInterpolation.StepAfter, icon: 'gf-interpolation-step-after' },
|
||||||
] as Array<SelectableValue<LineInterpolation>>,
|
] as Array<SelectableValue<LineInterpolation>>,
|
||||||
|
|
||||||
|
barAlignment: [
|
||||||
|
{ description: 'Before', value: BarAlignment.Before, icon: 'gf-bar-alignment-before' },
|
||||||
|
{ description: 'Center', value: BarAlignment.Center, icon: 'gf-bar-alignment-center' },
|
||||||
|
{ description: 'After', value: BarAlignment.After, icon: 'gf-bar-alignment-after' },
|
||||||
|
] as Array<SelectableValue<BarAlignment>>,
|
||||||
|
|
||||||
showPoints: [
|
showPoints: [
|
||||||
{ label: 'Auto', value: PointVisibility.Auto, description: 'Show points when the density is low' },
|
{ label: 'Auto', value: PointVisibility.Auto, description: 'Show points when the density is low' },
|
||||||
{ label: 'Always', value: PointVisibility.Always },
|
{ label: 'Always', value: PointVisibility.Always },
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
import { FALLBACK_COLOR, FieldColorMode, GrafanaTheme, ThresholdsConfig } from '@grafana/data';
|
import { DataFrameFieldIndex, FALLBACK_COLOR, FieldColorMode, GrafanaTheme, ThresholdsConfig } from '@grafana/data';
|
||||||
import tinycolor from 'tinycolor2';
|
import tinycolor from 'tinycolor2';
|
||||||
import uPlot, { Series } from 'uplot';
|
import uPlot, { Series } from 'uplot';
|
||||||
import {
|
import {
|
||||||
|
BarAlignment,
|
||||||
|
BarConfig,
|
||||||
DrawStyle,
|
DrawStyle,
|
||||||
LineConfig,
|
|
||||||
FillConfig,
|
FillConfig,
|
||||||
|
GraphGradientMode,
|
||||||
|
LineConfig,
|
||||||
|
LineInterpolation,
|
||||||
PointsConfig,
|
PointsConfig,
|
||||||
PointVisibility,
|
PointVisibility,
|
||||||
LineInterpolation,
|
|
||||||
GraphGradientMode,
|
|
||||||
} from '../config';
|
} from '../config';
|
||||||
import { PlotConfigBuilder } from '../types';
|
import { PlotConfigBuilder } from '../types';
|
||||||
import { DataFrameFieldIndex } from '@grafana/data';
|
import { getHueGradientFn, getOpacityGradientFn, getScaleGradientFn } from './gradientFills';
|
||||||
import { getScaleGradientFn, getOpacityGradientFn, getHueGradientFn } from './gradientFills';
|
|
||||||
|
|
||||||
export interface SeriesProps extends LineConfig, FillConfig, PointsConfig {
|
export interface SeriesProps extends LineConfig, BarConfig, FillConfig, PointsConfig {
|
||||||
scaleKey: string;
|
scaleKey: string;
|
||||||
gradientMode?: GraphGradientMode;
|
gradientMode?: GraphGradientMode;
|
||||||
/** Used when gradientMode is set to Scheme */
|
/** Used when gradientMode is set to Scheme */
|
||||||
@ -40,6 +41,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
|||||||
lineInterpolation,
|
lineInterpolation,
|
||||||
lineWidth,
|
lineWidth,
|
||||||
lineStyle,
|
lineStyle,
|
||||||
|
barAlignment,
|
||||||
showPoints,
|
showPoints,
|
||||||
pointColor,
|
pointColor,
|
||||||
pointSize,
|
pointSize,
|
||||||
@ -66,7 +68,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
|||||||
lineConfig.dash = lineStyle.dash ?? [10, 10];
|
lineConfig.dash = lineStyle.dash ?? [10, 10];
|
||||||
}
|
}
|
||||||
lineConfig.paths = (self: uPlot, seriesIdx: number, idx0: number, idx1: number) => {
|
lineConfig.paths = (self: uPlot, seriesIdx: number, idx0: number, idx1: number) => {
|
||||||
let pathsBuilder = mapDrawStyleToPathBuilder(drawStyle, lineInterpolation);
|
let pathsBuilder = mapDrawStyleToPathBuilder(drawStyle, lineInterpolation, barAlignment);
|
||||||
return pathsBuilder(self, seriesIdx, idx0, idx1);
|
return pathsBuilder(self, seriesIdx, idx0, idx1);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -146,11 +148,13 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface PathBuilders {
|
interface PathBuilders {
|
||||||
bars: Series.PathBuilder;
|
|
||||||
linear: Series.PathBuilder;
|
linear: Series.PathBuilder;
|
||||||
smooth: Series.PathBuilder;
|
smooth: Series.PathBuilder;
|
||||||
stepBefore: Series.PathBuilder;
|
stepBefore: Series.PathBuilder;
|
||||||
stepAfter: Series.PathBuilder;
|
stepAfter: Series.PathBuilder;
|
||||||
|
bars: Series.PathBuilder;
|
||||||
|
barsAfter: Series.PathBuilder;
|
||||||
|
barsBefore: Series.PathBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
let builders: PathBuilders | undefined = undefined;
|
let builders: PathBuilders | undefined = undefined;
|
||||||
@ -158,24 +162,32 @@ let builders: PathBuilders | undefined = undefined;
|
|||||||
function mapDrawStyleToPathBuilder(
|
function mapDrawStyleToPathBuilder(
|
||||||
style: DrawStyle,
|
style: DrawStyle,
|
||||||
lineInterpolation?: LineInterpolation,
|
lineInterpolation?: LineInterpolation,
|
||||||
opts?: any
|
barAlignment?: BarAlignment
|
||||||
): Series.PathBuilder {
|
): Series.PathBuilder {
|
||||||
// This should be global static, but Jest initalization was failing so we lazy load to avoid the issue
|
|
||||||
if (!builders) {
|
if (!builders) {
|
||||||
|
// This should be global static, but Jest initalization was failing so we lazy load to avoid the issue
|
||||||
const pathBuilders = uPlot.paths;
|
const pathBuilders = uPlot.paths;
|
||||||
const barWidthFactor = 0.6;
|
const barWidthFactor = 0.6;
|
||||||
const barMaxWidth = Infinity;
|
const barMaxWidth = Infinity;
|
||||||
|
|
||||||
builders = {
|
builders = {
|
||||||
bars: pathBuilders.bars!({ size: [barWidthFactor, barMaxWidth] }),
|
|
||||||
linear: pathBuilders.linear!(),
|
linear: pathBuilders.linear!(),
|
||||||
smooth: pathBuilders.spline!(),
|
smooth: pathBuilders.spline!(),
|
||||||
stepBefore: pathBuilders.stepped!({ align: -1 }),
|
stepBefore: pathBuilders.stepped!({ align: -1 }),
|
||||||
stepAfter: pathBuilders.stepped!({ align: 1 }),
|
stepAfter: pathBuilders.stepped!({ align: 1 }),
|
||||||
|
bars: pathBuilders.bars!({ size: [barWidthFactor, barMaxWidth] }),
|
||||||
|
barsBefore: pathBuilders.bars!({ size: [barWidthFactor, barMaxWidth], align: -1 }),
|
||||||
|
barsAfter: pathBuilders.bars!({ size: [barWidthFactor, barMaxWidth], align: 1 }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style === DrawStyle.Bars) {
|
if (style === DrawStyle.Bars) {
|
||||||
|
if (barAlignment === BarAlignment.After) {
|
||||||
|
return builders.barsAfter;
|
||||||
|
}
|
||||||
|
if (barAlignment === BarAlignment.Before) {
|
||||||
|
return builders.barsBefore;
|
||||||
|
}
|
||||||
return builders.bars;
|
return builders.bars;
|
||||||
}
|
}
|
||||||
if (style === DrawStyle.Line) {
|
if (style === DrawStyle.Line) {
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import {
|
import {
|
||||||
AxisPlacement,
|
AxisPlacement,
|
||||||
|
BarAlignment,
|
||||||
DrawStyle,
|
DrawStyle,
|
||||||
GraphFieldConfig,
|
GraphFieldConfig,
|
||||||
graphFieldOptions,
|
graphFieldOptions,
|
||||||
@ -36,6 +37,7 @@ export const defaultGraphConfig: GraphFieldConfig = {
|
|||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
fillOpacity: 0,
|
fillOpacity: 0,
|
||||||
gradientMode: GraphGradientMode.None,
|
gradientMode: GraphGradientMode.None,
|
||||||
|
barAlignment: BarAlignment.Center,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOptionsArgs<GraphFieldConfig> {
|
export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOptionsArgs<GraphFieldConfig> {
|
||||||
@ -71,6 +73,15 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption
|
|||||||
},
|
},
|
||||||
showIf: (c) => c.drawStyle === DrawStyle.Line,
|
showIf: (c) => c.drawStyle === DrawStyle.Line,
|
||||||
})
|
})
|
||||||
|
.addRadio({
|
||||||
|
path: 'barAlignment',
|
||||||
|
name: 'Bar alignment',
|
||||||
|
defaultValue: cfg.barAlignment,
|
||||||
|
settings: {
|
||||||
|
options: graphFieldOptions.barAlignment,
|
||||||
|
},
|
||||||
|
showIf: (c) => c.drawStyle === DrawStyle.Bars,
|
||||||
|
})
|
||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'lineWidth',
|
path: 'lineWidth',
|
||||||
name: 'Line width',
|
name: 'Line width',
|
||||||
|
Loading…
Reference in New Issue
Block a user