Implement topbar

Change-Id: Ifc1da63e420fbf72d46f2463bb09678a220a9d47
This commit is contained in:
Vincent Fournier 2015-08-03 13:51:47 -04:00
parent 43457faac2
commit 521f748087
17 changed files with 241 additions and 152 deletions

View File

@ -56,7 +56,8 @@ angular.module('bansho.authentication', [])
.factory('authService', [ '$http', '$location', '$rootScope', 'session', 'configManager', 'themeManager', 'surveilConfig', .factory('authService', [ '$http', '$location', '$rootScope', 'session', 'configManager', 'themeManager', 'surveilConfig',
function ($http, $location, $rootScope, session, configManager, themeManager, surveilConfig) { function ($http, $location, $rootScope, session, configManager, themeManager, surveilConfig) {
var authService = {}; var authService = {},
onLogin = [];
authService.login = function (credentials) { authService.login = function (credentials) {
return $http return $http
@ -70,6 +71,10 @@ angular.module('bansho.authentication', [])
configManager.fetchLayoutConfig(configManager.getConfig().useStoredConfig).then(function () { configManager.fetchLayoutConfig(configManager.getConfig().useStoredConfig).then(function () {
themeManager.setTheme(configManager.getTheme()); themeManager.setTheme(configManager.getTheme());
$location.path('/view'); $location.path('/view');
angular.forEach(onLogin, function (f) {
f();
});
}, function (message) { }, function (message) {
throw new Error(message); throw new Error(message);
}); });
@ -95,6 +100,10 @@ angular.module('bansho.authentication', [])
themeManager.switchTheme(); themeManager.switchTheme();
}; };
authService.registerOnLogin = function (f) {
onLogin.push(f);
};
return authService; return authService;
}]) }])

View File

