mirror of https://github.com/grafana/grafana.git
Trend/TimeSeries: Add "Show values" option (#108090)
Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
parent
67a6866c7b
commit
9fb5790166
|
@ -57,6 +57,7 @@
|
||||||
"type": "linear"
|
"type": "linear"
|
||||||
},
|
},
|
||||||
"showPoints": "auto",
|
"showPoints": "auto",
|
||||||
|
"showValues": true,
|
||||||
"spanNulls": false,
|
"spanNulls": false,
|
||||||
"stacking": {
|
"stacking": {
|
||||||
"group": "A",
|
"group": "A",
|
||||||
|
|
|
@ -635,6 +635,7 @@ export interface GraphFieldConfig extends LineConfig, FillConfig, PointsConfig,
|
||||||
drawStyle?: GraphDrawStyle;
|
drawStyle?: GraphDrawStyle;
|
||||||
gradientMode?: GraphGradientMode;
|
gradientMode?: GraphGradientMode;
|
||||||
insertNulls?: (boolean | number);
|
insertNulls?: (boolean | number);
|
||||||
|
showValues?: boolean;
|
||||||
thresholdsStyle?: GraphThresholdsStyleConfig;
|
thresholdsStyle?: GraphThresholdsStyleConfig;
|
||||||
transform?: GraphTransform;
|
transform?: GraphTransform;
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,7 @@ GraphFieldConfig: {
|
||||||
gradientMode?: GraphGradientMode
|
gradientMode?: GraphGradientMode
|
||||||
thresholdsStyle?: GraphThresholdsStyleConfig
|
thresholdsStyle?: GraphThresholdsStyleConfig
|
||||||
transform?: GraphTransform
|
transform?: GraphTransform
|
||||||
|
showValues?: bool
|
||||||
insertNulls?: bool | number
|
insertNulls?: bool | number
|
||||||
} @cuetsy(kind="interface")
|
} @cuetsy(kind="interface")
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ export interface SeriesProps extends LineConfig, BarConfig, FillConfig, PointsCo
|
||||||
dataFrameFieldIndex?: DataFrameFieldIndex;
|
dataFrameFieldIndex?: DataFrameFieldIndex;
|
||||||
theme: GrafanaTheme2;
|
theme: GrafanaTheme2;
|
||||||
value?: uPlot.Series.Value;
|
value?: uPlot.Series.Value;
|
||||||
|
showValues?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
||||||
|
|
|
@ -59,6 +59,7 @@ for (let i = 0; i < BIN_INCRS.length; i++) {
|
||||||
BIN_INCRS[i] = 2 ** i;
|
BIN_INCRS[i] = 2 ** i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { DrawStyle } from '@grafana/ui';
|
||||||
import {
|
import {
|
||||||
UPlotConfigBuilder,
|
UPlotConfigBuilder,
|
||||||
UPlotConfigPrepFn,
|
UPlotConfigPrepFn,
|
||||||
|
@ -74,6 +75,7 @@ const defaultConfig: GraphFieldConfig = {
|
||||||
drawStyle: GraphDrawStyle.Line,
|
drawStyle: GraphDrawStyle.Line,
|
||||||
showPoints: VisibilityMode.Auto,
|
showPoints: VisibilityMode.Auto,
|
||||||
axisPlacement: AxisPlacement.Auto,
|
axisPlacement: AxisPlacement.Auto,
|
||||||
|
showValues: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({
|
export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({
|
||||||
|
@ -529,6 +531,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({
|
||||||
softMax: customConfig.axisSoftMax,
|
softMax: customConfig.axisSoftMax,
|
||||||
// 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: field.state?.origin,
|
dataFrameFieldIndex: field.state?.origin,
|
||||||
|
showValues: customConfig.showValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Render thresholds in graph
|
// Render thresholds in graph
|
||||||
|
@ -553,6 +556,79 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({
|
||||||
|
|
||||||
builder.setStackingGroups(stackingGroups);
|
builder.setStackingGroups(stackingGroups);
|
||||||
|
|
||||||
|
const mightShowValues = frame.fields.some((field, i) => {
|
||||||
|
if (i === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customConfig = field.config.custom ?? {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
customConfig.showValues &&
|
||||||
|
(customConfig.drawStyle === GraphDrawStyle.Points || customConfig.showPoints !== VisibilityMode.Never)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mightShowValues) {
|
||||||
|
// since bars style doesnt show points in Auto mode, we can't piggyback on series.points.show()
|
||||||
|
// so we make a simple density-based callback to use here
|
||||||
|
const barsShowValues = (u: uPlot) => {
|
||||||
|
let width = u.bbox.width / uPlot.pxRatio;
|
||||||
|
let count = u.data[0].length;
|
||||||
|
|
||||||
|
// render values when each has at least 30px of width available
|
||||||
|
return width / count >= 30;
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.addHook('draw', (u: uPlot) => {
|
||||||
|
const baseFontSize = 12;
|
||||||
|
const font = `${baseFontSize * uPlot.pxRatio}px ${theme.typography.fontFamily}`;
|
||||||
|
|
||||||
|
const { ctx } = u;
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.fillStyle = theme.colors.text.primary;
|
||||||
|
ctx.font = font;
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
|
||||||
|
for (let seriesIdx = 1; seriesIdx < u.data.length; seriesIdx++) {
|
||||||
|
const series = u.series[seriesIdx];
|
||||||
|
const field = frame.fields[seriesIdx];
|
||||||
|
|
||||||
|
if (
|
||||||
|
field.config.custom?.showValues &&
|
||||||
|
// @ts-ignore points.show() is always callable on the instance (but may be boolean when passed to uPlot as init option)
|
||||||
|
(series.points?.show?.(u, seriesIdx) ||
|
||||||
|
(field.config.custom?.drawStyle === DrawStyle.Bars && barsShowValues(u)))
|
||||||
|
) {
|
||||||
|
const xData = u.data[0];
|
||||||
|
const yData = u.data[seriesIdx];
|
||||||
|
const yScale = series.scale!;
|
||||||
|
|
||||||
|
for (let dataIdx = 0; dataIdx < yData.length; dataIdx++) {
|
||||||
|
const yVal = yData[dataIdx];
|
||||||
|
|
||||||
|
if (yVal != null) {
|
||||||
|
const text = formattedValueToString(field.display!(yVal));
|
||||||
|
|
||||||
|
const isNegative = yVal < 0;
|
||||||
|
const textOffset = isNegative ? 15 : -5;
|
||||||
|
ctx.textBaseline = isNegative ? 'top' : 'bottom';
|
||||||
|
|
||||||
|
const xVal = xData[dataIdx];
|
||||||
|
const x = u.valToPos(xVal, 'x', true);
|
||||||
|
const y = u.valToPos(yVal, yScale, true);
|
||||||
|
|
||||||
|
ctx.fillText(text, x, y + textOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// hook up custom/composite renderers
|
// hook up custom/composite renderers
|
||||||
renderers?.forEach((r) => {
|
renderers?.forEach((r) => {
|
||||||
if (!indexByName) {
|
if (!indexByName) {
|
||||||
|
|
|
@ -41,6 +41,7 @@ export const defaultGraphConfig: GraphFieldConfig = {
|
||||||
axisGridShow: true,
|
axisGridShow: true,
|
||||||
axisCenteredZero: false,
|
axisCenteredZero: false,
|
||||||
axisBorderShow: false,
|
axisBorderShow: false,
|
||||||
|
showValues: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NullEditorSettings = { isTime: boolean };
|
export type NullEditorSettings = { isTime: boolean };
|
||||||
|
@ -208,6 +209,13 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
|
||||||
},
|
},
|
||||||
showIf: (config) => config.drawStyle !== GraphDrawStyle.Points,
|
showIf: (config) => config.drawStyle !== GraphDrawStyle.Points,
|
||||||
})
|
})
|
||||||
|
.addBooleanSwitch({
|
||||||
|
path: 'showValues',
|
||||||
|
name: t('timeseries.config.get-graph-field-config.name-show-values', 'Show values'),
|
||||||
|
category: categoryStyles,
|
||||||
|
defaultValue: false,
|
||||||
|
showIf: (config) => config.showPoints !== VisibilityMode.Never || config.drawStyle === GraphDrawStyle.Points,
|
||||||
|
})
|
||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'pointSize',
|
path: 'pointSize',
|
||||||
name: t('timeseries.config.get-graph-field-config.name-point-size', 'Point size'),
|
name: t('timeseries.config.get-graph-field-config.name-point-size', 'Point size'),
|
||||||
|
|
|
@ -13059,6 +13059,7 @@
|
||||||
"name-point-size": "Point size",
|
"name-point-size": "Point size",
|
||||||
"name-show-points": "Show points",
|
"name-show-points": "Show points",
|
||||||
"name-show-thresholds": "Show thresholds",
|
"name-show-thresholds": "Show thresholds",
|
||||||
|
"name-show-values": "Show values",
|
||||||
"name-style": "Style",
|
"name-style": "Style",
|
||||||
"name-transform": "Transform",
|
"name-transform": "Transform",
|
||||||
"transform-options": {
|
"transform-options": {
|
||||||
|
|
Loading…
Reference in New Issue