mirror of https://github.com/grafana/grafana
parent
8fd8853770
commit
4c1a67c34e
@ -0,0 +1,94 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import classNames from 'classnames'; |
||||||
|
import { inject, observer } from 'mobx-react'; |
||||||
|
import PageHeader from 'app/core/components/PageHeader/PageHeader'; |
||||||
|
|
||||||
|
export interface IProps { |
||||||
|
store: any; |
||||||
|
} |
||||||
|
|
||||||
|
@inject('store') |
||||||
|
@observer |
||||||
|
export class AlertRuleList extends React.Component<IProps, any> { |
||||||
|
constructor(props) { |
||||||
|
super(props); |
||||||
|
|
||||||
|
this.props.store.nav.load('alerting', 'alert-list'); |
||||||
|
this.props.store.alerting.loadRules(); |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<PageHeader model={this.props.store.nav} /> |
||||||
|
<div className="page-container page-body"> |
||||||
|
<div className="page-action-bar"> |
||||||
|
<div className="gf-form"> |
||||||
|
<label className="gf-form-label">Filter by state</label> |
||||||
|
|
||||||
|
<div className="gf-form-select-wrapper width-13"> |
||||||
|
<select |
||||||
|
className="gf-form-input" |
||||||
|
ng-model="ctrl.filters.state" |
||||||
|
ng-options="f.value as f.text for f in ctrl.stateFilters" |
||||||
|
ng-change="ctrl.filtersChanged()" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div className="page-action-bar__spacer" /> |
||||||
|
|
||||||
|
<a className="btn btn-secondary" ng-click="ctrl.openHowTo()"> |
||||||
|
<i className="fa fa-info-circle" /> How to add an alert |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<section className="card-section card-list-layout-list"> |
||||||
|
<ol className="card-list">{this.props.store.alerting.rules.map(AlertRuleItem)}</ol> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function AlertRuleItem(rule) { |
||||||
|
let stateClass = classNames({ |
||||||
|
fa: true, |
||||||
|
'fa-play': rule.state === 'paused', |
||||||
|
'fa-pause': rule.state !== 'paused', |
||||||
|
}); |
||||||
|
|
||||||
|
let ruleUrl = `dashboard/${rule.dashboardUri}?panelId=${rule.panelId}&fullscreen&edit&tab=alert`; |
||||||
|
|
||||||
|
return ( |
||||||
|
<li className="card-item-wrapper"> |
||||||
|
<div className="card-item card-item--alert"> |
||||||
|
<div className="card-item-header"> |
||||||
|
<div className="card-item-type"> |
||||||
|
<a className="card-item-cog" title="Pausing an alert rule prevents it from executing"> |
||||||
|
<i className={stateClass} /> |
||||||
|
</a> |
||||||
|
<a className="card-item-cog" href={ruleUrl} title="Edit alert rule"> |
||||||
|
<i className="icon-gf icon-gf-settings" /> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="card-item-body"> |
||||||
|
<div className="card-item-details"> |
||||||
|
<div className="card-item-name"> |
||||||
|
<a href={ruleUrl}>{rule.name}</a> |
||||||
|
</div> |
||||||
|
<div className="card-item-sub-name"> |
||||||
|
<span className={`alert-list-item-state ${rule.stateClass}`}> |
||||||
|
<i className={rule.stateIcon} /> {rule.stateText} |
||||||
|
</span> |
||||||
|
<span> for {rule.stateAge}</span> |
||||||
|
</div> |
||||||
|
{rule.info && <div className="small muted">{rule.info}</div>} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
); |
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
import { types, getEnv, flow } from 'mobx-state-tree'; |
||||||
|
import moment from 'moment'; |
||||||
|
import alertDef from 'app/features/alerting/alert_def'; |
||||||
|
|
||||||
|
export const AlertRule = types.model('AlertRule', { |
||||||
|
id: types.identifier(types.number), |
||||||
|
dashboardId: types.number, |
||||||
|
panelId: types.number, |
||||||
|
name: types.string, |
||||||
|
state: types.string, |
||||||
|
stateText: types.string, |
||||||
|
stateIcon: types.string, |
||||||
|
stateClass: types.string, |
||||||
|
stateAge: types.string, |
||||||
|
info: types.string, |
||||||
|
dashboardUri: types.string, |
||||||
|
}); |
||||||
|
|
||||||
|
export const AlertingStore = types |
||||||
|
.model('AlertingStore', { |
||||||
|
rules: types.array(AlertRule), |
||||||
|
}) |
||||||
|
.actions(self => ({ |
||||||
|
loadRules: flow(function* load() { |
||||||
|
let backendSrv = getEnv(self).backendSrv; |
||||||
|
|
||||||
|
let rules = yield backendSrv.get('/api/alerts'); |
||||||
|
|
||||||
|
self.rules.clear(); |
||||||
|
|
||||||
|
for (let rule of rules) { |
||||||
|
let stateModel = alertDef.getStateDisplayModel(rule.state); |
||||||
|
rule.stateText = stateModel.text; |
||||||
|
rule.stateIcon = stateModel.iconClass; |
||||||
|
rule.stateClass = stateModel.stateClass; |
||||||
|
rule.stateAge = moment(rule.newStateDate) |
||||||
|
.fromNow() |
||||||
|
.replace(' ago', ''); |
||||||
|
|
||||||
|
if (rule.executionError) { |
||||||
|
rule.info = 'Execution Error: ' + rule.executionError; |
||||||
|
} |
||||||
|
|
||||||
|
if (rule.evalData && rule.evalData.noData) { |
||||||
|
rule.info = 'Query returned no data'; |
||||||
|
} |
||||||
|
|
||||||
|
self.rules.push(AlertRule.create(rule)); |
||||||
|
} |
||||||
|
}), |
||||||
|
})); |
||||||
Loading…
Reference in new issue