@ -2,6 +2,63 @@
"banshoConfig": { "banshoConfig": {
"theme": "dark" "theme": "dark"
}, },
"topbar": {
"template": "page",
"components": [
{
"type": "tabpanel",
"attributes": {
"navigation": [
{
"title": "Open problems",
"panelId": "openProblems",
"provider": "nbServicesHostsOpenProblems"
},
{
"title": "All problems",
"panelId": "allProblems",
"provider": "nbServicesHostsProblems"
}
]
},
"components": [
{
"type": "panel",
"attributes": {
"panelId": "openProblems"
},
"components": [
{
"type": "host-tree",
"attributes": {
"inputSource": [
"hostOpenProblems",
"serviceOpenProblemsOnly"
]
}
}
]
},
{
"type": "panel",
"attributes": {
"panelId": "openProblems"
},
"components": [
{
"type": "host-tree",
"attributes": {
"inputSource": [
"servicesProblems"
]
}
}
]
}
]
}
]
},
"dashboardConfig": { "dashboardConfig": {
"template": "page", "template": "page",
"components": [ "components": [

View File

@ -96,11 +96,22 @@ angular.module('bansho.datasource', ['bansho.surveil'])
}; };
}]) }])
.service('sharedData', ['templateManager', 'surveilStatus', .service('sharedData', ['templateManager', 'surveilStatus', 'componentsConfig',
function (templateManager, surveilStatus) { function (templateManager, surveilStatus, componentsConfig) {
var sharedData = {}, var providerServices = {
status: surveilStatus
},
sharedData = {},
listeners = {}, listeners = {},
providers = { providers = {
'nbServicesHostsProblems': function () {
surveilStatus.getNbHostsProblems().then(function (nbHosts) {
surveilStatus.getNbServicesProblems().then(function (nbServices) {
sharedData.nbServicesHostsProblems = nbHosts + nbServices;
notifyListeners('nbServicesHostsProblems');
});
});
},
'nbHostsOpenProblems': function () { 'nbHostsOpenProblems': function () {
surveilStatus.getNbHostOpenProblems().then(function (nbHostProblems) { surveilStatus.getNbHostOpenProblems().then(function (nbHostProblems) {
sharedData.nbHostsOpenProblems = nbHostProblems; sharedData.nbHostsOpenProblems = nbHostProblems;
@ -167,6 +178,30 @@ angular.module('bansho.datasource', ['bansho.surveil'])
} }
return sharedData[key]; return sharedData[key];
},
getDataFromInputSource: function (source, onChange) {
if (listeners[source] === undefined) {
listeners[source] = [onChange];
var inputSource = componentsConfig.getInputSource(source);
providers[source] = function () {
providerServices[inputSource.provider].getData([], componentsConfig.getFilter(inputSource.filter).filter, inputSource.endpoint)
.then(function (newData) {
sharedData[source] = newData;
notifyListeners(source);
}, function (error) {
throw new Error('getTableData : Query failed' + error);
});
};
templateManager.addInterval(providers[source]);
providers[source]();
} else {
listeners[source].push(onChange);
}
return sharedData[source];
} }
}; };
}]); }]);

View File

@ -3,6 +3,7 @@
angular.module('bansho.directive', [ angular.module('bansho.directive', [
'bansho.actionbar', 'bansho.actionbar',
'bansho.host', 'bansho.host',
'bansho.hostTree',
'bansho.service', 'bansho.service',
'bansho.table', 'bansho.table',
'bansho.tabpanel', 'bansho.tabpanel',

View File

@ -4,7 +4,9 @@
<tbody> <tbody>
<tr> <tr>
<td>State</td> <td>State</td>
<td><bansho-host-state-icon state="param.host.host_state"></bansho-host-state-icon> {{param.host.host_state}}</td> <td bansho-host-state-icon state="param.host.host_state">
<span class="data-table__data">{{param.host.host_state}}</span>
</td>
</tr> </tr>
<tr> <tr>
<td>Output</td> <td>Output</td>

View File

@ -12,7 +12,9 @@
<tr ng-repeat="service in param.host.services"> <tr ng-repeat="service in param.host.services">
<td><a href="#/view?view=service&host_name={{service.service_host_name}}&description={{service.service_service_description}}">{{service.service_service_description}}</a> <td><a href="#/view?view=service&host_name={{service.service_host_name}}&description={{service.service_service_description}}">{{service.service_service_description}}</a>
<td>{{service.service_acknowledged ? "Yes" : "No"}}</td> <td>{{service.service_acknowledged ? "Yes" : "No"}}</td>
<td><bansho-service-state-icon state="service.service_state"></bansho-service-state-icon>{{service.service_state}}</td> <td bansho-service-state-icon state="service.service_state">
<span class="data-table__data">{{service.service_state}}</span>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -0,0 +1,22 @@
<ol class="problems__list">
<span data-ng-repeat="source in sources">
<span data-ng-repeat="(key, host) in source | groupBy: 'host_description'">
<li class="problems_item">
<a href="#/view?view=host&host_name={{key}}">
<strong class="problems__host" bansho-host-state-icon state="host[0].host_state">{{key}}</strong>
</a>
<dl class="problems__desclist" data-ng-repeat="service in host">
<span data-ng-show="service.service_service_description">
<dt class="problems__name" bansho-service-state-icon state="service.service_state">
<a href="#/view?view=service&host_name={{key}}&description={{service.service_service_description}}">
{{service.service_service_description}}
</a>
<small class="problems__duration">2 days, 8 hours</small>
</dt>
<dd class="problems__description">{{service.service_plugin_output}}</dd>
</span>
</dl>
</li>
</span>
</span>
</ol>

View File

@ -0,0 +1,23 @@
'use strict';
angular.module('bansho.hostTree', ['bansho.datasource'])
.directive('banshoHostTree', function () {
return {
restrict: 'E',
scope: {
options: '='
},
templateUrl: 'components/directive/hostTree/hostTree.html',
controller: ['$scope', 'sharedData',
function ($scope, sharedData) {
$scope.sources = {};
angular.forEach($scope.options.attributes.inputSource, function (source) {
$scope.sources[source] = sharedData.getDataFromInputSource(source, function (data) {
$scope.sources[source] = data;
});
});
$scope.components = $scope.options.components;
}]
};
});

View File

@ -4,7 +4,9 @@
<tbody> <tbody>
<tr> <tr>
<td>State</td> <td>State</td>
<td><bansho-service-state-icon state="param.service.service_state"></bansho-service-state-icon> {{param.service.service_state}}</td> <td bansho-service-state-icon state="param.service.service_state">
<span class="data-table__data">{{param.service.service_state}}</span>
</td>
</tr> </tr>
<tr> <tr>
<td>Output</td> <td>Output</td>

View File

@ -0,0 +1,48 @@
'use strict';
angular.module('bansho.table')
.directive('banshoHostStateIcon', function () {
return {
restrict: 'EA',
scope: {
state: '='
},
link: function (scope, element) {
scope.$watch('state', function () {
element.removeClass('state--ok');
element.removeClass('state--warning');
element.removeClass('state--error');
if (scope.state === 'UP') {
element.addClass('state--ok');
} else if (scope.state === 'DOWN' || scope.state === 'UNREACHABLE') {
element.addClass('state--error');
}
});
}
};
})
.directive('banshoServiceStateIcon', function () {
return {
restrict: 'EA',
scope: {
state: '='
},
link: function (scope, element) {
scope.$watch('state', function () {
element.removeClass('state--ok');
element.removeClass('state--warning');
element.removeClass('state--error');
if (scope.state === 'OK') {
element.addClass('state--ok');
} else if (scope.state === 'WARNING') {
element.addClass('state--warning');
} else if (scope.state === 'CRITICAL' || scope.state === 'UNKNOWN') {
element.addClass('state--error');
}
});
}
};
});

View File

@ -1,3 +1,3 @@
<td ng-controller="CellStatusHostStatusCtrl"> <td ng-controller="CellStatusHostStatusCtrl">
<span class="data-table__data">{{entry.host_state}}</span> <span class="data-table__data {{entry.host_state}}">{{entry.host_state}}</span>
</td> </td>

View File

@ -1,3 +0,0 @@
<span class="data-table__host {{stateClass}}">
<a class="data-table__data"></a>
</span>

View File

@ -1,48 +0,0 @@
'use strict';
angular.module('bansho.table')
.directive('banshoHostStateIcon', function () {
return {
restrict: 'E',
scope: {
state: '='
},
templateUrl: 'components/directive/table/state_icon/state_icon.html',
controller: ['$scope', function ($scope) {
$scope.$watch('state', function (newValue) {
if ($scope.state === 'UP') {
$scope.stateClass = 'state--ok';
} else if ($scope.state === 'WARNING') {
$scope.stateClass = 'state--warning';
} else if ($scope.state === '') {
$scope.stateClass = '';
} else {
$scope.stateClass = 'state--error';
}
});
}]
};
})
.directive('banshoServiceStateIcon', function () {
return {
restrict: 'E',
scope: {
state: '='
},
templateUrl: 'components/directive/table/state_icon/state_icon.html',
controller: ['$scope', function ($scope) {
$scope.$watch('state', function (newValue) {
if ($scope.state === 'OK') {
$scope.stateClass = 'state--ok';
} else if ($scope.state === 'WARNING') {
$scope.state = 'state--warning';
} else if ($scope.state === '') {
$scope.stateClass = '';
} else {
$scope.stateClass = 'state--error';
}
});
}]
};
});

View File

@ -236,6 +236,14 @@ angular.module('bansho.surveil')
}); });
return promise.promise; return promise.promise;
}, },
getNbServicesProblems: function () {
var promise = $q.defer();
getData([], componentsConfig.getFilter("allServicesProblems").filter, "services")
.then(function (data) {
promise.resolve(data.length);
});
return promise.promise;
},
getHostMetric: function (host, metric) { getHostMetric: function (host, metric) {
return getMetric(host, undefined, metric); return getMetric(host, undefined, metric);
}, },

