2 * Copyright (c) 2016 highstreet technologies GmbH and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 define(['app/mwtnFault/mwtnFault.module',
10 'app/mwtnFault/mwtnFault.services',
11 'app/mwtnFault/mwtnFault.directives'],
12 function(mwtnFaultApp) {
14 mwtnFaultApp.register.controller('mwtnFaultCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$mwtnFault', '$mwtnLog', '$http',
15 function(uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $mwtnFault, $mwtnLog, $http) {
18 var COMPONENT = 'mwtnFaultCtrl';
19 $mwtnLog.info({component: COMPONENT, message: 'mwtnFaultCtrl started!'});
21 $rootScope.section_logo = 'src/app/mwtnFault/images/mwtnFault.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif'
23 $scope.date = new Date().toISOString().toHumanReadableTimeFormat();
24 $scope.highlightFilteredHeader = $mwtnFault.highlightFilteredHeader;
25 $scope.oneATime = true;
27 // var rowTemplate = '<div ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ng-class="[\'ui-grid-cell\', row.entity.type]" ui-grid-cell></div>';
28 var iconCell = '<div class="ui-grid-cell-contents tooltip-uigrid" title="TOOLTIP"><i class="fa {{COL_FIELD}}" aria-hidden="true"></i></div>';
29 var getIconFromSeverity = function(severity) {
33 Critical : 'fa-exclamation-triangle',
34 Major : 'fa-exclamation-triangle',
35 Minor : 'fa-exclamation-triangle',
36 Warning : 'fa-times-circle'
38 return mapping[severity];
41 // Current Problem List
42 $scope.gridOptionsCurrentProblemList = JSON.parse(JSON.stringify($mwtnFault.gridOptions));
43 $scope.gridOptionsCurrentProblemList.columnDefs = [
44 // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true },
45 { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell },
46 { field: 'timestamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200, sort: {
47 direction: uiGridConstants.DESC,
50 { field: 'node', type: 'string', displayName: 'Node name', headerCellClass: $scope.highlightFilteredHeader, width: 200 },
51 { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 70, cellClass: 'number' },
52 { field: 'object', type: 'string', displayName: 'Object Id', headerCellClass: $scope.highlightFilteredHeader, width: 300 },
53 { field: 'problem', type: 'string', displayName: 'Alarm type', headerCellClass: $scope.highlightFilteredHeader, width : 200 },
54 { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 150 }
58 var processCurrentProblemEntries = function(logEntries) {
59 if (logEntries.data.hits.hits) {
60 $scope.gridOptionsCurrentProblemList.data = logEntries.data.hits.hits.map(function(entry){
63 icon: getIconFromSeverity(entry._source.faultCurrent.severity),
64 timestamp: $mwtnFault.formatTimeStamp(entry._source.faultCurrent.timeStamp),
65 node: entry._source.faultCurrent.nodeName,
66 counter: entry._source.faultCurrent.counter,
67 object: entry._source.faultCurrent.objectId,
68 problem: entry._source.faultCurrent.problem,
69 severity: entry._source.faultCurrent.severity,
72 $scope.progress.max = logEntries.data.hits.total;
73 $scope.progress.value = $scope.gridOptionsCurrentProblemList.data.length;
74 $scope.progress.show = $scope.gridOptionsCurrentProblemList.data.length < logEntries.data.hits.total;
78 $scope.refreshCurrentProblemList = function() {
79 // $scope.gridOptionsCurrentProblemList.data = [];
82 $scope.processing = true;
83 $mwtnFault.getAllCurrentProblemEntries(from, size).then(function(logEntries){
84 $scope.processing = false;
85 $scope.spinner.currentProblemList = false;
86 processCurrentProblemEntries(logEntries);
88 while (from < $scope.progress.max) {
89 $mwtnFault.getAllCurrentProblemEntries(from, size).then(function(logEntries){
90 processCurrentProblemEntries(logEntries);
92 console.error(JSON.stringify(error));
97 $scope.processing = false;
98 $scope.spinner.currentProblemList = false;
99 console.error(JSON.stringify(error));
103 // Alarm Notifications
104 $scope.gridOptionsAlarmNotifications = JSON.parse(JSON.stringify($mwtnFault.gridOptions));
105 $scope.gridOptionsAlarmNotifications.columnDefs = [
106 // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true },
107 { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell },
108 { field: 'timeStamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200,sort: {
109 direction: uiGridConstants.DESC,
112 { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 90 },
113 { field: 'nodeName', type: 'string', displayName: 'NetworkElement', headerCellClass: $scope.highlightFilteredHeader, width: 170 },
114 { field: 'objectId', type: 'string', displayName: 'Object', headerCellClass: $scope.highlightFilteredHeader, width: 400 },
116 { field: 'problem', type: 'string', displayName: 'Alarm', headerCellClass: $scope.highlightFilteredHeader, width : 140 },
117 { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 100 }
119 var listenToNotifications = function() {
120 $mwtnFault.getMwtnWebSocketUrl().then(function(success){
122 var notificationSocket = new WebSocket(success);
124 notificationSocket.onmessage = function(event) {
125 // we process our received event here
126 if (typeof event.data === 'string') {
127 // console.log("Client Received:\n" + event.data);
128 // console.log("---------------------------");
129 $mwtnFault.formatData(event).then(function(formated) {
130 switch (formated.notifType) {
131 case 'ProblemNotification':
132 formated.icon = getIconFromSeverity(formated.severity);
133 $scope.gridOptionsAlarmNotifications.data.push(formated);
134 $timeout(function(){$scope.refreshCurrentProblemList();}, 500);
136 case 'AttributeValueChangedNotification':
137 case 'ObjectCreationNotification':
138 case 'ObjectDeletionNotification':
142 console.error('Missing implementation for', formated.notifType);
150 notificationSocket.onerror = function(error) {
151 console.log("Socket error: " + error);
154 notificationSocket.onopen = function(event) {
155 console.log("Socket connection opened.");
157 function subscribe() {
158 if (notificationSocket.readyState === notificationSocket.OPEN) {
161 'scopes' : [ "ProblemNotification" ]
163 notificationSocket.send(JSON.stringify(data));
169 notificationSocket.onclose = function(event) {
170 console.log("Socket connection closed.");
173 console.error("Error when creating WebSocket.\n" + e);
176 console.error("Error when creating WebSocket.\n" + error);
179 listenToNotifications();
182 // $scope.gridOptionsAlarmLog = JSON.parse(JSON.stringify($mwtnFault.gridOptions));
184 $scope.paginationOptions = {
190 $scope.gridOptionsAlarmLog = {
191 paginationPageSizes: [25, 100, 1000, 10000],
192 paginationPageSize: 25,
193 useExternalPagination: true,
194 useExternalSorting: true,
195 enablePaginationControls: false,
196 enableFiltering: true,
197 useExternalFiltering: true,
199 // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true },
200 { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell },
201 { field: 'timestamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200, sort: {
202 direction: uiGridConstants.DESC,
205 { field: 'node', type: 'string', displayName: 'Node name', headerCellClass: $scope.highlightFilteredHeader, width: 200 },
206 { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 70, cellClass: 'number' },
207 { field: 'object', type: 'string', displayName: 'Object Id', headerCellClass: $scope.highlightFilteredHeader, width: 300 },
208 { field: 'problem', type: 'string', displayName: 'Alarm type', headerCellClass: $scope.highlightFilteredHeader, width : 200 },
209 { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 150 }
212 onRegisterApi: function(gridApi) {
213 $scope.gridApi = gridApi;
214 $scope.gridApi.core.on.filterChanged( $scope, $scope.filter);
215 $scope.gridApi.core.on.sortChanged( $scope, $scope.sortChanged );
216 $scope.sortChanged($scope.gridApi.grid, [ $scope.gridOptionsAlarmLog.columnDefs[1] ] );
218 $scope.gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
219 $scope.paginationOptions.pageNumber = newPage;
220 $scope.paginationOptions.pageSize = pageSize;
228 $scope.state.filter=false;
229 $scope.state.sort=false;
230 $scope.state.lastfilter=null;
231 $scope.state.lastSort=null;
233 $scope.maxCount=0; //value shown on screen
236 $scope.seekPage= function(page){
237 if(!page){ //catch NaN values
241 $scope.gridApi.pagination.seek(parseInt(page));
244 $scope.paginationStatusMessage = function() {
246 var startnum=($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize+1;
247 var pagenednum=($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize+1+$scope.data.length;
248 if(pagenednum>$scope.gridOptionsAlarmLog.totalItems) pagenednum=pagenednum-1; //reduce by initial added 1
250 if($scope.state.filter){
251 var filterTpl = 'Showing {0} to {1} of {2} items (filtered from {3} total items)';
252 return filterTpl.format(startnum, pagenednum, $scope.gridOptionsAlarmLog.totalItems, $scope.maxCount);
255 var defaultTpl = 'Showing {0} to {1} of {2} total items';
256 return defaultTpl.format( startnum, pagenednum, $scope.maxCount);
260 //list visible on screen
263 var getPage = function() {
264 //from, how many, sort, filter
265 getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize, $scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter)
266 .then(function (data) {
267 $scope.gridOptionsAlarmLog.totalItems = data.data.hits.total;
268 processResponseRecreateList(data);
273 $scope.filter = function()
275 var grid = this.grid;
278 //get all columns where data was typed in
279 angular.forEach(grid.columns, function(value, key) {
280 if(value.filters[0].term) {
281 var col=findColumn(value.displayName);
282 if(col==="fault.timeStamp"){
283 //convert timestamp to db format
284 var timestamp= $mwtnFault.TimeStampToONFFormat(value.filters[0].term);
285 columns.push({ column: col ,value: timestamp });
288 columns.push({ column: col ,value: value.filters[0].term }); //create column object
292 if(columns.length === 0){ //all filter data cleared away
293 $scope.state.filter=false;
294 $scope.state.lastfilter=null;
296 //get unfiltered data
297 getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) {
298 if (response.data.hits.hits) {
299 processResponseRecreateList(response);
306 var filter={"query":{"bool":{"must":[]}}};
308 //create filter objects
310 for(var obj of columns){
312 prefixObj[obj.column]=obj.value;//add like: {column: "fault.counter", value: "1"} => {"fault.counter":1}
313 prefixs.push({prefix:prefixObj}); // => {"prefix":{...}}
316 //add objects to must property
317 filter.query.bool.must=prefixs;
320 $scope.state.lastfilter=filter;
321 $scope.state.filter=true;
323 //send data to sdnevents/faultlog/_search
324 getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) {
325 if (response.data.hits.total>0) { //only, when hits exist
326 processResponseRecreateList(response);
327 $scope.gridOptionsAlarmLog.totalItems = response.data.hits.total;
329 //clear data from list
331 $scope.gridOptionsAlarmLog.totalItems =0;
332 $scope.state.filter=false;
333 $scope.state.lastfilter=null;
341 $scope.sortChanged=function(grid, sortColumns){ // sortColumns is an array containing just the column sorted in the grid
344 if(sortColumns.length>0){
345 if(sortColumns[0].sort){
346 var name = sortColumns[0].displayName; // the name of the column sorted
347 var direction = sortColumns[0].sort.direction; // the direction of the column sorted: "desc" or "asc"
348 sort(direction,findColumn(name));
351 $scope.state.sort=false;
352 $scope.state.lastSort=null;
355 getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) {
356 if (response.data.hits.hits) {
357 processResponseRecreateList(response);
363 function sort(direction, columnName){
366 var sort = [ sortObj];
368 case uiGridConstants.ASC:
371 sortObj[columnName]={order : 'asc'};
374 $scope.state.lastSort=sort;
376 getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) {
377 if (response.data.hits.hits) {
378 processResponseRecreateList(response);
379 $scope.state.sort=true;
385 case uiGridConstants.DESC:
387 sortObj[columnName]={order : 'desc'};
389 $scope.state.lastSort=sort;
391 getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) {
392 if (response.data.hits.hits) {
393 processResponseRecreateList(response);
394 $scope.state.sort=true;
401 $scope.state.sort=false;
402 $scope.state.lastSort=null;
404 getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter)
405 .then(function(response) {
406 if (response.data.hits.hits) {
407 processResponseRecreateList(response);
415 var findColumn = function(name) {
417 if(name==="Timestamp"){ return "fault.timeStamp"; }
418 else if(name==="Node name"){ return "fault.nodeName"; }
419 else if(name==="Counter"){ return "fault.counter"; }
420 else if(name==="Object Id"){ return "fault.objectId"; }
421 else if(name==="Alarm type"){return "fault.problem"; }
422 else if(name==="Severity"){ return "fault.severity"; }
426 var getData = function(from, size, sort, query){
427 if(sort === null){ //default sort value
428 sort = [ { "fault.timeStamp" : {order : 'desc'}}];
430 if(query === null){ //default filter value
431 query= {match_all: {}};
433 return $mwtnFault.getFilteredSortedData(from, size, sort, query);
436 var processResponseAddToList=function(response) {
437 if (response.data.hits.hits) {
438 response.data.hits.hits.map(function(entry){
441 icon: getIconFromSeverity(entry._source.fault.severity),
442 timestamp: $mwtnFault.formatTimeStamp(entry._source.fault.timeStamp),
443 node: entry._source.fault.nodeName,
444 counter: entry._source.fault.counter,
445 object: entry._source.fault.objectId,
446 problem: entry._source.fault.problem,
447 severity: entry._source.fault.severity,
450 $scope.data.push(log);
453 $scope.gridOptionsAlarmLog.totalItems = response.data.hits.total; // needed by ui-grid to calculate page number, always update!
454 if($scope.maxCount<response.data.hits.total){
455 $scope.maxCount=response.data.hits.total; //only if total is higher (can be lower due to eg filtering)
459 function processResponseRecreateList(response){
461 response.data.hits.hits.map(function(entry){
464 icon: getIconFromSeverity(entry._source.fault.severity),
465 timestamp: $mwtnFault.formatTimeStamp(entry._source.fault.timeStamp),
466 node: entry._source.fault.nodeName,
467 counter: entry._source.fault.counter,
468 object: entry._source.fault.objectId,
469 problem: entry._source.fault.problem,
470 severity: entry._source.fault.severity,
476 $scope.gridOptionsAlarmLog.totalItems = response.data.hits.total; // needed by ui-grid to calculate page number, always update!
477 if($scope.maxCount<response.data.hits.total){
478 $scope.maxCount=response.data.hits.total; //only if total is higher (can be lower due to eg filtering)
482 $scope.refreshLog = function() {
484 var from = ($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize;
485 var size = $scope.paginationOptions.pageSize;
486 $scope.processing = true;
487 getData(from, size,$scope.state.lastSort,$scope.state.lastfilter).then(function(logEntries){
488 $scope.processing = false;
489 $scope.spinner.alarmLog = false;
490 processResponseRecreateList(logEntries);
493 $scope.processing = false;
494 $scope.spinner.alarmLog = false;
495 console.error(JSON.stringify(error));
499 // [sko] TODO check from here on
504 $scope.clearLog = function () {
506 var modalInstance = $uibModal.open({
508 ariaLabelledBy: 'modal-title',
509 ariaDescribedBy: 'modal-body',
510 templateUrl: 'src/app/mwtnFault/templates/clearLogConfirmation.tpl.html',
511 controller: 'ClearFaultLogCtrl',
515 var onfDateAndTime = new Date().toISOString().replace(/-/g, '').replace(/T/g, '').replace(/:/g, '').substring(0,16) + 'Z';
516 return {timestamp: onfDateAndTime};
521 modalInstance.result.then(function (now) {
523 functionId : 'sdnevents',
524 docType : 'faultlog',
529 $mwtnFault.deleteDocType(spec).then(function(deleted){
530 //set all to 'null' (empty)
533 $scope.gridOptionsAlarmLog.totalItems=0;
535 $timeout( function() { $scope.refreshLog(); getPage(); }, 1000);
537 $mwtnLog.info({component: COMPONENT, message: 'Fault log cleared!'});
539 $mwtnLog.error({component: COMPONENT, message:JSON.stringify(error)});
542 $mwtnLog.info({component: COMPONENT, message: 'Clear fault log dismissed!'});
548 $scope.status = {currentProblemList: true};
549 $scope.spinner = {currentProblemList: false};
550 $scope.$watch('status', function(status, oldValue) {
551 Object.keys(status).map(function(key){
552 if (status[key] !== oldValue[key]) {
553 $scope.spinner[key] = status[key];
556 case 'currentProblemList':
558 $scope.refreshCurrentProblemList();
561 case 'alarmNotifications':
562 $scope.spinner[key] = false;
568 $mwtnLog.error({component: COMPONENT, message: key + ' is not implemented!'});
575 $scope.refreshCurrentProblemList();
581 mwtnFaultApp.register.controller('ClearFaultLogCtrl', ['$scope', '$uibModalInstance', '$mwtnFault', 'now',
582 function ($scope, $uibModalInstance, $mwtnFault, now) {
584 $scope.now = $mwtnFault.formatTimeStamp(now.timestamp);
585 $scope.processing = false;
587 $scope.ok = function () {
588 $uibModalInstance.close(now);
589 $scope.processing = true;
592 $scope.cancel = function () {
593 $uibModalInstance.dismiss();