diff --git a/pkg/services/sqlstore/migrations/annotation_category_mig.go b/pkg/services/sqlstore/migrations/annotation_category_mig.go new file mode 100644 index 00000000000..331aeea2500 --- /dev/null +++ b/pkg/services/sqlstore/migrations/annotation_category_mig.go @@ -0,0 +1,26 @@ +package migrations + +import ( + . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" +) + +func addAnnotationCategoryMig(mg *Migrator) { + category := Table{ + Name: "annotation_category", + Columns: []*Column{ + {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "org_id", Type: DB_BigInt, Nullable: false}, + {Name: "user_id", Type: DB_BigInt, Nullable: true}, + {Name: "name", Type: DB_Text, Nullable: false}, + }, + Indices: []*Index{ + {Cols: []string{"org_id", "name"}, Type: IndexType}, + }, + } + + // create table + mg.AddMigration("create annotation_category table", NewAddTableMigration(category)) + + // create indices + mg.AddMigration("add index org_id & name", NewAddIndexMigration(category, category.Indices[0])) +} diff --git a/pkg/services/sqlstore/migrations/migrations.go b/pkg/services/sqlstore/migrations/migrations.go index 163c6d762a8..e9e20fb190c 100644 --- a/pkg/services/sqlstore/migrations/migrations.go +++ b/pkg/services/sqlstore/migrations/migrations.go @@ -26,6 +26,7 @@ func AddMigrations(mg *Migrator) { addAnnotationMig(mg) addStatsMigrations(mg) addTestDataMigrations(mg) + // addAnnotationCategoryMig(mg) } func addMigrationLogMigrations(mg *Migrator) { diff --git a/public/app/features/all.js b/public/app/features/all.js index cd7adb49de6..96c28288e8e 100644 --- a/public/app/features/all.js +++ b/public/app/features/all.js @@ -1,7 +1,7 @@ define([ './panellinks/module', './dashlinks/module', - './annotations/annotations_srv', + './annotations/all', './templating/all', './dashboard/all', './playlist/all', diff --git a/public/app/features/annotations/all.ts b/public/app/features/annotations/all.ts new file mode 100644 index 00000000000..0be292a7fa1 --- /dev/null +++ b/public/app/features/annotations/all.ts @@ -0,0 +1,8 @@ + +import {AnnotationsSrv} from './annotations_srv'; +import {eventEditor} from './event_editor'; + +export { + AnnotationsSrv, + eventEditor +}; diff --git a/public/app/features/annotations/annotations_srv.ts b/public/app/features/annotations/annotations_srv.ts index 86c984b78dd..6ba70ea92f8 100644 --- a/public/app/features/annotations/annotations_srv.ts +++ b/public/app/features/annotations/annotations_srv.ts @@ -60,7 +60,7 @@ export class AnnotationsSrv { var panel = options.panel; var dashboard = options.dashboard; - if (panel && panel.alert) { + if (panel) { return this.backendSrv.get('/api/annotations', { from: options.range.from.valueOf(), to: options.range.to.valueOf(), @@ -133,10 +133,8 @@ export class AnnotationsSrv { return this.globalAnnotationsPromise; } - postAnnotation(annotations) { - return Promise.all(_.map(annotations, annotation => { - return this.backendSrv.post('/api/annotations', annotation); - })); + postAnnotation(annotation) { + return this.backendSrv.post('/api/annotations', annotation); } translateQueryResult(annotation, results) { diff --git a/public/app/features/annotations/event_editor.ts b/public/app/features/annotations/event_editor.ts new file mode 100644 index 00000000000..83aaf595923 --- /dev/null +++ b/public/app/features/annotations/event_editor.ts @@ -0,0 +1,60 @@ +/// + +import _ from 'lodash'; +import moment from 'moment'; +import coreModule from 'app/core/core_module'; +import {MetricsPanelCtrl} from 'app/plugins/sdk'; + +export class AnnotationItem { + dashboardId: number; + panelId: number; + time: Date; + timeEnd: Date; + isRegion: boolean; + title: string; + text: string; +} + +export class EventEditorCtrl { + panelCtrl: MetricsPanelCtrl; + timeFormat = 'YYYY-MM-DD HH:mm:ss'; + annotation: AnnotationItem; + timeRange: {from: number, to: number}; + form: any; + + /** @ngInject **/ + constructor() { + this.annotation = new AnnotationItem(); + this.annotation.panelId = this.panelCtrl.panel.id; + this.annotation.dashboardId = this.panelCtrl.dashboard.id; + this.annotation.text = "hello"; + + this.annotation.time = moment(this.timeRange.from); + if (this.timeRange.to) { + this.annotation.timeEnd = moment(this.timeRange.to); + this.annotation.isRegion = true; + } + } + + save() { + if (!this.form.$valid) { + return; + } + } +} + +export function eventEditor() { + return { + restrict: 'E', + controller: EventEditorCtrl, + bindToController: true, + controllerAs: 'ctrl', + templateUrl: 'public/app/features/annotations/partials/event_editor.html', + scope: { + "panelCtrl": "=", + "timeRange": "=" + } + }; +} + +coreModule.directive('eventEditor', eventEditor); diff --git a/public/app/features/annotations/partials/event_editor.html b/public/app/features/annotations/partials/event_editor.html new file mode 100644 index 00000000000..a99e1374e82 --- /dev/null +++ b/public/app/features/annotations/partials/event_editor.html @@ -0,0 +1,39 @@ + +
Add annotation
+ +
+
+
+ Title + +
+ +
+
+
+ Time + +
+
+
+ +
+
+ Start + +
+
+ End + +
+
+
+ Description + +
+ +
+ +
+
+
diff --git a/public/app/features/dashboard/addAnnotationModalCtrl.ts b/public/app/features/dashboard/addAnnotationModalCtrl.ts index 789d24bdbee..02b6462c0ed 100644 --- a/public/app/features/dashboard/addAnnotationModalCtrl.ts +++ b/public/app/features/dashboard/addAnnotationModalCtrl.ts @@ -4,12 +4,8 @@ import angular from 'angular'; import moment from 'moment'; export class AddAnnotationModalCtrl { - annotationTimeFormat = 'YYYY-MM-DD HH:mm:ss'; - annotationTimeFrom: any; - annotationTimeTo: any = null; - annotationTitle: string; - annotationTextFrom: string; - annotationTextTo: string; + timeFormat = 'YYYY-MM-DD HH:mm:ss'; + annotation: any; graphCtrl: any; /** @ngInject */ @@ -17,41 +13,31 @@ export class AddAnnotationModalCtrl { this.graphCtrl = $scope.ctrl; $scope.ctrl = this; - this.annotationTimeFrom = moment($scope.annotationTimeRange.from).format(this.annotationTimeFormat); + let dashboardId = this.graphCtrl.dashboard.id; + let panelId = this.graphCtrl.panel.id; + this.annotation = { + dashboardId: dashboardId, + panelId: panelId, + time: null, + timeTo: null, + title: "", + text: "" + }; + + this.annotation.time = moment($scope.annotationTimeRange.from).format(this.timeFormat);0 if ($scope.annotationTimeRange.to) { - this.annotationTimeTo = moment($scope.annotationTimeRange.to).format(this.annotationTimeFormat); + this.annotation.timeTo = moment($scope.annotationTimeRange.to).format(this.timeFormat); } } addAnnotation() { - let dashboardId = this.graphCtrl.dashboard.id; - let panelId = this.graphCtrl.panel.id; - let timeFrom = moment(this.annotationTimeFrom, this.annotationTimeFormat).valueOf(); - - let annotationFrom = { - dashboardId: dashboardId, - panelId: panelId, - time: timeFrom, - title: this.annotationTitle, - text: this.annotationTextFrom - }; - let annotations = [annotationFrom]; - - if (this.annotationTimeTo) { - let timeTo = moment(this.annotationTimeTo, this.annotationTimeFormat).valueOf(); - let annotationTo = { - dashboardId: dashboardId, - panelId: panelId, - time: timeTo, - title: this.annotationTitle, - text: this.annotationTextTo - }; - annotations.push(annotationTo); + this.annotation.time = moment(this.annotation.time, this.timeFormat).valueOf(); + if (this.annotation.timeTo) { + this.annotation.timeTo = moment(this.annotation.timeTo, this.timeFormat).valueOf(); } - this.graphCtrl.pushAnnotations(annotations) + this.graphCtrl.pushAnnotation(this.annotation) .then(response => { - console.log(response); this.close(); }) .catch(error => { diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js index 5a3d6ea5203..c3a71a11818 100644 --- a/public/app/features/dashboard/all.js +++ b/public/app/features/dashboard/all.js @@ -22,5 +22,4 @@ define([ './ad_hoc_filters', './row/row_ctrl', './repeat_option/repeat_option', - './event_editor', ], function () {}); diff --git a/public/app/features/dashboard/event_editor.ts b/public/app/features/dashboard/event_editor.ts deleted file mode 100644 index 35606a5ac73..00000000000 --- a/public/app/features/dashboard/event_editor.ts +++ /dev/null @@ -1,22 +0,0 @@ -/// - -import _ from 'lodash'; -import coreModule from 'app/core/core_module'; - -export class EventEditorCtrl { - /** @ngInject */ - constructor() { - } -} - -export function eventEditor() { - return { - restrict: 'E', - controller: EventEditorCtrl, - bindToController: true, - controllerAs: 'ctrl', - templateUrl: 'public/app/features/dashboard/partials/event_editor.html', - }; -} - -coreModule.directive('eventEditor', eventEditor); diff --git a/public/app/features/dashboard/partials/addAnnotationModal.html b/public/app/features/dashboard/partials/addAnnotationModal.html index 1ea3b7d7a6f..f55f888375f 100644 --- a/public/app/features/dashboard/partials/addAnnotationModal.html +++ b/public/app/features/dashboard/partials/addAnnotationModal.html @@ -28,38 +28,25 @@
Title - +
- Time - Time Start - + Time + Time Start +
-
+
Time Stop - +
-
Description
-
Description Start
+
Description
- - -
-
-
Description Stop
-
-
diff --git a/public/app/features/dashboard/partials/event_editor.html b/public/app/features/dashboard/partials/event_editor.html deleted file mode 100644 index 9d8d84bbee1..00000000000 --- a/public/app/features/dashboard/partials/event_editor.html +++ /dev/null @@ -1,27 +0,0 @@ - -
Create event
- -
-
-
- Title - -
-
- Time - -
-
- To - -
-
- Description - -
- -
- -
-
-
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 8eaf9d00b83..15de6cf3abc 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -79,29 +79,13 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) { } }, scope); - appEvents.on('graph-click', (event) => { - // Add event only for selected panel - let thisPanelEvent = event.panel.id === ctrl.panel.id; - - // Select time for new annotation - let createAnnotation = event.pos.ctrlKey || event.pos.metaKey; - if (createAnnotation && thisPanelEvent) { - let timeRange = { - from: event.pos.x, - to: null - }; - - showAddAnnotationView(timeRange); - } - }, scope); - function showAddAnnotationView(timeRange) { popoverSrv.show({ element: elem[0], classNames: 'drop-popover drop-popover--form', position: 'bottom center', openOn: 'click', - template: '', + template: '', model: { timeRange: timeRange, panelCtrl: ctrl, @@ -670,10 +654,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) { elem.bind("plotselected", function (event, ranges) { if (ranges.ctrlKey || ranges.metaKey) { - // Create new annotation from time range - let timeRange = ranges.xaxis; - showAddAnnotationView(timeRange); - //plot.clearSelection(); + showAddAnnotationView(ranges.xaxis); } else { scope.$apply(function() { timeSrv.setTime({ @@ -684,6 +665,15 @@ 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}); + } + }); + scope.$on('$destroy', function() { tooltip.destroy(); elem.off(); diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 5686ef2bfe8..aa2155f258b 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -306,21 +306,6 @@ class GraphCtrl extends MetricsPanelCtrl { alert('selection region while holding down CTRL or CMD'); } - // Get annotation info from dialog and push it to backend - pushAnnotations(annotations) { - return this.annotationsSrv.postAnnotation(annotations); - } - - showAddAnnotationModal(timeRange) { - let addAnnotationScope = this.$scope.$new(); - addAnnotationScope.annotationTimeRange = timeRange; - - this.publishAppEvent('show-modal', { - src: 'public/app/features/dashboard/partials/addAnnotationModal.html', - scope: addAnnotationScope - }); - } - legendValuesOptionChanged() { var legend = this.panel.legend; legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;