summaryrefslogtreecommitdiffstats
path: root/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main')
-rwxr-xr-xsdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/mwtnConnect.pngbin0 -> 2271 bytes
-rwxr-xr-xsdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/sdncConnect.pngbin0 -> 11379 bytes
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect-custom.css85
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.controller.js1143
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.module.js56
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.services.js75
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.tpl.html150
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/addToRequired.tpl.html79
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmDelete.tpl.html23
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmHide.tpl.html21
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/mountPointDetails.tpl.html125
11 files changed, 1757 insertions, 0 deletions
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/mwtnConnect.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/mwtnConnect.png
new file mode 100755
index 00000000..7417076f
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/mwtnConnect.png
Binary files differ
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/sdncConnect.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/sdncConnect.png
new file mode 100755
index 00000000..4542dc13
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/images/sdncConnect.png
Binary files differ
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect-custom.css
new file mode 100644
index 00000000..1fb5c597
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect-custom.css
@@ -0,0 +1,85 @@
+/**
+ * Add your application related css here
+ * width: 1260px;
+ */
+
+.modal-dialog {
+ width: 690px;
+ margin: 30px auto;
+}
+
+.modal-dialog .modal-lg {
+ min-width: 690px;
+ width: 690px;
+}
+
+.requiredNesGrid span {
+ color: #393939;
+}
+.mwtn-form-control {
+ font-family:'Courier New';
+ /* display: block; */
+ width: 600px;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.428571429;
+ color: #000000;
+ vertical-align: middle;
+ background-color: #eeeeee;
+ background-image: none;
+ border: 1px solid #d5d5d5;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -webkit-transition: all border-color ease-in-out .15s, box-shadow ease-in-out .15s linear;
+ -moz-transition: all border-color ease-in-out .15s, box-shadow ease-in-out .15s linear;
+ -ms-transition: all border-color ease-in-out .15s, box-shadow ease-in-out .15s linear;
+ -o-transition: all border-color ease-in-out .15s, box-shadow ease-in-out .15s linear;
+ transition: all border-color ease-in-out .15s, box-shadow ease-in-out .15s linear;
+}
+
+
+.green {
+ color: darkgreen;
+}
+.green span {
+ color: darkgreen;
+}
+
+h3.modal-title {
+ color: #393939;
+}
+
+.modal-body span {
+ color: #393939;
+}
+
+.modal-body h3 {
+ color: #393939;
+}
+
+.modal-body .green span {
+ color: darkgreen;
+}
+
+.requiredNesGrid {
+ height: 600px;
+ background-color: white;
+}
+
+.unknownNesGrid {
+ height: 600px;
+ background-color: white;
+}
+
+.unknownNesGrid .ui-grid-cell-contents span {
+ color: #393939;
+}
+
+.yangCapabilitiesGrid {
+ height: 300px;
+ background-color: white;
+}
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.controller.js
new file mode 100644
index 00000000..c72795c8
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.controller.js
@@ -0,0 +1,1143 @@
+/*
+ * Copyright (c) 2016 highstreet technologies GmbH and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+define(['app/mwtnConnect/mwtnConnect.module',
+ 'app/mwtnConnect/mwtnConnect.services',
+ 'app/mwtnCommons/mwtnCommons.module'],
+ function(mwtnConnectApp) {
+
+ mwtnConnectApp.register.controller('mwtnConnectCtrl', ['$scope', '$rootScope', '$timeout', '$window', '$q', 'uiGridConstants', '$uibModal', '$mwtnConnect', '$mwtnLog', 'NetConfServer',
+ function($scope, $rootScope, $timeout, $window, $q, uiGridConstants, $uibModal, $mwtnConnect, $mwtnLog, NetConfServer) {
+
+ var COMPONENT = 'mwtnConnectCtrl';
+ $mwtnLog.info({component: COMPONENT, message: 'mwtnConnectCtrl started!'});
+
+ $rootScope.section_logo = 'src/app/mwtnConnect/images/sdncConnect.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif'
+
+ $scope.highlightFilteredHeader = $mwtnConnect.highlightFilteredHeader;
+
+ $scope.oneAtATime = true;
+ $scope.status = {requiredNes: true};
+ $scope.spinner = {};
+ $scope.spinner.TEST = true;
+
+ var requiredNesConnectionStatusCellTemplate = [
+ '<div class="ui-grid-cell-contents" ng-class="{ \'green\': grid.getCellValue(row, col) === \'connected\'}">',
+ ' <i ng-class="{\'fa fa-link\': grid.getCellValue(row, col) === \'connected\', \'fa fa-chain-broken\': grid.getCellValue(row, col) !== \'connected\'}" aria-hidden="true"></i>',
+ ' <span>{{grid.getCellValue(row, col)}}</span>',
+ '</div>'].join('');
+
+ var nameCellTemplate = [
+ '<div class="ui-grid-cell-contents">',
+ ' <a href="{{row.entity.webUri}}" target="_blank" title="Access NE web application" ng-show="row.entity.webUri">',
+ ' <i class="fa fa-external-link" aria-hidden="true"></i>',
+ ' <span>{{grid.getCellValue(row, col)}}</span>',
+ ' </a>',
+ ' <span ng-show="!row.entity.webUri">{{grid.getCellValue(row, col)}}</span>',
+ '</div>'].join('');
+
+ // '<button class="btn btn-primary" ng-click="grid.appScope.edit(row.entity)"><i class="fa fa-pencil"></i></button>',
+ // '<button class="btn btn-default" ng-click="grid.appScope.delete(row.entity)"><i class="fa fa-times mwtnError"></i></button>',
+ var requiredNesActionCellTemplate = [
+ '<span>&nbsp;&nbsp;</span>',
+ '<div class="btn-group">',
+ ' <button class="btn btn-primary" ng-click="grid.appScope.connect(row.entity)" title="Mount"><i class="fa fa-link" aria-hidden="true"></i></button>',
+ ' <button class="btn btn-warning" ng-click="grid.appScope.disconnect(row.entity)" title="Unmount"><i class="fa fa-chain-broken" aria-hidden="true"></i></button>',
+ ' <button class="btn btn-success" ng-click="grid.appScope.showDetails(row.entity)" title="Information"><i class="fa fa-info-circle" aria-hidden="true"></i></button>',
+ '<div class="btn-group">',
+ '<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>',
+ '</div>',
+ ' <a class="btn btn-primary" ng-href="#/pnfFault/{{row.entity.name}}" title="Fault Management" target="fm">F</a>',
+ ' <a class="btn btn-primary" ng-href="#/pnfBrowser/{{row.entity.name}}" title="Configuration Management" target="cm">C</a>',
+ ' <a class="btn btn-default" title="Accounting Management" target="am">A</a>',
+ ' <a class="btn btn-primary" ng-href="#/pnfPerformanceHistory/{{row.entity.name}}" title="Performance Management" target="pm">P</a>',
+ ' <a class="btn btn-default" title="Security Management" target="sm">S</a>',
+ '</div>',
+ '<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>',
+ '<div class="btn-group">',
+ ' <a class="btn btn-primary" ng-href="#/pnfInventory/{{row.entity.name}}" title="Inventory Management" target="im">I</a>',
+ '</div>',
+ '<span>&nbsp;</span>'].join('');
+
+
+ $scope.requiredNesGridOptions = JSON.parse(JSON.stringify($mwtnConnect.gridOptions));
+ $scope.requiredNesGridOptions.rowHeight = 44;
+ $scope.requiredNesGridOptions.columnDefs = [
+ { field: 'connectionStatus', type: 'string', displayName: 'Connection status', headerCellClass: $scope.highlightFilteredHeader, width : 160, cellTemplate: requiredNesConnectionStatusCellTemplate },
+ // { field: 'id', type: 'number', displayName: 'Id', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true , sort: {
+ // direction: uiGridConstants.ASC,
+ // ignoreSort: false,
+ // priority: 0
+ // }},
+ { field: 'name', type: 'string', displayName: 'Name', headerCellClass: $scope.highlightFilteredHeader, width : 230, cellTemplate: nameCellTemplate, pinnedLeft : true , sort: {
+ direction: uiGridConstants.ASC,
+ ignoreSort: false,
+ priority: 0
+ }},
+ { field: 'ipaddress', type: 'number', displayName: 'IP address', headerCellClass: $scope.highlightFilteredHeader, width : 140, cellClass: 'number' },
+ { field: 'port', type: 'number', displayName: 'Port', headerCellClass: $scope.highlightFilteredHeader, width : 80, cellClass: 'number' },
+ { field: 'client', type: 'number', displayName: 'Client', headerCellClass: $scope.highlightFilteredHeader, width : 140 },
+ { field: 'username', type: 'string', displayName: 'User name', headerCellClass: $scope.highlightFilteredHeader, width : 100, visible: false },
+ { field: 'password', type: 'string', displayName: 'Password', headerCellClass: $scope.highlightFilteredHeader, width : 100, visible: false },
+ { field: 'radioSignalIds', type: 'string', displayName: 'Radio signal ids', headerCellClass: $scope.highlightFilteredHeader, width : 150, visible: false},
+ {
+ name : 'actions',
+ enableSorting : false,
+ enableFiltering: false,
+ cellTemplate: requiredNesActionCellTemplate,
+ width : 400,
+ pinnedRight : true
+ }
+ ];
+
+ var unknownNesActionCellTemplate = [
+ '<a class="vCenter" ng-class="{attention: grid.appScope.hover, hidden: onfAirInterfaceRevision}" >',
+ '<button class="btn btn-default" ng-show="row.entity[\'node-id\'] !== \'controller-config\'" ng-click="grid.appScope.unmount(row.entity)">Unmount</button>',
+ '<button class="btn btn-primary" ng-show="row.entity[\'node-id\'] !== \'controller-config\' && row.entity.onfCoreModelRevision" ng-click="grid.appScope.addToRequiredNetworkElements(row.entity)">',
+ '<i class="pull-left fa fa-spinner fa-pulse" ng-show="row.entity.spinner"></i>',
+ '<span class="white">{{ "MWTN_MAKE_KNOWN" | translate }}<span>',
+ '</button>',
+ '<button class="btn btn-default" ng-click="grid.appScope.showDetails(row.entity, false)"><i class="fa fa-info-circle" aria-hidden="true"></i></button>',
+ '</a>' ].join('<span>&nbsp;</span>');
+ $scope.unknownNesGridOptions = JSON.parse(JSON.stringify($mwtnConnect.gridOptions));
+ $scope.unknownNesGridOptions.rowHeight = 44;
+ $scope.unknownNesGridOptions.columnDefs = [
+ { field: 'node-id', type: 'string', displayName: 'Name', headerCellClass: $scope.highlightFilteredHeader, width : 200, sort: {
+ direction: uiGridConstants.ASC,
+ priority: 0
+ }},
+ { field: 'netconf-node-topology:host', type: 'number', displayName: 'IP address', headerCellClass: $scope.highlightFilteredHeader, width : 150, cellClass: 'number' },
+ { field: 'netconf-node-topology:port', type: 'number', displayName: 'NetConf port', headerCellClass: $scope.highlightFilteredHeader, width : 120, cellClass: 'number' },
+ { field: 'onfCoreModelRevision', type: 'string', displayName: 'CoreModel revision', headerCellClass: $scope.highlightFilteredHeader, width : 160, cellClass: 'number' },
+ { field: 'onfAirInterfaceRevision', type: 'string', displayName: 'AirInterface revision', headerCellClass: $scope.highlightFilteredHeader, width : 160, cellClass: 'number' },
+ { field: 'netconf-node-topology:connection-status', type: 'string', displayName: 'Connection status', headerCellClass: $scope.highlightFilteredHeader, width : 160 },
+ {
+ name : 'actions',
+ enableSorting : false,
+ enableFiltering: false,
+ cellTemplate: unknownNesActionCellTemplate,
+ width : 330,
+ pinnedRight : true
+ }
+ ];
+
+ /**
+ * Request all defined (required) network elements from database and
+ * update the corresponding table in the ui.
+ */
+ var getRequiredNetworkElements = function() {
+ $mwtnConnect.getRequiredNetworkElements().then(function(networkElements) {
+ $scope.requiredNesGridOptions.data = networkElements;
+ getActualNetworkElements();
+ }, function(error){
+ $scope.requiredNesGridOptions.data = [];
+ });
+ };
+ getRequiredNetworkElements();
+
+ /**
+ * A function, which returns a boolean, which indicates, whether a network
+ * element is required or not.
+ * @param {string} neId - A mount point identifier.
+ * @return {boolean} True, if network element is required in the network, otherwise false.
+ */
+ var isRequired = function(neId) {
+ if ($scope.requiredNesGridOptions.data) {
+ var result = false;
+ $scope.requiredNesGridOptions.data.map(function(rne) {
+ if (rne.name === neId) result = true;
+ });
+ return result;
+ } else {
+ return false;
+ }
+ };
+
+ var setConnectionStatus = function(neId, connectionStatus) {
+ if ($scope.requiredNesGridOptions.data) {
+ $scope.requiredNesGridOptions.data.map(function(rne) {
+ if (rne.name === neId) rne.connectionStatus = connectionStatus;
+ });
+ }
+ };
+
+ var setValues = function(ane) {
+ if ($scope.requiredNesGridOptions.data) {
+
+ var getExtension = function(extensions, name) {
+ if (extensions === undefined) {
+ return undefined;
+ }
+ var result = extensions.filter(function(ex){
+ return ex['value-name'] === name;
+ }).map(function(ex){
+ return ex.value;
+ });
+ if (result.length > 0) {
+ result = result[0];
+ } else {
+ result = undefined;
+ }
+ return result;
+ };
+
+ $scope.requiredNesGridOptions.data.map(function(rne) {
+ // TODO use filter! and avoid push?
+ if (rne.name === ane['node-id']) {
+ rne.connectionStatus = ane['netconf-node-topology:connection-status'];
+ rne.ipaddress = ane['netconf-node-topology:host'];
+ rne.port = ane['netconf-node-topology:port'];
+ rne.client = ane.client;
+
+ rne.onfCapabilities = ane.onfCapabilities;
+
+ var extensions = ['webUri', 'cliAddress', 'appCommand'];
+ extensions.map(function(extension){
+ rne[extension] = undefined;
+ });
+ if (ane.onfCoreModelRevision) {
+ $mwtnConnect.getActualNetworkElement(ane['node-id'], ane.onfCoreModelRevision).then(function(success){
+ success = $mwtnConnect.yangifyObject(success);
+ extensions.map(function(extension){
+ rne[extension] = getExtension(success['network-element'].extension, extension);
+ });
+ }, function(error){
+ // ignore
+ });
+ }
+ }
+ });
+ }
+ };
+
+ var getActualNetworkElements = function() {
+ // aneHash = [];
+ if ($scope.requiredNesGridOptions.data) {
+ $scope.requiredNesGridOptions.data.map(function(ne) {
+ // ne.connectionStatus = 'disconnected';
+ });
+ }
+ $mwtnConnect.getMountPoints().then(function(mountpoints) {
+ $scope.unknownNesGridOptions.data = [];
+ mountpoints.map(function(mountpoint) {
+ if (isRequired(mountpoint['node-id'])) {
+ // setConnectionStatus(ne['node-id'], ne['netconf-node-topology:connection-status']);
+ setValues(mountpoint);
+ } else {
+ // console.log('mountpoint', JSON.stringify(mountpoint));
+ $scope.unknownNesGridOptions.data.push(mountpoint);
+ }
+ });
+ }, function(error){
+ $mwtnLog.info({component: COMPONENT, message: JSON.stringify(error)});
+ });
+ };
+
+ $scope.netconfServer = {};
+
+ /**
+ * A function which inquires data from a netconf server and stores it in a database.
+ * @param {{'node-id': string, ipAddress: string, port: number, username: string, password: string}} netconfServer - A netConf server object with all connectivity parameters.
+ */
+ $scope.addToRequiredNetworkElements = function(netconfServer) {
+
+ $scope.netconfServer = netconfServer;
+ var neId = netconfServer['node-id'];
+
+ var index = $scope.unknownNesGridOptions.data.map(function(item) {
+ return item['node-id'];
+ }).indexOf(netconfServer['node-id']);
+
+ if (index !== -1 ) {
+ $mwtnConnect.getSingleDocument('mwtn', 'required-networkelement', neId).then(function(doc){
+ // Network element alrady exists in database
+ doc.required = true;
+ $scope.unknownNesGridOptions.data[index].spinner = true;
+ // add to aai
+ // $onapAai.createPnf(neId, doc).then(function(success){
+ // // do nothing
+ // }, function(error) {
+ // // do nothing
+ // });
+ // add to es
+ $mwtnConnect.createSingleDocument('mwtn', 'required-networkelement', neId, doc).then(function(success){
+ $timeout(function() {
+ $scope.status.requiredNes = true;
+ $scope.unknownNesGridOptions.data[index].spinner = false;
+ }, 1000);
+ }, function(error) {
+ $timeout(function() {
+ $scope.status.requiredNes = true;
+ $scope.unknownNesGridOptions.data[index].spinner = false;
+ }, 1000);
+ console.log(JSON.stringify(error));
+ });
+ }, function(error) {
+ // Network element does not exist in database, data inqured from real network element
+ var modalInstance = $uibModal.open({
+ animation: true,
+ ariaLabelledBy: 'modal-title',
+ ariaDescribedBy: 'modal-body',
+ templateUrl: 'src/app/mwtnConnect/templates/addToRequired.tpl.html',
+ controller: 'AddToRequiredMessageCtrl',
+ size: 'lg',
+ resolve: {
+ netconfServer: function () {
+ return $scope.netconfServer;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (netconfServer) {
+ $scope.unknownNesGridOptions.data[index].spinner = true;
+ $mwtnConnect.addRequiredNetworkElement(netconfServer).then(function(success){
+ $mwtnLog.info({component: COMPONENT, message: 'Adding to database: ' + netconfServer['node-id']});
+
+ // $onapAai.createPnf(netconfServer['node-id'], success.config.data).then(function(success){
+ // // do nothing
+ // }, function(error) {
+ // // do nothing
+ // });
+
+ $timeout(function() {
+ $scope.status.requiredNes = true;
+ $scope.unknownNesGridOptions.data[index].spinner = false;
+ }, 1000);
+ }, function(error){
+ $scope.unknownNesGridOptions.data[index].spinner = false;
+ $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)});
+ });
+ }, function () {
+ $mwtnLog.info({component: COMPONENT, message: 'Creation of new planned NetworkElement dismissed!'});
+ });
+ });
+ }
+ };
+
+ $scope.newMountingPoint = {
+ name: 'new-netconf-server',
+ ipaddress: '127.0.0.1',
+ port: 830,
+ username: 'admin',
+ password: 'admin'
+ };
+
+ $scope.mount = function() {
+ $scope.mountError = undefined;
+ $scope.mountSuccess = undefined;
+ $scope.processing = true;
+ $mwtnConnect.mount($scope.newMountingPoint).then(function(success){
+ $scope.processing = false;
+ $scope.mountSuccess = ['NETCONF server', $scope.newMountingPoint.name, 'successfully mounted.'].join(' ');
+ }, function(error){
+ $scope.processing = false;
+ $scope.mountError = ['NETCONF server', $scope.newMountingPoint.name, 'could not be mounted.'].join(' ');
+ });
+ };
+
+ $scope.connect = function(ne) {
+ ne.connectionStatus = 'connecting...';
+ $mwtnConnect.mount(ne).then(function(success){
+ // ne.connectionStatus = 'connected';
+ }, function(error){
+ // ne.connectionStatus = 'connected';
+ });
+ };
+
+ $scope.disconnect = function(ne) {
+ ne.connectionStatus = 'connecting...';
+ $mwtnConnect.unmount(ne.name).then(function(success){
+ ne.connectionStatus = 'disconnected';
+ }, function(error){
+ ne.connectionStatus = 'unknown';
+ });
+ };
+
+ $scope.showDetails = function(ne, required) {
+ $scope.currentNetworkElement = ne;
+ $scope.currentNetworkElement.required = required;
+ if (required !== false) {
+ $scope.currentNetworkElement.required = true;
+ }
+ var modalInstance = $uibModal.open({
+ animation: true,
+ ariaLabelledBy: 'modal-title',
+ ariaDescribedBy: 'modal-body',
+ templateUrl: 'src/app/mwtnConnect/templates/mountPointDetails.tpl.html',
+ controller: 'MountPointDetailsCtrl',
+ size: 'lg',
+ resolve: {
+ currentNetworkElement: function () {
+ return $scope.currentNetworkElement;
+ }
+ }
+ });
+
+ modalInstance.result.then(function(success) {
+ if (success.hide || success.delete) {
+ var nodeId = success.hide || success.delete;
+ $scope.requiredNesGridOptions.data.map(function(item, index, array){
+ if (item.name === nodeId) {
+ array.splice(index, 1);
+ }
+ });
+ }
+ $mwtnLog.info({component: COMPONENT, message: 'Mointpoint details closed'});
+ }, function (error) {
+ $mwtnLog.info({component: COMPONENT, message: 'Mointpoint details dismissed!'});
+ });
+ };
+
+ var removeFromNodeList = function(nodeId) {
+ var index = $scope.unknownNesGridOptions.data.length;
+ while (index--) {
+ if ($scope.unknownNesGridOptions.data[index]['node-id'] === nodeId) {
+ $scope.unknownNesGridOptions.data.splice(index, 1);
+ }
+ }
+ };
+
+ $scope.unmount = function(netConfServer) {
+ netConfServer['netconf-node-topology:connection-status'] = 'disconnecting...';
+ $mwtnConnect.unmount(netConfServer['node-id']).then(function(response) {
+ $mwtnLog.info({component: COMPONENT, message: 'Mounting point deleted: ' + netConfServer['node-id'] });
+ removeFromNodeList(netConfServer['node-id']);
+ }, function(error){
+ $mwtnLog.info({component: COMPONENT, message: 'Unmounting of '+netConfServer['node-id']+' failed!'});
+ removeFromNodeList(netConfServer['node-id']);
+ });
+ };
+
+ $scope.edit = function(row) {
+ console.info(JSON.stringify(row));
+ };
+ $scope.delete = function(row) {
+ console.info(JSON.stringify(row));
+ };
+
+ // Connection status log
+ $scope.gridOptionsConnectionStatusLog = {
+ paginationPageSizes: [25, 100, 1000, 10000],
+ paginationPageSize: 25,
+ useExternalPagination: true,
+ useExternalSorting: true,
+ enablePaginationControls: false,
+ enableFiltering: true,
+ useExternalFiltering: true,
+ maxCount: 0,
+ columnDefs : [
+ // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true },
+ { field: 'timestamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200, sort: {
+ direction: uiGridConstants.DESC,
+ priority: 1
+ } },
+ { field: 'nodeName', type: 'string', displayName: 'Node name', headerCellClass: $scope.highlightFilteredHeader, width: 200 },
+ { field: 'connectionStatus', type: 'string', displayName: 'Connection status', headerCellClass: $scope.highlightFilteredHeader, width: 500, cellTemplate: requiredNesConnectionStatusCellTemplate }
+ ],
+ data: 'data',
+ onRegisterApi: function(gridApi) {
+ $scope.gridApi = gridApi;
+ $scope.gridApi.core.on.filterChanged( $scope, $scope.filter);
+ $scope.gridApi.core.on.sortChanged( $scope, $scope.sortChanged );
+ $scope.sortChanged($scope.gridApi.grid, [ $scope.gridOptionsConnectionStatusLog.columnDefs[1] ] );
+
+ $scope.gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
+ $scope.paginationOptions.pageNumber = newPage;
+ $scope.paginationOptions.pageSize = pageSize;
+ getPage();
+ });
+ }
+ };
+
+ // data visible in connection status log
+ $scope.data = [];
+
+ //stateobject
+ $scope.state = {
+ filter: false,
+ sort: false,
+ lastfilter: null,
+ lastSort: null
+ };
+
+ //filter
+ $scope.filter = function() {
+ var grid = this.grid;
+ var columns=[];
+
+ //get all columns where data was typed in
+ angular.forEach(grid.columns, function(value, key) {
+ if(value.filters[0].term) {
+
+ var col = findColumn(value.displayName);
+ var val = value.filters[0].term;
+
+ switch (col) {
+ case 'event.timeStamp':
+ //convert timestamp to db format
+ val = $mwtnConnect.TimeStampToONFFormat(value.filters[0].term);
+ break;
+ case 'event.type':
+ if ('connected'.startsWith(value.filters[0].term.toLowerCase())) {
+ val = 'ObjectCreationNotificationXml'.toLowerCase();
+ }
+ if ('disconnected'.startsWith(value.filters[0].term.toLowerCase())) {
+ val = 'ObjectDeletionNotificationXml'.toLowerCase();
+ }
+ break;
+ }
+ columns.push({ column: col, value: val }); //create column object
+ }
+ });
+
+ if (columns.length ===0 ) { //all filter data cleared away
+ $scope.state.filter = false;
+ $scope.state.lastfilter = null;
+
+ //get unfiltered data
+ $mwtnConnect.getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,
+ $scope.paginationOptions.pageSize,
+ $scope.state.lastSort,
+ $scope.state.lastfilter).then(function(response) {
+ if (response.data.hits.hits) {
+ processResponseRecreateList(response);
+ }
+ });
+ } else {
+ //base filter string
+ var filter = {"query": {"bool":{"must":[]}}};
+ //create filter objects
+ var prefixs = columns.map(function(obj){
+ var prefixObj={};
+ prefixObj[obj.column] = obj.value;//add like: {column: "fault.counter", value: "1"} => {"fault.counter":1}
+ return {prefix:prefixObj}; // => {"prefix":{...}}
+ });
+ prefixs.push({"match":{"event.nodeName":"SDN-Controller"}});
+
+ //add objects to must property
+ filter.query.bool.must = prefixs;
+ //save filter
+ $scope.state.lastfilter=filter;
+ $scope.state.filter=true;
+
+ //send data to sdnevents/eventlog/_search
+ $mwtnConnect.getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,
+ $scope.paginationOptions.pageSize,
+ $scope.state.lastSort,
+ $scope.state.lastfilter).then(function(response) {
+ if (response.data.hits.total>0) { //only, when hits exist
+ processResponseRecreateList(response);
+ $scope.gridOptionsConnectionStatusLog.totalItems = response.data.hits.total;
+ } else {
+ //clear data from list
+ $scope.data=[];
+ $scope.gridOptionsConnectionStatusLog.totalItems = 0;
+ $scope.gridOptionsConnectionStatusLog.maxCount = 0;
+ $scope.state.filter=false;
+ $scope.state.lastfilter=null;
+ }
+ });
+ }
+ };
+
+ //sort
+ $scope.sortChanged=function(grid, sortColumns){ // sortColumns is an array containing just the column sorted in the grid
+ if (sortColumns.length > 0) {
+ if (sortColumns[0].sort) {
+ var name = sortColumns[0].displayName; // the name of the column sorted
+ var direction = sortColumns[0].sort.direction; // the direction of the column sorted: "desc" or "asc"
+ sort(direction, findColumn(name) );
+ }
+ } else {
+ $scope.state.sort = false;
+ $scope.state.lastSort=null;
+ //get unsorted data
+ $mwtnConnect.getData( ($scope.paginationOptions.pageNumber-1) * $scope.paginationOptions.pageSize,
+ $scope.paginationOptions.pageSize,
+ $scope.state.lastSort,
+ $scope.state.lastfilter).then(function(response) {
+ processResponseRecreateList(response);
+ }, function(error) {
+ processResponseRecreateList([]);
+ });
+ }
+ };
+
+ var processResponseRecreateList = function(response) {
+ if (!response.data || !response.data.hits) {
+ $scope.data = [];
+ $scope.gridOptionsConnectionStatusLog.totalItems = 0; // needed by ui-grid to calculate page number, always update!
+ $scope.gridOptionsConnectionStatusLog.maxCount = 0;
+ return;
+ }
+
+ if($scope.gridOptionsConnectionStatusLog.maxCount < response.data.hits.total){
+ $scope.gridOptionsConnectionStatusLog.maxCount = response.data.hits.total; //only if total is higher (can be lower due to eg filtering)
+ }
+ var list = response.data.hits.hits.map(function(entry) {
+
+ var status = 'unknown';
+ if (entry._source.event.type === 'ObjectCreationNotificationXml' ) {
+ status = 'connected';
+ } else if (entry._source.event.type === 'ObjectDeletionNotificationXml' ) {
+ status = 'disconnected';
+ }
+ return {
+ id: entry._id,
+ timestamp: $mwtnConnect.formatTimeStamp(entry._source.event.timeStamp),
+ nodeName: entry._source.event.objectId,
+ connectionStatus: status
+ };
+ });
+ $scope.data=list;
+ $scope.gridOptionsConnectionStatusLog.totalItems = response.data.hits.total; // needed by ui-grid to calculate page number, always update!
+ };
+
+ $scope.paginationOptions = {
+ pageNumber: 1,
+ pageSize: 25,
+ sort: null
+ };
+
+ var getPage = function() {
+ //from, how many, sort, filter
+ $mwtnConnect.getData( ($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,
+ $scope.paginationOptions.pageSize,
+ $scope.state.lastSort,
+ $scope.state.lastfilter).then(function (success) {
+ $scope.gridOptionsConnectionStatusLog.totalItems = success.data.hits.total;
+ processResponseRecreateList(success);
+ }, function(error) {
+ $scope.gridOptionsConnectionStatusLog.totalItems = success.data.hits.total;
+ processResponseRecreateList([]);
+ $mwtnLog.info({component: COMPONENT, message: JSON.stringify(error)});
+ });
+ };
+
+ var processResponseAddToList = function(response) {
+ if (response.data.hits.hits) {
+ if($scope.gridOptionsConnectionStatusLog.maxCount < response.data.hits.total) {
+ $scope.gridOptionsConnectionStatusLog.maxCount = response.data.hits.total; //only if total is higher (can be lower due to eg filtering)
+ }
+ response.data.hits.hits.map(function(entry) {
+ var status = 'disconnected';
+ if (entry._source.event.type === 'ObjectCreationNotificationXml' ) {
+ status = 'connected';
+ }
+ var log = {
+ id: entry._id,
+ timestamp: $mwtnConnect.formatTimeStamp(entry._source.event.timeStamp),
+ nodeName: entry._source.event.objectId,
+ connectionStatus: status
+ };
+ $scope.data.push(log);
+ });
+ }
+ $scope.gridOptionsConnectionStatusLog.totalItems = response.data.hits.total; // needed by ui-grid to calculate page number, always update!
+ };
+
+ var sort = function (direction, columnName) {
+
+ var sortObj={};
+ var sort = [ sortObj ];
+ switch (direction) {
+ case uiGridConstants.ASC:
+ //create sort object
+ sortObj[columnName]={order : 'asc'};
+ sort = [ sortObj ];
+ //save last sort
+ $scope.state.lastSort=sort;
+
+ $mwtnConnect.getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,
+ $scope.paginationOptions.pageSize,
+ $scope.state.lastSort,
+ $scope.state.lastfilter).then(function(response) {
+ if (response.data.hits.hits) {
+ processResponseRecreateList(response);
+ $scope.state.sort=true;
+ }
+ });
+ break;
+
+ case uiGridConstants.DESC:
+ sortObj[columnName]={order : 'desc'};
+ sort = [ sortObj];
+ $scope.state.lastSort=sort;
+
+ $mwtnConnect.getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) {
+ if (response.data.hits.hits) {
+ processResponseRecreateList(response);
+ $scope.state.sort=true;
+ }
+ });
+ break;
+
+ case undefined:
+
+ $scope.state.sort=false;
+ $scope.state.lastSort=null;
+
+ $mwtnConnect.getData(($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize,
+ $scope.paginationOptions.pageSize,
+ $scope.state.lastSort,
+ $scope.state.lastfilter).then(function(response) {
+ processResponseRecreateList(response);
+ });
+ break;
+ }
+ };
+
+ var findColumn= function(name) {
+ if(name === 'Timestamp'){ return 'event.timeStamp'; }
+ else if(name === 'Node name'){ return 'event.objectId'; }
+ else if(name === 'Connection status'){ return 'event.type'; }
+ };
+
+ $scope.paginationStatusMessage = function() {
+
+ var startnum=($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize+1;
+ var pagenednum=($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize+1+$scope.data.length;
+ if(pagenednum>$scope.gridOptionsConnectionStatusLog.totalItems) pagenednum=pagenednum-1; //reduce by initial added 1
+
+ if($scope.state.filter){
+ var filterTpl = 'Showing {0} to {1} of {2} items (filtered from {3} total items)';
+ return filterTpl.format(startnum, pagenednum, $scope.gridOptionsConnectionStatusLog.totalItems, $scope.gridOptionsConnectionStatusLog.maxCount);
+
+ } else {
+ var defaultTpl = 'Showing {0} to {1} of {2} total items';
+ return defaultTpl.format( startnum, pagenednum, $scope.gridOptionsConnectionStatusLog.maxCount);
+ }
+ };
+
+ $scope.refreshLog = function() {
+
+
+ var from = ($scope.paginationOptions.pageNumber-1)*$scope.paginationOptions.pageSize;
+ var size = $scope.paginationOptions.pageSize;
+ $scope.processing = true;
+ $scope.spinner.connectionStatusLog = true;
+ $mwtnConnect.getData(from, size, $scope.state.lastSort, $scope.state.lastfilter).then(function(logEntries){
+ $scope.processing = false;
+ $scope.spinner.connectionStatusLog = false;
+ processResponseRecreateList(logEntries);
+ }, function(error){
+ $scope.processing = false;
+ $scope.spinner.connectionStatusLog = false;
+ console.error(JSON.stringify(error));
+ });
+ };
+
+ // browser events
+ $scope.status = {requiredNes : true};
+ $scope.separator = $mwtnConnect.separator; //'&nbsp;'
+ $scope.$watch('status', function(status, oldValue) {
+ Object.keys(status).map(function(key){
+ if (status[key] && status[key] !== oldValue[key]) {
+ switch (key) {
+ case 'requiredNes':
+ getRequiredNetworkElements();
+ break;
+ case 'unkownNes':
+ getActualNetworkElements();
+ break;
+ case 'mount':
+ $scope.mountSuccess = undefined;
+ $scope.mountError = undefined;
+ break;
+ case 'connectionStatusLog':
+ $window.dispatchEvent(new Event("resize"));
+ $scope.refreshLog();
+ break;
+ }
+ }
+ });
+ }, true);
+
+ // odl events
+ // actualNetworkElements - NE added/deleted
+ var listenToActualNetworkElementsNotifications = function(socketLocation) {
+ try {
+ var notificatinSocket = new WebSocket(socketLocation);
+
+ notificatinSocket.onmessage = function(event) {
+ console.log('Event received.');
+ setTimeout(function() {
+ getActualNetworkElements();
+ }, 1000);
+ };
+ notificatinSocket.onerror = function(error) {
+ console.error("Socket error: " + error);
+ };
+ notificatinSocket.onopen = function(event) {
+ console.info("Socket connection opened.");
+ };
+ notificatinSocket.onclose = function(event) {
+ console.info("Socket connection closed.");
+ };
+ } catch (e) {
+ console.error("Error when creating WebSocket" + e);
+ }
+ };
+
+ // var path = '/network-topology:network-topology/network-topology:topology[network-topology:topology-id = "topology-netconf"]';
+ // var path = "/opendaylight-inventory:nodes"; // [sko] works!
+ var path = '/network-topology:network-topology'; // for whatever reason it does not work, but work in Lithium.
+ $mwtnConnect.registerForOdlEvents(path, function(socketLocation) {
+ listenToActualNetworkElementsNotifications(socketLocation);
+ });
+
+ var listenToEventManagerNotifications = function() {
+ $mwtnConnect.getMwtnWebSocketUrl().then(function(success){
+ try {
+ var notificationSocket = new WebSocket(success);
+
+ notificationSocket.onmessage = function(event) {
+ // we process our received event here
+ if (typeof event.data === 'string') {
+ // console.log("Client Received:\n" + event.data);
+ // console.log("---------------------------");
+ $mwtnConnect.formatData(event).then(function(formated) {
+ switch (formated.notifType) {
+ case 'ProblemNotification':
+ case 'AttributeValueChangedNotification':
+ // ignore
+ break;
+ case 'ObjectCreationNotification':
+ case 'ObjectDeletionNotification':
+ if (formated.nodeName === 'SDN-Controller') {
+ $timeout(function() {getActualNetworkElements();}, 500);
+ }
+ break;
+ default:
+ console.error('Missing implementation for', formated.notifType);
+ }
+ }, function(error) {
+ // do nothing
+ });
+ }
+ };
+
+ notificationSocket.onerror = function(error) {
+ console.log("Socket error: " + error);
+ };
+
+ notificationSocket.onopen = function(event) {
+ console.log("Socket connection opened.");
+
+ function subscribe() {
+ if (notificationSocket.readyState === notificationSocket.OPEN) {
+ var data = {
+ 'data' : 'scopes',
+ 'scopes' : [ 'ObjectCreationNotification', 'ObjectDeletionNotification' ]
+ };
+ notificationSocket.send(JSON.stringify(data));
+ }
+ }
+ subscribe();
+ };
+
+ notificationSocket.onclose = function(event) {
+ console.log("Socket connection closed.");
+ };
+ } catch (e) {
+ console.error("Error when creating WebSocket.\n" + e);
+ }
+ }, function(error){
+ console.error("Error when creating WebSocket.\n" + error);
+ });
+ };
+ listenToEventManagerNotifications();
+
+ }]);
+
+ mwtnConnectApp.register.controller('AddToRequiredMessageCtrl', ['$scope', '$uibModalInstance', '$mwtnConnect', 'netconfServer',
+ function ($scope, $uibModalInstance, $mwtnConnect, netconfServer) {
+
+ $scope.netconfServer = netconfServer;
+
+ $mwtnConnect.getMountPoint(netconfServer['node-id']).then(
+ /**
+ * @param {{'node-id':string, 'netconf-node-topology:tcp-only': boolean, 'netconf-node-topology:host', string, 'netconf-node-topology:keepalive-delay':number, 'netconf-node-topology:port':number, 'netconf-node-topology:username':string, 'netconf-node-topology:password': string}} mountpoint - The mointpoint form topology-netconf
+ */
+ function(mountpoint) {
+ $scope.netconfServer.username = mountpoint['netconf-node-topology:username'];
+ $scope.netconfServer.password = mountpoint['netconf-node-topology:password'];
+ },
+ function(error){
+ console.log(JSON.stringify(error));
+ }
+ );
+
+ $scope.sites = [];
+ var sort = [ {
+ id : {
+ order : 'asc'
+ }
+ }];
+ $mwtnConnect.getAllData('mwtn', 'site', 0, 20, sort).then(
+ function(sites){
+ // console.log(JSON.stringify(sites));
+ if (sites.data.hits.hits) {
+ sites.data.hits.hits.map(function(site){
+ $scope.sites.push({id:site._source.id, name:site._source.name});
+ });
+ // console.log($scope.sites);
+ }
+ },
+ function(error){
+ $scope.sites = [];
+ }
+ );
+
+ $scope.ok = function () {
+ $uibModalInstance.close($scope.netconfServer);
+ };
+
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss('cancel');
+ };
+
+ $scope.$watch('netconfServer.site', function(newValue, oldValue) {
+ if (newValue !== oldValue) {
+ var sort = [ {
+ id : {
+ order : 'asc'
+ }
+ }];
+ var query = {
+ prefix: {
+ name: newValue
+ }
+ };
+
+ $mwtnConnect.getFilteredSortedData('mwtn', 'site', 0, 20, sort, query).then(
+ function(sites){
+ // console.log(JSON.stringify(sites));
+ if (sites.data.hits.hits) {
+ $scope.sites = sites.data.hits.hits.map(function(site){
+ return {id:site._source.id, name:site._source.name};
+ });
+ // console.log($scope.sites);
+ }
+ },
+ function(error){
+ $scope.sites = [];
+ }
+ );
+ }
+ });
+ }]);
+
+ mwtnConnectApp.register.controller('MountPointDetailsCtrl', ['$scope', '$uibModalInstance', '$uibModal', '$mwtnConnect', '$mwtnLog', 'currentNetworkElement',
+ function ($scope, $uibModalInstance, $uibModal, $mwtnConnect, $mwtnLog, currentNetworkElement) {
+
+ var COMPONENT = 'MountPointDetailsCtrl';
+ // $mwtnLog.info({component: COMPONENT, message: 'MountPointDetailsCtrl started!'});
+
+ $scope.data = {
+ ne: currentNetworkElement,
+ web: {
+ supported: false,
+ protocol: 'http',
+ ipAddress: '127.0.0.1',
+ port: 80,
+ url: '/',
+ getLink : function() {
+ if (currentNetworkElement.webUri) {
+ return currentNetworkElement.webUri;
+ }
+ return [this.protocol,'://', this.ipAddress, this.url ].join('');
+ }
+ },
+ terminal: {
+ supported: false,
+ copied: false,
+ protocol: 'ssh',
+ user: 'cli',
+ ipAddress: '127.0.0.1',
+ getCommand : function() {
+ if (currentNetworkElement.cliAddress) {
+ return currentNetworkElement.cliAddress;
+ }
+ return [this.protocol, ' ', this.user, '@', this.ipAddress].join('');
+ },
+ copyToClipboard : function () {
+ $scope.data.application.copied = false;
+ this.copied = true;
+ var message = 'Copied to clipboard! ' + this.getCommand();
+ $mwtnLog.info({component: COMPONENT, message: message});
+ }
+ },
+ application: {
+ supported: false,
+ copied: false,
+ commandTemplate: 'VendorApp --ne {0}',
+ ipAddress: '127.0.0.1',
+ getCommand : function() {
+ if (currentNetworkElement.appCommand) {
+ return currentNetworkElement.appCommand;
+ }
+ return this.commandTemplate.format(this.ipAddress);
+ },
+ copyToClipboard : function () {
+ $scope.data.terminal.copied = false;
+ $scope.data.application.copied = true;
+ var message = 'Copied to clipboard! ' + this.getCommand();
+ $mwtnLog.info({component: COMPONENT, message: message});
+ }
+ }
+ };
+
+ var nodeId = $scope.data.ne.name || $scope.data.ne['node-id'];
+ $mwtnConnect.getMountPoint(nodeId).then(function(success){
+ $scope.data.mountpoint = success;
+ }, function(error){
+ $scope.data.mountpoint = undefined;
+ });
+
+ if (currentNetworkElement.webUri && currentNetworkElement.webUri !== '') {
+ $scope.data.web.supported = true;
+ $scope.data.web.protocol = currentNetworkElement.webUri.split(':')[0];
+ var matches = currentNetworkElement.webUri.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+ $scope.data.web.ipAddress = matches && matches[1]; // ipAddress will be null if no match is found
+ }
+ if (currentNetworkElement.cliAddress && currentNetworkElement.cliAddress !== '') {
+ $scope.data.terminal.supported = true;
+ var matches = currentNetworkElement.cliAddress.match(/([^@]+)@([^@]+)/i);
+ $scope.data.terminal.user = matches && matches[1];
+ $scope.data.terminal.ipAddress = matches && matches[2];
+ }
+ if (currentNetworkElement.appCommand && currentNetworkElement.appCommand !== '') {
+ $scope.data.application.supported = true;
+ // [sko] TODO once a mediator supports it
+ }
+
+ $scope.yangCapabilitiesGridOptions = JSON.parse(JSON.stringify($mwtnConnect.gridOptions));
+ $scope.yangCapabilitiesGridOptions.columnDefs = [
+ { field: 'module', type: 'string', displayName: 'module', headerCellClass: $scope.highlightFilteredHeader, width : 600 },
+ { field: 'revision', type: 'string', displayName: 'Revision', headerCellClass: $scope.highlightFilteredHeader, width : 150}
+ ];
+ $scope.yangCapabilitiesGridOptions.data = currentNetworkElement.onfCapabilities;
+
+ // clipboard
+ $scope.supported = false;
+ $scope.error = function (err) {
+ $mwtnLog.error({component: COMPONENT, message: err});
+ };
+
+ $scope.ok = function () {
+ $uibModalInstance.close({ne: currentNetworkElement});
+ };
+
+ $scope.hide = function (ne) {
+ $scope.hideNe = ne;
+ var modalInstance = $uibModal.open({
+ animation: true,
+ ariaLabelledBy: 'modal-title',
+ ariaDescribedBy: 'modal-body',
+ templateUrl: 'src/app/mwtnConnect/templates/confirmHide.tpl.html',
+ controller: 'MountPointHideCtrl',
+ size: 'lg',
+ resolve: {
+ hideNe: function () {
+ return $scope.hideNe;
+ }
+ }
+ });
+
+ modalInstance.result.then(
+ function(neId) {
+ $mwtnConnect.getSingleDocument('mwtn', 'required-networkelement', neId).then(
+ function(doc){
+ doc.required = false;
+ $mwtnConnect.createSingleDocument('mwtn', 'required-networkelement', neId, doc).then(
+ function(success){
+ $uibModalInstance.close({hide: neId});
+ },
+ function(error) {
+ $uibModalInstance.close({hide: neId});
+ }
+ );
+ },
+ function(error) {
+ $uibModalInstance.close({hide: neId});
+ }
+ );
+ $mwtnLog.info({component: COMPONENT, message: 'Confirm hide closed'});
+ },
+ function (error) {
+ $mwtnLog.info({component: COMPONENT, message: 'Confirm hide dismissed!'});
+ }
+ );
+ };
+
+ $scope.delete = function (ne) {
+ $scope.deleteNe = ne;
+ var modalInstance = $uibModal.open({
+ animation: true,
+ ariaLabelledBy: 'modal-title',
+ ariaDescribedBy: 'modal-body',
+ templateUrl: 'src/app/mwtnConnect/templates/confirmDelete.tpl.html',
+ controller: 'MountPointDeleteCtrl',
+ size: 'lg',
+ resolve: {
+ deleteNe: function () {
+ return $scope.deleteNe;
+ }
+ }
+ });
+
+ modalInstance.result.then(function(success) {
+ // delete from AAi
+ // $onapAai.deletePnf(success).then(function(deleted){
+ // $mwtnLog.info({component: COMPONENT, message: success + ' deleted from AAI.'});
+ // }, function(error){
+ // $mwtnLog.info({component: COMPONENT, message: 'Deletion from AAI failed: ' + success + '\n' + error});
+ // });
+ // delete from ES
+ $mwtnConnect.deleteSingleDocument('mwtn', 'required-networkelement', success).then(function(deleted){
+ $mwtnLog.info({component: COMPONENT, message: success + ' deleted from database.'});
+ $uibModalInstance.close({hide: success});
+ }, function(error){
+ $mwtnLog.info({component: COMPONENT, message: 'Deletion from database failed: ' + success + '\n' + error});
+ });
+ }, function (error) {
+ $mwtnLog.info({component: COMPONENT, message: 'Confirm delete dismissed!'});
+ });
+ };
+
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss('cancel');
+ };
+ }]);
+
+ mwtnConnectApp.register.controller('MountPointHideCtrl', ['$scope', '$uibModalInstance', '$mwtnConnect', '$mwtnLog', 'hideNe',
+ function ($scope, $uibModalInstance, $mwtnConnect, $mwtnLog, hideNe) {
+ $scope.hideNe = hideNe;
+ $scope.ok = function () {
+ $uibModalInstance.close($scope.hideNe.name);
+ };
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss('cancel');
+ };
+
+ }]);
+
+ mwtnConnectApp.register.controller('MountPointDeleteCtrl', ['$scope', '$uibModalInstance', '$mwtnConnect', '$mwtnLog', 'deleteNe',
+ function ($scope, $uibModalInstance, $mwtnConnect, $mwtnLog, deleteNe) {
+ $scope.deleteNe = deleteNe;
+ $scope.ok = function () {
+ $uibModalInstance.close($scope.deleteNe.name);
+ };
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss('cancel');
+ };
+
+ }]);
+
+}); \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.module.js
new file mode 100644
index 00000000..c280a956
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.module.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 highstreet technologies GmbH and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+define(['angularAMD',
+ 'app/routingConfig',
+ 'app/core/core.services',
+ 'common/config/env.module',
+ 'app/mwtnCommons/mwtnCommons.module'], function(ng) {
+ var mwtnConnectApp = angular.module('app.mwtnConnect', [ 'ui.grid', 'ui.bootstrap', 'app.core',
+ 'ui.router.state', 'config', 'ui.grid.exporter',
+ 'ui.grid.moveColumns', 'ui.grid.pinning', 'ui.grid.selection',
+ 'ui.grid.resizeColumns', 'angular-clipboard' ]);
+
+ mwtnConnectApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) {
+
+ mwtnConnectApp.register = {
+ controller : $controllerProvider.register,
+ directive : $compileProvider.directive,
+ factory : $provide.factory,
+ service : $provide.service
+ };
+
+ NavHelperProvider.addControllerUrl('app/mwtnConnect/mwtnConnect.controller');
+ NavHelperProvider.addToMenu('mwtnConnect', {
+ "link" : "#/connect",
+ "active" : "main.mwtnConnect",
+ "title" : "Connect",
+ "icon" : "fa fa-plug", // Add navigation icon css class here
+ "page" : {
+ "title" : "Connect",
+ "description" : "Connection supervision of physical network function to ONAP SDN-C-4-Wireless"
+ }
+ });
+
+ var access = routingConfig.accessLevels;
+
+ $stateProvider.state('main.mwtnConnect', {
+ url: 'connect',
+ access: access.admin,
+ views : {
+ 'content' : {
+ templateUrl: 'src/app/mwtnConnect/mwtnConnect.tpl.html',
+ controller: 'mwtnConnectCtrl'
+ }
+ }
+ });
+
+ });
+
+ return mwtnConnectApp;
+});
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.services.js
new file mode 100644
index 00000000..8f8b55c7
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.services.js
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016 highstreet technologies GmbH and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+define(['app/mwtnConnect/mwtnConnect.module','app/mwtnCommons/mwtnCommons.services'],function(mwtnConnectApp) {
+
+
+ mwtnConnectApp.register.factory('$mwtnConnect', function($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) {
+
+ var COMPONENT = '$mwtnConnect';
+ $mwtnLog.info({component: COMPONENT, message: '$mwtnConnect started!'});
+
+ var service = {};
+
+ service.addRequiredNetworkElement = $mwtnCommons.addRequiredNetworkElement;
+ service.createSingleDocument = $mwtnDatabase.createSingleDocument;
+ service.deleteSingleDocument = $mwtnDatabase.deleteSingleDocument;
+ service.formatData = $mwtnCommons.formatData;
+ service.formatTimeStamp = $mwtnCommons.formatTimeStamp;
+ service.getAllData = $mwtnDatabase.getAllData;
+ service.getFilteredSortedData = $mwtnDatabase.getFilteredSortedData;
+ service.getMountPoint = $mwtnCommons.getMountPoint;
+ service.getMountPoints = $mwtnCommons.getMountPoints;
+ service.getActualNetworkElement = $mwtnCommons.getActualNetworkElement;
+ service.getRequiredNetworkElements = $mwtnCommons.getRequiredNetworkElements;
+ service.getMwtnWebSocketUrl = $mwtnCommons.getMwtnWebSocketUrl;
+ service.getSingleDocument = $mwtnDatabase.getSingleDocument;
+ service.gridOptions = $mwtnCommons.gridOptions;
+ service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader;
+
+ service.registerForOdlEvents = $mwtnCommons.registerForOdlEvents;
+ service.separator = $mwtnCommons.separator;
+
+ service.mount = $mwtnCommons.mount;
+ service.unmount = $mwtnCommons.unmount;
+ service.yangifyObject = $mwtnCommons.yangifyObject;
+
+
+ service.getData = function(from, size, sort, query){
+ if (!sort) { //default sort value
+ sort = [ { 'event.timeStamp' : {order : 'desc'}}];
+ }
+ if (!query) { //default filter value
+ query= {prefix: {'event.nodeName': 'SDN-Controller'}};
+ }
+ return getFilteredSortedData(from, size, sort, query);
+ };
+
+ var getFilteredSortedData = function(from, size, sort, query){
+ var deferred = $q.defer();
+ $mwtnDatabase.getFilteredSortedData('sdnevents', 'eventlog', from, size, sort, query).then(function(success){
+ deferred.resolve(success);
+ }, function(error){
+ $mwtnLog.error({component: 'private getFilteredSortedData', message: JSON.stringify(error.data)});
+ deferred.reject(error);
+ });
+ return deferred.promise;
+ };
+
+ service.TimeStampToONFFormat = function(timestamp) {
+ timestamp=timestamp.split('-').join('');
+ timestamp=timestamp.split(':').join('');
+ timestamp=timestamp.split(' ').join('');
+ timestamp=timestamp.replace('UTC','Z');
+ return timestamp;
+ };
+
+ return service;
+ });
+
+});
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.tpl.html
new file mode 100644
index 00000000..73fc0fcf
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/mwtnConnect.tpl.html
@@ -0,0 +1,150 @@
+<ht-header help-link='sdnr/connect/0.4.0/README.md'></ht-header>
+
+<uib-accordion close-others="oneAtATime">
+
+<div uib-accordion-group class="panel-primary"
+ is-open="status.requiredNes">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status.requiredNes, 'fa-chevron-right': !status.requiredNes}"></i>
+ <span>{{'MWTN_REQUIRED_NETWORK_ELEMENTS' | translate}}</span>
+ </uib-accordion-heading>
+ <div id="requiredNesGrid" ui-grid="requiredNesGridOptions"
+ ui-grid-exporter ui-grid-selection ui-grid-pinning
+ ui-grid-resize-columns ui-grid-move-columns class="requiredNesGrid">
+ </div>
+</div>
+
+<div uib-accordion-group class="panel-default"
+ is-open="status.unkownNes">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status.unkownNes, 'fa-chevron-right': !status.unkownNes}"></i>
+ <span>{{'MWTN_UNKNOWN_NETWORK_ELEMENTS' | translate}}</span>
+ </uib-accordion-heading>
+ <div id="unknownNesGrid" ui-grid="unknownNesGridOptions"
+ ui-grid-exporter ui-grid-selection ui-grid-pinning
+ ui-grid-resize-columns ui-grid-move-columns class="unknownNesGrid">
+ </div>
+</div>
+
+<div uib-accordion-group class="panel-default"
+ is-open="status.mount">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status.mount, 'fa-chevron-right': !status.mount}"></i>
+ <span>{{'Mount NETCONF Servers (devices, nodes, mediators, controllers, ...)' | translate}}</span>
+ </uib-accordion-heading>
+ <div class="container">
+ <div class="row" ng-repeat="(key, value) in newMountingPoint">
+ <div class="col-md-2 text-right">
+ <span>{{['mwtn', key].join('_').toUpperCase() | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <input type="text" class="form-control"
+ ng-model="newMountingPoint[key]"></input>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-6 text-right">
+ <br />
+ <button type="button" class="btn btn-primary" ng-click="mount()">
+ <i class="fa fa-spinner" ng-class="{'fa-pulse':processing}" ng-show="processing" aria-hidden="true"></i>
+ <span>{{'MWTN_MOUNT' | translate}}</span>
+ </button>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-6">
+ <br />
+ <span class="mwtnSuccess" style="color: darkgreen;">{{mountSuccess}}</span>
+ <span class="mwtnError" style="color: red;">{{mountError}}</span>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div uib-accordion-group class="panel-default"
+ is-open="status.connectionStatusLog">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status.connectionStatusLog, 'fa-chevron-right': !status.connectionStatusLog}"></i>
+ <span>{{'MWTN_CONNECTION_STATUS_LOG' | translate}}</span>
+ <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.connectionStatusLog"></i>
+ </uib-accordion-heading>
+
+ <div id="mwtnConnectGridConnectionStatusLog"
+ ui-grid="gridOptionsConnectionStatusLog"
+ ui-grid-pagination
+ ui-grid-exporter
+ ui-grid-selection
+ ui-grid-pinning
+ ui-grid-resize-columns
+ ui-grid-move-columns class="mwtnConnectGrid">
+ </div>
+
+ <div class="ht-pagination">
+ <button class="btn btn-default"
+ ng-disabled="paginationOptions.pageNumber === 1"
+ ng-click="gridApi.pagination.seek(1)"
+ ng-class="{'cancelCursor':paginationOptions.pageNumber === 1}"
+ role="menuitem" type="button" title="Page to first" aria-label="Page to first">
+ <i class="fa fa-step-backward "></i>
+ </button>
+ <button class="btn btn-default"
+ ng-disabled="paginationOptions.pageNumber === 1"
+ ng-class="{'cancelCursor':paginationOptions.pageNumber === 1}"
+ ng-click="gridApi.pagination.previousPage()"
+
+ role="menuitem" type="button" title="Previous Page" aria-label="Previous Page">
+ <i class="fa fa-play fa-rotate-180 "></i>
+ </button>
+ <input class="btn btn-default" style="text-align:right;" border="1"
+ ng-model="paginationOptions.pageNumber"
+ ng-change="seekPage(paginationOptions.pageNumber)"
+ type="text" style="width:20px;"/>
+ <span class="dark">&nbsp;/ {{ gridApi.pagination.getTotalPages() }}</span>
+
+ <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page"
+ ng-disabled="gridApi.pagination.pageNumber === gridApi.pagination.getTotalPages()"
+ ng-click="gridApi.pagination.nextPage()">
+ <i class="fa fa-play "></i>
+ </button>
+ <button class="btn btn-default" ng-disabled="gridApi.pagination.pageNumber === gridApi.pagination.getTotalPages()"
+ ng-click="gridApi.pagination.seek(gridApi.pagination.getTotalPages())"
+ role="menuitem" type="button" title="Page to last" aria-label="Page to last">
+ <i class="fa fa-step-forward "></i>
+ </button>
+
+ <select
+ class="btn btn-default" name="repeatSelect" id="repeatSelect"
+ ng-init="gridOptionsConnectionStatusLog.paginationPageSize = gridOptionsConnectionStatusLog.paginationPageSizes[0]"
+ ng-model="gridOptionsConnectionStatusLog.paginationPageSize"
+ ng-options="option for option in gridOptionsConnectionStatusLog.paginationPageSizes"></select>
+
+ <span class="dark"> items per page </span>
+
+ <span class="pull-right dark">{{ paginationStatusMessage() }}</span>
+
+ </div>
+
+ <div class="text-right">
+ <!--
+ <button type="button" id="clearLog" class="btn btn-warning" ng-click="clearLog()">
+ <i class="fa fa-times" aria-hidden="true"></i>
+ <span>Clear log...</span>
+ </button>
+ see gird menu Export ...
+ <button type="button" id="saveLog" class="btn btn-default" ng-click="saveLog()">
+ <i class="fa fa-save" aria-hidden="true"></i>
+ <span>Save...</span>
+ </button> -->
+ <button type="button" id="refreshLog" class="btn btn-primary" ng-click="refreshLog()">
+ <span>{{'MWTN_REFRESH' | translate}}</span>
+ </button>
+ </div>
+
+</div>
+
+</uib-accordion>
+
+<hr />
+<div class="owl">
+ <span class="white">ONAP SDN-R | ONF Wireless for @distversion@ - Build: @buildtime@</span>
+</div> \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/addToRequired.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/addToRequired.tpl.html
new file mode 100644
index 00000000..d2a0903a
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/addToRequired.tpl.html
@@ -0,0 +1,79 @@
+
+<div class="modal-header">
+ <h3 class="modal-title" id="modal-title">{{'Add to required NetworkElements' | translate}}</h3>
+</div>
+<div class="modal-body" id="modal-body">
+
+ <div class="container" style="max-width: 600px;">
+
+ <div class="row">
+ <div class="col-md-12">
+ <span>Create a new NetworkElement in planning database as clone of existing real NetworkElement.</span>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-4 text-right">
+ <span>{{'MWTN_NAME' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <input class="form-control" type="text" ng-model="netconfServer['node-id']"></input>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-4 text-right">
+ <span>{{'MWTN_IPADDRESS' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <input class="form-control" type="text" ng-model="netconfServer['netconf-node-topology:host']"></input>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-4 text-right">
+ <span>{{'MWTN_NETCONF_PORT' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <input class="form-control" type="text" ng-model="netconfServer['netconf-node-topology:port']"></input>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-4 text-right">
+ <span>{{'MWTN_USERNAME' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <input class="form-control" type="text" ng-model="netconfServer.username"></input>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-4 text-right">
+ <span>{{'MWTN_PASSWORD' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <input class="form-control" type="password" ng-model="netconfServer.password"></input>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-4 text-right">
+ <span>{{'MWTN_SITE' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <div class="form-group">
+ <input list="sites" class="form-control" ng-model="netconfServer.site">
+ <datalist id="sites">
+ <option ng-repeat="site in sites" value="{{site.id}}" >{{site.name}}</option>
+ </datalist>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</div>
+<div class="modal-footer">
+ <button class="btn btn-primary" type="button" ng-click="ok()">{{'MWTN_ADD_TO_REQUIRED_NETWORKELEMENTS' | translate}}</button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">{{'MWTN_CANCEL' | translate}}</button>
+</div> \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmDelete.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmDelete.tpl.html
new file mode 100644
index 00000000..03a7de72
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmDelete.tpl.html
@@ -0,0 +1,23 @@
+<div class="modal-header">
+ <h3 class="modal-title" id="modal-title">{{'MWTN_DELETE' | translate}}</h3>
+</div>
+<div class="modal-body" id="modal-body">
+ <div class="container" style="max-width: 600px;">
+ <div class="row">
+ <div class="col-md-12">
+ <span>Delete {{node.id}} from the planning database.</span>
+ <br/>
+ <span>All the planning data for this network element will be lost.</span>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="modal-footer">
+ <button class="btn btn-danger" type="button" ng-click="ok()">
+ <i class="fa fa-trash" aria-hidden="true"></i>
+ <span>{{'MWTN_DELETE' | translate}}</span>
+ </button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">
+ <span>{{'MWTN_CANCEL' | translate}}</span>
+ </button>
+</div> \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmHide.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmHide.tpl.html
new file mode 100644
index 00000000..c52ee3f4
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/confirmHide.tpl.html
@@ -0,0 +1,21 @@
+<div class="modal-header">
+ <h3 class="modal-title" id="modal-title">{{'MWTN_HIDE' | translate}}</h3>
+</div>
+<div class="modal-body" id="modal-body">
+ <div class="container" style="max-width: 600px;">
+ <div class="row">
+ <div class="col-md-12">
+ <span>Remove {{node.id}} from the list of required network elements.</span>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="modal-footer">
+ <button class="btn btn-primary" type="button" ng-click="ok()">
+ <i class="fa fa-times" aria-hidden="true"></i>
+ <span>{{'MWTN_HIDE' | translate}}</span>
+ </button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">
+ <span>{{'MWTN_CANCEL' | translate}}</span>
+ </button>
+</div> \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/mountPointDetails.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/mountPointDetails.tpl.html
new file mode 100644
index 00000000..56563b4f
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/src/main/resources/mwtnConnect/templates/mountPointDetails.tpl.html
@@ -0,0 +1,125 @@
+<div class="modal-header">
+ <h3 class="modal-title" id="modal-title">{{ data.ne.name }}{{ data.ne['node-id'] }}</h3>
+</div>
+<div class="modal-body" id="modal-body" ng-hide="data.ne.required">
+ <div class="row">
+ <div class="col-md-2 text-right">
+ <span>{{'MWTN_NETWORKELEMENT' | translate}}</span>
+ </div>
+ <div class="col-md-10">
+ <b>{{data.ne['node-id']}}</b>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2 text-right">
+ <span>{{'MWTN_IPADDRESS' | translate}}</span>
+ </div>
+ <div class="col-md-10">
+ <b>{{data.ne['netconf-node-topology:host']}}</b>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2 text-right">
+ <span>{{'MWTN_PORT' | translate}}</span>
+ </div>
+ <div class="col-md-10">
+ <b>{{data.ne['netconf-node-topology:port']}}</b>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2 text-right">
+ <span>{{'MWTN_USERNAME' | translate}}</span>
+ </div>
+ <div class="col-md-10">
+ <b>{{data.mountpoint['netconf-node-topology:username']}}</b>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2 text-right">
+ <span>{{'MWTN_PASSWORD' | translate}}</span>
+ </div>
+ <div class="col-md-10">
+ <b>{{data.mountpoint['netconf-node-topology:password']}}</b>
+ </div>
+ </div>
+</div>
+<div class="modal-body" id="modal-body" ng-show="data.ne.required">
+ <!-- web -->
+ <div ng-show="data.web.supported">
+ <p>
+ <span>The network element supports a native web user interface.</span>
+ <br/>
+ <span> Please use following link:</span>
+ <div class="input-append">
+ <input class="mwtn-form-control" type="text" value="{{ data.web.getLink() }}" readonly></input>
+ <a class="btn btn-default" href="{{ data.web.getLink() }}" target="_blank">
+ <i class="fa fa-external-link" aria-hidden="true"></i>
+ </a>
+ </div>
+ <p>
+ </div>
+ <div ng-show="!data.web.supported">
+ <p>The network element does not support a native web user interface.</p>
+ </div>
+ <!-- terminal -->
+ <hr/>
+ <div ng-show="data.terminal.supported">
+ <p>
+ <span>The network element supports a native terminal or console application.</span>
+ <br/>
+ <span>Please the copy button and paste the command into a terminal window:</span>
+ <p>
+ <div class="input-append">
+ <input class="mwtn-form-control" type="text" value="{{ data.terminal.getCommand() }}" readonly></input>
+ <button class="btn btn-default" type="button" clipboard supported="supported" text="data.terminal.getCommand()" on-copied="data.terminal.copyToClipboard()" on-error="error(err)">
+ <i class="fa fa-clipboard" aria-hidden="true"></i>
+ </button>
+ <span ng-show="data.terminal.copied === true" class="green">Check your clipboard.</span>
+ </div>
+ </div>
+ <div ng-show="!data.web.supported">
+ <p>The network element does not support a native terminal or console application.</p>
+ </div>
+
+ <!-- application -->
+ <hr/>
+ <div ng-show="data.application.supported">
+ <p>
+ <span>The network element can be managed via a pre-installed application.</span>
+ <br/>
+ <span>Please the copy button and paste the command into a terminal window:</span>
+ <p>
+ <div class="input-append">
+ <input class="mwtn-form-control" type="text" value="{{ data.application.getCommand() }}" readonly></input>
+ <button class="btn btn-default" type="button" clipboard supported="supported" text="data.application.getCommand()" on-copied="data.application.copyToClipboard()" on-error="error(err)">
+ <i class="fa fa-clipboard" aria-hidden="true"></i>
+ </button>
+ <span ng-show="data.application.copied === true" class="green">Check your clipboard.</span>
+ </div>
+ </div>
+
+</div>
+<div class="modal-body" id="modal-body">
+ <!-- yang capabilites -->
+ <hr/>
+ <h3>{{ 'MWTN_YANG_CAPABILITIES' | translate }}</h3>
+ <div id="yangCapabilitiesGrid"
+ ui-grid="yangCapabilitiesGridOptions"
+ ui-grid-exporter ui-grid-selection ui-grid-pinning
+ ui-grid-resize-columns
+ ui-grid-move-columns class="yangCapabilitiesGrid">
+ </div>
+</div>
+<div class="modal-footer">
+ <button class="btn btn-danger" type="button" ng-show="data.ne.required" ng-click="delete(data.ne)">
+ <i class="fa fa-trash" aria-hidden="true"></i>
+ <span>{{'MWTN_DELETE' | translate}}...</span>
+ </button>
+ <button class="btn btn-warning" type="button" ng-show="data.ne.required" ng-click="hide(data.ne)">
+ <i class="fa fa-times" aria-hidden="true"></i>
+ <span>{{'MWTN_HIDE' | translate}}...</span>
+ </button>
+ <button class="btn btn-primary" type="button" ng-click="ok()">
+ <span>{{'MWTN_CLOSE' | translate}}</span>
+ </button>
+</div>