diff --git a/' b/'
deleted file mode 100644
index 2e342921a63..00000000000
--- a/'
+++ /dev/null
@@ -1,200 +0,0 @@
-
-/** Created by: Alex Wendland (me@alexwendland.com), 2014-08-06
- *
- * angular-json-tree
- *
- * Directive for creating a tree-view out of a JS Object. Only loads
- * sub-nodes on demand in order to improve performance of rendering large
- * objects.
- *
- * Attributes:
- * - object (Object, 2-way): JS object to build the tree from
- * - start-expanded (Boolean, 1-way, ?=true): should the tree default to expanded
- *
- * Usage:
- * // In the controller
- * scope.someObject = {
- * test: 'hello',
- * array: [1,1,2,3,5,8]
- * };
- * // In the html
- *
- *
- * Dependencies:
- * - utils (json-tree.js)
- * - ajsRecursiveDirectiveHelper (json-tree.js)
- *
- * Test: json-tree-test.js
- */
-
-import angular from 'angular';
-import coreModule from 'app/core/core_module';
-
-var utils = {
- /* See link for possible type values to check against.
- * http://stackoverflow.com/questions/4622952/json-object-containing-array
- *
- * Value Class Type
- * -------------------------------------
- * "foo" String string
- * new String("foo") String object
- * 1.2 Number number
- * new Number(1.2) Number object
- * true Boolean boolean
- * new Boolean(true) Boolean object
- * new Date() Date object
- * new Error() Error object
- * [1,2,3] Array object
- * new Array(1, 2, 3) Array object
- * new Function("") Function function
- * /abc/g RegExp object (function in Nitro/V8)
- * new RegExp("meow") RegExp object (function in Nitro/V8)
- * {} Object object
- * new Object() Object object
- */
- is: function is(obj, clazz) {
- return Object.prototype.toString.call(obj).slice(8, -1) === clazz;
- },
-
- // See above for possible values
- whatClass: function whatClass(obj) {
- return Object.prototype.toString.call(obj).slice(8, -1);
- },
-
- // Iterate over an objects keyset
- forKeys: function forKeys(obj, f) {
- for (var key in obj) {
- if (obj.hasOwnProperty(key) && typeof obj[key] !== 'function') {
- if (f(key, obj[key])) {
- break;
- }
- }
- }
- }
-};
-
-coreModule.directive('jsonTree', [function jsonTreeDirective() {
- return {
- restrict: 'E',
- scope: {
- object: '=',
- startExpanded: '=',
- rootName: '@',
- },
- template: ''
- };
-}]);
-
-coreModule.directive('jsonNode', ['ajsRecursiveDirectiveHelper', function jsonNodeDirective(ajsRecursiveDirectiveHelper) {
- return {
- restrict: 'E',
- scope: {
- key: '=',
- value: '=',
- startExpanded: '='
- },
- compile: function jsonNodeDirectiveCompile(elem) {
- return ajsRecursiveDirectiveHelper.compile(elem, this);
- },
- template: ' {{key}}' +
- ' {{value}}' +
- ' ' +
- ' {preview}}' +
- '
' +
- ' - ' +
- ' ' +
- '
' +
- '
',
- pre: function jsonNodeDirectiveLink(scope, elem, attrs) {
- // Set value's type as Class for CSS styling
- elem.addClass(utils.whatClass(scope.value).toLowerCase());
- // If the value is an Array or Object, use expandable view type
- if (utils.is(scope.value, 'Object') || utils.is(scope.value, 'Array')) {
- scope.isExpandable = true;
- // Add expandable class for CSS usage
- elem.addClass('expandable');
- // Setup preview text
- var isArray = utils.is(scope.value, 'Array');
- scope.preview = isArray ? '[ ' : '{ ';
- utils.forKeys(scope.value, function jsonNodeDirectiveLinkForKeys(key, value) {
- if (isArray) {
- scope.preview += value + ', ';
- } else {
- scope.preview += key + ': ' + value + ', ';
- }
- });
- scope.preview = scope.preview.substring(0, scope.preview.length - (scope.preview.length > 2 ? 2 : 0)) + (isArray ? ' ]' : ' }');
- // If directive initially has isExpanded set, also set shouldRender to true
- if (scope.startExpanded) {
- scope.shouldRender = true;
- elem.addClass('expanded');
- }
- // Setup isExpanded state handling
- scope.isExpanded = scope.startExpanded ? scope.startExpanded() : false;
- scope.toggleExpanded = function jsonNodeDirectiveToggleExpanded() {
- scope.isExpanded = !scope.isExpanded;
- if (scope.isExpanded) {
- elem.addClass('expanded');
- } else {
- elem.removeClass('expanded');
- }
- // For delaying subnode render until requested
- scope.shouldRender = true;
- };
- } else {
- scope.isExpandable = false;
- // Add expandable class for CSS usage
- elem.addClass('not-expandable');
- }
- }
- };
-}]);
-
-/** Added by: Alex Wendland (me@alexwendland.com), 2014-08-09
- * Source: http://stackoverflow.com/questions/14430655/recursion-in-angular-directives
- *
- * Used to allow for recursion within directives
- */
-coreModule.factory('ajsRecursiveDirectiveHelper', ['$compile', function RecursiveDirectiveHelper($compile) {
- return {
- /**
- * Manually compiles the element, fixing the recursion loop.
- * @param element
- * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
- * @returns An object containing the linking functions.
- */
- compile: function RecursiveDirectiveHelperCompile(element, link) {
- // Normalize the link parameter
- if (angular.isFunction(link)) {
- link = {
- post: link
- };
- }
-
- // Break the recursion loop by removing the contents
- var contents = element.contents().remove();
- var compiledContents;
- return {
- pre: (link && link.pre) ? link.pre : null,
- /**
- * Compiles and re-adds the contents
- */
- post: function RecursiveDirectiveHelperCompilePost(scope, element) {
- // Compile the contents
- if (!compiledContents) {
- compiledContents = $compile(contents);
- }
- // Re-add the compiled contents to the element
- compiledContents(scope, function (clone) {
- element.append(clone);
- });
-
- // Call the post-linking function, if any
- if (link && link.post) {
- link.post.apply(null, arguments);
- }
- }
- };
- }
- };
-}]);
diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go
index ef845337d7b..634e9650f01 100644
--- a/pkg/api/alerting.go
+++ b/pkg/api/alerting.go
@@ -39,10 +39,10 @@ func GetAlerts(c *middleware.Context) Response {
}
dashboardIds := make([]int64, 0)
- alertDTOs := make([]*dtos.AlertRuleDTO, 0)
+ alertDTOs := make([]*dtos.AlertRule, 0)
for _, alert := range query.Result {
dashboardIds = append(dashboardIds, alert.DashboardId)
- alertDTOs = append(alertDTOs, &dtos.AlertRuleDTO{
+ alertDTOs = append(alertDTOs, &dtos.AlertRule{
Id: alert.Id,
DashboardId: alert.DashboardId,
PanelId: alert.PanelId,
@@ -176,18 +176,16 @@ func DelAlert(c *middleware.Context) Response {
// }
func GetAlertNotifications(c *middleware.Context) Response {
- query := &models.GetAlertNotificationQuery{
- OrgID: c.OrgId,
- }
+ query := &models.GetAlertNotificationsQuery{OrgId: c.OrgId}
if err := bus.Dispatch(query); err != nil {
return ApiError(500, "Failed to get alert notifications", err)
}
- var result []dtos.AlertNotificationDTO
+ var result []dtos.AlertNotification
for _, notification := range query.Result {
- result = append(result, dtos.AlertNotificationDTO{
+ result = append(result, dtos.AlertNotification{
Id: notification.Id,
Name: notification.Name,
Type: notification.Type,
@@ -200,8 +198,8 @@ func GetAlertNotifications(c *middleware.Context) Response {
}
func GetAlertNotificationById(c *middleware.Context) Response {
- query := &models.GetAlertNotificationQuery{
- OrgID: c.OrgId,
+ query := &models.GetAlertNotificationsQuery{
+ OrgId: c.OrgId,
Id: c.ParamsInt64("notificationId"),
}
@@ -213,7 +211,7 @@ func GetAlertNotificationById(c *middleware.Context) Response {
}
func CreateAlertNotification(c *middleware.Context, cmd models.CreateAlertNotificationCommand) Response {
- cmd.OrgID = c.OrgId
+ cmd.OrgId = c.OrgId
if err := bus.Dispatch(&cmd); err != nil {
return ApiError(500, "Failed to create alert notification", err)
@@ -223,7 +221,7 @@ func CreateAlertNotification(c *middleware.Context, cmd models.CreateAlertNotifi
}
func UpdateAlertNotification(c *middleware.Context, cmd models.UpdateAlertNotificationCommand) Response {
- cmd.OrgID = c.OrgId
+ cmd.OrgId = c.OrgId
if err := bus.Dispatch(&cmd); err != nil {
return ApiError(500, "Failed to update alert notification", err)
@@ -242,5 +240,5 @@ func DeleteAlertNotification(c *middleware.Context) Response {
return ApiError(500, "Failed to delete alert notification", err)
}
- return Json(200, map[string]interface{}{"notificationId": cmd.Id})
+ return ApiSuccess("Notification deleted")
}
diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go
index 35fc3f9e638..91678600a4e 100644
--- a/pkg/api/dtos/alerting.go
+++ b/pkg/api/dtos/alerting.go
@@ -7,7 +7,7 @@ import (
m "github.com/grafana/grafana/pkg/models"
)
-type AlertRuleDTO struct {
+type AlertRule struct {
Id int64 `json:"id"`
DashboardId int64 `json:"dashboardId"`
PanelId int64 `json:"panelId"`
@@ -19,7 +19,7 @@ type AlertRuleDTO struct {
DashbboardUri string `json:"dashboardUri"`
}
-type AlertNotificationDTO struct {
+type AlertNotification struct {
Id int64 `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
diff --git a/pkg/models/alert_notifications.go b/pkg/models/alert_notifications.go
index 3ac23438b8e..464d6dc88da 100644
--- a/pkg/models/alert_notifications.go
+++ b/pkg/models/alert_notifications.go
@@ -7,34 +7,31 @@ import (
)
type AlertNotification struct {
- Id int64 `json:"id"`
- OrgId int64 `json:"-"`
- Name string `json:"name"`
- Type string `json:"type"`
- AlwaysExecute bool `json:"alwaysExecute"`
- Settings *simplejson.Json `json:"settings"`
- Created time.Time `json:"created"`
- Updated time.Time `json:"updated"`
+ Id int64 `json:"id"`
+ OrgId int64 `json:"-"`
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Settings *simplejson.Json `json:"settings"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
}
type CreateAlertNotificationCommand struct {
- Name string `json:"name" binding:"Required"`
- Type string `json:"type" binding:"Required"`
- AlwaysExecute bool `json:"alwaysExecute"`
- OrgID int64 `json:"-"`
- Settings *simplejson.Json `json:"settings"`
+ Name string `json:"name" binding:"Required"`
+ Type string `json:"type" binding:"Required"`
+ Settings *simplejson.Json `json:"settings"`
+ OrgId int64 `json:"-"`
Result *AlertNotification
}
type UpdateAlertNotificationCommand struct {
- Id int64 `json:"id" binding:"Required"`
- Name string `json:"name" binding:"Required"`
- Type string `json:"type" binding:"Required"`
- AlwaysExecute bool `json:"alwaysExecute"`
- OrgID int64 `json:"-"`
- Settings *simplejson.Json `json:"settings" binding:"Required"`
+ Id int64 `json:"id" binding:"Required"`
+ Name string `json:"name" binding:"Required"`
+ Type string `json:"type" binding:"Required"`
+ Settings *simplejson.Json `json:"settings" binding:"Required"`
+ OrgId int64 `json:"-"`
Result *AlertNotification
}
@@ -43,12 +40,11 @@ type DeleteAlertNotificationCommand struct {
OrgId int64
}
-type GetAlertNotificationQuery struct {
- Name string
- Id int64
- Ids []int64
- OrgID int64
- IncludeAlwaysExecute bool
+type GetAlertNotificationsQuery struct {
+ Name string
+ Id int64
+ Ids []int64
+ OrgId int64
Result []*AlertNotification
}
diff --git a/pkg/models/annotations.go b/pkg/models/annotations.go
new file mode 100644
index 00000000000..149181fe81a
--- /dev/null
+++ b/pkg/models/annotations.go
@@ -0,0 +1,22 @@
+package models
+
+import (
+ "time"
+
+ "github.com/grafana/grafana/pkg/components/simplejson"
+)
+
+type AnnotationType string
+
+type AnnotationEvent struct {
+ Id int64
+ OrgId int64
+ Type AnnotationType
+ Title string
+ Text string
+ AlertId int64
+ UserId int64
+ Timestamp time.Time
+
+ Data *simplejson.Json
+}
diff --git a/pkg/services/sqlstore/alert_notification.go b/pkg/services/sqlstore/alert_notification.go
index 3f4b9a03406..8a3c8543f91 100644
--- a/pkg/services/sqlstore/alert_notification.go
+++ b/pkg/services/sqlstore/alert_notification.go
@@ -3,7 +3,6 @@ package sqlstore
import (
"bytes"
"fmt"
- "strconv"
"time"
"github.com/go-xorm/xorm"
@@ -31,11 +30,11 @@ func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error {
})
}
-func AlertNotificationQuery(query *m.GetAlertNotificationQuery) error {
+func AlertNotificationQuery(query *m.GetAlertNotificationsQuery) error {
return getAlertNotifications(query, x.NewSession())
}
-func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Session) error {
+func getAlertNotifications(query *m.GetAlertNotificationsQuery, sess *xorm.Session) error {
var sql bytes.Buffer
params := make([]interface{}, 0)
@@ -43,16 +42,15 @@ func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Sessio
alert_notification.id,
alert_notification.org_id,
alert_notification.name,
- alert_notification.type,
+ alert_notification.type,
alert_notification.created,
- alert_notification.updated,
- alert_notification.settings,
- alert_notification.always_execute
+ alert_notification.updated,
+ alert_notification.settings
FROM alert_notification
`)
sql.WriteString(` WHERE alert_notification.org_id = ?`)
- params = append(params, query.OrgID)
+ params = append(params, query.OrgId)
if query.Name != "" {
sql.WriteString(` AND alert_notification.name = ?`)
@@ -61,60 +59,26 @@ func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Sessio
if query.Id != 0 {
sql.WriteString(` AND alert_notification.id = ?`)
- params = append(params, strconv.Itoa(int(query.Id)))
+ params = append(params, query.Id)
}
if len(query.Ids) > 0 {
- sql.WriteString(` AND (`)
-
- for i, id := range query.Ids {
- if i != 0 {
- sql.WriteString(` OR`)
- }
- sql.WriteString(` alert_notification.id = ?`)
- params = append(params, id)
- }
-
- sql.WriteString(`)`)
+ sql.WriteString(` AND alert_notification.id IN (?)`)
+ params = append(params, query.Ids)
}
- var searches []*m.AlertNotification
- if err := sess.Sql(sql.String(), params...).Find(&searches); err != nil {
+ results := make([]*m.AlertNotification, 0)
+ if err := sess.Sql(sql.String(), params...).Find(&results); err != nil {
return err
}
- var result []*m.AlertNotification
- var def []*m.AlertNotification
- if query.IncludeAlwaysExecute {
-
- if err := sess.Where("org_id = ? AND always_execute = 1", query.OrgID).Find(&def); err != nil {
- return err
- }
-
- result = append(result, def...)
- }
-
- for _, s := range searches {
- canAppend := true
- for _, d := range result {
- if d.Id == s.Id {
- canAppend = false
- break
- }
- }
-
- if canAppend {
- result = append(result, s)
- }
- }
-
- query.Result = result
+ query.Result = results
return nil
}
func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error {
return inTransaction(func(sess *xorm.Session) error {
- existingQuery := &m.GetAlertNotificationQuery{OrgID: cmd.OrgID, Name: cmd.Name, IncludeAlwaysExecute: false}
+ existingQuery := &m.GetAlertNotificationsQuery{OrgId: cmd.OrgId, Name: cmd.Name}
err := getAlertNotifications(existingQuery, sess)
if err != nil {
@@ -126,18 +90,15 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
}
alertNotification := &m.AlertNotification{
- OrgId: cmd.OrgID,
- Name: cmd.Name,
- Type: cmd.Type,
- Created: time.Now(),
- Settings: cmd.Settings,
- Updated: time.Now(),
- AlwaysExecute: cmd.AlwaysExecute,
+ OrgId: cmd.OrgId,
+ Name: cmd.Name,
+ Type: cmd.Type,
+ Settings: cmd.Settings,
+ Created: time.Now(),
+ Updated: time.Now(),
}
- _, err = sess.Insert(alertNotification)
-
- if err != nil {
+ if _, err = sess.Insert(alertNotification); err != nil {
return err
}
@@ -148,38 +109,34 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
return inTransaction(func(sess *xorm.Session) (err error) {
- current := &m.AlertNotification{}
- _, err = sess.Id(cmd.Id).Get(current)
+ current := m.AlertNotification{}
- if err != nil {
+ if _, err = sess.Id(cmd.Id).Get(¤t); err != nil {
return err
}
- alertNotification := &m.AlertNotification{
- Id: cmd.Id,
- OrgId: cmd.OrgID,
- Name: cmd.Name,
- Type: cmd.Type,
- Settings: cmd.Settings,
- Updated: time.Now(),
- Created: current.Created,
- AlwaysExecute: cmd.AlwaysExecute,
- }
-
- sess.UseBool("always_execute")
-
- var affected int64
- affected, err = sess.Id(alertNotification.Id).Update(alertNotification)
-
- if err != nil {
+ // check if name exists
+ sameNameQuery := &m.GetAlertNotificationsQuery{OrgId: cmd.OrgId, Name: cmd.Name}
+ if err := getAlertNotifications(sameNameQuery, sess); err != nil {
return err
}
- if affected == 0 {
+ if len(sameNameQuery.Result) > 0 && sameNameQuery.Result[0].Id != current.Id {
+ return fmt.Errorf("Alert notification name %s already exists", cmd.Name)
+ }
+
+ current.Updated = time.Now()
+ current.Settings = cmd.Settings
+ current.Name = cmd.Name
+ current.Type = cmd.Type
+
+ if affected, err := sess.Id(cmd.Id).Update(current); err != nil {
+ return err
+ } else if affected == 0 {
return fmt.Errorf("Could not find alert notification")
}
- cmd.Result = alertNotification
+ cmd.Result = ¤t
return nil
})
}
diff --git a/public/app/features/alerting/notification_edit_ctrl.ts b/public/app/features/alerting/notification_edit_ctrl.ts
index 43dceea8dc2..69e2e276862 100644
--- a/public/app/features/alerting/notification_edit_ctrl.ts
+++ b/public/app/features/alerting/notification_edit_ctrl.ts
@@ -15,10 +15,7 @@ export class AlertNotificationEditCtrl {
this.loadNotification($routeParams.notificationId);
} else {
this.notification = {
- settings: {
- sendCrit: true,
- sendWarn: true,
- }
+ type: 'email',
};
}
}
diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html
index fea91e5045a..8ed471887d5 100644
--- a/public/app/features/alerting/partials/notification_edit.html
+++ b/public/app/features/alerting/partials/notification_edit.html
@@ -6,14 +6,14 @@
Alert notification
-