From b6d4b701b98254a8779ea4310f842f18ac1c48a4 Mon Sep 17 00:00:00 2001 From: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:26:15 -0700 Subject: [PATCH] TimeSeries: Add option to disconnect values (#70097) Co-authored-by: nmarrs Co-authored-by: Leon Sorokin --- .../panel-timeseries/timeseries-nulls.json | 563 +++++++++++++----- .../components/GraphNG/nullInsertThreshold.ts | 2 +- .../panel/timeseries/InsertNullsEditor.tsx | 31 + .../panel/timeseries/NullsThresholdInput.tsx | 57 ++ .../panel/timeseries/SpanNullsEditor.tsx | 43 +- public/app/plugins/panel/timeseries/config.ts | 35 +- 6 files changed, 528 insertions(+), 203 deletions(-) create mode 100644 public/app/plugins/panel/timeseries/InsertNullsEditor.tsx create mode 100644 public/app/plugins/panel/timeseries/NullsThresholdInput.tsx diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json b/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json index 778cbde0638..b3040deb06a 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json @@ -924,6 +924,368 @@ "transformations": [], "type": "timeseries" }, + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 8, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 7, + "y": 14 + }, + "id": 32, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "7.5.0-pre", + "targets": [ + { + "alias": "", + "csvContent": "time, val\n2023-06-14T08:16:41Z, 20\n2023-06-14T08:16:42Z, 22\n2023-06-14T08:16:43Z, 24\n2023-06-14T08:16:45Z, 10\n2023-06-14T08:16:46Z, 12\n2023-06-14T08:17:46Z, 13\n2023-06-14T08:17:47Z, 14\n2023-06-14T08:17:57Z, 20\n2023-06-14T08:17:58Z, null\n2023-06-14T08:18:00Z, 22\n2023-06-14T08:18:25Z, 22", + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Default (only null disconnect)", + "type": "timeseries" + }, + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 5, + "x": 14, + "y": 14 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "30,null,1,20,90,null,30,null,5,0,null,30" + } + ], + "title": "Always show points between gaps", + "type": "timeseries" + }, + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 5, + "x": 19, + "y": 14 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,,,,,,60,,,,,,,,,,,,,,,,,,61,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,,,,,,60,,,,,,59,,,,,,60,,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,57,,,,,,56,,,,,,57,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,54,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,53,,,,,54,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,55,,,,,,56,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,57,,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,58,,,,,,59,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,58,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,61,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,60,,,,,,59,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,,59,,,,,,60,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,58,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,,,56,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,54,,,,,,53,,,,,,,,,,,,,,,,,,,52,,,,,,,,,,,51,,,,,,,,,,,,,,,,,,,,,,,,,52,,,,,,,54,,,,,,55,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,61,,,,,,,,,,,,,,,,,,,,,,,,60,,,,,,61,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62,,,,,,61,,,,,,62,,,,,,61,,,,,,62,,,,,,,,,,,,,,,,,,,63,,,,,,,,,,,,,,,,,,,,,,,,64,,,,,,63,,,,,,64,,,,,,63,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,61,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,,,,,,,63,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,64,,,,,,,,,,,,63,,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,," + } + ], + "title": "Always show points between gaps", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 8, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": 10000, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 7, + "y": 20 + }, + "id": 31, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "7.5.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 32, + "refId": "A" + } + ], + "title": "Connect Nulls < 10s", + "type": "timeseries" + }, { "datasource": { "type": "testdata" @@ -1014,8 +1376,8 @@ "gridPos": { "h": 8, "w": 7, - "x": 7, - "y": 14 + "x": 0, + "y": 22 }, "id": 9, "options": { @@ -1072,8 +1434,8 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "datasource", + "uid": "-- Dashboard --" }, "fieldConfig": { "defaults": { @@ -1094,14 +1456,15 @@ "tooltip": false, "viz": false }, + "insertNulls": 59000, "lineInterpolation": "linear", "lineWidth": 1, - "pointSize": 5, + "pointSize": 8, "scaleDistribution": { "type": "linear" }, - "showPoints": "never", - "spanNulls": 3600000, + "showPoints": "always", + "spanNulls": false, "stacking": { "group": "A", "mode": "none" @@ -1128,12 +1491,12 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 10, - "x": 14, - "y": 14 + "h": 6, + "w": 7, + "x": 7, + "y": 26 }, - "id": 13, + "id": 30, "options": { "legend": { "calcs": [], @@ -1149,39 +1512,21 @@ "pluginVersion": "7.5.0-pre", "targets": [ { - "alias": "", - "csvWave": { - "timeStep": 60, - "valuesCSV": "0,0,2,2,1,1" + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" }, - "lines": 10, - "points": [], - "pulseWave": { - "offCount": 3, - "offValue": 1, - "onCount": 3, - "onValue": 2, - "timeStep": 60 - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stream": { - "bands": 1, - "noise": 2.2, - "speed": 250, - "spread": 3.5, - "type": "signal" - }, - "stringInput": "1,20,90,null,30,5,0" + "panelId": 32, + "refId": "A" } ], - "title": "Span nulls below 1hr", + "title": "Disconnect Values > 59s", "type": "timeseries" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "datasource", + "uid": "-- Dashboard --" }, "fieldConfig": { "defaults": { @@ -1195,24 +1540,22 @@ "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", - "fillOpacity": 0, + "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, + "insertNulls": 59000, "lineInterpolation": "linear", - "lineStyle": { - "fill": "solid" - }, "lineWidth": 1, - "pointSize": 5, + "pointSize": 8, "scaleDistribution": { "type": "linear" }, - "showPoints": "never", - "spanNulls": false, + "showPoints": "always", + "spanNulls": 10000, "stacking": { "group": "A", "mode": "none" @@ -1233,105 +1576,18 @@ "value": 80 } ] - } + }, + "unit": "short" }, "overrides": [] }, "gridPos": { - "h": 8, - "w": 7, - "x": 0, - "y": 22 - }, - "id": 15, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "30,null,1,20,90,null,30,null,5,0,null,30" - } - ], - "title": "Always show points between gaps", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineStyle": { - "fill": "solid" - }, - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, + "h": 6, "w": 7, "x": 7, - "y": 22 + "y": 32 }, - "id": 16, + "id": 29, "options": { "legend": { "calcs": [], @@ -1344,18 +1600,18 @@ "sort": "none" } }, + "pluginVersion": "7.5.0-pre", "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "datasource", + "uid": "-- Dashboard --" }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,,,,,,60,,,,,,,,,,,,,,,,,,61,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,,,,,,60,,,,,,59,,,,,,60,,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,57,,,,,,56,,,,,,57,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,54,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,53,,,,,54,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,55,,,,,,56,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,57,,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,58,,,,,,59,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,58,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,61,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,60,,,,,,59,,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,,59,,,,,,60,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,58,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,,,56,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,54,,,,,,53,,,,,,,,,,,,,,,,,,,52,,,,,,,,,,,51,,,,,,,,,,,,,,,,,,,,,,,,,52,,,,,,,54,,,,,,55,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,58,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,,,,,,,60,,,,,,,,,,,,61,,,,,,,,,,,,,,,,,,,,,,,,60,,,,,,61,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62,,,,,,61,,,,,,62,,,,,,61,,,,,,62,,,,,,,,,,,,,,,,,,,63,,,,,,,,,,,,,,,,,,,,,,,,64,,,,,,63,,,,,,64,,,,,,63,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,61,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,,,,,,,63,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,64,,,,,,,,,,,,63,,,,,,,,,,,,,62,,,,,,,,,,,,,,,,,,,," + "panelId": 32, + "refId": "A" } ], - "title": "Always show points between gaps", + "title": "Connect Nulls < 10s, Disconnect Values > 59s", "type": "timeseries" }, { @@ -1418,7 +1674,7 @@ "h": 11, "w": 24, "x": 0, - "y": 30 + "y": 38 }, "id": 18, "maxDataPoints": 150, @@ -1508,7 +1764,7 @@ "h": 10, "w": 12, "x": 0, - "y": 41 + "y": 49 }, "id": 20, "maxDataPoints": 150, @@ -1598,7 +1854,7 @@ "h": 10, "w": 12, "x": 12, - "y": 41 + "y": 49 }, "id": 22, "maxDataPoints": 150, @@ -1688,7 +1944,7 @@ "h": 10, "w": 8, "x": 0, - "y": 51 + "y": 59 }, "id": 24, "maxDataPoints": 150, @@ -1778,7 +2034,7 @@ "h": 10, "w": 8, "x": 8, - "y": 51 + "y": 59 }, "id": 26, "maxDataPoints": 150, @@ -1868,7 +2124,7 @@ "h": 10, "w": 8, "x": 16, - "y": 51 + "y": 59 }, "id": 28, "maxDataPoints": 150, @@ -1899,7 +2155,8 @@ "type": "timeseries" } ], - "schemaVersion": 37, + "refresh": false, + "schemaVersion": 38, "style": "dark", "tags": [ "gdev", @@ -1910,13 +2167,13 @@ "list": [] }, "time": { - "from": "now-6h", - "to": "now" + "from": "2023-06-14T08:16:41.000Z", + "to": "2023-06-14T08:18:25.000Z" }, "timepicker": {}, "timezone": "", "title": "Panel Tests - Graph NG - Gaps and Connected", "uid": "8mmCAF1Mz", - "version": 1, + "version": 10, "weekStart": "" } diff --git a/packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.ts b/packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.ts index a4a71c1c190..9d58f0cde29 100644 --- a/packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.ts +++ b/packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.ts @@ -43,7 +43,7 @@ export function applyNullInsertThreshold(opts: NullInsertOptions): DataFrame { nullThresholdApplied: true, }; - const thresholds = frame.fields.map((field) => field.config.custom?.insertNulls ?? refField.config.interval ?? null); + const thresholds = frame.fields.map((field) => field.config.custom?.insertNulls || refField.config.interval || null); const uniqueThresholds = new Set(thresholds); diff --git a/public/app/plugins/panel/timeseries/InsertNullsEditor.tsx b/public/app/plugins/panel/timeseries/InsertNullsEditor.tsx new file mode 100644 index 00000000000..45115628499 --- /dev/null +++ b/public/app/plugins/panel/timeseries/InsertNullsEditor.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +import { FieldOverrideEditorProps, SelectableValue } from '@grafana/data'; +import { HorizontalGroup, RadioButtonGroup } from '@grafana/ui'; + +import { InputPrefix, NullsThresholdInput } from './NullsThresholdInput'; + +const DISCONNECT_OPTIONS: Array> = [ + { + label: 'Never', + value: false, + }, + { + label: 'Threshold', + value: 3600000, // 1h + }, +]; + +type Props = FieldOverrideEditorProps; + +export const InsertNullsEditor = ({ value, onChange }: Props) => { + const isThreshold = typeof value === 'number'; + DISCONNECT_OPTIONS[1].value = isThreshold ? value : 3600000; // 1h + + return ( + + + {isThreshold && } + + ); +}; diff --git a/public/app/plugins/panel/timeseries/NullsThresholdInput.tsx b/public/app/plugins/panel/timeseries/NullsThresholdInput.tsx new file mode 100644 index 00000000000..39797b3c25e --- /dev/null +++ b/public/app/plugins/panel/timeseries/NullsThresholdInput.tsx @@ -0,0 +1,57 @@ +import React from 'react'; + +import { rangeUtil } from '@grafana/data'; +import { Input } from '@grafana/ui'; + +export enum InputPrefix { + LessThan = 'lessthan', + GreaterThan = 'greaterthan', +} + +type Props = { value: number; onChange: (value?: number | boolean | undefined) => void; inputPrefix?: InputPrefix }; + +export const NullsThresholdInput = ({ value, onChange, inputPrefix }: Props) => { + const formattedTime = rangeUtil.secondsToHms(value / 1000); + const checkAndUpdate = (txt: string) => { + let val: boolean | number = false; + if (txt) { + try { + val = rangeUtil.intervalToMs(txt); + } catch (err) { + console.warn('ERROR', err); + } + } + onChange(val); + }; + + const handleEnterKey = (e: React.KeyboardEvent) => { + if (e.key !== 'Enter') { + return; + } + checkAndUpdate(e.currentTarget.value); + }; + + const handleBlur = (e: React.FocusEvent) => { + checkAndUpdate(e.currentTarget.value); + }; + + const prefix = + inputPrefix === InputPrefix.GreaterThan ? ( +
>
+ ) : inputPrefix === InputPrefix.LessThan ? ( +
<
+ ) : null; + + return ( + + ); +}; diff --git a/public/app/plugins/panel/timeseries/SpanNullsEditor.tsx b/public/app/plugins/panel/timeseries/SpanNullsEditor.tsx index bbf137d7411..ee80c9e8c34 100644 --- a/public/app/plugins/panel/timeseries/SpanNullsEditor.tsx +++ b/public/app/plugins/panel/timeseries/SpanNullsEditor.tsx @@ -1,7 +1,9 @@ import React from 'react'; -import { FieldOverrideEditorProps, rangeUtil, SelectableValue } from '@grafana/data'; -import { HorizontalGroup, Input, RadioButtonGroup } from '@grafana/ui'; +import { FieldOverrideEditorProps, SelectableValue } from '@grafana/data'; +import { HorizontalGroup, RadioButtonGroup } from '@grafana/ui'; + +import { InputPrefix, NullsThresholdInput } from './NullsThresholdInput'; const GAPS_OPTIONS: Array> = [ { @@ -22,47 +24,12 @@ type Props = FieldOverrideEditorProps; export const SpanNullsEditor = ({ value, onChange }: Props) => { const isThreshold = typeof value === 'number'; - const formattedTime = isThreshold ? rangeUtil.secondsToHms(value / 1000) : undefined; GAPS_OPTIONS[2].value = isThreshold ? value : 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) => { - if (e.key !== 'Enter') { - return; - } - checkAndUpdate(e.currentTarget.value); - }; - - const handleBlur = (e: React.FocusEvent) => { - checkAndUpdate(e.currentTarget.value); - }; - return ( - {isThreshold && ( - <} - spellCheck={false} - /> - )} + {isThreshold && } ); }; diff --git a/public/app/plugins/panel/timeseries/config.ts b/public/app/plugins/panel/timeseries/config.ts index 97803a7e71e..08e039d5b60 100644 --- a/public/app/plugins/panel/timeseries/config.ts +++ b/public/app/plugins/panel/timeseries/config.ts @@ -20,6 +20,7 @@ import { } from '@grafana/schema'; import { graphFieldOptions, commonOptionsBuilder } from '@grafana/ui'; +import { InsertNullsEditor } from './InsertNullsEditor'; import { LineStyleEditor } from './LineStyleEditor'; import { SpanNullsEditor } from './SpanNullsEditor'; import { ThresholdsStyleEditor } from './ThresholdsStyleEditor'; @@ -74,7 +75,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption settings: { options: graphFieldOptions.lineInterpolation, }, - showIf: (c) => c.drawStyle === GraphDrawStyle.Line, + showIf: (config) => config.drawStyle === GraphDrawStyle.Line, }) .addRadio({ path: 'barAlignment', @@ -84,7 +85,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption settings: { options: graphFieldOptions.barAlignment, }, - showIf: (c) => c.drawStyle === GraphDrawStyle.Bars, + showIf: (config) => config.drawStyle === GraphDrawStyle.Bars, }) .addSliderInput({ path: 'lineWidth', @@ -97,7 +98,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption step: 1, ariaLabelForHandle: 'Line width', }, - showIf: (c) => c.drawStyle !== GraphDrawStyle.Points, + showIf: (config) => config.drawStyle !== GraphDrawStyle.Points, }) .addSliderInput({ path: 'fillOpacity', @@ -110,7 +111,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption step: 1, ariaLabelForHandle: 'Fill opacity', }, - showIf: (c) => c.drawStyle !== GraphDrawStyle.Points, + showIf: (config) => config.drawStyle !== GraphDrawStyle.Points, }) .addRadio({ path: 'gradientMode', @@ -120,7 +121,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption settings: { options: graphFieldOptions.fillGradient, }, - showIf: (c) => c.drawStyle !== GraphDrawStyle.Points, + showIf: (config) => config.drawStyle !== GraphDrawStyle.Points, }) .addFieldNamePicker({ path: 'fillBelowTo', @@ -136,11 +137,11 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption path: 'lineStyle', name: 'Line style', category: categoryStyles, - showIf: (c) => c.drawStyle === GraphDrawStyle.Line, + showIf: (config) => config.drawStyle === GraphDrawStyle.Line, editor: LineStyleEditor, override: LineStyleEditor, process: identityOverrideProcessor, - shouldApply: (f) => f.type === FieldType.number, + shouldApply: (field) => field.type === FieldType.number, }) .addCustomEditor({ id: 'spanNulls', @@ -150,8 +151,20 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption defaultValue: false, editor: SpanNullsEditor, override: SpanNullsEditor, - showIf: (c) => c.drawStyle === GraphDrawStyle.Line, - shouldApply: (f) => f.type !== FieldType.time, + showIf: (config) => config.drawStyle === GraphDrawStyle.Line, + shouldApply: (field) => field.type !== FieldType.time, + process: identityOverrideProcessor, + }) + .addCustomEditor({ + id: 'insertNulls', + path: 'insertNulls', + name: 'Disconnect values', + category: categoryStyles, + defaultValue: false, + editor: InsertNullsEditor, + override: InsertNullsEditor, + showIf: (config) => config.drawStyle === GraphDrawStyle.Line, + shouldApply: (field) => field.type !== FieldType.time, process: identityOverrideProcessor, }) .addRadio({ @@ -162,7 +175,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption settings: { options: graphFieldOptions.showPoints, }, - showIf: (c) => c.drawStyle !== GraphDrawStyle.Points, + showIf: (config) => config.drawStyle !== GraphDrawStyle.Points, }) .addSliderInput({ path: 'pointSize', @@ -175,7 +188,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption step: 1, ariaLabelForHandle: 'Point size', }, - showIf: (c) => c.showPoints !== VisibilityMode.Never || c.drawStyle === GraphDrawStyle.Points, + showIf: (config) => config.showPoints !== VisibilityMode.Never || config.drawStyle === GraphDrawStyle.Points, }); commonOptionsBuilder.addStackingConfig(builder, cfg.stacking, categoryStyles);