Assign image keyname and pubkey at vnf level
[ccsdk/apps.git] / sdnr / wireless-transport / code-Carbon-SR1 / ux / mwtnBrowser / mwtnBrowser-module / src / main / resources / mwtnBrowser / mwtnBrowser.controller.js
1 /*
2  * @copyright 2017 highstreet technologies GmbH and others.  All rights reserved.
3  *
4  * @license 
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 define(['app/mwtnBrowser/mwtnBrowser.module',
11         'app/mwtnBrowser/mwtnBrowser.services'],
12         function(mwtnBrowserApp) {
13
14     var getControlType = function(type) {
15       var result = 'text'
16       switch (type) {
17         case 'boolean':
18           result = 'checkbox';
19           break;
20         case 'number':
21           result = 'number';
22           break;
23         case 'string':
24         case 'array':
25         case 'object':
26           break;
27         default:
28           var message = 'Check control type for ' + type;
29           $mwtnLog.warning({ component: COMPONENT, message: message });
30       }
31       return result;
32     };
33
34     mwtnBrowserApp.register.controller('ptpDefaultDsViewController', ['$scope', '$uibModalInstance', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', 'defaultDs', 
35       function ($scope, $uibModalInstance, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, defaultDs) {
36
37       var vm = this;
38       var COMPONENT = 'ptpDefaultDsViewController';
39       $scope.data = defaultDs;
40
41       $scope.getType = $mwtnGlobal.getType;
42
43
44       $mwtnCommons.getPtpDefaultDs(defaultDs).then(function (success) {
45
46         $scope.configuredData = success;
47         $scope.viewData = $mwtnGlobal.getViewData($scope.configuredData['default-ds']);
48
49         $mwtnDatabase.getSchema().then(function(schema){
50           var ordered = {};
51           var clone = JSON.parse(JSON.stringify($scope.viewData));
52           var keys = Object.keys(clone).map(function(key){
53             if ($mwtnGlobal.getType(key) !== 'string') {
54               console.log('key', key);
55               return;
56             }
57             var item = clone[key];
58             if (!schema[key]) {
59               var message = 'No schema information for ' + key;
60               $mwtnLog.warning({ component: COMPONENT, message: message });
61               item['order-number'] = $mwtnCommons.getOrderNumber(97, item);
62               item.description = 'No description available.';
63               item.visible = true;
64               return key;
65             }
66             if (schema[key].controlType === undefined) {
67               item.controlType = getControlType(item.type);
68             } else {
69               item.controlType = schema[key].controlType;
70             }
71             item.unit = schema[key].unit;
72             item['is-read-only'] = schema[key]['is-read-only'];
73             if (schema[key].min) {
74               item.min = schema[key].min;
75             }
76             if (schema[key].max) {
77               item.max = schema[key].max;
78               if (item.unit) {
79                 item.unit = schema[key].min + '..' + schema[key].max + ' ' + item.unit;
80               } else {
81                 item.unit = schema[key].min + '..' + schema[key].max;
82               }
83             }
84
85
86             item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item);
87             item.description = schema[key].description;
88             if (item.description === undefined || item.description === '') {
89               item.description = 'No description available.';
90             }
91             // hide complex types for now -> TODO
92             if (item.type === 'array' || item.type === 'object') {
93               item.visible = false;
94             }
95             return key;
96           }).sort(function(a,b){
97             if (clone[a]['order-number'] < clone[b]['order-number']) return -1;
98             if (clone[a]['order-number'] > clone[b]['order-number']) return 1;
99             return 0;
100           }).map(function(key){
101             ordered[key] = clone[key];
102           });
103           $scope.viewData = ordered;
104         }, function(error){
105           $scope.empty = true;
106         });
107                   
108       }, function (error) {
109         $scope.configuredData = undefined;
110         $mwtnLog.error({ component: COMPONENT, message: 'Requesting PTP default ds ' + JSON.stringify($scope.data) + ' failed!' });
111       });
112
113       $scope.$watch('viewData', function(newValue, oldValue) {
114         if (oldValue && newValue !== oldValue) {
115           Object.keys(newValue).filter(function(key){
116             return newValue[key]['is-read-only'] !== true && newValue[key].controlType === 'number' ;
117           }).map(function(key){
118             if (newValue[key].value < newValue[key].min) newValue[key].value = newValue[key].min;
119             if (newValue[key].value > newValue[key].max) newValue[key].value = newValue[key].max;
120             if (!newValue[key].value) newValue[key].value = newValue[key].min;
121           });
122         }
123       }, true);
124
125       $scope.newData = {};
126       $scope.ok = function () {
127         $scope.processing = true;
128         $scope.newData = {};
129         Object.keys($scope.viewData).map(function(key){
130           $scope.newData[key] = $scope.viewData[key].value;
131         });
132
133         $mwtnCommons.setPtpDefaultDs($scope.data, $scope.newData).then(function(success){
134           $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'};
135           $scope.processing = false;
136         }, function(error){
137           $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'};
138           $scope.processing = false;
139           $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)});
140         });
141
142       };
143     
144       $scope.cancel = function () {
145         $uibModalInstance.close($scope.newData);
146       };
147
148       // events
149
150
151     }]);
152
153     mwtnBrowserApp.register.controller('ptpPortConfigViewController', ['$scope', '$uibModalInstance', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', 'valueData', 
154       function ($scope, $uibModalInstance, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, data) {
155
156       var vm = this;
157       var COMPONENT = 'ptpPortConfigViewController';
158
159       $scope.data = data;
160
161       $scope.getType = $mwtnGlobal.getType;
162       console.warn(JSON.stringify(data));
163       $mwtnCommons.getPtpPort(data).then(function (success) {
164         
165         $scope.configuredData = success;
166         
167         $scope.viewData = $mwtnGlobal.getViewData($scope.configuredData['port-ds-list'][0]);
168         $mwtnDatabase.getSchema().then(function(schema){
169           var ordered = {};
170           var clone = JSON.parse(JSON.stringify($scope.viewData));
171           var keys = Object.keys(clone).map(function(key){
172             if ($mwtnGlobal.getType(key) !== 'string') {
173               console.log('key', key);
174               return;
175             }
176             var item = clone[key];
177             if (!schema[key]) {
178               var message = 'No schema information for ' + key;
179               $mwtnLog.warning({ component: COMPONENT, message: message });
180               item['order-number'] = $mwtnCommons.getOrderNumber(97, item);
181               item.description = 'No description available.';
182               item.visible = true;
183               return key;
184             }
185             if (schema[key].controlType === undefined) {
186               item.controlType = getControlType(item.type);
187             } else {
188               item.controlType = schema[key].controlType;
189             }
190             item.unit = schema[key].unit;
191             console.warn(key, schema[key]['is-read-only']);
192             item['is-read-only'] = schema[key]['is-read-only'];
193             if (schema[key].min) {
194               item.min = schema[key].min;
195             }
196             if (schema[key].max) {
197               item.max = schema[key].max;
198               if (item.unit) {
199                 item.unit = schema[key].min + '..' + schema[key].max + ' ' + item.unit;
200               } else {
201                 item.unit = schema[key].min + '..' + schema[key].max;
202               }
203             }
204
205
206             item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item);
207             item.description = schema[key].description;
208             if (item.description === undefined || item.description === '') {
209               item.description = 'No description available.';
210             }
211             // hide complex types for now -> TODO
212             if (item.type === 'array' || item.type === 'object') {
213               item.visible = false;
214             }
215             return key;
216           }).sort(function(a,b){
217             if (clone[a]['order-number'] < clone[b]['order-number']) return -1;
218             if (clone[a]['order-number'] > clone[b]['order-number']) return 1;
219             return 0;
220           }).map(function(key){
221             ordered[key] = clone[key];
222           });
223           $scope.viewData = ordered;
224         }, function(error){
225           $scope.empty = true;
226         });
227                   
228       }, function (error) {
229         $scope.configuredData = undefined;
230         $mwtnLog.error({ component: COMPONENT, message: 'Requesting PTP port ' + JSON.stringify($scope.data) + ' failed!' });
231       });
232
233       $scope.$watch('viewData', function(newValue, oldValue) {
234         if (oldValue && newValue !== oldValue) {
235           Object.keys(newValue).filter(function(key){
236             return newValue[key]['is-read-only'] !== true && newValue[key].controlType === 'number' ;
237           }).map(function(key){
238             if (newValue[key].value < newValue[key].min) newValue[key].value = newValue[key].min;
239             if (newValue[key].value > newValue[key].max) newValue[key].value = newValue[key].max;
240             if (!newValue[key].value) newValue[key].value = newValue[key].min;
241           });
242         }
243       }, true);
244
245       $scope.newData = {};
246       $scope.ok = function () {
247         $scope.processing = true;
248         $scope.newData = {};
249         Object.keys($scope.viewData).map(function(key){
250           $scope.newData[key] = $scope.viewData[key].value;
251         });
252
253         $mwtnCommons.setPtpPort($scope.data, $scope.newData).then(function(success){
254           $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'};
255           $scope.processing = false;
256         }, function(error){
257           $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'};
258           $scope.processing = false;
259           $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)});
260         });
261
262       };
263     
264       $scope.cancel = function () {
265         $uibModalInstance.close($scope.newData);
266       };
267
268       // events
269
270
271     }]);
272
273     mwtnBrowserApp.register.controller('mwtnPtpPortsController', ['$scope', '$filter', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnLog',
274       function ($scope, $filter, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnLog) {
275         var vm = this;
276         var COMPONENT = 'mwtnPtpPortsController';
277
278         $scope.info = false;
279         var data = JSON.parse(JSON.stringify($scope.data));
280         if (!data) {
281           var message = 'No data to be displayed!";'
282           $mwtnLog.info({ component: COMPONENT, message: message });
283           data = [{'message':message}];
284         }
285
286         if ($mwtnGlobal.getType(data) !== 'array')  {
287           var message = 'Data must be of type "array"!';
288           $mwtnLog.info({ component: COMPONENT, message: message });
289           data = [{'message':message}];
290         }
291
292         if (data.length === 0)  {
293           var message = 'Data list must have at least one entry!';
294           $mwtnLog.info({ component: COMPONENT, message: message });
295           data = [{'message':message}];
296         }
297
298         if ($mwtnGlobal.getType(data[0]) !== 'object')  {
299           data = data.map(function(item){
300             return {value: item};
301           });
302         }
303
304         $scope.ptpPorts = [];
305
306         $scope.gridOptions = JSON.parse(JSON.stringify($mwtnCommons.gridOptions));
307         $scope.gridOptions.data = 'ptpPorts';
308         $scope.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader;
309
310         // $scope.getTableHeight = function() {
311         //   var rowHeight = 30; 
312         //   var headerHeight = 40; 
313         //   var maxCount = 12;
314         //   var rowCount = $scope.gridOptions.data.length + 2;
315         //   if (rowCount > maxCount) {
316         //     return {
317         //         height: (maxCount * rowHeight + headerHeight) + 'px'
318         //     };
319         //   }
320         //   return {}; // use auto-resize feature
321         // };
322
323         var getCellTemplate = function(field) {
324           var object = ['transmission-mode-list', 'performance-data'];
325           if (object.contains(field)) {
326             return ['<div class="ui-grid-cell-contents">',
327                     '<i class="fa fa-info-circle pointer" aria-hidden="true"',
328                     ' ng-click="grid.appScope.show(grid.getCellValue(row, col))"></i> ',
329                     '{{grid.getCellValue(row, col)}}</div>'].join('');
330           } else if (field === 'action') {
331             return [
332               '<a class="vCenter" ng-class="{attention: grid.appScope.hover, hidden: onfAirInterfaceRevision}" >',
333               '  <i class="fa fa-pencil-square-o pointer" aria-hidden="true"  ng-click="grid.appScope.show(row.entity)"></i>',
334               '</a>' ].join('<span>&nbsp;</span>');
335           } else {
336             return '<div class="ui-grid-cell-contents">{{grid.getCellValue(row, col)}}</div>';
337           }
338         };
339
340         $scope.show = function(value){
341           var type = $mwtnGlobal.getType(value);
342           // if (type === 'object')
343           var modalInstance = $uibModal.open({
344             animation: true,
345             ariaLabelledBy: 'modal-title',
346             ariaDescribedBy: 'modal-body',
347             templateUrl: 'src/app/mwtnBrowser/templates/ptpPortConfigView.tpl.html',
348             controller: 'ptpPortConfigViewController',
349             size: 'huge',
350             resolve: {
351               valueData: function () {
352                 return {networkElement: $scope.networkElement, value:value};
353               }
354             }
355           });
356           modalInstance.result.then(function(object) {
357             console.warn(JSON.stringify(object));
358             $scope.ptpPorts.map(function(row, index){
359               if (row['port-number'] === object['port-number']) {
360                 console.log($scope.ptpPorts[index]['onf-ptp-dataset:master-only']);
361                 $scope.ptpPorts[index] = object;
362                 console.log($scope.ptpPorts[index]['onf-ptp-dataset:master-only']);
363               };
364             });
365           }, function () {
366               // ignore;
367           });
368         };
369
370         var enable = data.length > 10;
371         $scope.gridOptions.columnDefs = Object.keys(data[0]).map(function (field) {
372           var type = $mwtnGlobal.getType(data[0][field]);
373           var labelId = $mwtnGlobal.getLabelId(field);
374           var displayName = $filter('translate')(labelId);
375           var visible = $mwtnGlobal.getVisibilityOf(field);
376           if (labelId.contains('$$') || labelId === 'MWTN_SPEC') {
377             visible = false;
378           }
379           return {
380             field: field,
381             type: type,
382             displayName: displayName,
383             enableSorting: true,
384             enableFiltering: enable,
385             headerCellClass: $scope.highlightFilteredHeader,
386             cellTemplate: getCellTemplate(field),
387             cellClass: type,
388             visible: visible
389           };
390         });
391         $scope.gridOptions.columnDefs.push({
392             field: 'action',
393             displayName: 'Action',
394             enableSorting: false,
395             enableFiltering: false,
396             headerCellClass: $scope.highlightFilteredHeader,
397             cellTemplate: getCellTemplate('action'),
398             width: 100,
399             visible: true,  
400             pinnedRight : true
401
402           });
403         if ($scope.gridOptions.data.length < 10) {
404           $scope.gridOptions.minRowsToShow =  data.length; // 10 is default
405         } 
406         $scope.ptpPorts = data.map(function(item){
407           item.action = '';
408           return item;
409         });
410         // .sort(function(a, b){
411         //           if (a.type === 'object') return -1;
412         //           if (a.type === 'array' ) return -2;
413         //           return 0;
414         //         })
415
416         $scope.myClipboard = {
417           data: $scope.data,
418           supported: true,
419           getJson: function () {
420             return JSON.stringify(this.data, null, ' ');
421           },
422           copyToClipboard: function () {
423             var message = 'Copied to clipboard! ' + this.getJson();
424             $mwtnLog.info({ component: COMPONENT, message: message });
425           },
426           error: function (err) {
427             $mwtnLog.error({ component: COMPONENT, message: err });
428           }
429         };
430     }]);
431
432     mwtnBrowserApp.register.directive('mwtnPtpPorts', function () {
433       return {
434         restrict: 'E',
435         scope: {
436           data: '=',
437           path: '=',
438           networkElement: '='
439         },
440         controller: 'mwtnPtpPortsController',
441         controllerAs: 'vm',
442         templateUrl: 'src/app/mwtnBrowser/templates/mwtnPtpPorts.tpl.html'
443       };
444     });
445
446     mwtnBrowserApp.register.controller('mwtnPtpClockViewerController', ['$scope', '$timeout', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', '$mwtnBrowser',
447       function ($scope, $timeout, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, $mwtnBrowser) {
448         var vm = this;
449         var COMPONENT = 'mwtnPtpClockViewerController';
450         if ($scope.data) {
451           $scope.replace = false;
452           if ($scope.path && $scope.path.endsWith('-configuration') ) {
453             $scope.replace = true;
454           }
455           $scope.viewData = $mwtnGlobal.getViewData($scope.data, $scope.ne);
456           var path = [undefined, undefined, undefined];
457           if ($scope.path) {
458             path = $scope.path.split($mwtnCommons.separator);
459           }
460
461           var processData = function(schema) {
462             var ordered = {};
463             var clone = JSON.parse(JSON.stringify($scope.viewData));
464             var keys = Object.keys(clone).map(function(key){
465               if ($mwtnGlobal.getType(key) !== 'string') {
466                 console.log('key', key);
467                 return;
468               }
469               var item = clone[key];
470               if (!schema[key]) {
471                 var message = 'No schema information for ' + key;
472                 $mwtnLog.warning({ component: COMPONENT, message: message });
473                 item['order-number'] = $mwtnCommons.getOrderNumber(97, item);
474                 item.description = 'No description available.';
475                 item.visible = true;
476                 return key;
477               }
478               item.unit = schema[key].unit;
479               item.description = schema[key].description;
480               item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item);
481               if (item.description === undefined || item.description === '') {
482                 item.description = 'No description available.';
483               }
484               return key;
485             }).sort(function(a,b){
486               if (clone[a]['order-number'] < clone[b]['order-number']) return -1;
487               if (clone[a]['order-number'] > clone[b]['order-number']) return 1;
488               return 0;
489             }).map(function(key){
490               if ($mwtnGlobal.getType( clone[key].value ) === 'object') {
491                 Object.keys(clone[key].value).filter(function(subKey){
492                   return subKey.endsWith('-identity');
493                 }).map(function(subKey){
494                   var clockId = clone[key].value[subKey];
495                   if ($mwtnGlobal.getType(clockId) === 'object') {
496                     if (clockId['clock-identity']) {
497                       var ascii = clockId['clock-identity'].base64ToHex();
498                       clone[key].value[subKey]['clock-identity'] = [clone[key].value[subKey]['clock-identity'], '(ascii:', ascii, ')'].join(' ');
499                     }
500                   } else {
501                     var ascii = clone[key].value[subKey].base64ToHex();
502                     clone[key].value[subKey] = [clone[key].value[subKey], '(ascii:', ascii, ')'].join(' ');
503                   }
504                 });
505                 ordered[key] = clone[key];
506               } else {
507                 ordered[key] = clone[key];
508               }
509             });
510             $scope.info = false;
511             if (Object.keys(ordered).length === 0) {
512               $scope.info = 'An empty object is displayed. Please check if the NetConf server has send an empty object.';
513             }
514             return ordered;
515           };
516
517
518           $mwtnDatabase.getSchema().then(function(schema){
519             $scope.schema = schema;
520             $scope.viewData = processData($scope.schema);
521           }, function(error){
522             // ignore;
523           });
524         }
525
526         $scope.show = function(value){
527           var type = $mwtnGlobal.getType(value);
528           var modalInstance = $uibModal.open({
529             animation: true,
530             ariaLabelledBy: 'modal-title',
531             ariaDescribedBy: 'modal-body',
532             templateUrl: 'src/app/mwtnBrowser/templates/ptpDefaultDsConfigView.tpl.html',
533             controller: 'ptpDefaultDsViewController',
534             size: 'huge',
535             resolve: {
536               defaultDs: function () {
537                 return {networkElement: $scope.networkElement, value:value};
538               }
539             }
540           });
541           modalInstance.result.then(function(object) {
542             $mwtnBrowser.refreshPTP();
543           }, function () {
544               // ignore;
545           });
546         };
547     }]);
548     
549     mwtnBrowserApp.register.directive('mwtnPtpClockViewer', function () {
550       return {
551         restrict: 'E',
552         scope: {
553           data: '=',
554           path: '=',
555           ne: '=', // flag if ne class
556           networkElement: '='
557         },
558         controller: 'mwtnPtpClockViewerController',
559         controllerAs: 'vm',
560         templateUrl: 'src/app/mwtnBrowser/templates/mwtnPtpClockViewer.tpl.html'
561       };
562     });
563
564
565   mwtnBrowserApp.register.controller('mwtnBrowserCtrl', ['$scope', '$rootScope', '$mwtnLog', '$mwtnCommons', '$mwtnEthernet', '$mwtnBrowser', '$translate', 'OnfNetworkElement', 'PtpClock', 'LogicalTerminationPoint', 
566     function($scope, $rootScope, $mwtnLog, $mwtnCommons, $mwtnEthernet, $mwtnBrowser, $translate, OnfNetworkElement, PtpClock, LogicalTerminationPoint) {
567
568     var COMPONENT = 'mwtnBrowserCtrl';
569     $mwtnLog.info({component: COMPONENT, message: 'mwtnBrowserCtrl started!'});
570     $rootScope.section_logo = 'src/app/mwtnBrowser/images/mwtnBrowser.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif'
571
572     var pacTemplate = {
573         'layer-protocol': 'unknown'           
574     };
575
576     $scope.fcDeletion = {
577       nodeId: $scope.networkElementId, 
578       ltp:'', 
579       info: 'handle with care, no further warning, qualified user expected ;)'
580     };
581     $scope.deleteForwardingConstruct = function() {
582       $scope.fcDeletion.nodeId = $scope.networkElementId;
583       $scope.fcDeletion.info = 'Processing ...';
584       $scope.fcDeletion.error = undefined;
585       if ($scope.fcDeletion.ltp === undefined || $scope.fcDeletion.ltp === '') {
586         $scope.fcDeletion.error = 'Please select a valid LTP#1.!';
587         return;
588       }
589       $mwtnEthernet.deleteForwardingConstruct($scope.fcDeletion).then(function(success){
590         console.log(success);
591         $scope.fcDeletion.info = success;
592       }, function(error){
593         console.log(error);
594         $scope.fcDeletion.error = error;
595       });
596     }
597
598     $scope.fcCreation = {
599       nodeId: $scope.networkElementId, 
600       ltp1:'', 
601       ltp2:'', 
602       vlan:42, 
603       info:'handle with care, no further warning, qualified user expected ;)'
604     };
605     $scope.createForwardingConstruct = function() {
606       console.warn(JSON.stringify($scope.networkElementId));
607       console.warn(JSON.stringify($scope.networkElement));
608       $scope.fcCreation.nodeId = $scope.networkElementId;
609       $scope.fcCreation.info = 'Processing ...';
610       $scope.fcCreation.error = undefined;
611       if ($scope.fcCreation.ltp1 === undefined || $scope.fcCreation.ltp1 === '') {
612         $scope.fcCreation.error = 'Please select a valid LTP#1!';
613         return;
614       }
615       if ($scope.fcCreation.ltp2 === undefined || $scope.fcCreation.ltp2 === '') {
616         $scope.fcCreation.error = 'Please select a valid LTP#2!';
617         return;
618       }
619       if ($scope.fcCreation.vlan === undefined) {
620         $scope.fcCreation.error = 'Please select a valid vlan-id!';
621         return;
622       }
623       if ($scope.fcCreation.ltp1 === $scope.fcCreation.ltp2) {
624         $scope.fcCreation.error = 'Please select different LTPs. Loopback is not supported yet!';
625         return;
626       }
627       $mwtnEthernet.createForwardingConstruct($scope.fcCreation).then(function(success){
628         console.log(success);
629         $scope.fcCreation.info = success;
630       }, function(error){
631         console.log(error);
632         $scope.fcCreation.error = error;
633       });
634     }
635
636     // get important infromation from yang modules
637     console.error('help');
638     $mwtnBrowser.getModules().then(function(success){
639
640       var pacOrder = [
641         'onf-otn-odu-conditional-packages:otn-odu-termination-pac',
642         'onf-otn-odu-conditional-packages:otn-odu-connection-pac',
643         'onf-ethernet-conditional-packages:ethernet-pac',
644         'microwave-model:mw-air-interface-diversity-pac',
645         'microwave-model:mw-air-interface-hsb-end-point-pac',
646         'microwave-model:mw-air-interface-hsb-fc-switch-pac',
647         'onf-core-model-conditional-packages:holder-pac',
648         'onf-core-model-conditional-packages:connector-pac',
649         'onf-core-model-conditional-packages:equipment-pac',
650         'microwave-model:mw-ethernet-container-pac',
651         'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac',
652         'microwave-model:mw-ethernet-container-pac',
653         'microwave-model:mw-tdm-container-pac',
654         'microwave-model:mw-pure-ethernet-structure-pac',
655         'microwave-model:mw-hybrid-mw-structure-pac',
656         'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac',
657         'microwave-model:mw-air-interface-pac',
658         'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac'
659       ];
660
661       $scope.modules = success;
662       $scope.orderedPacs = [];
663       $scope.parts = [];
664       Object.keys(success).map(function(module){
665         Object.keys(success[module]).filter(function(key){
666           return key.endsWith('-pac') || key.endsWith('_Pac');
667         }).map(function(pacName){
668           $scope.orderedPacs.push([module, pacName].join(':'));
669           // sort 
670           $scope.orderedPacs.sort(function(a, b) {
671             if (!pacOrder.indexOf(a)) console.warn(a);
672             if (!pacOrder.indexOf(b)) console.warn(b);
673             if(pacOrder.indexOf(a) > pacOrder.indexOf(b)) return 1;
674             if(pacOrder.indexOf(a) < pacOrder.indexOf(b)) return -1;
675             return 0;
676           })
677
678           if (pacName === 'mw-air-interface-pac') {
679             $scope.parts = Object.keys(success[module][pacName]).filter(function(conditionalPackage){
680               return success[module][pacName][conditionalPackage]['local-name'];
681             }).map(function(conditionalPackage){
682               return success[module][pacName][conditionalPackage]['local-name'];
683             });
684           }
685         });
686       });
687     }, function(error){
688       $scope.modules = undefined;
689       $scope.orderedPacs = undefined;
690       $scope.parts = undefined;
691     });
692             
693     /**
694      * @function updateNe 
695      * A function, which updates onfNetworkElement by new data.
696      * @param {*} data New data recieved from OpenDaylight via RestConf
697      */
698     var updateNe = function(data) {
699       if (!data) return;
700       // update onfNetworkElement
701       switch ($scope.mountpoint.onfCoreModelRevision) {
702         case '2016-03-23':
703           $scope.onfNetworkElement = JSON.parse(JSON.stringify(data['network-element'][0]));
704           $scope.onfLtps = data['network-element'][0].ltp;
705           $scope.onfNetworkElement.ltp = undefined;
706           break;
707         case '2016-08-09':
708         case '2016-08-11':
709         case '2017-02-17':
710         case '2017-03-20':
711         case '2017-10-20':
712         // console.log(JSON.stringify(data));        
713           $scope.onfNetworkElement = new OnfNetworkElement(data['network-element']);
714           var fd = $scope.onfNetworkElement.getForwardingDomain();
715           $scope.forwardingDomain = undefined;
716           $scope.forwardingConstructs = undefined;
717           if (fd && fd.length > 0) {
718             $scope.forwardingDomain = fd[0]; // $mwtnBrowser.getViewData(fd[0]);
719             $scope.forwardingConstructs = [];
720             if (fd[0].fc) {
721               fd[0].fc.map(function(id){
722                 $mwtnBrowser.getForwardingConstruct($scope.networkElement, id).then(function(fc){
723
724                   // TODO make robust
725                   if (fc['forwarding-construct'] && fc['forwarding-construct'][0]) {
726                     var item = fc['forwarding-construct'][0];
727                     if (item['fc-port'] && 
728                         item['fc-port'][0] && item['fc-port'][0].ltp && item['fc-port'][0].ltp[0]  && 
729                         item['fc-port'][1] && item['fc-port'][1].ltp && item['fc-port'][1].ltp[0]) {
730                       $scope.forwardingConstructs.push( {
731                         uuid: item.uuid,
732                         'fc-port#1': $scope.onfNetworkElement.getLtp( item['fc-port'][0].ltp[0] ).getLabel(),
733                         'fc-port#2': $scope.onfNetworkElement.getLtp( item['fc-port'][1].ltp[0] ).getLabel()
734                       });
735                     }
736                   }
737                 });
738               });
739             }
740           }
741           $scope.onfLtps = $scope.onfNetworkElement.getLogicalTerminationPoints();
742           // $scope.onfNetworkElement.ltp = undefined;
743           break;
744         default:
745           $mwtnLog.info({component: COMPONENT, message: ['The ONF CoreModel revision', $scope.mountpoint.onfCoreModelRevision, ' is not supported (yet)!'].join(' ')});
746           $scope.onfNetworkElement = {};
747           $scope.onfLtps = {};
748       }
749       
750       var order = $mwtnBrowser.layerProtocolNameOrder;
751       // update onfLTPs
752       $scope.onfLtps.sort(function(a, b){
753         if(order[a.getLayer()] < order[b.getLayer()]) return -1;
754         if(order[a.getLayer()] > order[b.getLayer()]) return 1;
755         if(a.getId() < b.getId()) return -1;
756         if(a.getId() > b.getId()) return 1;
757         return 0;
758       });
759       
760       // calculate conditional packages
761       $scope.pacs = {};
762       $scope.onfLtps.map(function(ltp) {
763         ltp.getLayerProtocols().map(
764           /**
765            * A function processing a layer-protocol object
766            * @param {LayerProtocol} lp A layer-protocol object
767            */
768           function(lp) {
769             var template = JSON.parse(JSON.stringify(pacTemplate));
770             template['layer-protocol'] = lp.getId();
771             var conditionalPackage = lp.getConditionalPackage(true);
772             // console.log(conditionalPackage);
773             if (conditionalPackage !== '') {
774               if ($scope.pacs[conditionalPackage] === undefined) {
775                 // create missing pac array
776                 $scope.pacs[conditionalPackage] = [];
777               }
778               $scope.pacs[conditionalPackage].push(template);
779               console.error(conditionalPackage, JSON.stringify(template));
780             } else {
781               $mwtnLog.info({component: COMPONENT, message: 'No conditional package for  ' + ltp.getLabel() });
782             }
783         });
784       });
785       
786       // sort the conditional packages
787       if ($scope.orderedPacs) {
788         $scope.orderedPacs.filter(function(item){
789           return $scope.pacs[item] !== undefined;
790         }).map(function(item){
791           $scope.pacs[item].sort(function(a, b){
792             if(a['layer-protocol'] < b['layer-protocol']) return -1;
793             if(a['layer-protocol'] > b['layer-protocol']) return 1;
794             return 0;
795           });
796         });
797       }
798       data.revision = undefined;
799     };
800
801     var updateNetworkElementCurrentProblems = function(data) {
802       if (data && data['network-element-current-problems'] && data['network-element-current-problems']['current-problem-list'] ) {
803           data.revision = undefined;
804           $scope.neCurrentProblems = data['network-element-current-problems']['current-problem-list'];
805       } else {
806           $scope.neCurrentProblems = [];
807       }
808     };
809
810     var updateLtp = function(data) {
811       $scope.onfLtps.map(function(ltp){
812         if (ltp.getData().uuid === data.data.ltp[0].uuid) {
813           ltp = new LogicalTerminationPoint(data.data.ltp[0]);
814         }
815       });
816     };
817
818     /**
819      * @deprecated since all conditaional packages are handle the same way even for
820      *             3rd and 4th PoC model - 2nd PoC model not supported any more.
821      * @param {*} lpId 
822      * @param {*} part 
823      * @param {*} data 
824      */
825     var updateAirInterface = function(lpId, part, data) {
826       // console.log(JSON.stringify(data), lpId);
827       $scope.airinterfaces.map(function(airinterface){
828         // console.log(JSON.stringify(airinterface));
829         if (airinterface['layer-protocol'] === lpId) {
830           if (Object.keys(data)[0].startsWith('air-interface')) {
831             airinterface[part] = data;            
832           } else if (part === 'Capability') {
833             // 2. PoC
834             // console.log(part, JSON.stringify(data));
835             airinterface[part] = data['mw-air-interface-pac'][0]['air-interface-capability-list'];            
836           } else if (part === 'CurrentProblems') {
837             // 2. PoC
838             // console.log(part, JSON.stringify(data));
839             airinterface[part] = data['mw-air-interface-pac'][0]['air-interface-current-problem-list'];            
840           }
841         }
842       });
843       data.revision = undefined;
844     };
845
846     /**
847      * @deprecated since all conditaional packages are handle the same way even for
848      *             3rd and 4th PoC model - 2nd PoC model not supported any more.
849      * @param {*} lpId 
850      * @param {*} part 
851      * @param {*} data 
852      */
853     var updateStructure = function(lpId, part, data) {
854       // console.log(JSON.stringify(data), lpId);
855       $scope.structures.map(function(structure){
856         // console.log(JSON.stringify(structure));
857         if (structure['layer-protocol'] === lpId) {
858           if (Object.keys(data)[0].contains('tructure')) {
859             structure[part] = data;            
860           } else if (part === 'Capability') {
861             // 2. PoC
862             // console.log(part, JSON.stringify(data));
863             structure[part] = data['mw-structure-pac'][0]['structure.capability-list'];            
864           } else if (part === 'CurrentProblems') {
865             // 2. PoC
866             // console.log(part, JSON.stringify(data));
867             structure[part] = data['mw-structure-pac'][0]['structure-current-problem-list'];            
868           }
869         }
870       });
871       data.revision = undefined;
872     };
873
874     /**
875      * @deprecated since all conditaional packages are handle the same way even for
876      *             3rd and 4th PoC model - 2nd PoC model not supported any more.
877      * @param {*} lpId 
878      * @param {*} part 
879      * @param {*} data 
880      */
881     var updateContainer = function(lpId, part, data) {
882       // console.log(JSON.stringify(data), lpId);
883       $scope.containers.map(function(container){
884         // console.log(JSON.stringify(container));
885         if (container['layer-protocol'] === lpId) {
886           if (Object.keys(data)[0].contains('ontainer') ) {
887             container[part] = data;            
888           } else if (part === 'Capability') {
889             // 2. PoC
890             // console.log(part, JSON.stringify(data));
891             container[part] = data['mw-container-pac'][0]['container-capability-list'];            
892           } else if (part === 'CurrentProblems') {
893             // 2. PoC
894             // console.log(part, JSON.stringify(data));
895             container[part] = data['mw-container-pac'][0]['container-current-problem-list'];            
896           }
897         }
898       });
899       data.revision = undefined;
900     };
901
902     /**
903      * Creates a template of a conditional packages with its subclasses
904      * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass
905      */
906     var initPac = function(spec) {
907       $scope.pacs[spec.pacId].filter(function(conditionalPackage){
908         return conditionalPackage['layer-protocol'] === spec.layerProtocolId;
909       }).map(function(pac){
910         $scope.parts.map(function(localName){
911           pac[localName] = {id:$mwtnBrowser.getPartGlobalId(spec, localName),localName: localName, data:'No data available'}
912         });
913       });
914     };
915
916     /**
917      * Updates an existing template of a conditional packages with its subclasses
918      * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass
919      */
920     var updateSubClassData = function(spec, data) {
921       $scope.pacs[spec.pacId].filter(function(conditionalPackage){
922         return conditionalPackage['layer-protocol'] === spec.layerProtocolId;
923       }).map(function(conditionalPackage){
924         conditionalPackage[$mwtnBrowser.getPartLocalId(spec)].data = data[$mwtnBrowser.yangify(spec.partId)];
925       });
926     };
927
928     var updatePart = function(spec, data) {
929       switch (spec.pacId) {
930         case 'ne':
931           updateNe(data);
932           break;
933         case 'forwardingDomain':
934           // TODO $scope.forwardingDomain = new ForwardingDomain(data);
935           break;
936         case 'neCurrentProblems':
937           updateNetworkElementCurrentProblems(data);
938           break;
939         case 'clock':
940           if (data) {
941             $scope.clock = new PtpClock(data);
942           } else {
943             $scope.clock = undefined;
944           }
945           break;
946         case 'ltp':
947           updateLtp(data);
948           break;
949         case 'airinterface':
950           console.warn(JSON.stringify(spec, JSON.stringify(data)));
951           updateAirInterface(spec.layerProtocolId, spec.partId, data);
952           break;
953         case 'structure':
954           console.warn(JSON.stringify(data));
955           updateStructure(spec.layerProtocolId, spec.partId, data);
956           break;
957         case 'container':
958           console.warn(JSON.stringify(data));
959           updateContainer(spec.layerProtocolId, spec.partId, data);
960           break;  
961         // 3rd Poc
962         case 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac':
963         case 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac':
964         case 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac':
965         // 4th Poc
966         case 'microwave-model:mw-air-interface-pac':
967         case 'microwave-model:mw-air-interface-diversity-pac':
968         case 'microwave-model:mw-pure-ethernet-structure-pac':
969         case 'microwave-model:mw-hybrid-mw-structure-pac':
970         case 'microwave-model:mw-tdm-container-pac':
971         case 'microwave-model:mw-ethernet-container-pac':
972         case 'onf-ethernet-conditional-packages:ethernet-pac':
973           if (!spec.partId) {
974             initPac(spec);
975           } else {
976             updateSubClassData(spec, data);
977           }
978           break;  
979       }
980     };
981     
982     // events
983     $scope.status = {ne:false};
984     $scope.spinner = {ne:false};
985     $scope.separator = $mwtnBrowser.separator; //'&nbsp;'
986
987     $scope.collapseAll = function() {
988       // close all groups
989       Object.keys($scope.status).map(function(group){
990         $scope.status[group] = false;
991       });
992       Object.keys($scope.spinner).map(function(group){
993         $scope.spinner[group] = false;
994       });
995     };
996
997     $scope.$watch('status', function(status, oldValue) {
998       Object.keys(status).filter(function(key){
999         return $scope.networkElementId && status[key] && status[key] !== oldValue[key];
1000       }).map(function(key){
1001         $scope.spinner[key] = true;
1002         var info = key.split($scope.separator);
1003         var spec = {
1004           nodeId: $scope.networkElementId,
1005           revision: $scope.revision,
1006           pacId: info[0],
1007           layerProtocolId: info[1],
1008           partId: info[2]
1009         };
1010         $mwtnBrowser.getPacParts(spec).then(function(success){
1011           success = $mwtnBrowser.yangifyObject(success)
1012           updatePart(spec, success);
1013           $scope.spinner[key] = false;
1014         }, function(error){
1015           updatePart(spec, error);
1016           $scope.spinner[key] = false;
1017         });
1018       });
1019     }, true);
1020
1021     $scope.$watch('networkElement', function(neId, oldValue) {
1022       if (neId && neId !== '' && neId !== oldValue) {
1023
1024         $scope.collapseAll();
1025         
1026         // clear old data
1027         $scope.airinterfaces = [];
1028         $scope.structures = [];
1029         $scope.containers = [];
1030         $scope.onfLtps = [];
1031         $scope.clock = undefined;
1032
1033         $scope.networkElementId = neId;
1034         $scope.revision = $scope.mountPoints.filter(function(mountpoint){
1035           return mountpoint['node-id'] === neId;
1036         }).map(function(mountpoint){
1037           $scope.mountpoint = mountpoint;
1038           return mountpoint.onfCoreModelRevision;
1039         })[0];
1040
1041         var spec = {
1042           nodeId: $scope.networkElementId,
1043           revision: $scope.revision,
1044           pacId: 'ne'
1045         };
1046         $mwtnBrowser.getPacParts(spec).then(function(success){
1047           updatePart(spec, $mwtnBrowser.yangifyObject(success));
1048         }, function(error){
1049           updatePart(spec, error);
1050         });
1051
1052         // network element alarms
1053         var neAlarms = $scope.mountPoints.filter(function(mountpoint){
1054           return mountpoint['node-id'] === neId;
1055         }).map(function(mountpoint){
1056           return mountpoint.onfCapabilities.filter(function(cap){
1057             return cap.module === 'MicrowaveModel-NetworkElement-CurrentProblemList' || cap.module === 'onf-core-model-conditional-packages';
1058           });
1059         });
1060         
1061         if (neAlarms.length === 1 && neAlarms[0].length === 1 ) {
1062           $translate('MWTN_LOADING').then(function (translation) {
1063             $scope.neCurrentProblems = translation;
1064           });
1065         } else {
1066           $scope.neCurrentProblems = undefined;
1067         }
1068
1069         // ptp-clock
1070         var ptpClock = $scope.mountPoints.filter(function(mountpoint){
1071           return mountpoint['node-id'] === neId;
1072         }).map(function(mountpoint){
1073           return mountpoint.onfCapabilities.filter(function(cap){
1074             return cap.module === 'onf-ptp-dataset';
1075           });
1076         });
1077         if (ptpClock.length === 1 && ptpClock[0].length === 1 ) {
1078           $translate('MWTN_LOADING').then(function (translation) {
1079             $scope.clock = {'translation': translation};
1080           });
1081         } else {
1082           $scope.clock = undefined;
1083         }
1084         
1085       }
1086     });
1087
1088   }]);
1089
1090 });