Commit 4c1a67c3 by Torkel Ödegaard

tech: began reworking alerting list to mobx

parent 8fd88537
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>
);
}
......@@ -12,7 +12,7 @@ export class ServerStats extends React.Component<IProps, any> {
constructor(props) {
super(props);
this.props.store.nav.load('cfg', 'admin', 'server-stats', 1);
this.props.store.nav.load('cfg', 'admin', 'server-stats');
this.props.store.serverStats.load();
}
......
///<reference path="../../headers/common.d.ts" />
import _ from 'lodash';
import { QueryPartDef, QueryPart } from 'app/core/components/query_part/query_part';
......
import './dashboard_loaders';
import './ReactContainer';
import { ServerStats } from 'app/containers/ServerStats/ServerStats';
import { AlertRuleList } from 'app/containers/AlertRuleList/AlertRuleList';
/** @ngInject **/
export function setupAngularRoutes($routeProvider, $locationProvider) {
......@@ -225,6 +226,12 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
controller: 'AlertListCtrl',
controllerAs: 'ctrl',
})
.when('/alerting/list2', {
template: '<react-container />',
resolve: {
component: () => AlertRuleList,
},
})
.when('/alerting/notifications', {
templateUrl: 'public/app/features/alerting/partials/notifications_list.html',
controller: 'AlertNotificationsListCtrl',
......
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));
}
}),
}));
......@@ -24,18 +24,13 @@ export const NavStore = types
let parents = [];
for (let id of args) {
// if its a number then it's the index to use for main
if (_.isNumber(id)) {
main = parents[id];
break;
}
node = _.find(children, { id: id });
main = node;
children = node.children;
parents.push(node);
}
main = parents[parents.length - 2];
if (main.children) {
for (let item of main.children) {
item.active = false;
......
......@@ -2,6 +2,7 @@ import { types } from 'mobx-state-tree';
import { SearchStore } from './SearchStore';
import { ServerStatsStore } from './ServerStatsStore';
import { NavStore } from './NavStore';
import { AlertingStore } from './AlertingStore';
export const RootStore = types.model({
search: types.optional(SearchStore, {
......@@ -11,6 +12,9 @@ export const RootStore = types.model({
stats: [],
}),
nav: types.optional(NavStore, {}),
alerting: types.optional(AlertingStore, {
rules: [],
}),
});
type IRootStoreType = typeof RootStore.Type;
......
......@@ -14,21 +14,16 @@ export const ServerStatsStore = types
load: flow(function* load() {
let backendSrv = getEnv(self).backendSrv;
try {
let res = yield backendSrv.get('/api/admin/stats');
self.stats.clear();
self.stats.push(ServerStat.create({ name: 'Total dashboards', value: res.dashboards }));
self.stats.push(ServerStat.create({ name: 'Total users', value: res.users }));
self.stats.push(ServerStat.create({ name: 'Active users (seen last 30 days)', value: res.activeUsers }));
self.stats.push(ServerStat.create({ name: 'Total orgs', value: res.orgs }));
self.stats.push(ServerStat.create({ name: 'Total playlists', value: res.playlists }));
self.stats.push(ServerStat.create({ name: 'Total snapshots', value: res.snapshots }));
self.stats.push(ServerStat.create({ name: 'Total dashboard tags', value: res.tags }));
self.stats.push(ServerStat.create({ name: 'Total starred dashboards', value: res.stars }));
self.stats.push(ServerStat.create({ name: 'Total alerts', value: res.alerts }));
} catch (err) {
console.log('ServerStats.load error', err);
self.error = err.toString();
}
let res = yield backendSrv.get('/api/admin/stats');
self.stats.clear();
self.stats.push(ServerStat.create({ name: 'Total dashboards', value: res.dashboards }));
self.stats.push(ServerStat.create({ name: 'Total users', value: res.users }));
self.stats.push(ServerStat.create({ name: 'Active users (seen last 30 days)', value: res.activeUsers }));
self.stats.push(ServerStat.create({ name: 'Total orgs', value: res.orgs }));
self.stats.push(ServerStat.create({ name: 'Total playlists', value: res.playlists }));
self.stats.push(ServerStat.create({ name: 'Total snapshots', value: res.snapshots }));
self.stats.push(ServerStat.create({ name: 'Total dashboard tags', value: res.tags }));
self.stats.push(ServerStat.create({ name: 'Total starred dashboards', value: res.stars }));
self.stats.push(ServerStat.create({ name: 'Total alerts', value: res.alerts }));
}),
}));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment