mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
alert: alerting annotation improvements, fixes #8421
This commit is contained in:
parent
370db82238
commit
a0b9dcad4d
@ -41,6 +41,7 @@ func GetAnnotations(c *middleware.Context) Response {
|
|||||||
Title: item.Title,
|
Title: item.Title,
|
||||||
PanelId: item.PanelId,
|
PanelId: item.PanelId,
|
||||||
RegionId: item.RegionId,
|
RegionId: item.RegionId,
|
||||||
|
Type: string(item.Type),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ type Annotation struct {
|
|||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
Metric string `json:"metric"`
|
Metric string `json:"metric"`
|
||||||
RegionId int64 `json:"regionId"`
|
RegionId int64 `json:"regionId"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
Data *simplejson.Json `json:"data"`
|
Data *simplejson.Json `json:"data"`
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
///<reference path="../headers/common.d.ts" />
|
///<reference path="../headers/common.d.ts" />
|
||||||
///<reference path="./mod_defs.d.ts" />
|
///<reference path="./mod_defs.d.ts" />
|
||||||
|
|
||||||
import "./directives/annotation_tooltip";
|
|
||||||
import "./directives/dash_class";
|
import "./directives/dash_class";
|
||||||
import "./directives/confirm_click";
|
import "./directives/confirm_click";
|
||||||
import "./directives/dash_edit_link";
|
import "./directives/dash_edit_link";
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'lodash',
|
|
||||||
'../core_module',
|
|
||||||
],
|
|
||||||
function ($, _, coreModule) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
coreModule.default.directive('annotationTooltip', function($sanitize, dashboardSrv, $compile) {
|
|
||||||
|
|
||||||
function sanitizeString(str) {
|
|
||||||
try {
|
|
||||||
return $sanitize(str);
|
|
||||||
}
|
|
||||||
catch(err) {
|
|
||||||
console.log('Could not sanitize annotation string, html escaping instead');
|
|
||||||
return _.escape(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
link: function (scope, element) {
|
|
||||||
var event = scope.event;
|
|
||||||
var title = sanitizeString(event.title);
|
|
||||||
var dashboard = dashboardSrv.getCurrent();
|
|
||||||
var time = '<i>' + dashboard.formatDate(event.min) + '</i>';
|
|
||||||
|
|
||||||
var tooltip = '<div class="graph-annotation">';
|
|
||||||
tooltip += '<div class="graph-annotation-title">' + title + "</div>";
|
|
||||||
|
|
||||||
if (event.text) {
|
|
||||||
var text = sanitizeString(event.text);
|
|
||||||
tooltip += text.replace(/\n/g, '<br>') + '<br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
var tags = event.tags;
|
|
||||||
if (_.isString(event.tags)) {
|
|
||||||
tags = event.tags.split(',');
|
|
||||||
if (tags.length === 1) {
|
|
||||||
tags = event.tags.split(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tags && tags.length) {
|
|
||||||
scope.tags = tags;
|
|
||||||
tooltip += '<span class="label label-tag small" ng-repeat="tag in tags" tag-color-from-name="tag">{{tag}}</span><br/>';
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltip += '<div class="graph-annotation-time">' + time + '</div>' ;
|
|
||||||
tooltip += "</div>";
|
|
||||||
|
|
||||||
var $tooltip = $(tooltip);
|
|
||||||
$tooltip.appendTo(element);
|
|
||||||
|
|
||||||
$compile(element.contents())(scope);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -91,17 +91,9 @@ function getStateDisplayModel(state) {
|
|||||||
stateClass: 'alert-state-warning'
|
stateClass: 'alert-state-warning'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'execution_error': {
|
|
||||||
return {
|
|
||||||
text: 'EXECUTION ERROR',
|
|
||||||
iconClass: 'icon-gf icon-gf-critical',
|
|
||||||
stateClass: 'alert-state-critical'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'paused': {
|
case 'paused': {
|
||||||
return {
|
return {
|
||||||
text: 'paused',
|
text: 'PAUSED',
|
||||||
iconClass: "fa fa-pause",
|
iconClass: "fa fa-pause",
|
||||||
stateClass: 'alert-state-paused'
|
stateClass: 'alert-state-paused'
|
||||||
};
|
};
|
||||||
|
@ -3,10 +3,12 @@ import {AnnotationsSrv} from './annotations_srv';
|
|||||||
import {eventEditor} from './event_editor';
|
import {eventEditor} from './event_editor';
|
||||||
import {EventManager} from './event_manager';
|
import {EventManager} from './event_manager';
|
||||||
import {AnnotationEvent} from './event';
|
import {AnnotationEvent} from './event';
|
||||||
|
import {annotationTooltipDirective} from './annotation_tooltip';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AnnotationsSrv,
|
AnnotationsSrv,
|
||||||
eventEditor,
|
eventEditor,
|
||||||
EventManager,
|
EventManager,
|
||||||
AnnotationEvent,
|
AnnotationEvent,
|
||||||
|
annotationTooltipDirective,
|
||||||
};
|
};
|
||||||
|
80
public/app/features/annotations/annotation_tooltip.ts
Normal file
80
public/app/features/annotations/annotation_tooltip.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import angular from 'angular';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import coreModule from 'app/core/core_module';
|
||||||
|
import alertDef from '../alerting/alert_def';
|
||||||
|
|
||||||
|
/** @ngInject **/
|
||||||
|
export function annotationTooltipDirective($sanitize, dashboardSrv, $compile) {
|
||||||
|
|
||||||
|
function sanitizeString(str) {
|
||||||
|
try {
|
||||||
|
return $sanitize(str);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Could not sanitize annotation string, html escaping instead');
|
||||||
|
return _.escape(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
"event": "=",
|
||||||
|
},
|
||||||
|
link: function(scope, element) {
|
||||||
|
var event = scope.event;
|
||||||
|
var title = event.title;
|
||||||
|
var text = event.text;
|
||||||
|
var dashboard = dashboardSrv.getCurrent();
|
||||||
|
|
||||||
|
var tooltip = '<div class="graph-annotation">';
|
||||||
|
var titleStateClass = '';
|
||||||
|
|
||||||
|
if (event.source.name === 'panel-alert') {
|
||||||
|
var stateModel = alertDef.getStateDisplayModel(event.newState);
|
||||||
|
titleStateClass = stateModel.stateClass;
|
||||||
|
title = `<i class="icon-gf ${stateModel.iconClass}"></i> ${stateModel.text}`;
|
||||||
|
text = alertDef.getAlertAnnotationInfo(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip += `
|
||||||
|
<div class="graph-annotation-header">
|
||||||
|
<span class="graph-annotation-title ${titleStateClass}">${sanitizeString(title)}</span>
|
||||||
|
<span class="graph-annotation-time">${dashboard.formatDate(event.min)}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
tooltip += '<div class="graph-annotation-body">';
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
tooltip += sanitizeString(text).replace(/\n/g, '<br>') + '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
var tags = event.tags;
|
||||||
|
if (_.isString(event.tags)) {
|
||||||
|
tags = event.tags.split(',');
|
||||||
|
if (tags.length === 1) {
|
||||||
|
tags = event.tags.split(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags && tags.length) {
|
||||||
|
scope.tags = tags;
|
||||||
|
tooltip += '<span class="label label-tag small" ng-repeat="tag in tags" tag-color-from-name="tag">{{tag}}</span><br/>';
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip += "</div>";
|
||||||
|
|
||||||
|
var $tooltip = $(tooltip);
|
||||||
|
$tooltip.appendTo(element);
|
||||||
|
|
||||||
|
$compile(element.contents())(scope);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
coreModule.directive('annotationTooltip', annotationTooltipDirective);
|
@ -73,6 +73,8 @@ export class AnnotationsSrv {
|
|||||||
panelId: panel.id,
|
panelId: panel.id,
|
||||||
dashboardId: dashboard.id,
|
dashboardId: dashboard.id,
|
||||||
}).then(results => {
|
}).then(results => {
|
||||||
|
// this built in annotation source name `panel-alert` is used in annotation tooltip
|
||||||
|
// to know that this annotation is from panel alert
|
||||||
return this.translateQueryResult({iconColor: '#AA0000', name: 'panel-alert'}, results);
|
return this.translateQueryResult({iconColor: '#AA0000', name: 'panel-alert'}, results);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ function ($, _, angular, Drop) {
|
|||||||
function createAnnotationToolip(element, event) {
|
function createAnnotationToolip(element, event) {
|
||||||
var injector = angular.element(document).injector();
|
var injector = angular.element(document).injector();
|
||||||
var content = document.createElement('div');
|
var content = document.createElement('div');
|
||||||
content.innerHTML = '<annotation-tooltip></annotation-tooltip>';
|
content.innerHTML = '<annotation-tooltip event="event"></annotation-tooltip>';
|
||||||
|
|
||||||
injector.invoke(["$compile", "$rootScope", function($compile, $rootScope) {
|
injector.invoke(["$compile", "$rootScope", function($compile, $rootScope) {
|
||||||
var tmpScope = $rootScope.$new(true);
|
var tmpScope = $rootScope.$new(true);
|
||||||
@ -24,7 +24,7 @@ function ($, _, angular, Drop) {
|
|||||||
target: element[0],
|
target: element[0],
|
||||||
content: content,
|
content: content,
|
||||||
position: "bottom center",
|
position: "bottom center",
|
||||||
classes: 'drop-popover',
|
classes: 'drop-popover drop-popover--annotation',
|
||||||
openOn: 'hover',
|
openOn: 'hover',
|
||||||
hoverCloseDelay: 200,
|
hoverCloseDelay: 200,
|
||||||
tetherOptions: {
|
tetherOptions: {
|
||||||
|
@ -56,3 +56,9 @@ $easing: cubic-bezier(0, 0, 0.265, 1.00);
|
|||||||
max-width: none;
|
max-width: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.drop-element.drop-popover--annotation {
|
||||||
|
.drop-content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -287,10 +287,29 @@
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.graph-annotation-header {
|
||||||
|
background-color: $input-label-bg;
|
||||||
|
padding: 0.40rem 0.65rem;
|
||||||
|
}
|
||||||
|
|
||||||
.graph-annotation-title {
|
.graph-annotation-title {
|
||||||
font-weight: $font-weight-semi-bold;
|
font-weight: $font-weight-semi-bold;
|
||||||
|
padding-right: $spacer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -0.4rem;
|
top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-annotation-time {
|
||||||
|
color: $text-muted;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: normal;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-annotation-body {
|
||||||
|
padding: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@ -298,11 +317,6 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-annotation-time {
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
top: 0.6rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-yaxis-label {
|
.left-yaxis-label {
|
||||||
|
Loading…
Reference in New Issue
Block a user