Explorar o código

fix(dashboard): time regions spanning across midnight (#16201)

Fixes #14590
Marcus Efraimsson %!s(int64=6) %!d(string=hai) anos
pai
achega
6c9b9b360a

+ 99 - 30
devenv/dev-dashboards/panel_tests_graph_time_regions.json

@@ -463,15 +463,105 @@
         "align": false,
         "alignLevel": null
       }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-testdata",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 32
+      },
+      "id": 7,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "percentage": false,
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "refId": "A",
+          "scenarioId": "random_walk"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [
+        {
+          "colorMode": "gray",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.12)",
+          "from": "22:00",
+          "line": false,
+          "lineColor": "rgba(237, 46, 24, 0.60)",
+          "op": "time",
+          "to": "00:30"
+        }
+      ],
+      "timeShift": null,
+      "title": "From 22:00 to 00:30 (crossing midnight)",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
     }
   ],
   "refresh": false,
-  "schemaVersion": 16,
+  "schemaVersion": 18,
   "style": "dark",
-  "tags": [
-    "gdev",
-    "panel-tests"
-  ],
+  "tags": ["gdev", "panel-tests"],
   "templating": {
     "list": []
   },
@@ -480,32 +570,11 @@
     "to": "now"
   },
   "timepicker": {
-    "refresh_intervals": [
-      "5s",
-      "10s",
-      "30s",
-      "1m",
-      "5m",
-      "15m",
-      "30m",
-      "1h",
-      "2h",
-      "1d"
-    ],
-    "time_options": [
-      "5m",
-      "15m",
-      "1h",
-      "6h",
-      "12h",
-      "24h",
-      "2d",
-      "7d",
-      "30d"
-    ]
+    "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
+    "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
   },
   "timezone": "browser",
   "title": "Panel Tests - Graph (Time Regions)",
   "uid": "XMjIZPmik",
-  "version": 1
-}
+  "version": 9
+}

+ 27 - 0
public/app/plugins/panel/graph/specs/time_region_manager.test.ts

@@ -176,6 +176,33 @@ describe('TimeRegionManager', () => {
       });
     });
 
