Quellcode durchsuchen

progess on adding annotations

Torkel Ödegaard vor 8 Jahren
Ursprung
Commit
a151de1d37

+ 3 - 2
public/app/features/annotations/all.ts

@@ -1,8 +1,9 @@
 
 import {AnnotationsSrv} from './annotations_srv';
-import {eventEditor} from './event_editor';
+import {eventEditor, EventManager} from './event_editor';
 
 export {
   AnnotationsSrv,
-  eventEditor
+  eventEditor,
+  EventManager
 };

+ 73 - 16
public/app/features/annotations/event_editor.ts

@@ -17,22 +17,15 @@ export class AnnotationEvent {
 
 export class EventEditorCtrl {
   panelCtrl: MetricsPanelCtrl;
-  annotation: AnnotationEvent;
+  event: AnnotationEvent;
   timeRange: {from: number, to: number};
   form: any;
   close: any;
 
   /** @ngInject **/
   constructor(private annotationsSrv) {
-    this.annotation = new AnnotationEvent();
-    this.annotation.panelId = this.panelCtrl.panel.id;
-    this.annotation.dashboardId = this.panelCtrl.dashboard.id;
-
-    this.annotation.time = moment(this.timeRange.from);
-    if (this.timeRange.to) {
-      this.annotation.timeEnd = moment(this.timeRange.to);
-      this.annotation.isRegion = true;
-    }
+    this.event.panelId = this.panelCtrl.panel.id;
+    this.event.dashboardId = this.panelCtrl.dashboard.id;
   }
 
   save() {
@@ -40,15 +33,17 @@ export class EventEditorCtrl {
       return;
     }
 
-    let saveModel = _.cloneDeep(this.annotation);
+    let saveModel = _.cloneDeep(this.event);
     saveModel.time = saveModel.time.valueOf();
+    saveModel.timeEnd = 0;
+
     if (saveModel.isRegion) {
       saveModel.timeEnd = saveModel.timeEnd.valueOf();
-    }
 
-    if (saveModel.timeEnd < saveModel.time) {
-      console.log('invalid time');
-      return;
+      if (saveModel.timeEnd < saveModel.time) {
+        console.log('invalid time');
+        return;
+      }
     }
 
     this.annotationsSrv.saveAnnotationEvent(saveModel).then(() => {
@@ -56,6 +51,10 @@ export class EventEditorCtrl {
       this.close();
     });
   }
+
+  timeChanged() {
+    this.panelCtrl.render();
+  }
 }
 
 export function eventEditor() {
@@ -67,10 +66,68 @@ export function eventEditor() {
     templateUrl: 'public/app/features/annotations/partials/event_editor.html',
     scope: {
       "panelCtrl": "=",
-      "timeRange": "=",
+      "event": "=",
       "close": "&",
     }
   };
 }
 
 coreModule.directive('eventEditor', eventEditor);
+
+export class EventManager {
+  event: AnnotationEvent;
+
+  constructor(private panelCtrl: MetricsPanelCtrl,
+              private elem,
+              private popoverSrv) {
+              }
+
+              editorClosed() {
+                console.log('editorClosed');
+                this.event = null;
+                this.panelCtrl.render();
+              }
+
+              updateTime(range) {
+                let newEvent = true;
+
+                if (this.event) {
+                  newEvent = false;
+                } else {
+                  // init new event
+                  this.event = new AnnotationEvent();
+                  this.event.dashboardId = this.panelCtrl.dashboard.id;
+                  this.event.panelId = this.panelCtrl.panel.id;
+                }
+
+                // update time
+                this.event.time = moment(range.from);
+                this.event.isRegion = false;
+                if (range.to) {
+                  this.event.timeEnd = moment(range.to);
+                  this.event.isRegion = true;
+                }
+
+                // newEvent means the editor is not visible
+                if (!newEvent) {
+                  this.panelCtrl.render();
+                  return;
+                }
+
+                this.popoverSrv.show({
+                  element: this.elem[0],
+                  classNames: 'drop-popover drop-popover--form',
+                  position: 'bottom center',
+                  openOn: null,
+                  template: '<event-editor panel-ctrl="panelCtrl" event="event" close="dismiss()"></event-editor>',
+                  onClose: this.editorClosed.bind(this),
+                  model: {
+                    event: this.event,
+                    panelCtrl: this.panelCtrl,
+                  },
+                });
+
+                this.panelCtrl.render();
+              }
+}
+

+ 7 - 7
public/app/features/annotations/partials/event_editor.html

@@ -5,29 +5,29 @@
 	<div style="display: inline-block">
 		<div class="gf-form">
 			<span class="gf-form-label width-7">Title</span>
-			<input type="text" ng-model="ctrl.annotation.title" class="gf-form-input max-width-20" required>
+			<input type="text" ng-model="ctrl.event.title" class="gf-form-input max-width-20" required>
 		</div>
 		<!-- single event -->
-		<div ng-if="!ctrl.annotation.isRegion">
+		<div ng-if="!ctrl.event.isRegion">
       <div class="gf-form">
         <span class="gf-form-label width-7">Time</span>
-        <input type="text" ng-model="ctrl.annotation.time" class="gf-form-input max-width-20" input-datetime required>
+        <input type="text" ng-model="ctrl.event.time" class="gf-form-input max-width-20" input-datetime required ng-change="ctrl.timeChanged()">
       </div>
     </div>
     <!-- region event -->
-    <div ng-if="ctrl.annotation.isRegion">
+    <div ng-if="ctrl.event.isRegion">
       <div class="gf-form">
         <span class="gf-form-label width-7">Start</span>
-        <input type="text" ng-model="ctrl.annotation.time" class="gf-form-input max-width-20" input-datetime required>
+        <input type="text" ng-model="ctrl.event.time" class="gf-form-input max-width-20" input-datetime required ng-change="ctrl.timeChanged()">
       </div>
       <div class="gf-form">
         <span class="gf-form-label width-7">End</span>
-        <input type="text" ng-model="ctrl.annotation.timeEnd" class="gf-form-input max-width-20" input-datetime required>
+        <input type="text" ng-model="ctrl.event.timeEnd" class="gf-form-input max-width-20" input-datetime required ng-change="ctrl.timeChanged()">
       </div>
     </div>
     <div class="gf-form gf-form--v-stretch">
       <span class="gf-form-label width-7">Description</span>
-      <textarea class="gf-form-input width-20" rows="3" ng-model="ctrl.annotation.text"  placeholder="Event description"></textarea>
+      <textarea class="gf-form-input width-20" rows="3" ng-model="ctrl.event.text"  placeholder="Event description"></textarea>
     </div>
 
     <div class="gf-form-button-row">

+ 52 - 40
public/app/plugins/panel/graph/graph.ts

@@ -17,6 +17,7 @@ import {tickStep} from 'app/core/utils/ticks';
 import {appEvents, coreModule} from 'app/core/core';
 import GraphTooltip from './graph_tooltip';
 import {ThresholdManager} from './threshold_manager';
+import {EventManager} from 'app/features/annotations/all';
 import {convertValuesToHistogram, getSeriesValues} from './histogram';
 
 coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
@@ -27,13 +28,14 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
       var ctrl = scope.ctrl;
       var dashboard = ctrl.dashboard;
       var panel = ctrl.panel;
+      var annotations = [];
       var data;
-      var annotations;
       var plot;
       var sortedSeries;
       var legendSideLastValue = null;
       var rootScope = scope.$root;
       var panelWidth = 0;
+      var eventManager = new EventManager(ctrl, elem, popoverSrv);
       var thresholdManager = new ThresholdManager(ctrl);
       var tooltip = new GraphTooltip(elem, dashboard, scope, function() {
         return sortedSeries;
@@ -54,7 +56,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
         if (!data) {
           return;
         }
-        annotations = ctrl.annotations;
+        annotations = ctrl.annotations || [];
         render_panel();
       });
 
@@ -79,20 +81,6 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
         }
       }, scope);
 