View File

@ -17,96 +17,17 @@
type="button" type="button"
data-toggle="collapse" data-toggle="collapse"
data-target="#notificationsPanel" data-target="#notificationsPanel"
aria-expanded="false" aria-expanded="true"
aria-controls="notificationsPanel"> aria-controls="notificationsPanel">
<span class="visuallyhidden">Voir les notifications</span> <span class="visuallyhidden">Voir les notifications</span>
<i class="ico-bell-alt" data-notifications="{{allProblems}}"></i> <i class="ico-bell-alt" data-notifications="{{allProblems}}"></i>
</button> </button>
<div class="topbar__panel--fromleft collapse" id="notificationsPanel"> <div class="topbar__panel--fromleft collapse" id="notificationsPanel">
<div class="topbar__panel__content tabpanel"> <div class="topbar__panel__content">
<ul class="tablist clearfix"> <bansho-components components="components"></bansho-components>
<li role="presentation" class="tablist__item active">
<a href="#topOpenProblems"
class="tabpanel__tab"
aria-controls="topOpenProblems"
aria-expanded="true"
role="tab"
data-toggle="tab"
data-problems="27">Open problems
</a>
</li>
<li role="presentation" class="tablist__item">
<a href="#topAllProblems"
class="tabpanel__tab"
aria-controls="topAllProblems"
aria-expanded="false"
role="tab"
data-toggle="tab"
data-problems="38">All problems
</a>
</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="problems tab-pane active" id="topOpenProblems">
<ol class="problems__list">
<li class="problems__item">
<strong class="problems__host state--ok">localhost</strong>
<dl class="problems__desclist">
<dt class="problems__name state--warning">
<span>Root partition</span>
<small class="problems__duration">2 days, 8 hours</small>
</dt>
<dd class="problems__description">Disk warning - free space : / 673 MB (12% inode = 59%)</dd>
</dl>
</li>
<li class="problems__item">
<strong class="problems__host state--warning">www.theatlantic.com</strong>
<dl class="problems__desclist">
<dt class="problems__name state--warning">
<span>HTTP www.theatlantic.com</span>
<small class="problems__duration">6 days, 5 hours</small>
</dt>
<dd class="problems__description">Check_http: invalid onedirection - $</dd>
</dl>
</li>
<li class="problems__item">
<strong class="problems__host state--error">www.savoirfairelinux.com</strong>
<dl class="problems__desclist">
<dt class="problems__name state--warning">
<span>Verbis se superiores opere enim</span>
<small class="problems__duration">8 days, 5 hours</small>
</dt>
<dd class="problems__description">Check_http: invalid onedirection option - $</dd>
<dt class="problems__name state--error">
<span>CPU utilization</span>
<small class="problems__duration">1 days, 3 hours</small>
</dt>
<dd class="problems__description">NRPE: Command checkCPU not defined</dd>
<dt class="problems__name state--ok">
<span>Runnning services</span>
<small class="problems__duration">1 days, 12 hours</small>
</dt>
<dd class="problems__description">Levandi amicitias se fere - $</dd>
</dl>
</li>
</ol>
<button class="problems__viewall" type="button">View all open problems</button>
</div>
<div role="tabpanel" class="tab-pane" id="topAllProblems">
ALL PROBLEMS
</div> </div>
</div> </div>
</div>
</li>
</ul> </ul>
<ul class="topbar__list topbar__list--right"> <ul class="topbar__list topbar__list--right">

