problems: refactor
This commit is contained in:
@@ -1,118 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import angular from 'angular';
|
|
||||||
import Drop from 'tether-drop';
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.directives')
|
|
||||||
.directive('ackTooltip',
|
|
||||||
/** @ngInject */
|
|
||||||
function($sanitize, $compile) {
|
|
||||||
let buttonTemplate = '<a bs-tooltip="\'Acknowledges ({{trigger.acknowledges.length}})\'"' +
|
|
||||||
'<i ng-class="' +
|
|
||||||
"{'fa fa-comments': trigger.acknowledges.length, " +
|
|
||||||
"'fa fa-comments-o': !trigger.acknowledges.length, " +
|
|
||||||
'}"></i></a>';
|
|
||||||
|
|
||||||
return {
|
|
||||||
scope: {
|
|
||||||
ack: "=",
|
|
||||||
trigger: "=",
|
|
||||||
onAck: "=",
|
|
||||||
context: "="
|
|
||||||
},
|
|
||||||
link: function(scope, element) {
|
|
||||||
let acknowledges = scope.ack;
|
|
||||||
let $button = $(buttonTemplate);
|
|
||||||
$button.appendTo(element);
|
|
||||||
|
|
||||||
$button.click(function() {
|
|
||||||
let tooltip = '<div>';
|
|
||||||
|
|
||||||
if (acknowledges && acknowledges.length) {
|
|
||||||
tooltip += '<table class="table"><thead><tr>' +
|
|
||||||
'<th class="ack-time">Time</th>' +
|
|
||||||
'<th class="ack-user">User</th>' +
|
|
||||||
'<th class="ack-comments">Comments</th>' +
|
|
||||||
'</tr></thead><tbody>';
|
|
||||||
for (let ack of acknowledges) {
|
|
||||||
tooltip += '<tr><td>' + ack.time + '</td>' +
|
|
||||||
'<td>' + ack.user + '</td>' +
|
|
||||||
'<td>' + ack.message + '</td></tr>';
|
|
||||||
}
|
|
||||||
tooltip += '</tbody></table>';
|
|
||||||
} else {
|
|
||||||
tooltip += 'Add acknowledge';
|
|
||||||
}
|
|
||||||
|
|
||||||
let addAckButtonTemplate = '<div class="ack-add-button">' +
|
|
||||||
'<button id="add-acknowledge-btn"' +
|
|
||||||
'class="btn btn-mini btn-inverse gf-form-button">' +
|
|
||||||
'<i class="fa fa-plus"></i>' +
|
|
||||||
'</button></div>';
|
|
||||||
tooltip += addAckButtonTemplate;
|
|
||||||
tooltip += '</div>';
|
|
||||||
|
|
||||||
let drop = new Drop({
|
|
||||||
target: element[0],
|
|
||||||
content: tooltip,
|
|
||||||
position: "bottom left",
|
|
||||||
classes: 'drop-popover ack-tooltip',
|
|
||||||
openOn: 'hover',
|
|
||||||
hoverCloseDelay: 500,
|
|
||||||
tetherOptions: {
|
|
||||||
constraints: [{to: 'window', pin: true, attachment: "both"}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
drop.open();
|
|
||||||
drop.on('close', closeDrop);
|
|
||||||
|
|
||||||
$('#add-acknowledge-btn').on('click', onAddAckButtonClick);
|
|
||||||
|
|
||||||
function onAddAckButtonClick() {
|
|
||||||
let inputTemplate = '<div class="ack-input-group">' +
|
|
||||||
'<input type="text" id="ack-message">' +
|
|
||||||
'<button id="send-ack-button"' +
|
|
||||||
'class="btn btn-mini btn-inverse gf-form-button">' +
|
|
||||||
'Acknowledge </button>' +
|
|
||||||
'<button id="cancel-ack-button"' +
|
|
||||||
'class="btn btn-mini btn-inverse gf-form-button">' +
|
|
||||||
'Cancel' +
|
|
||||||
'</button></input></div>';
|
|
||||||
|
|
||||||
let $input = $(inputTemplate);
|
|
||||||
let $addAckButton = $('.ack-tooltip .ack-add-button');
|
|
||||||
$addAckButton.replaceWith($input);
|
|
||||||
$('.ack-tooltip #cancel-ack-button').on('click', onAckCancelButtonClick);
|
|
||||||
$('.ack-tooltip #send-ack-button').on('click', onAckSendlButtonClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAckCancelButtonClick() {
|
|
||||||
$('.ack-tooltip .ack-input-group').replaceWith(addAckButtonTemplate);
|
|
||||||
$('#add-acknowledge-btn').on('click', onAddAckButtonClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAckSendlButtonClick() {
|
|
||||||
let message = $('.ack-tooltip #ack-message')[0].value;
|
|
||||||
let onAck = scope.onAck.bind(scope.context);
|
|
||||||
onAck(scope.trigger, message).then(() => {
|
|
||||||
closeDrop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeDrop() {
|
|
||||||
setTimeout(function() {
|
|
||||||
try {
|
|
||||||
drop.destroy();
|
|
||||||
} catch (err) {
|
|
||||||
console.log('drop.destroy() error: ', err.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$compile(element.contents())(scope);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { ZBXTrigger } from 'panel-triggers/types';
|
||||||
|
|
||||||
|
interface AlertAcknowledgesProps {
|
||||||
|
problem: ZBXTrigger;
|
||||||
|
onClick: (event?) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AlertAcknowledges extends PureComponent<AlertAcknowledgesProps> {
|
||||||
|
handleClick = (event) => {
|
||||||
|
this.props.onClick(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { problem } = this.props;
|
||||||
|
const ackRows = problem.acknowledges && problem.acknowledges.map(ack => {
|
||||||
|
return (
|
||||||
|
<tr key={ack.acknowledgeid}>
|
||||||
|
<td>{ack.time}</td>
|
||||||
|
<td>{ack.user}</td>
|
||||||
|
<td>{ack.message}</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className="ack-tooltip">
|
||||||
|
<table className="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="ack-time">Time</th>
|
||||||
|
<th className="ack-user">User</th>
|
||||||
|
<th className="ack-comments">Comments</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{ackRows}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div className="ack-add-button">
|
||||||
|
<button id="add-acknowledge-btn" className="btn btn-mini btn-inverse gf-form-button" onClick={this.handleClick}>
|
||||||
|
<i className="fa fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ import { ProblemsPanelOptions, ZBXTrigger, ZBXTag } from '../../types';
|
|||||||
import { AckProblemData, Modal } from '.././Modal';
|
import { AckProblemData, Modal } from '.././Modal';
|
||||||
import EventTag from '../EventTag';
|
import EventTag from '../EventTag';
|
||||||
import Tooltip from '.././Tooltip/Tooltip';
|
import Tooltip from '.././Tooltip/Tooltip';
|
||||||
|
import AlertAcknowledges from './AlertAcknowledges';
|
||||||
|
import AlertIcon from './AlertIcon';
|
||||||
|
|
||||||
interface AlertCardProps {
|
interface AlertCardProps {
|
||||||
problem: ZBXTrigger;
|
problem: ZBXTrigger;
|
||||||
@@ -153,40 +155,6 @@ export default class AlertCard extends PureComponent<AlertCardProps, AlertCardSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AlertIconProps {
|
|
||||||
problem: ZBXTrigger;
|
|
||||||
color: string;
|
|
||||||
blink?: boolean;
|
|
||||||
highlightBackground?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function AlertIcon(props: AlertIconProps) {
|
|
||||||
const { problem, color, blink, highlightBackground } = props;
|
|
||||||
const priority = Number(problem.priority);
|
|
||||||
let iconClass = '';
|
|
||||||
if (problem.value === '1') {
|
|
||||||
if (priority >= 3) {
|
|
||||||
iconClass = 'icon-gf-critical';
|
|
||||||
} else {
|
|
||||||
iconClass = 'icon-gf-warning';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iconClass = 'icon-gf-online';
|
|
||||||
}
|
|
||||||
|
|
||||||
const className = classNames('icon-gf', iconClass, { 'zabbix-trigger--blinked': blink });
|
|
||||||
const style: CSSProperties = {};
|
|
||||||
if (!highlightBackground) {
|
|
||||||
style.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="alert-rule-item__icon" style={style}>
|
|
||||||
<i className={className}></i>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AlertHostProps {
|
interface AlertHostProps {
|
||||||
problem: ZBXTrigger;
|
problem: ZBXTrigger;
|
||||||
panelOptions: ProblemsPanelOptions;
|
panelOptions: ProblemsPanelOptions;
|
||||||
@@ -293,48 +261,3 @@ class AlertAcknowledgesButton extends PureComponent<AlertAcknowledgesButtonProps
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AlertAcknowledgesProps {
|
|
||||||
problem: ZBXTrigger;
|
|
||||||
onClick: (event?) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AlertAcknowledges extends PureComponent<AlertAcknowledgesProps> {
|
|
||||||
handleClick = (event) => {
|
|
||||||
this.props.onClick(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { problem } = this.props;
|
|
||||||
const ackRows = problem.acknowledges && problem.acknowledges.map(ack => {
|
|
||||||
return (
|
|
||||||
<tr key={ack.acknowledgeid}>
|
|
||||||
<td>{ack.time}</td>
|
|
||||||
<td>{ack.user}</td>
|
|
||||||
<td>{ack.message}</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div className="ack-tooltip">
|
|
||||||
<table className="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="ack-time">Time</th>
|
|
||||||
<th className="ack-user">User</th>
|
|
||||||
<th className="ack-comments">Comments</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{ackRows}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div className="ack-add-button">
|
|
||||||
<button id="add-acknowledge-btn" className="btn btn-mini btn-inverse gf-form-button" onClick={this.handleClick}>
|
|
||||||
<i className="fa fa-plus"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
37
src/panel-triggers/components/AlertList/AlertIcon.tsx
Normal file
37
src/panel-triggers/components/AlertList/AlertIcon.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import React, { CSSProperties } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { ZBXTrigger } from 'panel-triggers/types';
|
||||||
|
|
||||||
|
interface AlertIconProps {
|
||||||
|
problem: ZBXTrigger;
|
||||||
|
color: string;
|
||||||
|
blink?: boolean;
|
||||||
|
highlightBackground?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AlertIcon(props: AlertIconProps) {
|
||||||
|
const { problem, color, blink, highlightBackground } = props;
|
||||||
|
const priority = Number(problem.priority);
|
||||||
|
let iconClass = '';
|
||||||
|
if (problem.value === '1') {
|
||||||
|
if (priority >= 3) {
|
||||||
|
iconClass = 'icon-gf-critical';
|
||||||
|
} else {
|
||||||
|
iconClass = 'icon-gf-warning';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iconClass = 'icon-gf-online';
|
||||||
|
}
|
||||||
|
|
||||||
|
const className = classNames('icon-gf', iconClass, { 'zabbix-trigger--blinked': blink });
|
||||||
|
const style: CSSProperties = {};
|
||||||
|
if (!highlightBackground) {
|
||||||
|
style.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="alert-rule-item__icon" style={style}>
|
||||||
|
<i className={className}></i>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
import {TriggerPanelCtrl} from './triggers_panel_ctrl';
|
import {TriggerPanelCtrl} from './triggers_panel_ctrl';
|
||||||
import {loadPluginCss} from 'grafana/app/plugins/sdk';
|
import {loadPluginCss} from 'grafana/app/plugins/sdk';
|
||||||
import './datasource-selector.directive';
|
import './datasource-selector.directive';
|
||||||
import './ack-tooltip.directive';
|
|
||||||
|
|
||||||
loadPluginCss({
|
loadPluginCss({
|
||||||
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
|
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
|
||||||
|
|||||||
@@ -1,97 +1 @@
|
|||||||
<div class="triggers-panel-container">
|
<div class="triggers-panel-container"></div>
|
||||||
<div class="triggers-panel-scroll">
|
|
||||||
<section class="card-section card-list-layout-list">
|
|
||||||
<ol class="alert-rule-list">
|
|
||||||
<!-- Trigger list item -->
|
|
||||||
<li class="alert-rule-item zbx-trigger-card" ng-repeat="trigger in ctrl.currentTriggersPage"
|
|
||||||
ng-class="{'zbx-trigger-highlighted': ctrl.panel.highlightBackground}"
|
|
||||||
ng-style="ctrl.panel.highlightBackground && {background: ctrl.getBackground(trigger)}">
|
|
||||||
|
|
||||||
<!-- Heart icon -->
|
|
||||||
<div class="alert-rule-item__icon" ng-style="!ctrl.panel.highlightBackground && {color: trigger.color}">
|
|
||||||
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert-rule-item__body">
|
|
||||||
<div class="alert-rule-item__header">
|
|
||||||
|
|
||||||
<p class="alert-rule-item__name">
|
|
||||||
<span class="zabbix-trigger-name">{{trigger.description}}</span>
|
|
||||||
<span class="zabbix-hostname" ng-if="ctrl.panel.hostField || ctrl.panel.hostTechNameField">
|
|
||||||
<i ng-if="trigger.maintenance" class="fa fa-wrench zbx-maintenance-icon"></i>
|
|
||||||
{{ ctrl.formatHostName(trigger) }}
|
|
||||||
</span>
|
|
||||||
<span class="zabbix-hostname" ng-if="ctrl.panel.hostGroups">
|
|
||||||
{{ ctrl.formatHostGroups(trigger) }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="zbx-trigger-tags" ng-if="ctrl.panel.showTags && trigger.tags">
|
|
||||||
<span ng-repeat="tag in trigger.tags" ng-click="ctrl.addTagFilter(tag, trigger.datasource)"
|
|
||||||
tag-color-from-name="tag.tag+tag.value" class="label label-tag zbx-tag">
|
|
||||||
{{tag.tag}}: {{tag.value}}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="alert-rule-item__text">
|
|
||||||
<span ng-if="ctrl.panel.statusField" class="zbx-trigger-state"
|
|
||||||
ng-class="ctrl.getAlertStateClass(trigger)">
|
|
||||||
{{ctrl.triggerStatusMap[trigger.value]}}
|
|
||||||
</span>
|
|
||||||
<span ng-if="ctrl.panel.severityField" class="zbx-trigger-severity"
|
|
||||||
ng-class="ctrl.getAlertStateClass(trigger)"
|
|
||||||
ng-style="!ctrl.panel.highlightBackground && {color: trigger.color}">
|
|
||||||
{{trigger.severity}}
|
|
||||||
</span>
|
|
||||||
<span class="alert-rule-item__time">
|
|
||||||
{{trigger.age && "for " + trigger.age}}
|
|
||||||
</span>
|
|
||||||
<span class="zbx-description"
|
|
||||||
ng-if="ctrl.panel.descriptionField && !ctrl.panel.descriptionAtNewLine"
|
|
||||||
ng-bind-html="trigger.comments">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- If description at the new line -->
|
|
||||||
<div class="alert-rule-item__text"
|
|
||||||
ng-if="trigger.comments && ctrl.panel.descriptionField && ctrl.panel.descriptionAtNewLine">
|
|
||||||
<span class="alert-rule-item__info zbx-description zbx-description--newline"
|
|
||||||
ng-bind-html="trigger.comments">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Datasource name -->
|
|
||||||
<div class="alert-rule-item__time zabbix-trigger-source" ng-if="ctrl.panel.datasources.length > 1">
|
|
||||||
<span>
|
|
||||||
<i class="fa fa-database"></i>
|
|
||||||
{{trigger.datasource}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert-rule-item__time zbx-trigger-lastchange">
|
|
||||||
<span>{{trigger.lastchange || "last change unknown"}}</span>
|
|
||||||
|
|
||||||
<div class="trigger-info-block zbx-status-icons">
|
|
||||||
<a ng-if="trigger.url" href="{{trigger.url}}" target="_blank">
|
|
||||||
<i class="fa fa-external-link"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<span ng-if="trigger.state === '1'" bs-tooltip="'{{trigger.error}}'">
|
|
||||||
<i class="fa fa-question-circle"></i>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<ack-tooltip ng-if="trigger.lastEvent" ack="trigger.acknowledges" trigger="trigger"
|
|
||||||
on-ack="ctrl.acknowledgeTrigger" context="ctrl">
|
|
||||||
</ack-tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="triggers-panel-footer"></div>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user