summaryrefslogtreecommitdiffstats
path: root/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module
diff options
context:
space:
mode:
authordemx8as6 <martin.skorupski@highstreet-technologies.com>2018-07-10 18:07:44 +0200
committerTimoney, Dan (dt5972) <dt5972@att.com>2018-07-11 16:30:28 -0400
commit27fb2d06608fbb070ae2c15a5580a4f5b2423d15 (patch)
treeccd717991b4e556b67f1fd2cacb345b4d174b41f /sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module
parent60315525ab5e7c12a9f47c409092e8dba6ad656d (diff)
Add seed code for sdnr app based on ONF Centennial
At this point in time all the Carbon code from ONF Centennial is added to ONAP. Later it needs to be refactored and modified for ODL Oxygen. Change-Id: Iff85dd940c05c3827f1c4e6f9542ecd060c58a46 Issue-ID: SDNC-374 Signed-off-by: demx8as6 <martin.skorupski@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module')
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/pom.xml15
-rwxr-xr-xsdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/images/mwtnCompare.pngbin0 -> 3342 bytes
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare-custom.css36
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.controller.js526
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.directives.js21
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.module.js50
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.services.js26
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.tpl.html333
-rw-r--r--sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/templates/compare.tpl.html12
9 files changed, 1019 insertions, 0 deletions
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/pom.xml
new file mode 100644
index 00000000..c0de516d
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/pom.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>mwtnCompare</artifactId>
+ <groupId>com.highstreet.technologies.odl.dlux</groupId>
+ <version>0.5.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>mwtnCompare-module</artifactId>
+ <name>${prefix} ${project.artifactId}</name>
+ <packaging>jar</packaging>
+
+ </project> \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/images/mwtnCompare.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/images/mwtnCompare.png
new file mode 100755
index 00000000..f4f9c096
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/images/mwtnCompare.png
Binary files differ
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare-custom.css
new file mode 100644
index 00000000..1cab6029
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare-custom.css
@@ -0,0 +1,36 @@
+/**
+ * Add your application related css here
+ * Build: @buildtime@
+ */
+
+#mwtnCompare .footable > thead > tr > th {
+ background-color: #428bca;
+ color: #ffffff;
+ background-image: none;
+ border: none;
+ box-shadow: none;
+}
+
+.connected {
+ color: lightgreen;
+}
+
+.connected span {
+ color: lightgreen;
+}
+
+.match {
+ color: lightgreen;
+}
+
+.match span {
+ color: lightgreen;
+}
+
+.nowrap {
+ white-space: nowrap;
+}
+
+.red {
+ color: red;
+} \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.controller.js
new file mode 100644
index 00000000..e83885a6
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.controller.js
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2017 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/mwtnCompare/mwtnCompare.module',
+ 'app/mwtnCompare/mwtnCompare.services',
+ 'app/mwtnCommons/mwtnCommons.services',
+ 'app/mwtnCompare/mwtnCompare.directives',
+ 'app/mwtnCommons/bower_components/angular-ui-grid/ui-grid.min'], function(mwtnCompareApp) {
+
+ mwtnCompareApp.register.controller('mwtnCompareCtrl', ['$scope', '$rootScope', '$mwtnCompare', '$mwtnLog', 'orderByFilter', 'OnfNetworkElement', 'MicrowavePhysicalSection', 'MicrowaveSection',
+ function($scope, $rootScope, $mwtnCompare, $mwtnLog, orderBy, OnfNetworkElement, MicrowavePhysicalSection, MicrowaveSection) {
+
+ $rootScope.section_logo = 'src/app/mwtnCompare/images/mwtnCompare.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif'
+
+ var rOnfNe;
+ var aOnfNe;
+
+ $scope.status = {ne:false};
+ $scope.spinner = {ne:false};
+ $scope.separator = $mwtnCompare.separator; //'&nbsp;'
+ $scope.connectionStatus = 'disconnected';
+ $scope.oneATime = true;
+ $scope.match = {
+ numberOfLTPs: false,
+ numberOfLTPsStatus: 'unknown',
+ radioSignalIds: false,
+ radioSignalIdsStatus: 'unknown',
+ mapping: {},
+ addActualRadioSignalId: function(rsId) {
+ if (!this.actualRadioSignalIds) {
+ this.actualRadioSignalIds = [];
+ }
+ if (this.actualRadioSignalIds.contains(rsId)) {
+ return;
+ }
+ this.actualRadioSignalIds.push(rsId);
+ this.actualRadioSignalIds.sort();
+ this.checkRadioSignalIdsStatus();
+ },
+ clearActualNumberOfLtps: function() {
+ this.actualNumberOfLtps = undefined;
+ this.numberOfLTPs = false;
+ this.numberOfLTPsStatus = this.requiredNumberOfLtps;
+ },
+ clearActualRadioSignalIds: function() {
+ this.actualRadioSignalIds = undefined;
+ this.radioSignalIds = false;
+ this.radioSignalIdsStatus = this.requiredRadioSignalIds;
+ },
+ setRequiredNumberOfLtps: function(rNoLtps) {
+ this.requiredNumberOfLtps = rNoLtps;
+ this.checkNumberOfLTPs();
+ },
+ setRequiredRadioSignalIds: function(rRsIds) {
+ this.requiredRadioSignalIds = rRsIds.sort();
+ this.checkRadioSignalIdsStatus();
+ },
+ setActualNumberOfLtps: function(aNoLtps) {
+ this.actualNumberOfLtps = aNoLtps;
+ this.checkNumberOfLTPs();
+ },
+ setActualRadioSignalIds: function(aRsIds) {
+ this.actualRadioSignalIds = aRsIds.sort();
+ this.checkRadioSignalIdsStatus();
+ },
+ checkNumberOfLTPs: function() {
+ if (!this.requiredNumberOfLtps) {
+ this.numberOfLTPs = false;
+ this.numberOfLTPsStatus = 'unknown';
+ } else {
+ if (!this.actualNumberOfLtps) {
+ this.numberOfLTPs = false;
+ this.numberOfLTPsStatus = this.requiredNumberOfLtps;
+ } else {
+ if (this.requiredNumberOfLtps === this.actualNumberOfLtps) {
+ this.numberOfLTPs = true;
+ this.numberOfLTPsStatus = this.requiredNumberOfLtps;
+ } else {
+ this.numberOfLTPs = false;
+ this.numberOfLTPsStatus = ['required:', this.requiredNumberOfLtps, 'does not match actual:',this.actualNumberOfLtps].join(' ');
+ }
+ }
+ }
+ },
+ checkRadioSignalIdsStatus: function() {
+ if (!this.requiredRadioSignalIds) {
+ this.radioSignalIds = false;
+ this.radioSignalIdsStatus = 'unknown';
+ } else {
+ if (!this.actualRadioSignalIds) {
+ this.radioSignalIds = false;
+ this.radioSignalIdsStatus = this.requiredRadioSignalIds;
+ } else {
+ if (JSON.stringify(this.requiredRadioSignalIds) === JSON.stringify(this.actualRadioSignalIds)) {
+ this.radioSignalIds = true;
+ this.radioSignalIdsStatus = this.requiredRadioSignalIds;
+ } else {
+ this.radioSignalIds = false;
+ this.radioSignalIdsStatus = ['required:', this.requiredRadioSignalIds, 'does not match actual:',this.actualRadioSignalIds].join(' ');
+ }
+ }
+ }
+ }
+
+ };
+
+ $scope.schema = {initShowObjectCtrl:false};
+ $mwtnCompare.getSchema().then(function(data){
+ $scope.schema = data;
+ });
+
+ var initNodeList = function(nodes){
+ $scope.neSelection = [];
+ if (nodes.length > 0) {
+ nodes.map(function(ne) {
+ if (ne._source.onfAirInterfaceRevision) {
+ $scope.neSelection.push({id:ne._id, revision:ne._source.onfAirInterfaceRevision});
+
+ }
+ });
+ $scope.neSelection.sort(function(a, b){
+ if(a.id < b.id) return -1;
+ if(a.id > b.id) return 1;
+ return 0;
+ });
+ }
+ };
+ $scope.requiredNetworkElements = [];
+ $mwtnCompare.getRequiredNetworkElements(true).then(function(nodes){
+ $scope.requiredNetworkElements = nodes;
+ initNodeList(nodes);
+ }, function(error){
+ $scope.neSelection = [];
+ $scope.requiredNetworkElements = [];
+ });
+
+ $scope.collapseAll = function() {
+ // close all groups
+ Object.keys($scope.status).map(function(group){
+ $scope.status[group] = false;
+ });
+ Object.keys($scope.spinner).map(function(group){
+ $scope.spinner[group] = false;
+ });
+ };
+
+
+ // events
+ $scope.$watch('selection', function(neId, oldValue) {
+ if (neId && neId !== '' && neId !== oldValue) {
+ $scope.collapseAll();
+ $scope.connectionStatus = 'disconnected';
+ $scope.match.clearActualNumberOfLtps();
+ $scope.match.clearActualRadioSignalIds();
+ $mwtnCompare.getConnectionStatus(neId).then(function(connectionStatus){
+ $scope.connectionStatus = connectionStatus;
+ // get actual data
+ if ($scope.connectionStatus === 'connected') {
+ var key = 'ne';
+ var spec = {
+ nodeId: $scope.selection,
+ revision: $scope.requiredNetworkElement.onfAirInterfaceRevision,
+ pacId: key,
+ };
+ $mwtnCompare.getPacParts(spec).then(function(success){
+ updatePart(spec, success);
+ $scope.spinner[key] = false;
+ }, function(error){
+ updatePart(spec, error);
+ $scope.spinner[key] = false;
+ });
+ }
+
+ },function(error){
+ $scope.connectionStatus = 'disconnected';
+ });
+
+ $scope.requiredNetworkElements.map(function(rne){
+ console.warn(JSON.stringify(rne._id, neId, rne._id === neId));
+ if (rne._id === neId) {
+ $scope.requiredNetworkElement = rne._source;
+ rOnfNe = new OnfNetworkElement(rne._source['core-model:network-element']);
+ $scope.match.setRequiredNumberOfLtps(rOnfNe.getNumberOfLtps());
+ // required NE
+ var rMwpsList = rOnfNe.getLTPMwpsList().map(function(mwpsLtp){
+ var key = 'microwave-model:mw-air-interface-pac';
+ if ($scope.requiredNetworkElement.onfAirInterfaceRevision.contains('2016')) {
+ key = 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac';
+ }
+ var rMwpsList = $scope.requiredNetworkElement[key].map(function(mwps){
+ if (mwps.layerProtocol === mwpsLtp.getLayerProtocols()[0].getId()) {
+ return new MicrowavePhysicalSection(mwps);
+ }
+ });
+
+ if (rMwpsList) {
+ return rMwpsList.clean(undefined)[0];
+ } else {
+ return {};
+ }
+ });
+
+ var rRadioSignalIds = rMwpsList.map(function(rMwps){
+ return rMwps.getRadioSignalId();
+ });
+ $scope.match.setRequiredRadioSignalIds(rRadioSignalIds);
+ }
+ });
+ }
+ });
+
+ var getArrayValueToHtml = function(array) {
+ if (array === undefined) {
+ return '';
+ }
+ if (array.length > 0 && ($mwtnCompare.getType(array[0]) === 'object' || $mwtnCompare.getType(array[0]) === 'array') ) {
+ var converted = array.map(function(item){
+ if ($mwtnCompare.getType(item) === 'object' && Object.keys(item).length === 2 ) {
+ return [item[Object.keys(item)[0]], item[Object.keys(item)[1]]].join(':');
+ } else {
+ return JSON.stringify(item);
+ }
+ });
+ return converted.join('<br/>');
+ } else {
+ return array.join('<br/>');
+ }
+ };
+
+ var getCompares = function(obj, actualData) {
+ var compares = [];
+
+ for (var labelId in obj) {
+ var missingActualValueLabelId = 'not connected';
+ var match = false;
+
+ switch (labelId) {
+ case 'compares':
+ break;
+ case 'open':
+ break;
+// case 'nameList':
+// var requiredName = obj[labelId][0].value;
+// var actualName = '';
+// if (actualData) {
+// actualName = actualData[labelId][0].value;
+// }
+// match = ((requiredName === '' || actualName === '') || (requiredName === actualName));
+// // console.log('NAME', requiredName, actualName, match);
+// compares.push({
+// labelId : 'NE name',
+// requiredValue : requiredName,
+// actualValue : actualName,
+// match : match,
+// missingActualValueLabelId : missingActualValueLabelId,
+//// unit : $scope.schema[labelId].unit,
+//// description : $scope.schema[labelId].description,
+// showDescriptions : false
+// });
+// break;
+ case '_ltpRefList':
+ var requiredLtpLength = obj[labelId].length;
+ var actualLtpLength = '';
+ if (actualData) {
+ actualLtpLength = actualData[labelId].length;
+ }
+ match = ((requiredLtpLength === '' || actualLtpLength === '') || (requiredLtpLength === actualLtpLength));
+ compares.push({
+ labelId : 'numberOfLTPs',
+ requiredValue : requiredLtpLength,
+ actualValue : actualLtpLength,
+ match : match,
+ missingActualValueLabelId : missingActualValueLabelId,
+ unit : $scope.schema[labelId].unit,
+ order: $scope.schema[labelId]['order-number'],
+ description : $scope.schema[labelId].description,
+ showDescriptions : false
+ });
+ break;
+ default:
+ if (labelId === 'installedCapacity') {
+ missingActualValueLabelId = '<pure planning value>';
+ }
+ if (labelId === 'timeSlotIDList') {
+ var requiredTimeSlotIDListLength = obj[labelId].length;
+ var actualTimeSlotIDListLength = '';
+ if (actualData) {
+ actualTimeSlotIDListLength = actualData[labelId].length;
+ }
+ compares.push({
+ labelId : 'currentNumberOfTimeSlots',
+ requiredValue : requiredTimeSlotIDListLength,
+ actualValue : actualTimeSlotIDListLength,
+ match : true,
+ missingActualValueLabelId : missingActualValueLabelId,
+ unit : $scope.schema[labelId].unit,
+ order: $scope.schema[labelId]['order-number'],
+ description : $scope.schema[labelId].description,
+ showDescriptions : false
+ });
+ }
+
+ switch($mwtnCompare.getType(obj[labelId])) {
+ case 'object':
+ if (actualData) {
+ var withActual = getCompares(obj[labelId], actualData[labelId]);
+ compares = compares.concat(withActual);
+ } else {
+ var withoutActual = getCompares(obj[labelId]);
+ compares = compares.concat(withoutActual);
+ }
+ break;
+ case 'array':
+ var requiredDataValue = getArrayValueToHtml(obj[labelId]);
+ var actualDataValue = '';
+ if (actualData) {
+ actualDataValue = getArrayValueToHtml(actualData[labelId]);
+ }
+ match = ((requiredDataValue === '' || actualDataValue === '') || (requiredDataValue === actualDataValue));
+ compares.push({
+ labelId : labelId,
+ requiredValue : requiredDataValue,
+ actualValue : actualDataValue,
+ match : match,
+ missingActualValueLabelId : missingActualValueLabelId,
+ unit : $scope.schema[labelId].unit,
+ order: $scope.schema[labelId]['order-number'],
+ description : $scope.schema[labelId].description,
+ showDescriptions : false
+ });
+ break;
+ default:
+ var requiredValue = obj[labelId];
+ var actualValue = actualData ? actualData[labelId] : '';
+// // console.log('match');
+// // console.log('match1', requiredValue, (requiredValue === ''));
+// // console.log('match2', actualValue, (actualValue === ''));
+// // console.log('match3', requiredValue, actualValue, (requiredValue === actualValue));
+// // console.log('match4', (requiredValue === '' || actualValue === '') || (requiredValue === actualValue));
+ match = (requiredValue === '' || actualValue === '') || (requiredValue === actualValue);
+ compares.push({
+ labelId : labelId,
+ requiredValue : requiredValue,
+ actualValue : actualValue,
+ match : match,
+ missingActualValueLabelId : missingActualValueLabelId,
+ unit : $scope.schema[labelId].unit,
+ order: $scope.schema[labelId]['order-number'],
+ description : $scope.schema[labelId].description,
+ showDescriptions : false
+ });
+ }
+ }
+ }
+ return orderBy(compares, 'order', false);
+ };
+
+ var updateNe = function(data) {
+
+ var rne = $scope.requiredNetworkElement;
+ if (!data) {
+ rne['core-model:network-element'].compares = getCompares(rne['core-model:network-element']);
+ return;
+ }
+ rne['core-model:network-element'].compares = getCompares(rne['core-model:network-element'], data['core-model:network-element']);
+ console.error(JSON.stringify(data));
+ aOnfNe = new OnfNetworkElement(data['core-model:network-element']);
+ $scope.match.setActualNumberOfLtps(aOnfNe.getNumberOfLtps());
+ var aMwpsList = aOnfNe.getLTPMwpsList().map(function(mwpsLtp){
+
+ var spec = {
+ nodeId: $scope.selection,
+ revision: $scope.requiredNetworkElement.onfAirInterfaceRevision,
+ pacId: 'microwave-model:mw-air-interface-pac',
+ layerProtocolId: mwpsLtp.getLayerProtocols()[0].getId(),
+ partId: 'configuration'
+ };
+
+ $mwtnCompare.getPacParts(spec).then(function(success){
+ updatePart(spec, success);
+ }, function(error){
+ updatePart(spec, error);
+ });
+ return mwpsLtp._lpList[0].uuid;
+ });
+ // console.log(aMwpsList)
+ var mwClient = rne['microwave-model:mw-ethernet-container-pac'][0];
+ $scope.match.mapping[mwClient.layerProtocol] = aOnfNe.getLTPEthCtpList()[0].getLayerProtocols()[0].getId();
+ };
+
+ var addShowDescriptionEvent = function(obj) {
+ $scope.$watch(function() {
+ return obj.showDescriptions;
+ }, function(newValue, oldValue) {
+ if (newValue !== oldValue) {
+ obj.compares.map(function(compare){
+ compare.showDescriptions = newValue;
+ });
+ }
+ });
+ };
+
+ var updateAirInterface = function(spec, data) {
+ if (!data) {
+ $scope.requiredNetworkElement['microwave-model:mw-air-interface-pac'].map(function(mwps){
+ mwps.compares = getCompares(mwps.airInterfaceConfiguration);
+ addShowDescriptionEvent(mwps);
+ });
+ } else {
+ var actual = new MicrowavePhysicalSection(data);
+ $scope.match.addActualRadioSignalId(actual.getRadioSignalId());
+ // console.log(actual.getRadioSignalId());
+ $scope.requiredNetworkElement['microwave-model:mw-air-interface-pac'].map(function(mwps){
+ var required = new MicrowavePhysicalSection(mwps);
+ if (actual.getRadioSignalId() === required.getRadioSignalId()) {
+ $scope.match.mapping[required.getLayerProtocolId()] = actual.getLayerProtocolId();
+ var actualData = data.airInterfaceConfiguration;
+ mwps.compares = getCompares(mwps.airInterfaceConfiguration, actualData);
+ addShowDescriptionEvent(mwps);
+
+ // MWS mapping
+ var rMws = rOnfNe.getClientLtpIds(required.getLayerProtocolId());
+ var aMws = aOnfNe.getClientLtpIds(actual.getLayerProtocolId());
+ // In PoC just a 1:1 relation between MWPS and MWS
+ $scope.match.mapping[rOnfNe.getLpByLtpRef(rMws[0]).uuid] = aOnfNe.getLpByLtpRef(aMws[0]).uuid;
+ }
+ });
+ }
+ };
+
+ var updateStructure = function(spec, data) {
+ if (!data) {
+ $scope.requiredNetworkElement.MW_PureEthernetStructure_Pac.map(function(mws){
+ mws.compares = getCompares(mws.pureEthernetStructureConfiguration);
+ addShowDescriptionEvent(mws);
+ });
+ } else {
+ $scope.requiredNetworkElement.MW_PureEthernetStructure_Pac.map(function(mws){
+ if ($scope.match.mapping[mws.layerProtocol] === data.layerProtocol) {
+ var actualData = data.pureEthernetStructureConfiguration;
+ mws.compares = getCompares(mws.pureEthernetStructureConfiguration, actualData);
+ addShowDescriptionEvent(mws);
+ }
+ });
+ }
+ };
+
+ var updateContainer = function(spec, data) {
+ // there is only one container in PoCs
+ var mwClient = $scope.requiredNetworkElement.MW_EthernetContainer_Pac[0];
+ if (!data) {
+ mwClient.compares = getCompares(mwClient.ethernetContainerConfiguration);
+ addShowDescriptionEvent(mwClient);
+ } else {
+ var actualData = data.ethernetContainerConfiguration;
+ mwClient.compares = getCompares(mwClient.ethernetContainerConfiguration, actualData);
+ addShowDescriptionEvent(mwClient);
+ }
+ };
+
+ var updatePart = function(spec, data) {
+ switch (spec.pacId) {
+ case 'ne':
+ updateNe(data);
+ break;
+ case 'airinterface':
+ // console.log(JSON.stringify(spec, JSON.stringify(data)));
+ updateAirInterface(spec, data);
+ break;
+ case 'structure':
+ // console.log(JSON.stringify(data));
+ updateStructure(spec, data);
+ break;
+ case 'container':
+ // console.log(JSON.stringify(data));
+ updateContainer(spec, data);
+ break;
+ }
+ };
+
+ $scope.$watch('status', function(status, oldValue) {
+ Object.keys(status).map(function(key){
+ if ($scope.selection && status[key] && status[key] !== oldValue[key]) {
+ var info = key.split($scope.separator);
+ var spec = {
+ nodeId: $scope.selection,
+ revision: $scope.requiredNetworkElement.onfAirInterfaceRevision,
+ pacId: info[0],
+ requiredLayerProtocolId: info[1],
+ layerProtocolId: $scope.match.mapping[info[1]],
+ partId: 'Configuration'
+ };
+
+ if ($scope.connectionStatus !== 'connected') {
+ updatePart(spec, undefined);
+ return;
+ }
+ if (info.length > 1 && !$scope.match.mapping[info[1]]) {
+ updatePart(spec, undefined);
+ return;
+ }
+
+ $scope.spinner[key] = true;
+ $mwtnCompare.getPacParts(spec).then(function(success){
+ updatePart(spec, success);
+ $scope.spinner[key] = false;
+ }, function(error){
+ updatePart(spec, error);
+ $scope.spinner[key] = false;
+ });
+
+ }
+ });
+ }, true);
+
+
+
+ }]);
+
+
+});
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.directives.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.directives.js
new file mode 100644
index 00000000..f5fadd77
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.directives.js
@@ -0,0 +1,21 @@
+/*
+ * 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/mwtnCompare/mwtnCompare.module' ], function(mwtnCompareApp) {
+
+ mwtnCompareApp.register.directive('compare', function() {
+ return {
+ restrict : 'A',
+ scope: {
+ item: '=compare'
+ },
+ templateUrl : 'src/app/mwtnCompare/templates/compare.tpl.html'
+ };
+ });
+
+}); \ No newline at end of file
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.module.js
new file mode 100644
index 00000000..e3761f36
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.module.js
@@ -0,0 +1,50 @@
+/*
+ * 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'], function(ng) {
+ var mwtnCompareApp = angular.module('app.mwtnCompare', ['app.core', 'ui.router.state','config', 'pascalprecht.translate']);
+
+ mwtnCompareApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) {
+ mwtnCompareApp.register = {
+ controller : $controllerProvider.register,
+ directive : $compileProvider.directive,
+ factory : $provide.factory,
+ service : $provide.service
+
+ };
+
+
+ NavHelperProvider.addControllerUrl('app/mwtnCompare/mwtnCompare.controller');
+ NavHelperProvider.addToMenu('mwtnCompare', {
+ "link" : "#/pnfCompare/",
+ "active" : "main.mwtnCompare",
+ "title" : "pnf Compare",
+ "icon" : "fa fa-tags", // Add navigation icon css class here
+ "page" : {
+ "title" : "pnf Compare",
+ "description" : "mwtnCompare"
+ }
+ });
+
+ var access = routingConfig.accessLevels;
+
+ $stateProvider.state('main.mwtnCompare', {
+ url: 'pnfCompare/:nodeId',
+ access: access.admin,
+ views : {
+ 'content' : {
+ templateUrl: 'src/app/mwtnCompare/mwtnCompare.tpl.html',
+ controller: 'mwtnCompareCtrl'
+ }
+ }
+ });
+
+ });
+
+ return mwtnCompareApp;
+});
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.services.js
new file mode 100644
index 00000000..9a133e3b
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.services.js
@@ -0,0 +1,26 @@
+/*
+ * 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/mwtnCompare/mwtnCompare.module'],function(mwtnCompareApp) {
+
+ mwtnCompareApp.register.factory('$mwtnCompare', function($mwtnCommons, $mwtnDatabase) {
+
+ var service = {};
+
+ service.getConnectionStatus = $mwtnCommons.getConnectionStatus;
+ service.getPacParts = $mwtnCommons.getPacParts;
+ service.getRequiredNetworkElements = $mwtnCommons.getRequiredNetworkElements;
+ service.getSchema = $mwtnDatabase.getSchema;
+ service.getType = $mwtnCommons.getType;
+ service.separator = $mwtnCommons.separator;
+
+
+ return service;
+ });
+
+});
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.tpl.html
new file mode 100644
index 00000000..b3601ec2
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/mwtnCompare.tpl.html
@@ -0,0 +1,333 @@
+<ht-header help-link='sdnr/mwtnCompare/0.4.0/README.md'></ht-header>
+<div id="mwtnCompare">
+ <div class="owl container" style="width: 100%">
+ <div class="row" ng-show="neSelection.length === 0">
+ <p>
+ <span>{{ 'MWTN_NO_DEVICES_CONNECTED' | translate }}</span>
+ <span>Please check</span>
+ <a href="#/mwtnConnect" class="white">
+ <span>MWTN Connect</span>
+ </a>
+ <span>.</span>
+ </p>
+ </div>
+ <div class="row" ng-show="neSelection.length > 0">
+ <div class="col-md-2 text-right radio">
+ <span class="white">{{'Select planned NetworkElement' | translate}}</span>
+ </div>
+ <div class="col-md-4">
+ <div class="form-group">
+
+ <input list="networkElements" class="form-control" ng-model="selection">
+ <datalist id="networkElements">
+ <option ng-repeat="ne in neSelection" value="{{ne.id}}">{{ne.id}}</option>
+ </datalist>
+
+ </div>
+ </div>
+ <div class="col-md-2 text-right">
+ <span class="white" ng-class="{'connected':connectionStatus === 'connected'}">{{'MWTN_CONNECTIONSTATUS' | translate}}: </span><br/>
+ <span class="white" ng-class="{'match':match.numberOfLTPs}">{{'MWTN_NUMBEROFLTPS' | translate}}: </span><br/>
+ <span class="white" ng-class="{'match':match.radioSignalIds}">{{'MWTN_RADIOSIGNALIDS' | translate}}: </span>
+ </div>
+ <div class="col-md-2">
+ <a href="#/mwtnConnect">
+ <i ng-show="connectionStatus === 'connected'" class="fa fa-link" aria-hidden="true" ng-class="{'connected':connectionStatus === 'connected'}"></i>
+ <span class="white" ng-class="{'connected':connectionStatus === 'connected'}">{{connectionStatus}}</span>
+ </a><br/>
+ <i ng-class="{'match':match.numberOfLTPs}" ng-show="match.numberOfLTPs" class="fa fa-check-square-o" aria-hidden="true"></i>
+ <span class="white" ng-class="{'match':match.numberOfLTPs}">{{match.numberOfLTPsStatus}}</span><br/>
+ <i ng-class="{'match':match.radioSignalIds}" ng-show="match.radioSignalIds" class="fa fa-check-square-o" aria-hidden="true"></i>
+ <span class="white" ng-class="{'match':match.radioSignalIds}">{{match.radioSignalIdsStatus}}</span>
+ </div>
+ <div class="col-md-2 text-right">
+ <div class="form-group">
+ <button type="button" class="btn btn-default" ng-click="collapseAll()">{{'Collapse all' | translate}}</button>
+ </div>
+ </div>
+
+ </div>
+ </div>
+ <div class="owl container" style="width: 100%">
+ <hr/>
+ <div class="row">
+ <div class="col-md-12">
+ <uib-accordion close-others="oneATime">
+
+ <div uib-accordion-group class="panel-primary" is-open="status.ne">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status.ne, 'fa-chevron-right': !status.ne}"></i>
+ <span>{{'MWTN_NETWORKELEMENT' | translate}} '{{requiredNetworkElement['core-model:network-element'].nameList[0].value}}'</span>
+ <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.ne"></i>
+ </uib-accordion-heading>
+<pre>{{requiredNetworkElement | json}}</pre>
+
+ <table class="table">
+ <tr>
+ <td>
+ <table class="footable table table-hover">
+ <thead>
+ <tr>
+ <th class="nowrap">{{ 'Label' | translate }}</th>
+ <th class="nowrap">{{ 'Required value' | translate }}</th>
+ <th class="nowrap">{{ 'Actual value' | translate }}</th>
+ <th>{{ 'Unit' | translate }}</th>
+ <th ng-show="mwps.showDescriptions">{{ 'Description' | translate }}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="compare in requiredNetworkElement['core-model:network-element'].compares" compare="compare"></tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <h4 style="color: #444444;">
+ <b>NetworkElement</b>
+ </h4>
+ <p>{{ schema['NetworkElement'].description }}</p>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div ng-repeat="mwps in requiredNetworkElement.MW_AirInterface_Pac" uib-accordion-group class="panel-primary" is-open="status['airinterface' + separator + mwps.layerProtocol]">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status[['airinterface', mwps.layerProtocol].join(separator)], 'fa-chevron-right': !status['airinterface' + separator + airinterface.layerProtocol]}"></i>
+ <span>AirInterface MWPS '{{mwps.layerProtocol}}'</span>
+ <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner[['airinterface', mwps.layerProtocol].join(separator)]"></i>
+ </uib-accordion-heading>
+
+ <div class="text-right">
+ <a style="cursor: pointer;" ng-click="mwps.showDescriptions = !mwps.showDescriptions">
+ <span ng-show="mwps.showDescriptions" style="color: #444444">Hide </span>
+ <span ng-show="!mwps.showDescriptions" style="color: #444444">Show </span>
+ <span style="color: #444444"> descriptions</span>
+ </a>
+ </div>
+
+ <table class="table" ng-show="mwps.showDescriptions">
+ <tr>
+
+ <td style="width: 50%">
+ <div ng-repeat="item in ['LogicalTerminationPoint', 'LayerProtocol', 'MW_AirInterface_Pac']">
+ <h4 style="color: #444444;">
+ <b>{{item}}</b>
+ </h4>
+ {{schema[item].description}}
+ </div>
+ </td>
+ <td style="width: 50%">
+ <h4 style="color: #444444;">
+ <b>AirInterfaceConfiguration</b>
+ </h4>
+ {{schema['AirInterfaceConfiguration'].description}}
+ </td>
+
+ </tr>
+ </table>
+
+
+ <table class="footable table table-hover">
+ <thead>
+ <tr>
+ <th>{{ 'Label' | translate }}</th>
+ <th>{{ 'Required value' | translate }}</th>
+ <th>{{ 'Actual value' | translate }}</th>
+ <th>{{ 'Unit' | translate }}</th>
+ <th ng-show="mwps.showDescriptions">{{ 'Description' | translate }}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="compare in mwps.compares" compare="compare"></tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="99" ng-class="text-center">
+ <button class="btn btn-default" title="Operation to planning" ng-click="message('operation2Planning', mwps)">
+ <i class="icon-forward"></i>
+ </button>
+ <button class="btn btn-default" title="Planning to operation" ng-click="message('planning2Operation', mwps)">
+ <i class="icon-backward"></i>
+ </button>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+
+ </div>
+
+ <div ng-repeat="mws in requiredNetworkElement.MW_PureEthernetStructure_Pac" uib-accordion-group class="panel-primary" heading=""
+ is-open="status['structure' + separator + mws.layerProtocol]">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status[['structure', mws.layerProtocol].join(separator)], 'fa-chevron-right': !status['structure' + separator + structure.layerProtocol]}"></i>
+ <span>Structure MWS '{{mws.layerProtocol}}'</span>
+ <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner[['structure', mws.layerProtocol].join(separator)]"></i>
+ </uib-accordion-heading>
+
+ <div class="text-right">
+ <a style="cursor: pointer;" ng-click="mws.showDescriptions = !mws.showDescriptions">
+ <span ng-show="mws.showDescriptions" style="color: #444444">Hide </span>
+ <span ng-show="!mws.showDescriptions" style="color: #444444">Show </span>
+ <span style="color: #444444"> descriptions</span>
+ </a>
+ </div>
+
+ <table class="table" ng-show="mws.showDescriptions">
+ <tr>
+
+ <td style="width: 50%">
+ <div ng-repeat="item in ['LogicalTerminationPoint', 'LayerProtocol', 'MW_PureEthernetStructure_Pac']">
+ <h4 style="color: #444444;">
+ <b>{{item}}</b>
+ </h4>
+ {{schema[item].description}}
+ </div>
+ </td>
+ <td style="width: 50%">
+ <h4 style="color: #444444;">
+ <b>PureEthernetStructureConfiguration</b>
+ </h4>
+ {{schema['PureEthernetStructureConfiguration'].description}}
+ </td>
+
+ </tr>
+ </table>
+ <table class="footable table table-hover">
+ <thead>
+ <tr>
+ <th>{{ 'Label' | translate }}</th>
+ <th>{{ 'Required value' | translate }}</th>
+ <th>{{ 'Actual value' | translate }}</th>
+ <th>{{ 'Unit' | translate }}</th>
+ <th ng-show="mws.showDescriptions">{{ 'Description' | translate }}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="compare in mws.compares" compare="compare"></tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="99" ng-class="text-center">
+ <button class="btn btn-default" title="Operation to planning" ng-click="message('operation2Planning', mws)">
+ <i class="icon-forward"></i>
+ </button>
+ <button class="btn btn-default" title="Planning to operation" ng-click="message('planning2Operation', mws)">
+ <i class="icon-backward"></i>
+ </button>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div ng-repeat="mwClient in requiredNetworkElement.MW_EthernetContainer_Pac" uib-accordion-group class="panel-primary" is-open="status['container' + separator + mwClient.layerProtocol]">
+ <uib-accordion-heading>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': status[['container', mwClient.layerProtocol].join(separator)], 'fa-chevron-right': !status['container' + separator + container.layerProtocol]}"></i>
+ <span>Container ETH '{{mwClient.layerProtocol}}'</span>
+ <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner[['container', mwClient.layerProtocol].join(separator)]"></i>
+ </uib-accordion-heading>
+
+ <div class="text-right">
+ <a style="cursor: pointer;" ng-click="mwClient.showDescriptions = !mwClient.showDescriptions">
+ <span ng-show="mwClient.showDescriptions" style="color: #444444">Hide </span>
+ <span ng-show="!mwClient.showDescriptions" style="color: #444444">Show </span>
+ <span style="color: #444444"> descriptions</span>
+ </a>
+ </div>
+ <table class="table" ng-show="mwClient.showDescriptions">
+ <tr>
+ <td style="width: 50%">
+ <div ng-repeat="item in ['LogicalTerminationPoint', 'LayerProtocol', 'MW_EthernetContainer_Pac']">
+ <h4 style="color: #444444;">
+ <b>{{item}}</b>
+ </h4>
+ {{schema[item].description}}
+ </div>
+ </td>
+ <td style="width: 50%">
+ <div ng-repeat="item in ['EthernetContainerConfiguration', 'ethernetContainerConfiguration']">
+ <h4 style="color: #444444;">
+ <b>{{item}}</b>
+ </h4>
+ {{schema[item].description}}
+ </div>
+ </td>
+ </tr>
+ </table>
+
+ <table class="footable table table-hover">
+ <thead>
+ <tr>
+ <th>{{ 'Label' | translate }}</th>
+ <th>{{ 'Required value' | translate }}</th>
+ <th>{{ 'Actual value' | translate }}</th>
+ <th>{{ 'Unit' | translate }}</th>
+ <th ng-show="mwClient.showDescriptions">{{ 'Description' | translate }}</th>
+ </tr>
+ </thead>
+ </tbody>
+ <tr ng-repeat="compare in mwClient.compares" compare="compare"></tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="99" ng-class="text-center">
+ <button class="btn btn-default" title="Operation to planning" ng-click="message('operation2Planning', mwClient)">
+ <i class="icon-forward"></i>
+ </button>
+ <button class="btn btn-default" title="Planning to operation" ng-click="message('planning2Operation', mwClient)">
+ <i class="icon-backward"></i>
+ </button>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ </uib-accordion>
+ </div>
+ </div>
+ </div>
+
+ <div class="container" style="width: 100%">
+ <div class="row">
+ <uib-accordion close-others="oneAtATime">
+ <div uib-accordion-group panel-class="panel-odl" ng-repeat="ne in referenceValues.network.networkElement" is-open="ne.open">
+ <uib-accordion-heading>
+ <i class="pull-left" ng-class="{'icon-angle-down': ne.open, 'icon-angle-right': !ne.open}"></i> <span>Network element: </span> <b>"{{ne.name}}"</b> </uib-accordion-heading>
+ <accordion close-others="oneAtATime">
+ <div uib-accordion-group panel-class="panel-odl" is-open="ne['core-model:network-element'][0].open">
+ <uib-accordion-heading>
+ <i class="pull-left" ng-class="{'icon-angle-down': ne['core-model:network-element'][0].open, 'icon-angle-right': !ne['core-model:network-element'][0].open}"></i> <span>
+ {{ 'Network element' | translate}}
+ <span></uib-accordion-heading>
+1
+
+
+
+</div> <div uib-accordion-group panel-class="panel-odl" ng-repeat="mwps in ne.MW_AirInterface_Pac" is-open="mwps.open"> <uib-accordion-heading>
+<i class="pull-left" ng-class="{'icon-angle-down': mwps.open, 'icon-angle-right': !mwps.open}"></i> <span>
+ LTP ({{mwps.layerProtocol}})
+ <span></uib-accordion-heading>
+
+
+ </div>
+ <div uib-accordion-group panel-class="panel-odl" ng-repeat="mws in ne.MW_PureEthernetStructure_Pac" is-open="mws.open"> <uib-accordion-heading>
+ <i class="pull-left" ng-class="{'icon-angle-down': mws.open, 'icon-angle-right': !mws.open}"></i> <span>
+ LTP ({{mws.layerProtocol}})
+ <span></uib-accordion-heading>
+
+
+ </div>
+ <div uib-accordion-group panel-class="panel-odl" ng-repeat="mwClient in ne.MW_EthernetContainer_Pac" is-open="mwClient.open"> <uib-accordion-heading>
+ <i class="pull-left" ng-class="{'icon-angle-down': mwClient.open, 'icon-angle-right': !mwClient.open}"></i> <span>
+ LTP ({{mwClient.layerProtocol}})
+ <span></uib-accordion-heading>
+ </div>
+ </uib-accordion>
+ <div>
+</div>
+</div>
+<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/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/templates/compare.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/templates/compare.tpl.html
new file mode 100644
index 00000000..c5cbc50a
--- /dev/null
+++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-module/src/main/resources/mwtnCompare/templates/compare.tpl.html
@@ -0,0 +1,12 @@
+<td style="text-align: right;" ng-class="{ 'red': !item.match }">{{['mwtn', item.labelId].join('_').toUpperCase() | translate}}</td>
+<td><b ng-class="{ 'red': !item.match }" ng-bind-html="item.requiredValue"></b></td>
+
+<td>
+ <!-- [sko]: Bug reported by Amy: Of cause item.actualValue === false does not mean "missing"
+ <b ng-show="!item.actualValue">{{ item.missingActualValueLabelId | translate }}</b> -->
+ <b ng-class="{ 'red': !item.match }" ng-bind-html="item.actualValue"></b>
+</td>
+<td>{{ item.unit }}</td>
+<td style="max-width: 300px;" ng-show="item.showDescriptions">
+ {{item.description}}
+</td> \ No newline at end of file