+    plotOptionsScenario('for time from/to region crossing midnight', ctx => {
+      const regions = [{ from: '22:00', to: '00:30', fill: true, colorMode: 'red' }];
+      const from = moment('2018-12-01T12:00+01:00');
+      const to = moment('2018-12-04T08:00+01:00');
+      ctx.setup(regions, from, to);
+
+      it('should add 3 markings', () => {
+        expect(ctx.options.grid.markings.length).toBe(3);
+      });
+
+      it('should add one fill between 22:00 and 00:30 each day', () => {
+        const markings = ctx.options.grid.markings;
+
+        expect(moment(markings[0].xaxis.from).format()).toBe(moment('2018-12-01T23:00:00+01:00').format());
+        expect(moment(markings[0].xaxis.to).format()).toBe(moment('2018-12-02T01:30:00+01:00').format());
+        expect(markings[0].color).toBe(colorModes.red.color.fill);
+
+        expect(moment(markings[1].xaxis.from).format()).toBe(moment('2018-12-02T23:00:00+01:00').format());
+        expect(moment(markings[1].xaxis.to).format()).toBe(moment('2018-12-03T01:30:00+01:00').format());
+        expect(markings[1].color).toBe(colorModes.red.color.fill);
+
+        expect(moment(markings[2].xaxis.from).format()).toBe(moment('2018-12-03T23:00:00+01:00').format());
+        expect(moment(markings[2].xaxis.to).format()).toBe(moment('2018-12-04T01:30:00+01:00').format());
+        expect(markings[2].color).toBe(colorModes.red.color.fill);
+      });
+    });
+
     plotOptionsScenario('for day of week from/to region', ctx => {
       const regions = [{ fromDayOfWeek: 7, toDayOfWeek: 7, fill: true, colorMode: 'red' }];
       const from = moment('2018-01-01T18:45:05+01:00');

+ 39 - 54
public/app/plugins/panel/graph/time_region_manager.ts

@@ -143,70 +143,55 @@ export class TimeRegionManager {
 
       regions = [];
 
-      if (
-        hRange.from.h >= tRange.from.hour() &&
-        hRange.from.h <= tRange.from.hour() &&
-        hRange.from.m >= tRange.from.minute() &&
-        hRange.from.m <= tRange.from.minute() &&
-        hRange.to.h >= tRange.to.hour() &&
-        hRange.to.h <= tRange.to.hour() &&
-        hRange.to.m >= tRange.to.minute() &&
-        hRange.to.m <= tRange.to.minute()
-      ) {
-        regions.push({ from: tRange.from.valueOf(), to: tRange.to.startOf('hour').valueOf() });
-      } else {
-        fromStart = moment(tRange.from);
-        fromStart.set('hour', 0);
-        fromStart.set('minute', 0);
-        fromStart.set('second', 0);
-        fromStart.add(hRange.from.h, 'hours');
-        fromStart.add(hRange.from.m, 'minutes');
-        fromStart.add(hRange.from.s, 'seconds');
-
-        while (fromStart.unix() <= tRange.to.unix()) {
-          while (hRange.from.dayOfWeek && hRange.from.dayOfWeek !== fromStart.isoWeekday()) {
-            fromStart.add(24, 'hours');
-          }
-
-          if (fromStart.unix() > tRange.to.unix()) {
-            break;
-          }
-
-          fromEnd = moment(fromStart);
+      fromStart = moment(tRange.from);
+      fromStart.set('hour', 0);
+      fromStart.set('minute', 0);
+      fromStart.set('second', 0);
+      fromStart.add(hRange.from.h, 'hours');
+      fromStart.add(hRange.from.m, 'minutes');
+      fromStart.add(hRange.from.s, 'seconds');
+
+      while (fromStart.unix() <= tRange.to.unix()) {
+        while (hRange.from.dayOfWeek && hRange.from.dayOfWeek !== fromStart.isoWeekday()) {
+          fromStart.add(24, 'hours');
+        }
 
-          if (hRange.from.h <= hRange.to.h) {
-            fromEnd.add(hRange.to.h - hRange.from.h, 'hours');
-          } else if (hRange.from.h + hRange.to.h < 23) {
-            fromEnd.add(hRange.to.h, 'hours');
+        if (fromStart.unix() > tRange.to.unix()) {
+          break;
+        }
 
-            while (fromEnd.hour() !== hRange.to.h) {
-              fromEnd.add(-1, 'hours');
-            }
-          } else {
-            fromEnd.add(24 - hRange.from.h, 'hours');
+        fromEnd = moment(fromStart);
 
-            while (fromEnd.hour() !== hRange.to.h) {
-              fromEnd.add(1, 'hours');
-            }
+        if (hRange.from.h <= hRange.to.h) {
+          fromEnd.add(hRange.to.h - hRange.from.h, 'hours');
+        } else if (hRange.from.h > hRange.to.h) {
+          while (fromEnd.hour() !== hRange.to.h) {
+            fromEnd.add(1, 'hours');
           }
+        } else {
+          fromEnd.add(24 - hRange.from.h, 'hours');
 
-          fromEnd.set('minute', hRange.to.m);
-          fromEnd.set('second', hRange.to.s);
-
-          while (hRange.to.dayOfWeek && hRange.to.dayOfWeek !== fromEnd.isoWeekday()) {
-            fromEnd.add(24, 'hours');
+          while (fromEnd.hour() !== hRange.to.h) {
+            fromEnd.add(1, 'hours');
           }
+        }
 
-          const outsideRange =
-            (fromStart.unix() < tRange.from.unix() && fromEnd.unix() < tRange.from.unix()) ||
-            (fromStart.unix() > tRange.to.unix() && fromEnd.unix() > tRange.to.unix());
+        fromEnd.set('minute', hRange.to.m);
+        fromEnd.set('second', hRange.to.s);
 
-          if (!outsideRange) {
-            regions.push({ from: fromStart.valueOf(), to: fromEnd.valueOf() });
-          }
+        while (hRange.to.dayOfWeek && hRange.to.dayOfWeek !== fromEnd.isoWeekday()) {
+          fromEnd.add(24, 'hours');
+        }
 
-          fromStart.add(24, 'hours');
+        const outsideRange =
+          (fromStart.unix() < tRange.from.unix() && fromEnd.unix() < tRange.from.unix()) ||
+          (fromStart.unix() > tRange.to.unix() && fromEnd.unix() > tRange.to.unix());
+
+        if (!outsideRange) {
+          regions.push({ from: fromStart.valueOf(), to: fromEnd.valueOf() });
         }
+
+        fromStart.add(24, 'hours');
       }
 
       timeRegionColor = getColor(timeRegion, this.theme);