diff --git a/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html b/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html
index 1db00904c04..ad68312b727 100644
--- a/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html
+++ b/public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html
@@ -3,9 +3,11 @@
Index name
-
- Search query (lucene) Use [[filterName]] in query to replace part of the query with a filter value
-
+
+
+
+
@@ -33,4 +35,4 @@
-
\ No newline at end of file
+
diff --git a/public/app/plugins/datasource/grafana/partials/annotations.editor.html b/public/app/plugins/datasource/grafana/partials/annotations.editor.html
index 54e21ac902e..a1528a6d708 100644
--- a/public/app/plugins/datasource/grafana/partials/annotations.editor.html
+++ b/public/app/plugins/datasource/grafana/partials/annotations.editor.html
@@ -1,6 +1,5 @@
-
Filters
Type
diff --git a/public/app/plugins/datasource/graphite/partials/annotations.editor.html b/public/app/plugins/datasource/graphite/partials/annotations.editor.html
index 421f7c3f3e5..9d228b8e4f9 100644
--- a/public/app/plugins/datasource/graphite/partials/annotations.editor.html
+++ b/public/app/plugins/datasource/graphite/partials/annotations.editor.html
@@ -1,10 +1,13 @@
Column mappings If your influxdb query returns more than one column you need to specify the column names below. An annotation event is composed of a title, tags, and an additional text field.
+
Field mappings If your influxdb query returns more than one field you need to specify the column names below. An annotation event is composed of a title, tags, and an additional text field.
From d2f3d7d138bde58708c61bbd2932b61847f94085 Mon Sep 17 00:00:00 2001
From: Alexander Zobnin
Date: Wed, 12 Apr 2017 16:06:48 +0300
Subject: [PATCH 07/37] graph(add annotation): get alerts for all panels
---
public/app/features/annotations/annotations_srv.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/app/features/annotations/annotations_srv.ts b/public/app/features/annotations/annotations_srv.ts
index d3b83982f51..380cc93ead9 100644
--- a/public/app/features/annotations/annotations_srv.ts
+++ b/public/app/features/annotations/annotations_srv.ts
@@ -53,7 +53,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(),
From 0156a94a491886ee64440092f6ea648ea0cb3244 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torkel=20=C3=96degaard?=
Date: Wed, 12 Apr 2017 15:46:41 +0200
Subject: [PATCH 08/37] annotations: you can now read annoations via manually
created annoation query
---
pkg/api/annotations.go | 3 +++
pkg/api/api.go | 6 ++++--
pkg/api/dtos/annotations.go | 1 +
pkg/services/annotations/annotations.go | 1 +
public/app/features/annotations/annotations_srv.ts | 7 +++++++
public/app/features/dashboard/addAnnotationModalCtrl.ts | 1 -
.../datasource/grafana/partials/annotations.editor.html | 2 +-
public/app/plugins/panel/graph/graph.ts | 6 ++----
public/app/plugins/panel/graph/module.ts | 5 ++---
9 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go
index af72b9d3876..88e8c955497 100644
--- a/pkg/api/annotations.go
+++ b/pkg/api/annotations.go
@@ -39,6 +39,7 @@ func GetAnnotations(c *middleware.Context) Response {
Text: item.Text,
Metric: item.Metric,
Title: item.Title,
+ PanelId: item.PanelId,
})
}
@@ -55,6 +56,8 @@ func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response
Epoch: cmd.Time / 1000,
Title: cmd.Title,
Text: cmd.Text,
+ CategoryId: cmd.CategoryId,
+ Type: annotations.EventType,
}
err := repo.Save(&item)
diff --git a/pkg/api/api.go b/pkg/api/api.go
index 0b9a8acf851..6dcc900c16f 100644
--- a/pkg/api/api.go
+++ b/pkg/api/api.go
@@ -277,8 +277,10 @@ func (hs *HttpServer) registerRoutes() {
}, reqEditorRole)
r.Get("/annotations", wrap(GetAnnotations))
- r.Post("/annotations", bind(dtos.PostAnnotationsCmd{}), wrap(PostAnnotation))
- r.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), wrap(DeleteAnnotations))
+
+ r.Group("/annotations", func() {
+ r.Post("/", bind(dtos.PostAnnotationsCmd{}), wrap(PostAnnotation))
+ }, reqEditorRole)
// error test
r.Get("/metrics/error", wrap(GenerateError))
diff --git a/pkg/api/dtos/annotations.go b/pkg/api/dtos/annotations.go
index cd8c0c1d523..28e048db3ec 100644
--- a/pkg/api/dtos/annotations.go
+++ b/pkg/api/dtos/annotations.go
@@ -19,6 +19,7 @@ type Annotation struct {
type PostAnnotationsCmd struct {
DashboardId int64 `json:"dashboardId"`
PanelId int64 `json:"panelId"`
+ CategoryId int64 `json:"categoryId"`
Time int64 `json:"time"`
Title string `json:"title"`
Text string `json:"text"`
diff --git a/pkg/services/annotations/annotations.go b/pkg/services/annotations/annotations.go
index a308f546c8a..a3b4eacc0c3 100644
--- a/pkg/services/annotations/annotations.go
+++ b/pkg/services/annotations/annotations.go
@@ -49,6 +49,7 @@ type ItemType string
const (
AlertType ItemType = "alert"
+ EventType ItemType = "event"
)
type Item struct {
diff --git a/public/app/features/annotations/annotations_srv.ts b/public/app/features/annotations/annotations_srv.ts
index d3b83982f51..691153b197b 100644
--- a/public/app/features/annotations/annotations_srv.ts
+++ b/public/app/features/annotations/annotations_srv.ts
@@ -35,6 +35,13 @@ export class AnnotationsSrv {
// combine the annotations and flatten results
var annotations = _.flattenDeep([results[0], results[1]]);
+ // filter out annotations that do not belong to requesting panel
+ annotations = _.filter(annotations, item => {
+ if (item.panelId && options.panel.id !== item.panelId) {
+ return false;
+ }
+ return true;
+ });
// look for alert state for this panel
var alertState = _.find(results[2], {panelId: options.panel.id});
diff --git a/public/app/features/dashboard/addAnnotationModalCtrl.ts b/public/app/features/dashboard/addAnnotationModalCtrl.ts
index 7c3962074cf..789d24bdbee 100644
--- a/public/app/features/dashboard/addAnnotationModalCtrl.ts
+++ b/public/app/features/dashboard/addAnnotationModalCtrl.ts
@@ -61,7 +61,6 @@ export class AddAnnotationModalCtrl {
}
close() {
- this.graphCtrl.inAddAnnotationMode = false;
this.$scope.dismiss();
}
}
diff --git a/public/app/plugins/datasource/grafana/partials/annotations.editor.html b/public/app/plugins/datasource/grafana/partials/annotations.editor.html
index a1528a6d708..24a06a2abd6 100644
--- a/public/app/plugins/datasource/grafana/partials/annotations.editor.html
+++ b/public/app/plugins/datasource/grafana/partials/annotations.editor.html
@@ -4,7 +4,7 @@
Type
-
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts
index 7ae1b19ca21..4d68e10bbc0 100755
--- a/public/app/plugins/panel/graph/graph.ts
+++ b/public/app/plugins/panel/graph/graph.ts
@@ -84,7 +84,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
let thisPanelEvent = event.panel.id === ctrl.panel.id;
// Select time for new annotation
- let createAnnotation = ctrl.inAddAnnotationMode || event.pos.ctrlKey || event.pos.metaKey;
+ let createAnnotation = event.pos.ctrlKey || event.pos.metaKey;
if (createAnnotation && thisPanelEvent) {
let timeRange = {
from: event.pos.x,
@@ -92,7 +92,6 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
};
ctrl.showAddAnnotationModal(timeRange);
- ctrl.inAddAnnotationMode = false;
}
}, scope);
@@ -656,12 +655,11 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
}
elem.bind("plotselected", function (event, ranges) {
- if (ctrl.inAddAnnotationMode || ranges.ctrlKey || ranges.metaKey) {
+ if (ranges.ctrlKey || ranges.metaKey) {
// Create new annotation from time range
let timeRange = ranges.xaxis;
ctrl.showAddAnnotationModal(timeRange);
plot.clearSelection();
- ctrl.inAddAnnotationMode = false;
} else {
scope.$apply(function() {
timeSrv.setTime({
diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts
index 5a24f39cf80..5686ef2bfe8 100644
--- a/public/app/plugins/panel/graph/module.ts
+++ b/public/app/plugins/panel/graph/module.ts
@@ -24,7 +24,6 @@ class GraphCtrl extends MetricsPanelCtrl {
dataList: any = [];
annotations: any = [];
alertState: any;
- inAddAnnotationMode = false;
annotationsPromise: any;
dataWarning: any;
@@ -303,8 +302,8 @@ class GraphCtrl extends MetricsPanelCtrl {
}
enableAddAnnotationMode() {
- // TODO: notify user about time selection mode
- this.inAddAnnotationMode = true;
+ // placehoder for some other way to teach users
+ alert('selection region while holding down CTRL or CMD');
}
// Get annotation info from dialog and push it to backend
From b867921b3b533b847725463891d141278e89c49d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torkel=20=C3=96degaard?=
Date: Wed, 12 Apr 2017 15:49:59 +0200
Subject: [PATCH 09/37] annotation: cleanup
---
.../app/features/annotations/annotations_srv.ts | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/public/app/features/annotations/annotations_srv.ts b/public/app/features/annotations/annotations_srv.ts
index 691153b197b..86c984b78dd 100644
--- a/public/app/features/annotations/annotations_srv.ts
+++ b/public/app/features/annotations/annotations_srv.ts
@@ -134,20 +134,9 @@ export class AnnotationsSrv {
}
postAnnotation(annotations) {
- console.log("POST /api/annotations\n", annotations);
-
- // Not implemented yet
- let implemented = true;
- if (implemented) {
- return Promise.all(_.map(annotations, annotation => {
- return this.backendSrv.post('/api/annotations', annotation);
- }))
- .catch(error => {
- console.log(error);
- });
- } else {
- return Promise.resolve("Not implemented");
- }
+ return Promise.all(_.map(annotations, annotation => {
+ return this.backendSrv.post('/api/annotations', annotation);
+ }));
}
translateQueryResult(annotation, results) {
From 593b2ef866e96bfaa8c2db568de234a2e38d70cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torkel=20=C3=96degaard?=
Date: Wed, 12 Apr 2017 16:26:34 +0200
Subject: [PATCH 10/37] annotation: added region support to annoations
---
pkg/api/annotations.go | 22 ++++++++++++++++---
pkg/api/dtos/annotations.go | 5 +++++
pkg/services/annotations/annotations.go | 2 ++
pkg/services/sqlstore/annotation.go | 11 ++++++++++
.../sqlstore/migrations/annotation_mig.go | 4 ++++
5 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go
index 88e8c955497..a7783e4be88 100644
--- a/pkg/api/annotations.go
+++ b/pkg/api/annotations.go
@@ -40,6 +40,7 @@ func GetAnnotations(c *middleware.Context) Response {
Metric: item.Metric,
Title: item.Title,
PanelId: item.PanelId,
+ RegionId: item.RegionId,
})
}
@@ -57,15 +58,30 @@ func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response
Title: cmd.Title,
Text: cmd.Text,
CategoryId: cmd.CategoryId,
+ NewState: cmd.FillColor,
Type: annotations.EventType,
}
- err := repo.Save(&item)
-
- if err != nil {
+ if err := repo.Save(&item); err != nil {
return ApiError(500, "Failed to save annotation", err)
}
+ // handle regions
+ if cmd.IsRegion {
+ item.RegionId = item.Id
+
+ if err := repo.Update(&item); err != nil {
+ return ApiError(500, "Failed set regionId on annotation", err)
+ }
+
+ item.Id = 0
+ item.Epoch = cmd.EndTime
+
+ if err := repo.Save(&item); err != nil {
+ return ApiError(500, "Failed save annotation for region end time", err)
+ }
+ }
+
return ApiSuccess("Annotation added")
}
diff --git a/pkg/api/dtos/annotations.go b/pkg/api/dtos/annotations.go
index 28e048db3ec..bd9dd06c457 100644
--- a/pkg/api/dtos/annotations.go
+++ b/pkg/api/dtos/annotations.go
@@ -12,6 +12,7 @@ type Annotation struct {
Title string `json:"title"`
Text string `json:"text"`
Metric string `json:"metric"`
+ RegionId int64 `json:"regionId"`
Data *simplejson.Json `json:"data"`
}
@@ -23,6 +24,10 @@ type PostAnnotationsCmd struct {
Time int64 `json:"time"`
Title string `json:"title"`
Text string `json:"text"`
+
+ FillColor string `json:"fillColor"`
+ IsRegion bool `json:"isRegion"`
+ EndTime int64 `json:"endTime"`
}
type DeleteAnnotationsCmd struct {
diff --git a/pkg/services/annotations/annotations.go b/pkg/services/annotations/annotations.go
index a3b4eacc0c3..be9d3f2d4d0 100644
--- a/pkg/services/annotations/annotations.go
+++ b/pkg/services/annotations/annotations.go
@@ -4,6 +4,7 @@ import "github.com/grafana/grafana/pkg/components/simplejson"
type Repository interface {
Save(item *Item) error
+ Update(item *Item) error
Find(query *ItemQuery) ([]*Item, error)
Delete(params *DeleteParams) error
}
@@ -58,6 +59,7 @@ type Item struct {
DashboardId int64 `json:"dashboardId"`
PanelId int64 `json:"panelId"`
CategoryId int64 `json:"categoryId"`
+ RegionId int64 `json:"regionId"`
Type ItemType `json:"type"`
Title string `json:"title"`
Text string `json:"text"`
diff --git a/pkg/services/sqlstore/annotation.go b/pkg/services/sqlstore/annotation.go
index e219f48d2fe..62a10ee2106 100644
--- a/pkg/services/sqlstore/annotation.go
+++ b/pkg/services/sqlstore/annotation.go
@@ -23,6 +23,17 @@ func (r *SqlAnnotationRepo) Save(item *annotations.Item) error {
})
}
+func (r *SqlAnnotationRepo) Update(item *annotations.Item) error {
+ return inTransaction(func(sess *xorm.Session) error {
+
+ if _, err := sess.Table("annotation").Id(item.Id).Update(item); err != nil {
+ return err
+ }
+
+ return nil
+ })
+}
+
func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.Item, error) {
var sql bytes.Buffer
params := make([]interface{}, 0)
diff --git a/pkg/services/sqlstore/migrations/annotation_mig.go b/pkg/services/sqlstore/migrations/annotation_mig.go
index 4a7206f9d64..aeb2afed4fb 100644
--- a/pkg/services/sqlstore/migrations/annotation_mig.go
+++ b/pkg/services/sqlstore/migrations/annotation_mig.go
@@ -54,4 +54,8 @@ func addAnnotationMig(mg *Migrator) {
{Name: "new_state", Type: DB_NVarchar, Length: 25, Nullable: false},
{Name: "data", Type: DB_Text, Nullable: false},
}))
+
+ mg.AddMigration("Add column region_id to annotation table", NewAddColumnMigration(table, &Column{
+ Name: "region_id", Type: DB_BigInt, Nullable: true, Default: "0",
+ }))
}
From de21be30d2526861c80c57ba34ce81d9bd9a3e47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torkel=20=C3=96degaard?=
Date: Wed, 12 Apr 2017 17:28:32 +0200
Subject: [PATCH 11/37] ux: working on how to show form in popover
---
public/app/core/components/switch.ts | 2 +-
public/app/features/dashboard/all.js | 1 +
public/app/features/dashboard/event_editor.ts | 22 +++++++++++++++
.../dashboard/partials/event_editor.html | 27 +++++++++++++++++++
public/app/plugins/panel/graph/graph.ts | 19 ++++++++++---
5 files changed, 67 insertions(+), 4 deletions(-)
create mode 100644 public/app/features/dashboard/event_editor.ts
create mode 100644 public/app/features/dashboard/partials/event_editor.html
diff --git a/public/app/core/components/switch.ts b/public/app/core/components/switch.ts
index 2a64ec487f7..889398d5138 100644
--- a/public/app/core/components/switch.ts
+++ b/public/app/core/components/switch.ts
@@ -9,7 +9,7 @@ import Drop from 'tether-drop';
var template = `
diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js
index c3a71a11818..5a3d6ea5203 100644
--- a/public/app/features/dashboard/all.js
+++ b/public/app/features/dashboard/all.js
@@ -22,4 +22,5 @@ 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
new file mode 100644
index 00000000000..35606a5ac73
--- /dev/null
+++ b/public/app/features/dashboard/event_editor.ts
@@ -0,0 +1,22 @@
+///
+
+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/event_editor.html b/public/app/features/dashboard/partials/event_editor.html
new file mode 100644
index 00000000000..3aaa9d6855f
--- /dev/null
+++ b/public/app/features/dashboard/partials/event_editor.html
@@ -0,0 +1,27 @@
+
+
Add annotation event
+
+
+ Title
+
+
+
+ Time
+
+
+
+ To
+
+
+
+ Description
+
+
+
+
+
+
+
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts
index 4d68e10bbc0..a0e18dae597 100755
--- a/public/app/plugins/panel/graph/graph.ts
+++ b/public/app/plugins/panel/graph/graph.ts
@@ -19,7 +19,7 @@ import GraphTooltip from './graph_tooltip';
import {ThresholdManager} from './threshold_manager';
import {convertValuesToHistogram, getSeriesValues} from './histogram';
-coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
+coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
return {
restrict: 'A',
template: '',
@@ -91,10 +91,23 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
to: null
};
- ctrl.showAddAnnotationModal(timeRange);
+ showAddAnnotationView(timeRange);
}
}, scope);
+ function showAddAnnotationView(timeRange) {
+ popoverSrv.show({
+ element: elem[0],
+ position: 'bottom center',
+ openOn: 'click',
+ template: '',
+ model: {
+ timeRange: timeRange,
+ panelCtrl: ctrl,
+ },
+ });
+ }
+
function getLegendHeight(panelHeight) {
if (!panel.legend.show || panel.legend.rightSide) {
return 0;
@@ -658,7 +671,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
if (ranges.ctrlKey || ranges.metaKey) {
// Create new annotation from time range
let timeRange = ranges.xaxis;
- ctrl.showAddAnnotationModal(timeRange);
+ showAddAnnotationView(timeRange);
plot.clearSelection();
} else {
scope.$apply(function() {
From 8a1c35e1c233562ea595d8c8a226afb3ee758e33 Mon Sep 17 00:00:00 2001
From: Alexander Zobnin
Date: Wed, 12 Apr 2017 20:27:32 +0300
Subject: [PATCH 12/37] graph(create annotation): refactor, fix two modal after
range selection
bind create annotation handler directly to plotclick event, not to global graph-click
---
public/app/plugins/panel/graph/graph.ts | 30 ++++++++++++-------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts
index 4d68e10bbc0..88a0f545cc9 100755
--- a/public/app/plugins/panel/graph/graph.ts
+++ b/public/app/plugins/panel/graph/graph.ts
@@ -79,22 +79,6 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
}
}, 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
- };
-
- ctrl.showAddAnnotationModal(timeRange);
- }
- }, scope);
-
function getLegendHeight(panelHeight) {
if (!panel.legend.show || panel.legend.rightSide) {
return 0;
@@ -670,6 +654,20 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
}
});
+ 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) {
+ let timeRange = {
+ from: pos.x,
+ to: null
+ };
+
+ ctrl.showAddAnnotationModal(timeRange);
+ }
+ });
+
scope.$on('$destroy', function() {
tooltip.destroy();
elem.off();
From ef99ff0ad737a8b1c9d493f6307039cf5e3e7455 Mon Sep 17 00:00:00 2001
From: Alexander Zobnin
Date: Wed, 12 Apr 2017 20:37:33 +0300
Subject: [PATCH 13/37] graph(create annotation): use single description for
range
---
.../dashboard/partials/addAnnotationModal.html | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/public/app/features/dashboard/partials/addAnnotationModal.html b/public/app/features/dashboard/partials/addAnnotationModal.html
index 1ea3b7d7a6f..49832075a17 100644
--- a/public/app/features/dashboard/partials/addAnnotationModal.html
+++ b/public/app/features/dashboard/partials/addAnnotationModal.html
@@ -42,8 +42,7 @@