View File

@ -6,8 +6,8 @@ angular.module('bansho.topbar', ['bansho.surveil'])
return { return {
restrict: 'E', restrict: 'E',
templateUrl: 'components/topbar/topbar.html', templateUrl: 'components/topbar/topbar.html',
controller: ['$scope', '$timeout', 'authService', 'themeManager', controller: ['$compile', '$element', '$scope', 'authService', 'themeManager', 'viewsTemplate', 'sharedData', 'configManager',
function ($scope, $timeout, authService, themeManager) { function ($compile, $element, $scope, authService, themeManager, viewsTemplate, sharedData, configManager) {
$scope.logout = function () { $scope.logout = function () {
authService.logout(); authService.logout();
}; };
@ -15,6 +15,15 @@ angular.module('bansho.topbar', ['bansho.surveil'])
$scope.switchTheme = function () { $scope.switchTheme = function () {
themeManager.switchTheme(); themeManager.switchTheme();
}; };
authService.registerOnLogin(function () {
$scope.allProblems = sharedData.getData('nbServicesHostsOpenProblems', function (data) {
$scope.allProblems = data;
});
$scope.components = configManager.getConfigData('topbar').components;
$compile($element.contents())($scope);
});
}] }]
}; };
}); });

View File

@ -91,7 +91,7 @@
<script src="components/directive/table/cell_status_service_check/cell_status_service_check.js"></script> <script src="components/directive/table/cell_status_service_check/cell_status_service_check.js"></script>
<script src="components/directive/table/cell_status_host_address/cell_status_host_address.js"></script> <script src="components/directive/table/cell_status_host_address/cell_status_host_address.js"></script>
<script src="components/directive/table/cell_status_host_status/cell_status_host_status.js"></script> <script src="components/directive/table/cell_status_host_status/cell_status_host_status.js"></script>
<script src="components/directive/table/state_icon/state_icon.js"></script> <script src="components/directive/state_icon/state_icon.js"></script>
<script src="components/grafana/grafana.js"></script> <script src="components/grafana/grafana.js"></script>
<script src="components/directive/host/host.js"></script> <script src="components/directive/host/host.js"></script>
@ -101,6 +101,7 @@
<script src="components/directive/host/host_main/host_main.js"></script> <script src="components/directive/host/host_main/host_main.js"></script>
<script src="components/directive/host/host_live/host_live.js"></script> <script src="components/directive/host/host_live/host_live.js"></script>
<script src="components/directive/host/host_services_list/host_services_list.js"></script> <script src="components/directive/host/host_services_list/host_services_list.js"></script>
<script src="components/directive/hostTree/hostTree.js"></script>
<script src="components/directive/service/service.js"></script> <script src="components/directive/service/service.js"></script>
<script src="components/directive/service/service_main/service_main.js"></script> <script src="components/directive/service/service_main/service_main.js"></script>
<script src="components/directive/service/service_live/service_live.js"></script> <script src="components/directive/service/service_live/service_live.js"></script>