-      function showAddAnnotationView(timeRange) {
-        popoverSrv.show({
-          element: elem[0],
-          classNames: 'drop-popover drop-popover--form',
-          position: 'bottom center',
-          openOn: 'click',
-          template: '<event-editor panel-ctrl="panelCtrl" time-range="timeRange" close="dismiss()"></event-editor>',
-          model: {
-            timeRange: timeRange,
-            panelCtrl: ctrl,
-          },
-        });
-      }
-
       function getLegendHeight(panelHeight) {
         if (!panel.legend.show || panel.legend.rightSide) {
           return 0;
@@ -343,7 +331,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
         }
 
         thresholdManager.addPlotOptions(options, panel);
-        addAnnotations(options);
+        addAnnotationEvents(options);
         configureAxisOptions(data, options);
 
         sortedSeries = _.sortBy(data, function(series) { return series.zindex; });
@@ -475,8 +463,12 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
         };
       }
 
-      function addAnnotations(options) {
-        if (!annotations || annotations.length === 0) {
+      function hasAnnotationEvents() {
+        return eventManager.event || annotations.length > 0 ;
+      }
+
+      function addAnnotationEvents(options) {
+        if (!hasAnnotationEvents()) {
           return;
         }
 
@@ -501,26 +493,41 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
 
         types['$__execution_error'] = ['$__no_data'];
 
-        for (var i = 0; i < annotations.length; i++) {
-          var item = annotations[i];
-          if (item.newState) {
-            console.log(item.newState);
-            item.eventType = '$__' + item.newState;
-            continue;
-          }
+        var annotationsToShow;
+        // adding/edditing event, only show that one
+        if (eventManager.event) {
+          const event = eventManager.event;
+          annotationsToShow = [
+            {
+              min: event.time.valueOf(),
+              title: event.title,
+              description: event.text,
+              eventType: '$__alerting',
+            }
+          ];
+        } else {
+          // annotations from query
+          for (var i = 0; i < annotations.length; i++) {
+            var item = annotations[i];
+            if (item.newState) {
+              item.eventType = '$__' + item.newState;
+              continue;
+            }
 
-          if (!types[item.source.name]) {
-            types[item.source.name] = {
-              color: item.source.iconColor,
-              position: 'BOTTOM',
-              markerSize: 5,
-            };
+            if (!types[item.source.name]) {
+              types[item.source.name] = {
+                color: item.source.iconColor,
+                position: 'BOTTOM',
+                markerSize: 5,
+              };
+            }
           }
+          annotationsToShow = annotations;
         }
 
         options.events = {
           levels: _.keys(types).length + 1,
-          data: annotations,
+          data: annotationsToShow,
           types: types,
         };
       }
@@ -653,8 +660,10 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
       }
 
       elem.bind("plotselected", function (event, ranges) {
-        if (ranges.ctrlKey || ranges.metaKey) {
-          showAddAnnotationView(ranges.xaxis);
+        if (ranges.ctrlKey || ranges.metaKey)  {
+          scope.$apply(() => {
+            eventManager.updateTime(ranges.xaxis);
+          });
         } else {
           scope.$apply(function() {
             timeSrv.setTime({
@@ -666,11 +675,14 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
       });
 
       elem.bind("plotclick", function (event, pos, item) {
-        // Skip if range selected (added in "plotselected" event handler)
-        let isRangeSelection = pos.x !== pos.x1;
-        let createAnnotation = !isRangeSelection && (pos.ctrlKey || pos.metaKey);
-        if (createAnnotation) {
-          showAddAnnotationView({from: pos.x, to: null});
+        if (pos.ctrlKey || pos.metaKey || eventManager.event)  {
+          // Skip if range selected (added in "plotselected" event handler)
+          let isRangeSelection = pos.x !== pos.x1;
+          if (!isRangeSelection) {
+            scope.$apply(() => {
+              eventManager.updateTime({from: pos.x, to: null});
+            });
+          }
         }
       });