mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 00:47:38 -06:00
Timeseries: add UI to control the span nulls threshold (#32222)
This commit is contained in:
parent
d33a77a67f
commit
ea186947d2
@ -155,18 +155,28 @@ Dot spacing set to 0, 30:
|
||||
|
||||
Choose how null values (gaps in the data) are displayed on the graph.
|
||||
|
||||
#### Gaps
|
||||
#### Connect null values
|
||||
|
||||
If there is a gap in the series, the line in the graph will be broken and show the gap.
|
||||
If there are null values in the series, the line can be connected or show gaps
|
||||
|
||||
![Null values gaps example](/img/docs/time-series-panel/line-graph-null-gaps-7-4.png)
|
||||
|
||||
#### Connected
|
||||
#### Never
|
||||
|
||||
If there is a gap in the series, the line will skip the gap and connect to the next non-null value.
|
||||
When values are missing in the data, they will be rendered as gaps in the line
|
||||
|
||||
#### Always
|
||||
|
||||
If there is a gap in the data, the line will be shown connected to the next non-null value
|
||||
|
||||
![Null values connected example](/img/docs/time-series-panel/line-graph-null-connected-7-4.png)
|
||||
|
||||
#### Threshold
|
||||
|
||||
The threshold settings allows specifying a maximum time between points that should be connected.
|
||||
|
||||
|
||||
|
||||
### Show points
|
||||
|
||||
Choose when the points should be shown on the graph.
|
||||
|
65
public/app/plugins/panel/timeseries/SpanNullsEditor.tsx
Normal file
65
public/app/plugins/panel/timeseries/SpanNullsEditor.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import { FieldOverrideEditorProps, rangeUtil, SelectableValue } from '@grafana/data';
|
||||
import { HorizontalGroup, Input, RadioButtonGroup } from '@grafana/ui';
|
||||
|
||||
const GAPS_OPTIONS: Array<SelectableValue<boolean | number>> = [
|
||||
{
|
||||
label: 'Never',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
label: 'Always',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'Threshold',
|
||||
value: 3600000, // 1h
|
||||
},
|
||||
];
|
||||
|
||||
export const SpanNullsEditor: React.FC<FieldOverrideEditorProps<boolean | number, any>> = ({ value, onChange }) => {
|
||||
const isThreshold = typeof value === 'number';
|
||||
const formattedTime = isThreshold ? rangeUtil.secondsToHms((value as number) / 1000) : undefined;
|
||||
GAPS_OPTIONS[2].value = isThreshold ? (value as number) : 3600000; // 1h
|
||||
|
||||
const checkAndUpdate = (txt: string) => {
|
||||
let val: boolean | number = false;
|
||||
if (txt) {
|
||||
try {
|
||||
val = rangeUtil.intervalToSeconds(txt) * 1000;
|
||||
} catch (err) {
|
||||
console.warn('ERROR', err);
|
||||
}
|
||||
}
|
||||
onChange(val);
|
||||
};
|
||||
|
||||
const handleEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key !== 'Enter') {
|
||||
return;
|
||||
}
|
||||
checkAndUpdate((e.target as any).value);
|
||||
};
|
||||
|
||||
const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||
checkAndUpdate(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<HorizontalGroup>
|
||||
<RadioButtonGroup value={value} options={GAPS_OPTIONS} onChange={onChange} />
|
||||
{isThreshold && (
|
||||
<Input
|
||||
autoFocus={true}
|
||||
placeholder="never"
|
||||
width={10}
|
||||
defaultValue={formattedTime}
|
||||
onKeyDown={handleEnterKey}
|
||||
onBlur={handleBlur}
|
||||
prefix={<div><</div>}
|
||||
spellCheck={false}
|
||||
/>
|
||||
)}
|
||||
</HorizontalGroup>
|
||||
);
|
||||
};
|
@ -30,6 +30,7 @@ import { ScaleDistributionEditor } from './ScaleDistributionEditor';
|
||||
import { LineStyleEditor } from './LineStyleEditor';
|
||||
import { FillBellowToEditor } from './FillBelowToEditor';
|
||||
import { OptionsWithLegend } from './types';
|
||||
import { SpanNullsEditor } from './SpanNullsEditor';
|
||||
|
||||
export const defaultGraphConfig: GraphFieldConfig = {
|
||||
drawStyle: DrawStyle.Line,
|
||||
@ -133,17 +134,16 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption
|
||||
process: identityOverrideProcessor,
|
||||
shouldApply: (f) => f.type === FieldType.number,
|
||||
})
|
||||
.addRadio({
|
||||
.addCustomEditor<void, boolean>({
|
||||
id: 'spanNulls',
|
||||
path: 'spanNulls',
|
||||
name: 'Null values',
|
||||
name: 'Connect null values',
|
||||
defaultValue: false,
|
||||
settings: {
|
||||
options: [
|
||||
{ label: 'Gaps', value: false },
|
||||
{ label: 'Connected', value: true },
|
||||
],
|
||||
},
|
||||
editor: SpanNullsEditor,
|
||||
override: SpanNullsEditor,
|
||||
showIf: (c) => c.drawStyle === DrawStyle.Line,
|
||||
shouldApply: (f) => f.type !== FieldType.time,
|
||||
process: identityOverrideProcessor,
|
||||
})
|
||||
.addRadio({
|
||||
path: 'showPoints',
|
||||
|
Loading…
Reference in New Issue
Block a user