New: App health displayed in UI

This commit is contained in:
Mark McDowall 2014-02-25 21:40:47 -08:00
parent 90a6bcaa47
commit c8ae9f40fb
54 changed files with 873 additions and 44 deletions

View file

@ -48,7 +48,7 @@
.icon-nd-warning:before {
.icon(@warning-sign);
color : #f89406;
color : @orange;
}
.icon-nd-edit:before {
@ -79,7 +79,7 @@
.icon-nd-form-warning:before {
.icon(@warning-sign);
color: #f89406;
color: @orange;
}
.icon-nd-form-danger:before {
@ -175,4 +175,14 @@
.icon-nd-restart:before {
.icon(@repeat);
}
.icon-nd-health-warning:before {
.icon(@exclamation-sign);
color : @orange
}
.icon-nd-health-error:before {
.icon(@exclamation-sign);
color : @errorText
}

View file

@ -22,6 +22,8 @@
li {
list-style-type : none;
display : inline-block;
position : relative;
a {
&:focus {
@ -38,21 +40,20 @@
font-weight : 100;
}
span.label.pull-right {
position : relative;
top : 24px;
right : 14px;
position : absolute;
top : 28px;
right : 18px;
}
}
}
.backdrop #nav-region {
background-color : #000000;
.opacity(0.85);
}
.backdrop {
#nav-region {
background-color : #000000;
.opacity(0.85);
}
#nav-region li a:hover, #in-sub-nav li a.active {
background-color : #555555;
text-decoration : none;
}
#nav-region {
@ -62,6 +63,19 @@
.span12 {
margin-left : 0px;
}
li {
a {
&:hover {
background-color : #555555;
text-decoration : none;
}
.label {
cursor: pointer;
}
}
}
}
.search {

View file

@ -0,0 +1,16 @@
'use strict';
define(
[
'backbone',
'Health/HealthModel',
'Mixins/backbone.signalr.mixin'
], function (Backbone, HealthModel) {
var Collection = Backbone.Collection.extend({
url : window.NzbDrone.ApiRoot + '/health',
model: HealthModel
});
var collection = new Collection().bindSignalR();
collection.fetch();
return collection;
});

View file

@ -0,0 +1,9 @@
'use strict';
define(
[
'backbone'
], function (Backbone) {
return Backbone.Model.extend({
});
});

View file

@ -0,0 +1,39 @@
'use strict';
define(
[
'underscore',
'marionette',
'Health/HealthCollection'
], function (_, Marionette, HealthCollection) {
return Marionette.ItemView.extend({
initialize: function () {
this.listenTo(HealthCollection, 'sync', this._healthSync);
HealthCollection.fetch();
},
render: function () {
this.$el.empty();
if (HealthCollection.length === 0) {
return this;
}
var count = HealthCollection.length;
var label = 'label-warning';
var errors = HealthCollection.some(function (model) {
return model.get('type') === 'error';
});
if (errors) {
label = 'label-important';
}
this.$el.html('<span class="label pull-right {0}">{1}</span>'.format(label, count));
return this;
},
_healthSync: function () {
this.render();
}
});
});

View file

@ -47,6 +47,7 @@
<i class="icon-laptop"></i>
<br>
System
<span id="x-health"></span>
</a>
</li>
<li>

View file

@ -3,10 +3,15 @@ define(
[
'marionette',
'jquery',
'Health/HealthView',
'Navbar/Search'
], function (Marionette, $) {
return Marionette.ItemView.extend({
template: 'Navbar/NavbarTemplate',
], function (Marionette, $, HealthView) {
return Marionette.Layout.extend({
template: 'Navbar/NavbarLayoutTemplate',
regions: {
health: '#x-health'
},
ui: {
search: '.x-series-search'
@ -18,6 +23,7 @@ define(
onRender: function () {
this.ui.search.bindSearch();
this.health.show(new HealthView());
},
onClick: function (event) {
@ -30,9 +36,9 @@ define(
var href = event.target.getAttribute('href');
//if couldn't find it look up'
if (!href && target.parent('a') && target.parent('a')[0]) {
if (!href && target.closest('a') && target.closest('a')[0]) {
var linkElement = target.parent('a')[0];
var linkElement = target.closest('a')[0];
href = linkElement.getAttribute('href');
this.setActive(linkElement);

View file

@ -1,7 +1,7 @@
'use strict';
define([
'vent',
'marionette',
'vent',
'marionette',
'backgrid',
'System/Info/DiskSpace/DiskSpaceCollection',
'Shared/LoadingView',
@ -14,6 +14,7 @@ define([
regions: {
grid: '#x-grid'
},
columns:
[
{
@ -37,6 +38,7 @@ define([
this.collection = new DiskSpaceCollection();
this.listenTo(this.collection, 'sync', this._showTable);
},
onRender : function() {
this.grid.show(new LoadingView());
},
@ -44,6 +46,7 @@ define([
onShow: function() {
this.collection.fetch();
},
_showTable: function() {
this.grid.show(new Backgrid.Grid({
row: Backgrid.Row,

View file

@ -0,0 +1,18 @@
'use strict';
define(
[
'Cells/NzbDroneCell'
], function (NzbDroneCell) {
return NzbDroneCell.extend({
className: 'log-level-cell',
render: function () {
var level = this._getValue();
this.$el.html('<i class="icon-nd-health-{0}" title="{1}"/>'.format(this._getValue().toLowerCase(), level));
return this;
}
});
});

View file

@ -0,0 +1,55 @@
'use strict';
define(
[
'marionette',
'backgrid',
'Health/HealthCollection',
'System/Info/Health/HealthCell',
'System/Info/Health/HealthOkView'
], function (Marionette, Backgrid, HealthCollection, HealthCell, HealthOkView) {
return Marionette.Layout.extend({
template: 'System/Info/Health/HealthLayoutTemplate',
regions: {
grid: '#x-health-grid'
},
columns:
[
{
name: 'type',
label: '',
cell: HealthCell
},
{
name: 'message',
label: 'Message',
cell: 'string'
}
],
initialize: function () {
this.listenTo(HealthCollection, 'sync', this.render);
HealthCollection.fetch();
},
onRender : function() {
if (HealthCollection.length === 0) {
this.grid.show(new HealthOkView());
}
else {
this._showTable();
}
},
_showTable: function() {
this.grid.show(new Backgrid.Grid({
row: Backgrid.Row,
columns: this.columns,
collection: HealthCollection,
className:'table table-hover'
}));
}
});
});

View file

@ -0,0 +1,6 @@
<fieldset class="x-health">
<legend>Health</legend>
<div id="x-health-grid"/>
</fieldset>

View file

@ -0,0 +1,9 @@
'use strict';
define(
[
'marionette'
], function (Marionette) {
return Marionette.ItemView.extend({
template: 'System/Info/Health/HealthOkViewTemplate'
});
});

View file

@ -0,0 +1,2 @@
No issues with your configuration

View file

@ -4,22 +4,26 @@ define(
'backbone',
'marionette',
'System/Info/About/AboutView',
'System/Info/DiskSpace/DiskSpaceLayout'
'System/Info/DiskSpace/DiskSpaceLayout',
'System/Info/Health/HealthLayout'
], function (Backbone,
Marionette,
AboutView,
DiskSpaceLayout) {
DiskSpaceLayout,
HealthLayout) {
return Marionette.Layout.extend({
template: 'System/Info/SystemInfoLayoutTemplate',
regions: {
about : '#about',
diskSpace: '#diskspace'
diskSpace: '#diskspace',
health : '#health'
},
onRender: function () {
this.about.show(new AboutView());
this.diskSpace.show(new DiskSpaceLayout());
this.health.show(new HealthLayout());
}
});
});

View file

@ -1,4 +1,8 @@
<div class="row">
<div class="span12" id="health"></div>
</div>
<div class="row">
<div class="span12" id="about"></div>
</div>

View file

@ -33,9 +33,9 @@ define(
var href = event.target.getAttribute('href');
if (!href && $target.parent('a') && $target.parent('a')[0]) {
if (!href && $target.closest('a') && $target.closest('a')[0]) {
var linkElement = $target.parent('a')[0];
var linkElement = $target.closest('a')[0];
href = linkElement.getAttribute('href');
}