diff options
Diffstat (limited to 'sdnr/wireless-transport/code-Carbon-SR1/ux')
335 files changed, 40685 insertions, 0 deletions
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-bundle/pom.xml new file mode 100644 index 00000000..d0850dea --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-bundle/pom.xml @@ -0,0 +1,118 @@ +<?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> + + <artifactId>ethService-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + + <parent> + <artifactId>ethService</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>ethService-module</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>ethService-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..b92ee913 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="ethService"/> + <property name="url" value="/src/app/ethService"/> + <property name="directory" value="/ethService"/> + <property name="requireJs" value="app/ethService/ethService.module"/> + <property name="angularJs" value="app.ethService"/> + <property name="cssDependencies"> + <list> + <value>src/app/ethService/ethService-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/pom.xml new file mode 100644 index 00000000..6a99723c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/pom.xml @@ -0,0 +1,14 @@ +<?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> + <artifactId>ethService-module</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>jar</packaging> + <parent> + <artifactId>ethService</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService-custom.css new file mode 100644 index 00000000..fed4402a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService-custom.css @@ -0,0 +1,58 @@ +/** + * Add your application related css here + */ +.ethServiceGrid { + height: 600px; + background-color: white; +} + +.ethServiceGrid span { + color: #393939; +} +.ht-pagination span { + color: #393939; +} +.ht-pagination span.dark { + color: #393939; +} +.dark { + color: #393939; +} + + + +.ethServiceGrid div.debug { + color: #393939; + background-color: white; +} +.ethServiceGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.ethServiceGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.ethServiceGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.controller.js new file mode 100644 index 00000000..080aa33b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.controller.js @@ -0,0 +1,25 @@ +/* + * 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/ethService/ethService.module', + 'app/ethService/ethService.services'], + function (ethServiceApp) { + + ethServiceApp.register.controller('ethServiceCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$ethService', '$mwtnLog', + function (uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $ethService, $mwtnLog) { + + var COMPONENT = 'ethServiceCtrl'; + $mwtnLog.info({ component: COMPONENT, message: 'ethServiceCtrl started!' }); + + $rootScope.section_logo = 'src/app/ethService/images/ethService.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.highlightFilteredHeader = $ethService.highlightFilteredHeader; + + }]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.module.js new file mode 100644 index 00000000..14729451 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.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 ethServiceApp = angular.module('app.ethService', ['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', 'ui.grid.infiniteScroll','ui.grid.pagination' ]); + + ethServiceApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + ethServiceApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/ethService/ethService.controller'); + NavHelperProvider.addToMenu('ethService', { + "link" : "#/ethService/", + "active" : "main.ethService", + "title" : "ETH Service", + "icon" : "fa fa-arrows-h", // Add navigation icon css class here + "page" : { + "title" : "ETH Service", + "description" : "Ethernet Service Provisioning" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.ethService', { + url: 'ethService/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/ethService/ethService.tpl.html', + controller: 'ethServiceCtrl' + } + } + }); + + }); + + return ethServiceApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.services.js new file mode 100644 index 00000000..fa8ef2f6 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.services.js @@ -0,0 +1,20 @@ +/* + * 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/ethService/ethService.module', 'app/mwtnCommons/mwtnCommons.services'], function (ethServiceApp) { + + ethServiceApp.register.factory('$ethService', function ($q, $http, Base64, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.checkModules = $mwtnCommons.checkModules; + + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.tpl.html new file mode 100644 index 00000000..b5f022f8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/ethService.tpl.html @@ -0,0 +1,9 @@ +<ht-header help-link='sdnr/ethService/0.4.0/README.md'></ht-header> + +<h1 style="color: red; transform: rotate(-30deg);">Under Construction</h1> +<br/><br/><br/><br/><br/> + +<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/ethService/ethService-module/src/main/resources/ethService/images/ethService.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/images/ethService.png Binary files differnew file mode 100755 index 00000000..9cca24f1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/ethService-module/src/main/resources/ethService/images/ethService.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/pom.xml new file mode 100644 index 00000000..ba49da79 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ethService/pom.xml @@ -0,0 +1,23 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>ethService</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>pom</packaging> + + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + + <modules> + <module>ethService-module</module> + <module>ethService-bundle</module> + </modules> + +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/features/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/features/pom.xml new file mode 100644 index 00000000..13eba24e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/features/pom.xml @@ -0,0 +1,65 @@ +<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> + + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnFeatures</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>ONF :: Wireless :: ${project.artifactId}</name> + + <parent> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>features-parent</artifactId> + <version>1.8.1-Carbon</version> + </parent> + + <properties> + <prefix>ONF :: Wireless :: </prefix> + + <apache.felix.compendium>1.4.0</apache.felix.compendium> + <decanter.version>1.1.0</decanter.version> + <elasticsearch.version>2.2.0</elasticsearch.version> + <osgi.core.version>5.0.0</osgi.core.version> + + <dlux.version>0.5.1-Carbon</dlux.version> + <mdsal.version>1.5.1-Carbon</mdsal.version> + <mdsal.model.version>0.10.1-Carbon</mdsal.model.version> + <restconf.version>1.5.1-Carbon</restconf.version> + <yangtools.version>1.1.1-Carbon</yangtools.version> + <openflow.plugin.version>0.4.1-Carbon</openflow.plugin.version> + <netconf.version>1.2.1-Carbon</netconf.version> + <l2switch.version>0.5.1-Carbon</l2switch.version> + <dlux.loader.version>0.5.1-Carbon</dlux.loader.version> + <securityproject.version>0.5.1</securityproject.version> + <configfile.directory>etc/opendaylight/karaf</configfile.directory> + </properties> + + <!-- <dependencyManagement> <dependencies> <dependency> <groupId>org.opendaylight.controller</groupId> + <artifactId>mdsal-artifacts</artifactId> <version>${mdsal.version}</version> + <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> --> + <dependencies> + + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>features-dlux</artifactId> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + <version>0.5.3-Carbon</version> + </dependency> + <!-- <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>features-yangtools</artifactId> + <classifier>features</classifier> <type>xml</type> <scope>runtime</scope> + <version>${yangtools.version}</version> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> + <artifactId>features-mdsal</artifactId> <classifier>features</classifier> + <type>xml</type> <scope>runtime</scope> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> + <artifactId>features-restconf</artifactId> <classifier>features</classifier> + <type>xml</type> <scope>runtime</scope> </dependency> --> + + <!-- WTN app dependencies - -> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>mwtnCommons</artifactId> <version>${project.version}</version> + </dependency> --> + <!-- <dependency> <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTopology</artifactId> <version>0.5.1-SNAPSHOT</version> </dependency> --> + </dependencies> + +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/features/src/main/features/features.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/features/src/main/features/features.xml new file mode 100644 index 00000000..5fe79651 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/features/src/main/features/features.xml @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="UTF-8"?> +<features name="odl-mwtn-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + +<!-- + => Only to be placed into feature-parents + <repository>mvn:org.apache.karaf.decanter/apache-karaf-decanter/${decanter.version}/xml/features</repository> + --> + +<!-- + Section 2: UX basis feature, used by all features in section 3 + --> + + <feature name="sdnr-wt-ux-all" version="${project.version}" description="ONAP :: SDN-R :: WT :: UX :: All"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/onapAai-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnFault-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnBrowser-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnInventory-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnMediator-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/help-bundle/${project.version}</bundle> + </feature> + + <feature name="onap-sdnr-ux-all" version="${project.version}" description="ONAP :: OpenDaylight :: SDN-R :: UX :: All"> + <feature version="${project.version}">odl-mwtn-ux-connect</feature> + + <feature version="${project.version}">onap-sdnr-aai-ux</feature> + <feature version="${project.version}">onap-sdnr-dcae-ux</feature> + <feature version="${project.version}">onap-sdnr-so-ux</feature> + + <!-- + <feature version="${project.version}">odl-eth-ux-service</feature> + <feature version="${project.version}">odl-otn-ux-config</feature> --> + + <feature version="${project.version}">odl-mwtn-ux-fault</feature> + <feature version="${project.version}">odl-mwtn-ux-config</feature> + <feature version="${project.version}">odl-mwtn-ux-performance</feature> + <feature version="${project.version}">odl-mwtn-ux-inventory</feature> + <feature version="${project.version}">odl-mwtn-ux-topology</feature> + <!-- sko not ready yet + <feature version="${project.version}">odl-mwtn-ux-compare</feature> + <feature version="${project.version}">odl-mwtn-ux-spectrum</feature> + <feature version="${project.version}">odl-mwtn-ux-closed-loop</feature> --> + <feature version="${project.version}">odl-mwtn-ux-mediator</feature> + <feature version="${project.version}">odl-help-core</feature> + + <!-- not needed + <feature version="${project.version}">odl-mwtn-ux-events</feature> + <feature version="${project.version}">odl-mwtn-ux-test</feature> + <feature version="${project.version}">odl-mwtn-ux-log</feature> + <feature version="${project.version}">odl-mwtn-ux-chat</feature> --> + </feature> + +<!-- PoC Specific feature for "poc180628" delivery --> + <feature name="ht-mwtn-ux-poc180628" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Release1806"> + <feature version="${project.version}">odl-mwtn-ux-connect</feature> + <feature version="${project.version}">onap-sdnr-so-ux</feature> + <feature version="${project.version}">onap-sdnr-dcae-ux</feature> + <feature version="${project.version}">onap-sdnr-aai-ux</feature> + <feature version="${project.version}">odl-mwtn-ux-fault</feature> + <feature version="${project.version}">odl-mwtn-ux-config</feature> + <feature version="${project.version}">odl-mwtn-ux-performance</feature> + <bundle>mvn:org.onap.sdnc.dluxapps/security-bundle/${securityproject.version}</bundle> + <feature version="${project.version}">odl-mwtn-ux-inventory</feature> + <feature version="${project.version}">odl-mwtn-ux-topology</feature> + <feature version="${project.version}">odl-mwtn-ux-mediator</feature> + <feature version="${project.version}">odl-mwtn-ux-log</feature> + <feature version="${project.version}">odl-ux-help</feature> + </feature> + +<!-- All UC features for test purpose --> + <feature name="odl-mwtn-ux-all" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: All"> + <feature version="${project.version}">odl-mwtn-ux-connect</feature> + + <feature version="${project.version}">onap-sdnr-aai-ux</feature> + <feature version="${project.version}">onap-sdnr-dcae-ux</feature> + <feature version="${project.version}">onap-sdnr-so-ux</feature> + + <feature version="${project.version}">odl-mwtn-ux-fault</feature> + <feature version="${project.version}">odl-mwtn-ux-performance</feature> + <feature version="${project.version}">odl-mwtn-ux-config</feature> + <feature version="${project.version}">odl-mwtn-ux-topology</feature> + <feature version="${project.version}">odl-mwtn-ux-inventory</feature> + <!-- sko not ready yet + <feature version="${project.version}">odl-mwtn-ux-compare</feature> + <feature version="${project.version}">odl-mwtn-ux-spectrum</feature> + <feature version="${project.version}">odl-mwtn-ux-closed-loop</feature> --> + <feature version="${project.version}">odl-mwtn-ux-mediator</feature> + <feature version="${project.version}">odl-mwtn-ux-events</feature> + <feature version="${project.version}">odl-mwtn-ux-test</feature> + <feature version="${project.version}">odl-mwtn-ux-log</feature> + <feature version="${project.version}">odl-mwtn-ux-chat</feature> + <feature version="${project.version}">odl-ux-help</feature> + </feature> + +<!-- + Section 2: UX basis feature, used by all features in section 3 + --> + + <feature name="odl-ux-commons" version="${project.version}" description="OpenDaylight :: UX :: Commons"> + <bundle>mvn:com.highstreet.technologies.apigateway/apigateway-impl/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnCommons-bundle/${project.version}</bundle> + </feature> + +<!-- + Section 3: Entry per GUI element/project + --> + + <feature name="odl-mwtn-ux-connect" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Connect"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + </feature> + + <feature name="onap-sdnr-aai-ux" version="${project.version}" description="ONAP :: AAI :: SDN-R :: UX"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/onapAai-bundle/${project.version}</bundle> + </feature> + + <feature name="onap-sdnr-dcae-ux" version="${project.version}" description="ONAP :: DCAE :: SDN-R :: UX"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/onapDcae-bundle/${project.version}</bundle> + </feature> + + <feature name="onap-sdnr-so-ux" version="${project.version}" description="ONAP :: SO :: SDN-R :: UX"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/onapSo-bundle/${project.version}</bundle> + </feature> + + <!-- sko not needed + <feature name="odl-eth-ux-service" version="${project.version}" description="OpenDaylight :: ETH :: UX :: Service"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/ethService-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-otn-ux-config" version="${project.version}" description="OpenDaylight :: OTN :: UX :: Configuration"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/otnBrowser-bundle/${project.version}</bundle> + </feature> + --> + + <feature name="odl-mwtn-ux-fault" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Fault"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnFault-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-config" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Configuration"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnBrowser-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-performance" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Performance"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnPerformanceCurrent-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnPerformanceHistory-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnPerformanceLink-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-inventory" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Inventory"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnInventory-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-topology" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Topology"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnTopology-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-tdm" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: TDM"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnTdm-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-ux-help" version="${project.version}" description="OpenDaylight :: UX :: Help"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/help-bundle/${project.version}</bundle> + </feature> + +<!-- + <feature name="odl-mwtn-ux-compare" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Comparision"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnCompare-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-spectrum" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Spectrum Management"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:cn.com.zte.odl.dlux/mwtnSpectrum-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-closed-loop" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Closed Loop Automation"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnClosedLoop-bundle/${project.version}</bundle> + </feature> +--> + <feature name="odl-mwtn-ux-events" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Events"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnEvents-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-test" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Test"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/${project.version}</bundle> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnTest-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-mediator" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Mediator"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnMediator-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-log" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Log"> + <feature version="${project.version}">odl-ux-commons</feature> + <bundle>mvn:com.highstreet.technologies.odl.dlux/mwtnLog-bundle/${project.version}</bundle> + </feature> + + <feature name="odl-mwtn-ux-chat" version="${project.version}" description="OpenDaylight :: MWTN :: UX :: Chat"> + <bundle>mvn:com.highstreet.technologies.odl.dlux/odlChat-bundle/${project.version}</bundle> + </feature> + +</features> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-bundle/pom.xml new file mode 100644 index 00000000..06081c2c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>help</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>help-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>help-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>help-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..490a2301 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="help"/> + <property name="url" value="/src/app/help"/> + <property name="directory" value="/help"/> + <property name="requireJs" value="app/help/help.module"/> + <property name="angularJs" value="app.help"/> + <property name="cssDependencies"> + <list> + <value>src/app/help/help.custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/pom.xml new file mode 100644 index 00000000..dd744b3a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/pom.xml @@ -0,0 +1,14 @@ +<?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>help</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>help-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/help/help-module/src/main/resources/help/help.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.controller.js new file mode 100644 index 00000000..c82464a8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.controller.js @@ -0,0 +1,284 @@ +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +define("help.tree", ["require", "exports", "angularAMD"], function (require, exports, angular) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var help = angular.module('app.help'); + // class HelpTreeController implements ng.IController { + // constructor(private $scope: ng.IScope & { rootNode: Node, data: Node[]}) { + // $scope.$watch("rootNode", (n, o) => { + // $scope.data = Object.keys($scope.rootNode).map(key => $scope.rootNode[key]); + // }); + // } + // } + // help.controller("treeCtrl", ["$scope", HelpTreeController]); + var helpTree = function ($compile) { + return { + restrict: "E", + transclude: true, + scope: { rootNode: '=' }, + //controller: 'treeCtrl', + template: '<ul>' + + '<li ng-transclude></li>' + + '<li ng-repeat="child in rootNode.nodes">' + + '<tree root-node="child"><div ng-transclude></div></tree>' + + '</li>' + + '</ul>', + compile: function (tElement, tAttr, transclude) { + var contents = tElement.contents().remove(); + var compiledContents; + return function (scope, iElement, iAttr) { + if (!compiledContents) { + compiledContents = $compile(contents, transclude); + } + compiledContents(scope, function (clone, scope) { + iElement.append(clone); + }); + }; + } + }; + }; + help.directive("tree", ["$compile", helpTree]); +}); +define("help.service", ["require", "exports", "angularAMD"], function (require, exports, angular) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var help = angular.module('app.help'); + var Helpservice = /** @class */ (function () { + function Helpservice($q, $http, env) { + this.$q = $q; + this.$http = $http; + this.env = env; + this.tocNodeCollection = null; + this.documents = {}; + } + Helpservice.prototype.getTableOfContents = function () { + var _this = this; + if (this.tocNodeCollection) { + return this.$q.resolve(this.tocNodeCollection); + } + return this.$http({ + method: "GET", + url: window.location.origin + "/help/?meta" + }).then(function (result) { + if (result.status === 200) { + _this.tocNodeCollection = result.data; + return result.data; + } + }); + }; + Helpservice.prototype.getDocument = function (path) { + var _this = this; + if (this.documents[path] != null) { + return this.$q.resolve(this.documents[path]); + } + return this.$http({ + method: "GET", + url: window.location.origin + "/help/" + path + }).then(function (result) { + if (result.status === 200) { + return _this.documents[path] = { + basePath: result.config && result.config.url && result.config.url, + document: result.data + }; + } + }); + }; + return Helpservice; + }()); + help.service('helpService', ['$q', '$http', Helpservice]); +}); +define("help.utilities", ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.resolvePath = function () { + var paths = []; + for (var _i = 0; _i < arguments.length; _i++) { + paths[_i] = arguments[_i]; + } + console.log(paths); + function resolve(pathA, pathB) { + // ‘a’ => ['a'] + // 'a/b' => ['a', 'b'] + // '/a/b' => ['', 'a', 'b'] + // '/a/b/' => ['', 'a', 'b', ''] + pathB = pathB.split('/'); + if (pathB[0] === '') { + return pathB.join('/'); + } + pathA = pathA.split('/'); + var aLastIndex = pathA.length - 1; + if (pathA[aLastIndex] !== '') { + pathA[aLastIndex] = ''; + } + var part; + var i = 0; + while (typeof (part = pathB[i]) === 'string') { + switch (part) { + case '..': + pathA.pop(); + pathA.pop(); + pathA.push(''); + break; + case '.': + pathA.pop(); + pathA.push(''); + break; + default: + pathA.pop(); + pathA.push(part); + pathA.push(''); + break; + } + i++; + } + if (pathB[pathB.length - 1] !== '') + pathA.pop(); + return pathA.join('/'); + } + var i = 0; + var path; + var r = location.pathname; + var urlRegex = /^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i; + var multiSlashReg = /\/\/+/g; + while (typeof (path = paths[i]) === 'string') { + // debugger; + var matches = path && path.match(urlRegex); + if (matches || !i) { + r = path; + } + else { + path = path.replace(multiSlashReg, '/'); + r = resolve(r, path); + } + i++; + } + return r; + }; +}); +define( ["require", "exports", "./lib/marked", "help.utilities", "help.tree", "help.service"], function (require, exports, marked, help_utilities_1) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var currentPath = '/help'; + var currentDoc = ''; + var renderer = new marked.Renderer(); + renderer.link = function (href, title, text) { + // check if href is rel or abs + var absUrlMatch = href.trim().match(/^https?:\/\//i); + return "<a "+(absUrlMatch ? "target=\"_blank\"":"")+" href=\"" + (absUrlMatch ? href : help_utilities_1.resolvePath('#/help/', currentDoc, href)) + "\" title=\"" + title + "\" >" + text + "</a>"; + }; + renderer.image = function (href, title, text) { + return "<img src=\"" + help_utilities_1.resolvePath(currentPath, href) + "\" alt=\"" + title + "\" />"; + }; + marked.setOptions({ + renderer: renderer, + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: true, + smartypants: false, + xhtml: false + }); + var help = angular.module('app.help'); + var HelpDirective = function () { + return { + restrict: 'AE', + template: "<div class=\"global-help\" ><a href=\"{{ '#/help/'+ link }}\"><i class=\"fa fa-question-circle\"></i> Help</a></div>", + scope: { + link: '@' + }, + replace: true + }; + }; + help.directive('help', [HelpDirective]); + var MarkdownItDirective = function ($sanitize) { + var attribute = 'markdownIt'; + var render = function (value) { + var md2html = (marked instanceof Function) ? marked : marked.default; + return value + ? $sanitize(md2html(value.trim())) + : ''; + }; + return { + restrict: 'AE', + scope: { + markdownIt: '=' + }, + replace: true, + link: function (scope, element, attrs) { + if (attrs[attribute]) { + scope.$watch(attribute, function (value) { + element.html(render(value)); + }); + } + else { + element.html(render(element.text())); + } + } + }; + }; + help.directive('markdownIt', ['$sanitize', MarkdownItDirective]); + var mapNode = function (tocNode) { + return tocNode && Object.keys(tocNode).map(function (key) { + return __assign({}, tocNode[key], { href: "#/help/" + tocNode[key]['versions']['current']['path'], nodes: mapNode(tocNode[key].nodes) }); + }); + }; + var HelpController = /** @class */ (function () { + function HelpController($scope, $rootScope, $state, $timeout, helpService) { + var _this = this; + this.$scope = $scope; + this.$state = $state; + this.$timeout = $timeout; + this.helpService = helpService; + this._content = "## Loading"; + this._path = ''; + this._toc = {}; + + $rootScope.section_logo = 'src/app/help/images/help.png'; + + helpService.getTableOfContents().then(function (toc) { + _this._toc = { nodes: mapNode(toc) }; + if (!$state.params.path) { + $state.go('main.help', { path: toc['sdnr']['versions']['current']['path'] }); + } + else { + _this.navigateTo($state.params.path); + } + }); + } + Object.defineProperty(HelpController.prototype, "content", { + get: function () { return this._content; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(HelpController.prototype, "path", { + get: function () { return this._path; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(HelpController.prototype, "toc", { + get: function () { return this._toc; }, + enumerable: true, + configurable: true + }); + HelpController.prototype.navigateTo = function (path) { + var _this = this; + this.helpService.getDocument(path).then(function (result) { + currentDoc = path; + currentPath = result.basePath; + _this._content = result.document; + }); + }; + return HelpController; + }()); + help.controller('helpCtrl', ['$scope', '$rootScope', '$state', '$timeout', 'helpService', HelpController]); +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscC5jb250cm9sbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2FwcC9oZWxwL2hlbHAudHJlZS50cyIsInNyYy9hcHAvaGVscC9oZWxwLnNlcnZpY2UudHMiLCJzcmMvYXBwL2hlbHAvaGVscC51dGlsaXRpZXMudHMiLCJzcmMvYXBwL2hlbHAvaGVscC5jb250cm9sbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0lBY0EsSUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUV4Qyx1REFBdUQ7SUFDdkQsK0VBQStFO0lBQy9FLDRDQUE0QztJQUM1QyxxRkFBcUY7SUFDckYsVUFBVTtJQUNWLE1BQU07SUFDTixJQUFJO0lBRUosK0RBQStEO0lBRS9ELElBQU0sUUFBUSxHQUFHLFVBQVUsUUFBUTtRQUNqQyxNQUFNLENBQUM7WUFDTCxRQUFRLEVBQUUsR0FBRztZQUNiLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7WUFDeEIseUJBQXlCO1lBQ3pCLFFBQVEsRUFDTixNQUFNO2dCQUNOLHlCQUF5QjtnQkFDekIsMENBQTBDO2dCQUMxQywwREFBMEQ7Z0JBQzFELE9BQU87Z0JBQ1AsT0FBTztZQUNULE9BQU8sRUFBRSxVQUFVLFFBQVEsRUFBRSxLQUFLLEVBQUUsVUFBVTtnQkFDNUMsSUFBSSxRQUFRLEdBQUcsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM1QyxJQUFJLGdCQUFnQixDQUFDO2dCQUNyQixNQUFNLENBQUMsVUFBVSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUs7b0JBQ3JDLEVBQUUsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO3dCQUN0QixnQkFBZ0IsR0FBRyxRQUFRLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO29CQUNwRCxDQUFDO29CQUNELGdCQUFnQixDQUFDLEtBQUssRUFBRSxVQUFVLEtBQUssRUFBRSxLQUFLO3dCQUM1QyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN6QixDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQUM7WUFDSixDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUMsQ0FBQztJQUVGLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7Ozs7O0lDcEQvQyxJQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBMkN4QztRQUtDLHFCQUFvQixFQUFxQixFQUFVLEtBQTJCLEVBQVUsR0FBUztZQUE3RSxPQUFFLEdBQUYsRUFBRSxDQUFtQjtZQUFVLFVBQUssR0FBTCxLQUFLLENBQXNCO1lBQVUsUUFBRyxHQUFILEdBQUcsQ0FBTTtZQUM5RixJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO1lBQzlCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLENBQUM7UUFFTSx3Q0FBa0IsR0FBekI7WUFBQSxpQkFjQztZQWJDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNuRCxDQUFDO1lBRUQsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7Z0JBQ2QsTUFBTSxFQUFFLEtBQUs7Z0JBQ2hCLEdBQUcsRUFBSyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsZ0JBQWE7YUFDaEQsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFDLE1BQWdEO2dCQUN2RCxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQzlCLEtBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO29CQUNyQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztnQkFDakIsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVNLGlDQUFXLEdBQWxCLFVBQW1CLElBQVk7WUFBL0IsaUJBaUJDO1lBaEJDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDakMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUMvQyxDQUFDO1lBRUYsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7Z0JBQ2YsTUFBTSxFQUFFLEtBQUs7Z0JBQ2IsR0FBRyxFQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxjQUFTLElBQU07YUFDckQsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFDLE1BQXFDO2dCQUM1QyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQzFCLE1BQU0sQ0FBQyxLQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHO3dCQUM1QixRQUFRLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUc7d0JBQ2pFLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSTtxQkFDdEIsQ0FBQztnQkFDSixDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFTCxDQUFDO1FBQ0gsa0JBQUM7SUFBRCxDQUFDLEFBNUNELElBNENDO0lBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRyxXQUFXLENBQUMsQ0FBQyxDQUFDOzs7OztJQzNGdkQsUUFBQSxXQUFXLEdBQUc7UUFBVSxlQUFrQjthQUFsQixVQUFrQixFQUFsQixxQkFBa0IsRUFBbEIsSUFBa0I7WUFBbEIsMEJBQWtCOztRQUNuRCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25CLGlCQUFpQixLQUFLLEVBQUUsS0FBSztZQUMzQixvQkFBb0I7WUFDcEIseUJBQXlCO1lBQ3pCLDZCQUE2QjtZQUM3QixpQ0FBaUM7WUFDakMsS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekIsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pCLENBQUM7WUFDRCxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6QixJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNsQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDN0IsS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUN6QixDQUFDO1lBRUQsSUFBSSxJQUFJLENBQUM7WUFDVCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDVixPQUFPLE9BQU8sQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQzdDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7b0JBQ2IsS0FBSyxJQUFJO3dCQUNQLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDWixLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7d0JBQ1osS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFDZixLQUFLLENBQUM7b0JBQ1IsS0FBSyxHQUFHO3dCQUNOLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDWixLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO3dCQUNmLEtBQUssQ0FBQztvQkFDUjt3QkFDRSxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7d0JBQ1osS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzt3QkFDakIsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFDZixLQUFLLENBQUM7Z0JBQ1YsQ0FBQztnQkFDRCxDQUFDLEVBQUUsQ0FBQztZQUNOLENBQUM7WUFDRCxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2hELE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDVixJQUFJLElBQUksQ0FBQztRQUNULElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFFMUIsSUFBTSxRQUFRLEdBQUcsc0NBQXNDLENBQUM7UUFDeEQsSUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDO1FBRS9CLE9BQU8sT0FBTyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM3QyxRQUFRLENBQUM7WUFDVCxJQUFNLE9BQU8sR0FBRyxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3QyxFQUFFLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNsQixDQUFDLEdBQUcsSUFBSSxDQUFDO1lBQ1gsQ0FBQztZQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNOLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDeEMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDdkIsQ0FBQztZQUNELENBQUMsRUFBRSxDQUFDO1FBQ04sQ0FBQztRQUVELE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDLENBQUM7Ozs7O0lDbkRGLElBQUksV0FBVyxHQUFHLE9BQU8sQ0FBQztJQUMxQixJQUFJLFVBQVUsR0FBRyxFQUFFLENBQUM7SUFFcEIsSUFBTSxRQUFRLEdBQUcsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7SUFFdkMsUUFBUSxDQUFDLElBQUksR0FBRyxVQUFDLElBQVksRUFBRSxLQUFhLEVBQUUsSUFBWTtRQUN4RCw4QkFBOEI7UUFDOUIsSUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUN2RCxNQUFNLENBQUMsZ0JBQVksV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLDRCQUFXLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsb0JBQVksS0FBSyxZQUFNLElBQUksU0FBTSxDQUFBO0lBQ25ILENBQUMsQ0FBQztJQUVGLFFBQVEsQ0FBQyxLQUFLLEdBQUcsVUFBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLElBQVk7UUFDekQsTUFBTSxDQUFDLGdCQUFhLDRCQUFXLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxpQkFBVSxLQUFLLFVBQU0sQ0FBQTtJQUN6RSxDQUFDLENBQUM7SUFFRixNQUFNLENBQUMsVUFBVSxDQUFDO1FBQ2hCLFFBQVEsRUFBRSxRQUFRO1FBQ2xCLEdBQUcsRUFBRSxJQUFJO1FBQ1QsTUFBTSxFQUFFLElBQUk7UUFDWixNQUFNLEVBQUUsS0FBSztRQUNiLFFBQVEsRUFBRSxLQUFLO1FBQ2YsUUFBUSxFQUFFLEtBQUs7UUFDZixVQUFVLEVBQUUsSUFBSTtRQUNoQixXQUFXLEVBQUUsS0FBSztRQUNsQixLQUFLLEVBQUUsS0FBSztLQUNiLENBQUMsQ0FBQztJQUVILElBQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFFeEMsSUFBTSxhQUFhLEdBQUc7UUFFcEIsTUFBTSxDQUFDO1lBQ0wsUUFBUSxFQUFFLElBQUk7WUFDZCxRQUFRLEVBQUUsNEhBQXNIO1lBQ2hJLEtBQUssRUFBRTtnQkFDTCxJQUFJLEVBQUUsR0FBRzthQUNWO1lBQ0QsT0FBTyxFQUFFLElBQUk7U0FDZCxDQUFDO0lBQ0osQ0FBQyxDQUFBO0lBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBRXhDLElBQU0sbUJBQW1CLEdBQUcsVUFBQyxTQUE0QztRQUN2RSxJQUFNLFNBQVMsR0FBRyxZQUFZLENBQUM7UUFFL0IsSUFBTSxNQUFNLEdBQUcsVUFBVSxLQUFLO1lBQzVCLElBQU0sT0FBTyxHQUFHLENBQUMsTUFBTSxZQUFZLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUM7WUFDdkUsTUFBTSxDQUFDLEtBQUs7Z0JBQ1YsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ2xDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDVCxDQUFDLENBQUM7UUFFRixNQUFNLENBQUM7WUFDTCxRQUFRLEVBQUUsSUFBSTtZQUNkLEtBQUssRUFBRTtnQkFDTCxVQUFVLEVBQUUsR0FBRzthQUNoQjtZQUNELE9BQU8sRUFBRSxJQUFJO1lBQ2IsSUFBSSxFQUFFLFVBQVUsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLO2dCQUNuQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNyQixLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxVQUFVLEtBQUs7d0JBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBQzlCLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUM7Z0JBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDdkMsQ0FBQztZQUNILENBQUM7U0FDRixDQUFDO0lBQ0osQ0FBQyxDQUFBO0lBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxXQUFXLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO0lBTWpFLElBQU0sT0FBTyxHQUFHLFVBQUMsT0FBMEI7UUFDekMsTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFBLEdBQUc7WUFDNUMsTUFBTSxjQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFDZixJQUFJLEVBQUUsWUFBVSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFHLEVBQzdELEtBQUssRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUNsQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDO0lBRUY7UUFLRSx3QkFBb0IsTUFBa0IsRUFBVSxNQUFNLEVBQVUsUUFBaUMsRUFBVSxXQUF5QjtZQUFwSSxpQkFVQztZQVZtQixXQUFNLEdBQU4sTUFBTSxDQUFZO1lBQVUsV0FBTSxHQUFOLE1BQU0sQ0FBQTtZQUFVLGFBQVEsR0FBUixRQUFRLENBQXlCO1lBQVUsZ0JBQVcsR0FBWCxXQUFXLENBQWM7WUFKNUgsYUFBUSxHQUFHLFlBQVksQ0FBQztZQUN4QixVQUFLLEdBQUcsRUFBRSxDQUFDO1lBQ1gsU0FBSSxHQUFVLEVBQUcsQ0FBQztZQUl4QixXQUFXLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBQSxHQUFHO2dCQUN2QyxLQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFFO2dCQUNyQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztvQkFDeEIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtnQkFDdEYsQ0FBQztnQkFBQyxJQUFJLENBQUMsQ0FBQztvQkFDTixLQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RDLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxzQkFBVyxtQ0FBTztpQkFBbEIsY0FBdUIsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDOzs7V0FBQTtRQUM5QyxzQkFBVyxnQ0FBSTtpQkFBZixjQUFvQixNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7OztXQUFBO1FBQ3hDLHNCQUFXLCtCQUFHO2lCQUFkLGNBQW1CLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzs7O1dBQUE7UUFFOUIsbUNBQVUsR0FBbEIsVUFBbUIsSUFBWTtZQUEvQixpQkFNQztZQUxDLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFDLE1BQU07Z0JBQzdDLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ2xCLFdBQVcsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO2dCQUM5QixLQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUM7WUFDbEMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUgscUJBQUM7SUFBRCxDQUFDLEFBN0JELElBNkJDO0lBRUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsY0FBYyxDQUFFLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFuZ3VsYXIgZnJvbSAnYW5ndWxhckFNRCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZSB7XG4gIGxhYmVsPzogc3RyaW5nLFxuICBub2Rlcz86IE5vZGVbXSxcbiAgdmVyc2lvbnM/OiB7XG4gICAgW3ZlcnNpb246IHN0cmluZ106IHsgXG4gICAgICBsYWJlbDogc3RyaW5nLFxuICAgICAgZGF0ZTogc3RyaW5nLFxuICAgICAgcGF0aDogc3RyaW5nXG4gICAgfVxuICB9IFxufVxuXG5jb25zdCBoZWxwID0gYW5ndWxhci5tb2R1bGUoJ2FwcC5oZWxwJyk7XG5cbi8vIGNsYXNzIEhlbHBUcmVlQ29udHJvbGxlciBpbXBsZW1lbnRzIG5nLklDb250cm9sbGVyIHtcbi8vICAgY29uc3RydWN0b3IocHJpdmF0ZSAkc2NvcGU6IG5nLklTY29wZSAmIHsgcm9vdE5vZGU6IE5vZGUsIGRhdGE6IE5vZGVbXX0pIHtcbi8vICAgICAkc2NvcGUuJHdhdGNoKFwicm9vdE5vZGVcIiwgKG4sIG8pID0+IHtcbi8vICAgICAgICRzY29wZS5kYXRhID0gT2JqZWN0LmtleXMoJHNjb3BlLnJvb3ROb2RlKS5tYXAoa2V5ID0+ICRzY29wZS5yb290Tm9kZVtrZXldKTtcbi8vICAgICB9KTtcbi8vICAgfVxuLy8gfVxuXG4vLyBoZWxwLmNvbnRyb2xsZXIoXCJ0cmVlQ3RybFwiLCBbXCIkc2NvcGVcIiwgSGVscFRyZWVDb250cm9sbGVyXSk7XG5cbmNvbnN0IGhlbHBUcmVlID0gZnVuY3Rpb24gKCRjb21waWxlKSB7XG4gIHJldHVybiB7XG4gICAgcmVzdHJpY3Q6IFwiRVwiLFxuICAgIHRyYW5zY2x1ZGU6IHRydWUsXG4gICAgc2NvcGU6IHsgcm9vdE5vZGU6ICc9JyB9LFxuICAgIC8vY29udHJvbGxlcjogJ3RyZWVDdHJsJyxcbiAgICB0ZW1wbGF0ZTpcbiAgICAgICc8dWw+JyArXG4gICAgICAnPGxpIG5nLXRyYW5zY2x1ZGU+PC9saT4nICtcbiAgICAgICc8bGkgbmctcmVwZWF0PVwiY2hpbGQgaW4gcm9vdE5vZGUubm9kZXNcIj4nICtcbiAgICAgICc8dHJlZSByb290LW5vZGU9XCJjaGlsZFwiPjxkaXYgbmctdHJhbnNjbHVkZT48L2Rpdj48L3RyZWU+JyArXG4gICAgICAnPC9saT4nICtcbiAgICAgICc8L3VsPicsXG4gICAgY29tcGlsZTogZnVuY3Rpb24gKHRFbGVtZW50LCB0QXR0ciwgdHJhbnNjbHVkZSkge1xuICAgICAgdmFyIGNvbnRlbnRzID0gdEVsZW1lbnQuY29udGVudHMoKS5yZW1vdmUoKTtcbiAgICAgIHZhciBjb21waWxlZENvbnRlbnRzO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIChzY29wZSwgaUVsZW1lbnQsIGlBdHRyKSB7XG4gICAgICAgIGlmICghY29tcGlsZWRDb250ZW50cykge1xuICAgICAgICAgIGNvbXBpbGVkQ29udGVudHMgPSAkY29tcGlsZShjb250ZW50cywgdHJhbnNjbHVkZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29tcGlsZWRDb250ZW50cyhzY29wZSwgZnVuY3Rpb24gKGNsb25lLCBzY29wZSkge1xuICAgICAgICAgIGlFbGVtZW50LmFwcGVuZChjbG9uZSk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9XG4gIH07XG59O1xuXG5oZWxwLmRpcmVjdGl2ZShcInRyZWVcIiwgW1wiJGNvbXBpbGVcIiwgaGVscFRyZWVdKTsiLCJpbXBvcnQgKiBhcyBhbmd1bGFyIGZyb20gJ2FuZ3VsYXJBTUQnO1xuXG5jb25zdCBoZWxwID0gYW5ndWxhci5tb2R1bGUoJ2FwcC5oZWxwJyk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvbkluZm8ge1xuICBsYWJlbDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIGRhdGU6IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRvY05vZGUge1xuICBsYWJlbDogc3RyaW5nOyBcbiAgdmVyc2lvbnM6IHtcbiAgICBbdmVyc2lvbktleTogc3RyaW5nXTogVmVyc2lvbkluZm9cbiAgfTtcbiAgbm9kZXM/OiBUb2NOb2RlQ29sbGVjdGlvbjtcbn1cblxuZXhwb3J0IHR5cGUgVG9jTm9kZUNvbGxlY3Rpb24gPSB7IFt0b2NOb2RlS2V5OiBzdHJpbmddOiBUb2NOb2RlIH07XG5cblxuaW50ZXJmYWNlIElFbnYge1xuICBnZXRCYXNlVVJMOiAoc2FsVHlwZTogJ0FEX1NBTCcgfCAnTURfU0FMJykgPT4gc3RyaW5nO1xufVxuXG4vKiogUmVwcmVzZW50cyBhIHNlcnZpY2UgdXNlZCBmb3IgdGhlIGhlbHAgYXBwbGljYXRpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIElIZWxwU2VydmljZSB7XG5cbiAgLyoqXG4gICAqIFF1ZXJpZXMgdGhlIHRhYmxlIG9mIGNvbnRlbnRzIGZvciBhIHNwZWNpZmljIHZlcnNpb24uXG4gICAqIEBwYXJhbSB2ZXJzaW9uIFRoZSB2ZXJzaW9uIHRoZSB0YWJsZSBvZiBjb250ZW50cyBzaGFsbCBiZSByZXF1ZXN0ZWQgZm9yLlxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgY29udGFpbmluZyB0aGUgcmVxdWVzdGVkIHRhYmxlIG9mIGNvbnRlbnRzLlxuICAgKiBcbiAgICovXG4gIGdldFRhYmxlT2ZDb250ZW50cyh2ZXJzaW9uPzogc3RyaW5nKTogYW5ndWxhci5JUHJvbWlzZTxUb2NOb2RlQ29sbGVjdGlvbj47XG5cbiAgLyoqXG4gICAqIEdldCBhIHNwZWNpdGljIGRvY3VtZW50IGJ5IGl0cyBwYXRoLlxuICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCBvZiB0aGUgZG9jdW1lbnQgdG8gZ2V0LlxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgY29udGFpbmluZyB0aGUgcmVxdWVzdGVkIGRvY3VtZW50LlxuICAgKiBcbiAgICovXG4gIGdldERvY3VtZW50KHBhdGg6IHN0cmluZyk6IGFuZ3VsYXIuSVByb21pc2U8eyBiYXNlUGF0aDogc3RyaW5nLCBkb2N1bWVudDogc3RyaW5nIH0+O1xufVxuXG5jbGFzcyBIZWxwc2VydmljZSBpbXBsZW1lbnRzIElIZWxwU2VydmljZSB7XG5cbiAgcHJpdmF0ZSB0b2NOb2RlQ29sbGVjdGlvbjogVG9jTm9kZUNvbGxlY3Rpb247XG4gIHByaXZhdGUgZG9jdW1lbnRzOiB7IFtwYXRoOiBzdHJpbmddOiB7IGJhc2VQYXRoOiBzdHJpbmcsIGRvY3VtZW50OiBzdHJpbmcgfSB9O1xuXG5cdGNvbnN0cnVjdG9yKHByaXZhdGUgJHE6IGFuZ3VsYXIuSVFTZXJ2aWNlLCBwcml2YXRlICRodHRwOiBhbmd1bGFyLklIdHRwU2VydmljZSwgcHJpdmF0ZSBlbnY6IElFbnYpIHtcbiAgICB0aGlzLnRvY05vZGVDb2xsZWN0aW9uID0gbnVsbDtcbiAgICB0aGlzLmRvY3VtZW50cyA9IHt9O1xuICB9XG4gXG4gIHB1YmxpYyBnZXRUYWJsZU9mQ29udGVudHMoKTogYW5ndWxhci5JUHJvbWlzZTxUb2NOb2RlQ29sbGVjdGlvbj4ge1xuICAgIGlmICh0aGlzLnRvY05vZGVDb2xsZWN0aW9uKSB7XG4gICAgICByZXR1cm4gdGhpcy4kcS5yZXNvbHZlKHRoaXMudG9jTm9kZUNvbGxlY3Rpb24pO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLiRodHRwKHtcbiAgICAgIG1ldGhvZDogXCJHRVRcIixcblx0XHRcdHVybDogYCR7dGhpcy5lbnYuZ2V0QmFzZVVSTCgnTURfU0FMJyl9L2hlbHAvP21ldGFgXG4gICAgfSkudGhlbigocmVzdWx0OiBhbmd1bGFyLklIdHRwUmVzcG9uc2U8VG9jTm9kZUNvbGxlY3Rpb24+KSA9PiB7XG4gICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gMjAwKSB7XG5cdFx0XHRcdHRoaXMudG9jTm9kZUNvbGxlY3Rpb24gPSByZXN1bHQuZGF0YTtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdC5kYXRhO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldERvY3VtZW50KHBhdGg6IHN0cmluZyk6IGFuZ3VsYXIuSVByb21pc2U8e2Jhc2VQYXRoOiBzdHJpbmcsIGRvY3VtZW50OiBzdHJpbmd9PiB7XG4gICAgaWYgKHRoaXMuZG9jdW1lbnRzW3BhdGhdICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLiRxLnJlc29sdmUodGhpcy5kb2N1bWVudHNbcGF0aF0pO1xuICAgIH1cblxuICAgcmV0dXJuIHRoaXMuJGh0dHAoe1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgdXJsOiBgJHt0aGlzLmVudi5nZXRCYXNlVVJMKCdNRF9TQUwnKX0vaGVscC8ke3BhdGh9YFxuICAgIH0pLnRoZW4oKHJlc3VsdDogYW5ndWxhci5JSHR0cFJlc3BvbnNlPHN0cmluZz4pID0+IHtcbiAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9jdW1lbnRzW3BhdGhdID0ge1xuICAgICAgICAgIGJhc2VQYXRoOiByZXN1bHQuY29uZmlnICYmIHJlc3VsdC5jb25maWcudXJsICYmIHJlc3VsdC5jb25maWcudXJsLFxuICAgICAgICAgIGRvY3VtZW50OiByZXN1bHQuZGF0YVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0pO1xuXG4gIH0gXG59XG5cbmhlbHAuc2VydmljZSgnaGVscFNlcnZpY2UnLCBbJyRxJywgJyRodHRwJywgJ0VOVicsICBIZWxwc2VydmljZV0pOyIsImV4cG9ydCB2YXIgcmVzb2x2ZVBhdGggPSBmdW5jdGlvbiAoLi4ucGF0aHM6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgY29uc29sZS5sb2cocGF0aHMpO1xuICBmdW5jdGlvbiByZXNvbHZlKHBhdGhBLCBwYXRoQikge1xuICAgIC8vICDigJhh4oCZICAgICA9PiBbJ2EnXVxuICAgIC8vICAnYS9iJyAgID0+IFsnYScsICdiJ11cbiAgICAvLyAgJy9hL2InICA9PiBbJycsICdhJywgJ2InXVxuICAgIC8vICAnL2EvYi8nID0+IFsnJywgJ2EnLCAnYicsICcnXVxuICAgIHBhdGhCID0gcGF0aEIuc3BsaXQoJy8nKTtcbiAgICBpZiAocGF0aEJbMF0gPT09ICcnKSB7XG4gICAgICByZXR1cm4gcGF0aEIuam9pbignLycpO1xuICAgIH1cbiAgICBwYXRoQSA9IHBhdGhBLnNwbGl0KCcvJyk7XG4gICAgdmFyIGFMYXN0SW5kZXggPSBwYXRoQS5sZW5ndGggLSAxO1xuICAgIGlmIChwYXRoQVthTGFzdEluZGV4XSAhPT0gJycpIHtcbiAgICAgIHBhdGhBW2FMYXN0SW5kZXhdID0gJyc7XG4gICAgfVxuXG4gICAgdmFyIHBhcnQ7XG4gICAgdmFyIGkgPSAwO1xuICAgIHdoaWxlICh0eXBlb2YgKHBhcnQgPSBwYXRoQltpXSkgPT09ICdzdHJpbmcnKSB7XG4gICAgICBzd2l0Y2ggKHBhcnQpIHtcbiAgICAgICAgY2FzZSAnLi4nOlxuICAgICAgICAgIHBhdGhBLnBvcCgpO1xuICAgICAgICAgIHBhdGhBLnBvcCgpO1xuICAgICAgICAgIHBhdGhBLnB1c2goJycpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICcuJzpcbiAgICAgICAgICBwYXRoQS5wb3AoKTtcbiAgICAgICAgICBwYXRoQS5wdXNoKCcnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBwYXRoQS5wb3AoKTtcbiAgICAgICAgICBwYXRoQS5wdXNoKHBhcnQpO1xuICAgICAgICAgIHBhdGhBLnB1c2goJycpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaSsrO1xuICAgIH1cbiAgICBpZiAocGF0aEJbcGF0aEIubGVuZ3RoIC0gMV0gIT09ICcnKSBwYXRoQS5wb3AoKTsgXG4gICAgcmV0dXJuIHBhdGhBLmpvaW4oJy8nKTtcbiAgfVxuXG4gIHZhciBpID0gMDtcbiAgdmFyIHBhdGg7XG4gIHZhciByID0gbG9jYXRpb24ucGF0aG5hbWU7XG5cbiAgY29uc3QgdXJsUmVnZXggPSAvXmh0dHBzP1xcOlxcL1xcLyhbXlxcLz8jXSspKD86W1xcLz8jXXwkKS9pO1xuICBjb25zdCBtdWx0aVNsYXNoUmVnID0gL1xcL1xcLysvZztcblxuICB3aGlsZSAodHlwZW9mIChwYXRoID0gcGF0aHNbaV0pID09PSAnc3RyaW5nJykge1xuICAgIGRlYnVnZ2VyO1xuICAgIGNvbnN0IG1hdGNoZXMgPSBwYXRoICYmIHBhdGgubWF0Y2godXJsUmVnZXgpO1xuICAgIGlmIChtYXRjaGVzIHx8ICFpKSB7XG4gICAgICByID0gcGF0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0aCA9IHBhdGgucmVwbGFjZShtdWx0aVNsYXNoUmVnLCAnLycpO1xuICAgICAgciA9IHJlc29sdmUociwgcGF0aCk7XG4gICAgfVxuICAgIGkrKztcbiAgfVxuXG4gIHJldHVybiByO1xufTsiLCJkZWNsYXJlIHZhciBhbmd1bGFyOiBhbmd1bGFyLklBbmd1bGFyU3RhdGljO1xuXG5pbXBvcnQgKiBhcyBtYXJrZWQgZnJvbSBcIi4vbGliL21hcmtlZFwiOyAgXG5cbmltcG9ydCBcIi4vaGVscC50cmVlXCI7XG5pbXBvcnQgXCIuL2hlbHAuc2VydmljZVwiO1xuXG5pbXBvcnQgeyBJSGVscFNlcnZpY2UgLCBUb2NOb2RlQ29sbGVjdGlvbiB9IGZyb20gXCIuL2hlbHAuc2VydmljZVwiO1xuaW1wb3J0IHsgcmVzb2x2ZVBhdGggfSBmcm9tICcuL2hlbHAudXRpbGl0aWVzJztcbmltcG9ydCB7IE5vZGUgfSBmcm9tICBcIi4vaGVscC50cmVlXCI7XG5cbmxldCBjdXJyZW50UGF0aCA9ICcvaGVscCc7XG5sZXQgY3VycmVudERvYyA9ICcnO1xuXG5jb25zdCByZW5kZXJlciA9IG5ldyBtYXJrZWQuUmVuZGVyZXIoKTtcblxucmVuZGVyZXIubGluayA9IChocmVmOiBzdHJpbmcsIHRpdGxlOiBzdHJpbmcsIHRleHQ6IHN0cmluZykgPT4ge1xuICAvLyBjaGVjayBpZiBocmVmIGlzIHJlbCBvciBhYnNcbiAgY29uc3QgYWJzVXJsTWF0Y2ggPSBocmVmLnRyaW0oKS5tYXRjaCgvXmh0dHBzPzpcXC9cXC8vaSk7XG4gIHJldHVybiBgPGEgaHJlZj1cIiR7YWJzVXJsTWF0Y2ggPyBocmVmIDogcmVzb2x2ZVBhdGgoJyMvaGVscC8nLCBjdXJyZW50RG9jLCBocmVmKX1cIiB0aXRsZT1cIiR7dGl0bGV9XCIgPiR7dGV4dH08L2E+YFxufTtcblxucmVuZGVyZXIuaW1hZ2UgPSAoaHJlZjogc3RyaW5nLCB0aXRsZTogc3RyaW5nLCB0ZXh0OiBzdHJpbmcpID0+IHtcbiAgcmV0dXJuIGA8aW1nIHNyYz1cIiR7cmVzb2x2ZVBhdGgoY3VycmVudFBhdGgsIGhyZWYpfVwiIGFsdD1cIiR7dGl0bGV9XCIgLz5gXG59O1xuXG5tYXJrZWQuc2V0T3B0aW9ucyh7XG4gIHJlbmRlcmVyOiByZW5kZXJlcixcbiAgZ2ZtOiB0cnVlLFxuICB0YWJsZXM6IHRydWUsXG4gIGJyZWFrczogZmFsc2UsXG4gIHBlZGFudGljOiBmYWxzZSxcbiAgc2FuaXRpemU6IGZhbHNlLFxuICBzbWFydExpc3RzOiB0cnVlLFxuICBzbWFydHlwYW50czogZmFsc2UsXG4gIHhodG1sOiBmYWxzZVxufSk7XG5cbmNvbnN0IGhlbHAgPSBhbmd1bGFyLm1vZHVsZSgnYXBwLmhlbHAnKTtcblxuY29uc3QgSGVscERpcmVjdGl2ZSA9ICgpID0+IHtcblxuICByZXR1cm4ge1xuICAgIHJlc3RyaWN0OiAnQUUnLFxuICAgIHRlbXBsYXRlOiBgPGRpdiBjbGFzcz1cImdsb2JhbC1oZWxwXCIgPjxhIGhyZWY9XCJ7eyAnIy9oZWxwLycrJHNjb3BlLmxpbmsgfX1cIj48aSBjbGFzcz1cImZhIGZhLXF1ZXN0aW9uLWNpcmNsZVwiPjwvaT4gSGVscDwvYT48L2Rpdj5gLFxuICAgIHNjb3BlOiB7XG4gICAgICBsaW5rOiAnQCdcbiAgICB9LFxuICAgIHJlcGxhY2U6IHRydWVcbiAgfTtcbn1cblxuaGVscC5kaXJlY3RpdmUoJ2hlbHAnLCBbSGVscERpcmVjdGl2ZV0pO1xuXG5jb25zdCBNYXJrZG93bkl0RGlyZWN0aXZlID0gKCRzYW5pdGl6ZTogYW5ndWxhci5zYW5pdGl6ZS5JU2FuaXRpemVTZXJ2aWNlKSA9PiB7XG4gIGNvbnN0IGF0dHJpYnV0ZSA9ICdtYXJrZG93bkl0JztcbiAgXG4gIGNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIGNvbnN0IG1kMmh0bWwgPSAobWFya2VkIGluc3RhbmNlb2YgRnVuY3Rpb24pID8gbWFya2VkIDogbWFya2VkLmRlZmF1bHQ7XG4gICAgcmV0dXJuIHZhbHVlXG4gICAgICA/ICRzYW5pdGl6ZShtZDJodG1sKHZhbHVlLnRyaW0oKSkpXG4gICAgICA6ICcnO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgcmVzdHJpY3Q6ICdBRScsXG4gICAgc2NvcGU6IHtcbiAgICAgIG1hcmtkb3duSXQ6ICc9J1xuICAgIH0sXG4gICAgcmVwbGFjZTogdHJ1ZSxcbiAgICBsaW5rOiBmdW5jdGlvbiAoc2NvcGUsIGVsZW1lbnQsIGF0dHJzKSB7XG4gICAgICBpZiAoYXR0cnNbYXR0cmlidXRlXSkge1xuICAgICAgICBzY29wZS4kd2F0Y2goYXR0cmlidXRlLCBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICBlbGVtZW50Lmh0bWwocmVuZGVyKHZhbHVlKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudC5odG1sKHJlbmRlcihlbGVtZW50LnRleHQoKSkpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbn1cblxuaGVscC5kaXJlY3RpdmUoJ21hcmtkb3duSXQnLCBbJyRzYW5pdGl6ZScsIE1hcmtkb3duSXREaXJlY3RpdmVdKTtcblxuaW50ZXJmYWNlIElIZWxwU2NvcGUgZXh0ZW5kcyBhbmd1bGFyLklTY29wZSB7XG4gIHRvYzogVG9jTm9kZUNvbGxlY3Rpb25cbn1cblxuY29uc3QgbWFwTm9kZSA9ICh0b2NOb2RlOiBUb2NOb2RlQ29sbGVjdGlvbik6IE5vZGVbXSA9PiB7XG4gIHJldHVybiB0b2NOb2RlICYmIE9iamVjdC5rZXlzKHRvY05vZGUpLm1hcChrZXkgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICAuLi50b2NOb2RlW2tleV0sXG4gICAgICBocmVmOiBgIy9oZWxwLyR7dG9jTm9kZVtrZXldWyd2ZXJzaW9ucyddWydjdXJyZW50J11bJ3BhdGgnXX1gLFxuICAgICAgbm9kZXM6IG1hcE5vZGUodG9jTm9kZVtrZXldLm5vZGVzKVxuICAgIH07XG4gIH0pO1xufTtcblxuY2xhc3MgSGVscENvbnRyb2xsZXIge1xuICBwcml2YXRlIF9jb250ZW50ID0gXCIjIyBMb2FkaW5nXCI7XG4gIHByaXZhdGUgX3BhdGggPSAnJztcbiAgcHJpdmF0ZSBfdG9jIDogTm9kZSA9IHsgfTsgXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSAkc2NvcGU6IElIZWxwU2NvcGUsIHByaXZhdGUgJHN0YXRlLCBwcml2YXRlICR0aW1lb3V0OiBhbmd1bGFyLklUaW1lb3V0U2VydmljZSwgcHJpdmF0ZSBoZWxwU2VydmljZTogSUhlbHBTZXJ2aWNlKSB7XG4gIFxuICAgIGhlbHBTZXJ2aWNlLmdldFRhYmxlT2ZDb250ZW50cygpLnRoZW4odG9jID0+IHtcbiAgICAgIHRoaXMuX3RvYyA9IHsgbm9kZXM6IG1hcE5vZGUodG9jKSB9IDtcbiAgICAgIGlmICghJHN0YXRlLnBhcmFtcy5wYXRoKSB7XG4gICAgICAgICRzdGF0ZS5nbygnbWFpbi5oZWxwJywgeyBwYXRoOiB0b2NbJ29wZW5kYXlsaWdodCddWyd2ZXJzaW9ucyddWydjdXJyZW50J11bJ3BhdGgnXSB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5uYXZpZ2F0ZVRvKCRzdGF0ZS5wYXJhbXMucGF0aCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGNvbnRlbnQoKSB7IHJldHVybiB0aGlzLl9jb250ZW50OyB9XG4gIHB1YmxpYyBnZXQgcGF0aCgpIHsgcmV0dXJuIHRoaXMuX3BhdGg7IH1cbiAgcHVibGljIGdldCB0b2MoKSB7IHJldHVybiB0aGlzLl90b2M7IH1cblxuICBwcml2YXRlIG5hdmlnYXRlVG8ocGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5oZWxwU2VydmljZS5nZXREb2N1bWVudChwYXRoKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgIGN1cnJlbnREb2MgPSBwYXRoO1xuICAgICAgY3VycmVudFBhdGggPSByZXN1bHQuYmFzZVBhdGg7XG4gICAgICB0aGlzLl9jb250ZW50ID0gcmVzdWx0LmRvY3VtZW50O1xuICAgIH0pO1xuICB9XG5cbn1cblxuaGVscC5jb250cm9sbGVyKCdoZWxwQ3RybCcsIFsnJHNjb3BlJywgJyRzdGF0ZScsICckdGltZW91dCcsICdoZWxwU2VydmljZScsIEhlbHBDb250cm9sbGVyIF0pOyJdfQ==
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.controller.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.controller.ts new file mode 100644 index 00000000..5a12bbfe --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.controller.ts @@ -0,0 +1,130 @@ +declare var angular: angular.IAngularStatic; + +import * as marked from "./lib/marked"; + +import "./help.tree"; +import "./help.service"; + +import { IHelpService , TocNodeCollection } from "./help.service"; +import { resolvePath } from './help.utilities'; +import { Node } from "./help.tree"; + +let currentPath = '/help'; +let currentDoc = ''; + +const renderer = new marked.Renderer(); + +renderer.link = (href: string, title: string, text: string) => { + // check if href is rel or abs + const absUrlMatch = href.trim().match(/^https?:\/\//i); + return `<a href="${absUrlMatch ? href : resolvePath('#/help/', currentDoc, href)}" title="${title}" >${text}</a>` +}; + +renderer.image = (href: string, title: string, text: string) => { + return `<img src="${resolvePath(currentPath, href)}" alt="${title}" />` +}; + +marked.setOptions({ + renderer: renderer, + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: true, + smartypants: false, + xhtml: false +}); + +const help = angular.module('app.help'); + +const HelpDirective = () => { + + return { + restrict: 'AE', + template: `<div class="global-help" ><a href="{{ '#/help/'+ link }}"><i class="fa fa-question-circle"></i> Help</a></div>`, + scope: { + link: '@' + }, + replace: true + }; +} + +help.directive('help', [HelpDirective]); + +const MarkdownItDirective = ($sanitize: angular.sanitize.ISanitizeService) => { + const attribute = 'markdownIt'; + + const render = function (value) { + const md2html = (marked instanceof Function) ? marked : marked.default; + return value + ? $sanitize(md2html(value.trim())) + : ''; + }; + + return { + restrict: 'AE', + scope: { + markdownIt: '=' + }, + replace: true, + link: function (scope, element, attrs) { + if (attrs[attribute]) { + scope.$watch(attribute, function (value) { + element.html(render(value)); + }); + } else { + element.html(render(element.text())); + } + } + }; +} + +help.directive('markdownIt', ['$sanitize', MarkdownItDirective]); + +interface IHelpScope extends angular.IScope { + toc: TocNodeCollection +} + +const mapNode = (tocNode: TocNodeCollection): Node[] => { + return tocNode && Object.keys(tocNode).map(key => { + return { + ...tocNode[key], + href: `#/help/${tocNode[key]['versions']['current']['path']}`, + nodes: mapNode(tocNode[key].nodes) + }; + }); +}; + +class HelpController { + private _content = "## Loading"; + private _path = ''; + private _toc : Node = { }; + + constructor(private $scope: IHelpScope, private $state, private $timeout: angular.ITimeoutService, private helpService: IHelpService) { + + helpService.getTableOfContents().then(toc => { + this._toc = { nodes: mapNode(toc) } ; + if (!$state.params.path) { + $state.go('main.help', { path: toc['sdnr']['versions']['current']['path'] }) + } else { + this.navigateTo($state.params.path); + } + }); + } + + public get content() { return this._content; } + public get path() { return this._path; } + public get toc() { return this._toc; } + + private navigateTo(path: string): void { + this.helpService.getDocument(path).then((result) => { + currentDoc = path; + currentPath = result.basePath; + this._content = result.document; + }); + } + +} + +help.controller('helpCtrl', ['$scope', '$state', '$timeout', 'helpService', HelpController ]);
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.custom.css new file mode 100644 index 00000000..d54b5c25 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.custom.css @@ -0,0 +1,105 @@ +.app-help { + color:azure; +} + +.global-help { + float: left; + margin: 5px; + margin-left: 8px; +} + +.app-help th { + padding: 3px; + border-bottom: #eeeeee solid 1px; +} + +.app-help td { + padding: 2px; +} + +.app-help tbody { + padding: 2px; + border-bottom: #eeeeee solid 1px; + margin-bottom: 20px; +} + +.app-help .toc { + padding-left: 0; + padding-top: 25px; + max-width: 170px; +} + +.app-help a[href^="http://"]:after { + content: "\f08e"; + display: inline-block; + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + text-decoration: none; + padding-left: 3px; +} + +.app-help a[href^="https://"]:after { + content: "\f08e"; + display: inline-block; + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + text-decoration: none; + padding-left: 3px; +} + +.app-help a, .global-help a { + color:azure; + text-decoration: none; +} + +.app-help a:visited, .global-help a:visited { + color:azure; + text-decoration: none; +} + +.app-help a:hover, .global-help a:hover { + color:bisque; +} + +.app-help .toc ul { + margin: 0; + padding: 0; + list-style: none; + border: none; + overflow: hidden; +} + +.app-help .toc li { + line-height: 1.5em; + position: relative; + padding: 0 0 0 20px; +} + +.app-help .toc > tree > ul > li { + padding: 0 +} + +.app-help .toc li a { + color:azure; + text-decoration: none; +} + +.app-help .toc li a:visited { + color:azure; + text-decoration: none; +} + +.app-help .toc li a:hover { + color:bisque; + text-decoration: none; +} + +.app-help > .help { + color:azure; +} + +.app-help > .help img { + width: 100% +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.module.js new file mode 100644 index 00000000..71d43be9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.module.js @@ -0,0 +1,33 @@ +define( ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.help = angular.module('app.help', ['app.core']); + exports.help.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + //$translatePartialLoaderProvider.addPart('app/help/locale/locale'); + NavHelperProvider.addControllerUrl('app/help/help.controller'); + NavHelperProvider.addToMenu('help', { + "link": "#/help/", + "active": "main.help", + "title": "Help", + "icon": "fa fa-question-circle", + "page": { + "title": "Help", + "description": "help" + } + }); + $stateProvider.state('main.help', { + url: 'help/*path', + access: 2, + views: { + 'content': { + templateUrl: 'src/app/help/help.tpl.html', + controller: 'helpCtrl as vm' + } + } + }); + }); +}); +/* non ES6 export */ +// export = help; +// export default help; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscC5tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzcmMvYXBwL2hlbHAvaGVscC5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0lBRWEsUUFBQSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBRTdELFlBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLGFBQWEsRUFBRSxrQkFBa0IsRUFBRSwrQkFBK0I7UUFFMUssb0VBQW9FO1FBRXBFLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDL0QsaUJBQWlCLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRTtZQUNsQyxNQUFNLEVBQUUsU0FBUztZQUNqQixRQUFRLEVBQUUsV0FBVztZQUNyQixPQUFPLEVBQUUsTUFBTTtZQUNmLE1BQU0sRUFBRSx1QkFBdUI7WUFDL0IsTUFBTSxFQUFFO2dCQUNOLE9BQU8sRUFBRSxXQUFXO2dCQUNwQixhQUFhLEVBQUUsTUFBTTthQUN0QjtTQUNGLENBQUMsQ0FBQztRQUVILGNBQWMsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFO1lBQ2hDLEdBQUcsRUFBRSxZQUFZO1lBQ2pCLE1BQU0sRUFBRSxDQUFDO1lBQ1QsS0FBSyxFQUFFO2dCQUNMLFNBQVMsRUFBRTtvQkFDVCxXQUFXLEVBQUUsNEJBQTRCO29CQUN6QyxVQUFVLEVBQUUsZ0JBQWdCO2lCQUM3QjthQUNGO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7O0FBRUgsb0JBQW9CO0FBQ3BCLG9CQUFvQjtBQUNwQix1QkFBdUIiLCJzb3VyY2VzQ29udGVudCI6WyJkZWNsYXJlIHZhciBhbmd1bGFyOiBhbmd1bGFyLklBbmd1bGFyU3RhdGljO1xuXG5leHBvcnQgY29uc3QgaGVscCA9IGFuZ3VsYXIubW9kdWxlKCdhcHAuaGVscCcsIFsnYXBwLmNvcmUnXSk7XG5cbmhlbHAuY29uZmlnKGZ1bmN0aW9uICgkc3RhdGVQcm92aWRlciwgJGNvbXBpbGVQcm92aWRlciwgJGNvbnRyb2xsZXJQcm92aWRlciwgJHByb3ZpZGUsIE5hdkhlbHBlclByb3ZpZGVyLCAkaHR0cFByb3ZpZGVyLCAkdHJhbnNsYXRlUHJvdmlkZXIsICR0cmFuc2xhdGVQYXJ0aWFsTG9hZGVyUHJvdmlkZXIpIHtcblxuICAvLyR0cmFuc2xhdGVQYXJ0aWFsTG9hZGVyUHJvdmlkZXIuYWRkUGFydCgnYXBwL2hlbHAvbG9jYWxlL2xvY2FsZScpO1xuXG4gIE5hdkhlbHBlclByb3ZpZGVyLmFkZENvbnRyb2xsZXJVcmwoJ2FwcC9oZWxwL2hlbHAuY29udHJvbGxlcicpO1xuICBOYXZIZWxwZXJQcm92aWRlci5hZGRUb01lbnUoJ2hlbHAnLCB7XG4gICAgXCJsaW5rXCI6IFwiIy9oZWxwL1wiLFxuICAgIFwiYWN0aXZlXCI6IFwibWFpbi5oZWxwXCIsXG4gICAgXCJ0aXRsZVwiOiBcIkhlbHBcIixcbiAgICBcImljb25cIjogXCJmYSBmYS1xdWVzdGlvbi1jaXJjbGVcIiwgIC8vIEFkZCBuYXZpZ2F0aW9uIGljb24gY3NzIGNsYXNzIGhlcmVcbiAgICBcInBhZ2VcIjoge1xuICAgICAgXCJ0aXRsZVwiOiBcIk1XVE4gRGVtb1wiLFxuICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImhlbHBcIlxuICAgIH1cbiAgfSk7XG5cbiAgJHN0YXRlUHJvdmlkZXIuc3RhdGUoJ21haW4uaGVscCcsIHtcbiAgICB1cmw6ICdoZWxwLypwYXRoJyxcbiAgICBhY2Nlc3M6IDIsXG4gICAgdmlld3M6IHtcbiAgICAgICdjb250ZW50Jzoge1xuICAgICAgICB0ZW1wbGF0ZVVybDogJ3NyYy9hcHAvaGVscC9oZWxwLnRwbC5odG1sJyxcbiAgICAgICAgY29udHJvbGxlcjogJ2hlbHBDdHJsIGFzIHZtJ1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59KTtcblxuLyogbm9uIEVTNiBleHBvcnQgKi9cbi8vIGV4cG9ydCA9IGhlbHA7ICAgXG4vLyBleHBvcnQgZGVmYXVsdCBoZWxwOyJdfQ== diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.module.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.module.ts new file mode 100644 index 00000000..d3acc645 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.module.ts @@ -0,0 +1,35 @@ +declare var angular: angular.IAngularStatic; + +export const help = angular.module('app.help', ['app.core']); + +help.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + + //$translatePartialLoaderProvider.addPart('app/help/locale/locale'); + + NavHelperProvider.addControllerUrl('app/help/help.controller'); + NavHelperProvider.addToMenu('help', { + "link": "#/help/", + "active": "main.help", + "title": "Help", + "icon": "fa fa-question-circle", // Add navigation icon css class here + "page": { + "title": "MWTN Demo", + "description": "help" + } + }); + + $stateProvider.state('main.help', { + url: 'help/*path', + access: 2, + views: { + 'content': { + templateUrl: 'src/app/help/help.tpl.html', + controller: 'helpCtrl as vm' + } + } + }); +}); + +/* non ES6 export */ +// export = help; +// export default help;
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.service.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.service.ts new file mode 100644 index 00000000..f09ec7b7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.service.ts @@ -0,0 +1,92 @@ +import * as angular from 'angularAMD'; + +const help = angular.module('app.help'); + +export interface VersionInfo { + label: string, + path: string, + date: string +} + +export interface TocNode { + label: string; + versions: { + [versionKey: string]: VersionInfo + }; + nodes?: TocNodeCollection; +} + +export type TocNodeCollection = { [tocNodeKey: string]: TocNode }; + + +interface IEnv { + getBaseURL: (salType: 'AD_SAL' | 'MD_SAL') => string; +} + +/** Represents a service used for the help application. */ +export interface IHelpService { + + /** + * Queries the table of contents for a specific version. + * @param version The version the table of contents shall be requested for. + * @returns A Promise containing the requested table of contents. + * + */ + getTableOfContents(version?: string): angular.IPromise<TocNodeCollection>; + + /** + * Get a specitic document by its path. + * @param path The path of the document to get. + * @returns A Promise containing the requested document. + * + */ + getDocument(path: string): angular.IPromise<{ basePath: string, document: string }>; +} + +class Helpservice implements IHelpService { + + private tocNodeCollection: TocNodeCollection; + private documents: { [path: string]: { basePath: string, document: string } }; + + constructor(private $q: angular.IQService, private $http: angular.IHttpService, private env: IEnv) { + this.tocNodeCollection = null; + this.documents = {}; + } + + public getTableOfContents(): angular.IPromise<TocNodeCollection> { + if (this.tocNodeCollection) { + return this.$q.resolve(this.tocNodeCollection); + } + + return this.$http({ + method: "GET", + url: `${this.env.getBaseURL('MD_SAL')}/help/?meta` + }).then((result: angular.IHttpResponse<TocNodeCollection>) => { + if (result.status === 200) { + this.tocNodeCollection = result.data; + return result.data; + } + }); + } + + public getDocument(path: string): angular.IPromise<{basePath: string, document: string}> { + if (this.documents[path] != null) { + return this.$q.resolve(this.documents[path]); + } + + return this.$http({ + method: "GET", + url: `${this.env.getBaseURL('MD_SAL')}/help/${path}` + }).then((result: angular.IHttpResponse<string>) => { + if (result.status === 200) { + return this.documents[path] = { + basePath: result.config && result.config.url && result.config.url, + document: result.data + }; + } + }); + + } +} + +help.service('helpService', ['$q', '$http', 'ENV', Helpservice]);
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tpl.html new file mode 100644 index 00000000..6c2970c8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tpl.html @@ -0,0 +1,17 @@ +<ht-header help-link='sdnr/0.4.0/README.md'></ht-header> + +<div class="app-help"> + + <div class="toc col-sm-12 col-md-2"> + <tree root-node= "vm.toc" > + <a href="{{rootNode.href}}" >{{ rootNode.label }}</a> + </tree> + </div> + + <div markdown-it="vm.content" class="help col-sm-12 col-md-10" ></div> + +</div> +<hr class="col-sm-12"/> +<div class="owl col-sm-12"> + <span class="white">ONAP SDN-R | ONF Wireless - Build: @buildtime@</span> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tree.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tree.html new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tree.html diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tree.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tree.ts new file mode 100644 index 00000000..3d142804 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.tree.ts @@ -0,0 +1,55 @@ +import * as angular from 'angularAMD'; + +export interface Node { + label?: string, + nodes?: Node[], + versions?: { + [version: string]: { + label: string, + date: string, + path: string + } + } +} + +const help = angular.module('app.help'); + +// class HelpTreeController implements ng.IController { +// constructor(private $scope: ng.IScope & { rootNode: Node, data: Node[]}) { +// $scope.$watch("rootNode", (n, o) => { +// $scope.data = Object.keys($scope.rootNode).map(key => $scope.rootNode[key]); +// }); +// } +// } + +// help.controller("treeCtrl", ["$scope", HelpTreeController]); + +const helpTree = function ($compile) { + return { + restrict: "E", + transclude: true, + scope: { rootNode: '=' }, + //controller: 'treeCtrl', + template: + '<ul>' + + '<li ng-transclude></li>' + + '<li ng-repeat="child in rootNode.nodes">' + + '<tree root-node="child"><div ng-transclude></div></tree>' + + '</li>' + + '</ul>', + compile: function (tElement, tAttr, transclude) { + var contents = tElement.contents().remove(); + var compiledContents; + return function (scope, iElement, iAttr) { + if (!compiledContents) { + compiledContents = $compile(contents, transclude); + } + compiledContents(scope, function (clone, scope) { + iElement.append(clone); + }); + }; + } + }; +}; + +help.directive("tree", ["$compile", helpTree]);
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.utilities.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.utilities.ts new file mode 100644 index 00000000..ec34b624 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/help.utilities.ts @@ -0,0 +1,63 @@ +export var resolvePath = function (...paths: string[]): string { + console.log(paths); + function resolve(pathA, pathB) { + // ‘a’ => ['a'] + // 'a/b' => ['a', 'b'] + // '/a/b' => ['', 'a', 'b'] + // '/a/b/' => ['', 'a', 'b', ''] + pathB = pathB.split('/'); + if (pathB[0] === '') { + return pathB.join('/'); + } + pathA = pathA.split('/'); + var aLastIndex = pathA.length - 1; + if (pathA[aLastIndex] !== '') { + pathA[aLastIndex] = ''; + } + + var part; + var i = 0; + while (typeof (part = pathB[i]) === 'string') { + switch (part) { + case '..': + pathA.pop(); + pathA.pop(); + pathA.push(''); + break; + case '.': + pathA.pop(); + pathA.push(''); + break; + default: + pathA.pop(); + pathA.push(part); + pathA.push(''); + break; + } + i++; + } + if (pathB[pathB.length - 1] !== '') pathA.pop(); + return pathA.join('/'); + } + + var i = 0; + var path; + var r = location.pathname; + + const urlRegex = /^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i; + const multiSlashReg = /\/\/+/g; + + while (typeof (path = paths[i]) === 'string') { + // debugger; + const matches = path && path.match(urlRegex); + if (matches || !i) { + r = path; + } else { + path = path.replace(multiSlashReg, '/'); + r = resolve(r, path); + } + i++; + } + + return r; +};
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/images/help.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/images/help.png Binary files differnew file mode 100755 index 00000000..5ca1f1cc --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/images/help.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/lib/marked.d.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/lib/marked.d.ts new file mode 100644 index 00000000..74a11ae8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/lib/marked.d.ts @@ -0,0 +1,284 @@ +// Type definitions for Marked 0.3 +// Project: https://github.com/chjj/marked +// Definitions by: William Orr <https://github.com/worr> +// BendingBender <https://github.com/BendingBender> +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare var marked : marked.markedStatic; + +export as namespace marked; + +export = marked; + +declare namespace marked { + /** + * Compiles markdown to HTML. + * + * @param src String of markdown source to be compiled + * @param callback Function called when the markdownString has been fully parsed when using async highlighting + * @return String of compiled HTML + */ + function markedStatic(src: string, callback: (error: any | undefined, parseResult: string) => void): string; + + /** + * Compiles markdown to HTML. + * + * @param src String of markdown source to be compiled + * @param options Hash of options + * @param callback Function called when the markdownString has been fully parsed when using async highlighting + * @return String of compiled HTML + */ + function markedStatic(src: string, options?: marked.MarkedOptions, callback?: (error: any | undefined, parseResult: string) => void): string; + + /** + * @param src String of markdown source to be compiled + * @param options Hash of options + */ + function lexer(src: string, options?: MarkedOptions): TokensList; + + /** + * Compiles markdown to HTML. + * + * @param src String of markdown source to be compiled + * @param callback Function called when the markdownString has been fully parsed when using async highlighting + * @return String of compiled HTML + */ + function parse(src: string, callback: (error: any | undefined, parseResult: string) => void): string; + + /** + * Compiles markdown to HTML. + * + * @param src String of markdown source to be compiled + * @param options Hash of options + * @param callback Function called when the markdownString has been fully parsed when using async highlighting + * @return String of compiled HTML + */ + function parse(src: string, options?: MarkedOptions, callback?: (error: any | undefined, parseResult: string) => void): string; + + /** + * @param src Tokenized source as array of tokens + * @param options Hash of options + */ + function parser(src: TokensList, options?: MarkedOptions): string; + + /** + * Sets the default options. + * + * @param options Hash of options + */ + function setOptions(options: MarkedOptions): typeof marked; + + class Renderer { + constructor(options?: MarkedOptions); + code(code: string, language: string, isEscaped: boolean): string; + blockquote(quote: string): string; + html(html: string): string; + heading(text: string, level: number, raw: string): string; + hr(): string; + list(body: string, ordered: boolean): string; + listitem(text: string): string; + paragraph(text: string): string; + table(header: string, body: string): string; + tablerow(content: string): string; + tablecell(content: string, flags: { + header: boolean; + align: 'center' | 'left' | 'right' | null; + }): string; + strong(text: string): string; + em(text: string): string; + codespan(code: string): string; + br(): string; + del(text: string): string; + link(href: string, title: string, text: string): string; + image(href: string, title: string, text: string): string; + text(text: string): string; + } + + class Lexer { + rules: Rules; + tokens: TokensList; + constructor(options?: MarkedOptions); + lex(src: string): TokensList; + } + + interface Rules { + [ruleName: string]: RegExp | Rules; + } + + type TokensList = Token[] & { + links: { + [key: string]: { href: string; title: string; } + } + }; + + type Token = + Tokens.Space + | Tokens.Code + | Tokens.Heading + | Tokens.Table + | Tokens.Hr + | Tokens.BlockquoteStart + | Tokens.BlockquoteEnd + | Tokens.ListStart + | Tokens.LooseItemStart + | Tokens.ListItemStart + | Tokens.ListItemEnd + | Tokens.ListEnd + | Tokens.Paragraph + | Tokens.HTML + | Tokens.Text; + + namespace Tokens { + interface Space { + type: 'space'; + } + + interface Code { + type: 'code'; + lang?: string; + text: string; + } + + interface Heading { + type: 'heading'; + depth: number; + text: string; + } + + interface Table { + type: 'table'; + header: string[]; + align: Array<'center' | 'left' | 'right' | null>; + cells: string[][]; + } + + interface Hr { + type: 'hr'; + } + + interface BlockquoteStart { + type: 'blockquote_start'; + } + + interface BlockquoteEnd { + type: 'blockquote_end'; + } + + interface ListStart { + type: 'list_start'; + ordered: boolean; + } + + interface LooseItemStart { + type: 'loose_item_start'; + } + + interface ListItemStart { + type: 'list_item_start'; + } + + interface ListItemEnd { + type: 'list_item_end'; + } + + interface ListEnd { + type: 'list_end'; + } + + interface Paragraph { + type: 'paragraph'; + pre?: boolean; + text: string; + } + + interface HTML { + type: 'html'; + pre: boolean; + text: string; + } + + interface Text { + type: 'text'; + text: string; + } + } + + interface MarkedOptions { + /** + * Type: object Default: new Renderer() + * + * An object containing functions to render tokens to HTML. + */ + renderer?: Renderer; + + /** + * Enable GitHub flavored markdown. + */ + gfm?: boolean; + + /** + * Enable GFM tables. This option requires the gfm option to be true. + */ + tables?: boolean; + + /** + * Enable GFM line breaks. This option requires the gfm option to be true. + */ + breaks?: boolean; + + /** + * Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior. + */ + pedantic?: boolean; + + /** + * Sanitize the output. Ignore any HTML that has been input. + */ + sanitize?: boolean; + + /** + * Optionally sanitize found HTML with a sanitizer function. + */ + sanitizer?(html: string): string; + + /** + * Mangle autolinks (<email@domain.com>). + */ + mangle?: boolean; + + /** + * Use smarter list behavior than the original markdown. May eventually be default with the old behavior moved into pedantic. + */ + smartLists?: boolean; + + /** + * Shows an HTML error message when rendering fails. + */ + silent?: boolean; + + /** + * A function to highlight code blocks. The function takes three arguments: code, lang, and callback. + */ + highlight?(code: string, lang: string, callback?: (error: any | undefined, code: string) => void): string; + + /** + * Set the prefix for code block classes. + */ + langPrefix?: string; + + /** + * Use "smart" typograhic punctuation for things like quotes and dashes. + */ + smartypants?: boolean; + + /** + * Set the prefix for header tag ids. + */ + headerPrefix?: string; + + /** + * Generate closing slash for self-closing tags (<br/> instead of <br>) + */ + xhtml?: boolean; + } +} diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/lib/marked.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/lib/marked.js new file mode 100644 index 00000000..04386a6c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/help-module/src/main/resources/help/lib/marked.js @@ -0,0 +1,1320 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +; (function () { + 'use strict'; + + /** + * Block-Level Grammar + */ + + var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^( *[-*_]){3,} *(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + table: noop, + paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, + text: /^[^\n]+/ + }; + + block.bullet = /(?:[*+-]|\d+\.)/; + block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; + block.item = replace(block.item, 'gm') + (/bull/g, block.bullet) + (); + + block.list = replace(block.list) + (/bull/g, block.bullet) + ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') + ('def', '\\n+(?=' + block.def.source + ')') + (); + + block.blockquote = replace(block.blockquote) + ('def', block.def) + (); + + block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; + + block.html = replace(block.html) + ('comment', /<!--[\s\S]*?-->/) + ('closed', /<(tag)[\s\S]+?<\/\1>/) + ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/) + (/tag/g, block._tag) + (); + + block.paragraph = replace(block.paragraph) + ('hr', block.hr) + ('heading', block.heading) + ('lheading', block.lheading) + ('blockquote', block.blockquote) + ('tag', '<' + block._tag) + ('def', block.def) + (); + + /** + * Normal Block Grammar + */ + + block.normal = merge({}, block); + + /** + * GFM Block Grammar + */ + + block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ + }); + + block.gfm.paragraph = replace(block.paragraph) + ('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + (); + + /** + * GFM + Tables Block Grammar + */ + + block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ + }); + + /** + * Block Lexer + */ + + function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } + } + + /** + * Expose Block Rules + */ + + Lexer.rules = block; + + /** + * Static Lex Method + */ + + Lexer.lex = function (src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); + }; + + /** + * Preprocessing + */ + + Lexer.prototype.lex = function (src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); + }; + + /** + * Lexing + */ + + Lexer.prototype.token = function (src, top, bq) { + var src = src.replace(/^ +$/gm, '') + , next + , loose + , cap + , bull + , b + , item + , space + , i + , l; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] || '' + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top, true); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + + this.tokens.push({ + type: 'list_start', + ordered: bull.length > 1 + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1]) [0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); + + // Recurse. + this.token(item, false, bq); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }); + continue; + } + + // def + if ((!bq && top) && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.links[cap[1].toLowerCase()] = { + href: cap[2], + title: cap[3] + }; + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; + }; + + /** + * Inline-Level Grammar + */ + + var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<([^ <>]+(@|:\/)[^ <>]+)>/, + url: noop, + tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^<'">])*?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + code: /^(`+)([\s\S]*?[^`])\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/ + }; + + inline._inside = /(?:\[[^\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/; + inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/; + + inline.link = replace(inline.link) + ('inside', inline._inside) + ('href', inline._href) + (); + + inline.reflink = replace(inline.reflink) + ('inside', inline._inside) + (); + + /** + * Normal Inline Grammar + */ + + inline.normal = merge({}, inline); + + /** + * Pedantic Inline Grammar + */ + + inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ + }); + + /** + * GFM Inline Grammar + */ + + inline.gfm = merge({}, inline.normal, { + escape: replace(inline.escape)('])', '~|])')(), + url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: replace(inline.text) + (']|', '~]|') + ('|', '|https?://|') + () + }); + + /** + * GFM + Line Breaks Inline Grammar + */ + + inline.breaks = merge({}, inline.gfm, { + br: replace(inline.br)('{2,}', '*')(), + text: replace(inline.gfm.text)('{2,}', '*')() + }); + + /** + * Inline Lexer & Compiler + */ + + function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer; + this.renderer.options = this.options; + + if (!this.links) { + throw new + Error('Tokens array requires a `links` property.'); + } + + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; + } + } + + /** + * Expose Inline Rules + */ + + InlineLexer.rules = inline; + + /** + * Static Lexing/Compiling Method + */ + + InlineLexer.output = function (src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); + }; + + /** + * Lexing/Compiling + */ + + InlineLexer.prototype.output = function (src) { + var out = '' + , link + , text + , href + , cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape( + cap[1].charAt(6) === ':' + ? this.mangle(cap[1].substring(7)) + : this.mangle(cap[1]) + ); + href = this.mangle('mailto:') + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + src = src.substring(cap[0].length); + text = escape(cap[1]); + href = text; + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^<a /i.test(cap[0])) { + this.inLink = true; + } else if (this.inLink && /^<\/a>/i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0] + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2].trim(), true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.text(escape(this.smartypants(cap[0]))); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; + }; + + /** + * Compile Link + */ + + InlineLexer.prototype.outputLink = function (cap, link) { + var href = escape(link.href) + , title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); + }; + + /** + * Smartypants Transformations + */ + + InlineLexer.prototype.smartypants = function (text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); + }; + + /** + * Mangle Links + */ + + InlineLexer.prototype.mangle = function (text) { + if (!this.options.mangle) return text; + var out = '' + , l = text.length + , i = 0 + , ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; + }; + + /** + * Renderer + */ + + function Renderer(options) { + this.options = options || {}; + } + + Renderer.prototype.code = function (code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '<pre><code>' + + (escaped ? code : escape(code, true)) + + '\n</code></pre>'; + } + + return '<pre><code class="' + + this.options.langPrefix + + escape(lang, true) + + '">' + + (escaped ? code : escape(code, true)) + + '\n</code></pre>\n'; + }; + + Renderer.prototype.blockquote = function (quote) { + return '<blockquote>\n' + quote + '</blockquote>\n'; + }; + + Renderer.prototype.html = function (html) { + return html; + }; + + Renderer.prototype.heading = function (text, level, raw) { + return '<h' + + level + + ' id="' + + this.options.headerPrefix + + raw.toLowerCase().replace(/[^\w]+/g, '-') + + '">' + + text + + '</h' + + level + + '>\n'; + }; + + Renderer.prototype.hr = function () { + return this.options.xhtml ? '<hr/>\n' : '<hr>\n'; + }; + + Renderer.prototype.list = function (body, ordered) { + var type = ordered ? 'ol' : 'ul'; + return '<' + type + '>\n' + body + '</' + type + '>\n'; + }; + + Renderer.prototype.listitem = function (text) { + return '<li>' + text + '</li>\n'; + }; + + Renderer.prototype.paragraph = function (text) { + return '<p>' + text + '</p>\n'; + }; + + Renderer.prototype.table = function (header, body) { + return '<table>\n' + + '<thead>\n' + + header + + '</thead>\n' + + '<tbody>\n' + + body + + '</tbody>\n' + + '</table>\n'; + }; + + Renderer.prototype.tablerow = function (content) { + return '<tr>\n' + content + '</tr>\n'; + }; + + Renderer.prototype.tablecell = function (content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '</' + type + '>\n'; + }; + + // span level renderer + Renderer.prototype.strong = function (text) { + return '<strong>' + text + '</strong>'; + }; + + Renderer.prototype.em = function (text) { + return '<em>' + text + '</em>'; + }; + + Renderer.prototype.codespan = function (text) { + return '<code>' + text + '</code>'; + }; + + Renderer.prototype.br = function () { + return this.options.xhtml ? '<br/>' : '<br>'; + }; + + Renderer.prototype.del = function (text) { + return '<del>' + text + '</del>'; + }; + + Renderer.prototype.link = function (href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return text; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return text; + } + } + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '<a href="' + href + '"'; + if (title) { + out += ' title="' + title + '"'; + } + out += '>' + text + '</a>'; + return out; + }; + + Renderer.prototype.image = function (href, title, text) { + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '<img src="' + href + '" alt="' + text + '"'; + if (title) { + out += ' title="' + title + '"'; + } + out += this.options.xhtml ? '/>' : '>'; + return out; + }; + + Renderer.prototype.text = function (text) { + return text; + }; + + /** + * Parsing & Compiling + */ + + function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer; + this.renderer = this.options.renderer; + this.renderer.options = this.options; + } + + /** + * Static Parse Method + */ + + Parser.parse = function (src, options, renderer) { + var parser = new Parser(options, renderer); + return parser.parse(src); + }; + + /** + * Parse Loop + */ + + Parser.prototype.parse = function (src) { + this.inline = new InlineLexer(src.links, this.options, this.renderer); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; + }; + + /** + * Next Token + */ + + Parser.prototype.next = function () { + return this.token = this.tokens.pop(); + }; + + /** + * Preview Next Token + */ + + Parser.prototype.peek = function () { + return this.tokens[this.tokens.length - 1] || 0; + }; + + /** + * Parse Text Tokens + */ + + Parser.prototype.parseText = function () { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); + }; + + /** + * Parse Current Token + */ + + Parser.prototype.tok = function () { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + this.token.text); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '' + , body = '' + , i + , row + , cell + , flags + , j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + flags = { header: true, align: this.token.align[i] }; + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + var body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + var body = '' + , ordered = this.token.ordered; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered); + } + case 'list_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } + }; + + /** + * Helpers + */ + + function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function (_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); + } + + function replace(regex, opt) { + regex = regex.source; + opt = opt || ''; + return function self(name, val) { + if (!name) return new RegExp(regex, opt); + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return self; + }; + } + + function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (/^[^:]+:\/*[^/]*$/.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = base.replace(/[^/]*$/, ''); + } + } + base = baseUrls[' ' + base]; + + if (href.slice(0, 2) === '//') { + return base.replace(/:[\s\S]*/, ':') + href; + } else if (href.charAt(0) === '/') { + return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; + } else { + return base + href; + } + } + var baseUrls = {}; + var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + + function noop() { } + noop.exec = noop; + + function merge(obj) { + var i = 1 + , target + , key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; + } + + + /** + * Marked + */ + + function marked(src, opt, callback) { + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight + , tokens + , pending + , i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function (err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function (token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function (err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/chjj/marked.'; + if ((opt || marked.defaults).silent) { + return '<p>An error occurred:</p><pre>' + + escape(e.message + '', true) + + '</pre>'; + } + throw e; + } + } + + /** + * Options + */ + + marked.options = + marked.setOptions = function (opt) { + merge(marked.defaults, opt); + return marked; + }; + + marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + sanitizer: null, + mangle: true, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer, + xhtml: false, + baseUrl: null + }; + + /** + * Expose + */ + + marked.Parser = Parser; + marked.parser = Parser.parse; + + marked.Renderer = Renderer; + + marked.Lexer = Lexer; + marked.lexer = Lexer.lex; + + marked.InlineLexer = InlineLexer; + marked.inlineLexer = InlineLexer.output; + + marked.parse = marked; + + if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; + } else if (typeof define === 'function' && define.amd) { + define(function () { return marked; }); + } else { + this.marked = marked; + } + +}).call(function () { + return this || (typeof window !== 'undefined' ? window : global); +}());
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/help/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/pom.xml new file mode 100644 index 00000000..91fc77bb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/help/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>help</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>help-module</module> + <module>help-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-bundle/pom.xml new file mode 100644 index 00000000..7499a987 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnBrowser</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnBrowser-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnBrowser-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnBrowser-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..383b124b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnBrowser"/> + <property name="url" value="/src/app/mwtnBrowser"/> + <property name="directory" value="/mwtnBrowser"/> + <property name="requireJs" value="app/mwtnBrowser/mwtnBrowser.module"/> + <property name="angularJs" value="app.mwtnBrowser"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnBrowser/mwtnBrowser-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/pom.xml new file mode 100644 index 00000000..7c33ed89 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/pom.xml @@ -0,0 +1,14 @@ +<?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> + <artifactId>mwtnBrowser-module</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>jar</packaging> + <parent> + <artifactId>mwtnBrowser</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/images/mwtnBrowser.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/images/mwtnBrowser.png Binary files differnew file mode 100755 index 00000000..ae596db7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/images/mwtnBrowser.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/images/mwtnConfig.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/images/mwtnConfig.png Binary files differnew file mode 100755 index 00000000..ae596db7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/images/mwtnConfig.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser-custom.css new file mode 100644 index 00000000..15c398c1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser-custom.css @@ -0,0 +1,24 @@ +/** + * Add your application related css here + */ + +.json-formatter-row .constructor-name { + cursor: pointer; + color: #333333; +} + +.json-formatter-row .toggler:after { + color: darkgreen; + font-weight: bold; + display: inline-block; + transition: transform .1s ease-in; + content: ">" +} + +.owl span.key-text { + color: #333333; +} + +.owl span.colon { + color: #333333; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.controller.js new file mode 100644 index 00000000..76d3148d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.controller.js @@ -0,0 +1,1090 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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/mwtnBrowser/mwtnBrowser.module', + 'app/mwtnBrowser/mwtnBrowser.services'], + function(mwtnBrowserApp) { + + var getControlType = function(type) { + var result = 'text' + switch (type) { + case 'boolean': + result = 'checkbox'; + break; + case 'number': + result = 'number'; + break; + case 'string': + case 'array': + case 'object': + break; + default: + var message = 'Check control type for ' + type; + $mwtnLog.warning({ component: COMPONENT, message: message }); + } + return result; + }; + + mwtnBrowserApp.register.controller('ptpDefaultDsViewController', ['$scope', '$uibModalInstance', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', 'defaultDs', + function ($scope, $uibModalInstance, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, defaultDs) { + + var vm = this; + var COMPONENT = 'ptpDefaultDsViewController'; + $scope.data = defaultDs; + + $scope.getType = $mwtnGlobal.getType; + + + $mwtnCommons.getPtpDefaultDs(defaultDs).then(function (success) { + + $scope.configuredData = success; + $scope.viewData = $mwtnGlobal.getViewData($scope.configuredData['default-ds']); + + $mwtnDatabase.getSchema().then(function(schema){ + var ordered = {}; + var clone = JSON.parse(JSON.stringify($scope.viewData)); + var keys = Object.keys(clone).map(function(key){ + if ($mwtnGlobal.getType(key) !== 'string') { + console.log('key', key); + return; + } + var item = clone[key]; + if (!schema[key]) { + var message = 'No schema information for ' + key; + $mwtnLog.warning({ component: COMPONENT, message: message }); + item['order-number'] = $mwtnCommons.getOrderNumber(97, item); + item.description = 'No description available.'; + item.visible = true; + return key; + } + if (schema[key].controlType === undefined) { + item.controlType = getControlType(item.type); + } else { + item.controlType = schema[key].controlType; + } + item.unit = schema[key].unit; + item['is-read-only'] = schema[key]['is-read-only']; + if (schema[key].min) { + item.min = schema[key].min; + } + if (schema[key].max) { + item.max = schema[key].max; + if (item.unit) { + item.unit = schema[key].min + '..' + schema[key].max + ' ' + item.unit; + } else { + item.unit = schema[key].min + '..' + schema[key].max; + } + } + + + item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item); + item.description = schema[key].description; + if (item.description === undefined || item.description === '') { + item.description = 'No description available.'; + } + // hide complex types for now -> TODO + if (item.type === 'array' || item.type === 'object') { + item.visible = false; + } + return key; + }).sort(function(a,b){ + if (clone[a]['order-number'] < clone[b]['order-number']) return -1; + if (clone[a]['order-number'] > clone[b]['order-number']) return 1; + return 0; + }).map(function(key){ + ordered[key] = clone[key]; + }); + $scope.viewData = ordered; + }, function(error){ + $scope.empty = true; + }); + + }, function (error) { + $scope.configuredData = undefined; + $mwtnLog.error({ component: COMPONENT, message: 'Requesting PTP default ds ' + JSON.stringify($scope.data) + ' failed!' }); + }); + + $scope.$watch('viewData', function(newValue, oldValue) { + if (oldValue && newValue !== oldValue) { + Object.keys(newValue).filter(function(key){ + return newValue[key]['is-read-only'] !== true && newValue[key].controlType === 'number' ; + }).map(function(key){ + if (newValue[key].value < newValue[key].min) newValue[key].value = newValue[key].min; + if (newValue[key].value > newValue[key].max) newValue[key].value = newValue[key].max; + if (!newValue[key].value) newValue[key].value = newValue[key].min; + }); + } + }, true); + + $scope.newData = {}; + $scope.ok = function () { + $scope.processing = true; + $scope.newData = {}; + Object.keys($scope.viewData).map(function(key){ + $scope.newData[key] = $scope.viewData[key].value; + }); + + $mwtnCommons.setPtpDefaultDs($scope.data, $scope.newData).then(function(success){ + $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'}; + $scope.processing = false; + }, function(error){ + $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'}; + $scope.processing = false; + $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)}); + }); + + }; + + $scope.cancel = function () { + $uibModalInstance.close($scope.newData); + }; + + // events + + + }]); + + mwtnBrowserApp.register.controller('ptpPortConfigViewController', ['$scope', '$uibModalInstance', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', 'valueData', + function ($scope, $uibModalInstance, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, data) { + + var vm = this; + var COMPONENT = 'ptpPortConfigViewController'; + + $scope.data = data; + + $scope.getType = $mwtnGlobal.getType; + console.warn(JSON.stringify(data)); + $mwtnCommons.getPtpPort(data).then(function (success) { + + $scope.configuredData = success; + + $scope.viewData = $mwtnGlobal.getViewData($scope.configuredData['port-ds-list'][0]); + $mwtnDatabase.getSchema().then(function(schema){ + var ordered = {}; + var clone = JSON.parse(JSON.stringify($scope.viewData)); + var keys = Object.keys(clone).map(function(key){ + if ($mwtnGlobal.getType(key) !== 'string') { + console.log('key', key); + return; + } + var item = clone[key]; + if (!schema[key]) { + var message = 'No schema information for ' + key; + $mwtnLog.warning({ component: COMPONENT, message: message }); + item['order-number'] = $mwtnCommons.getOrderNumber(97, item); + item.description = 'No description available.'; + item.visible = true; + return key; + } + if (schema[key].controlType === undefined) { + item.controlType = getControlType(item.type); + } else { + item.controlType = schema[key].controlType; + } + item.unit = schema[key].unit; + console.warn(key, schema[key]['is-read-only']); + item['is-read-only'] = schema[key]['is-read-only']; + if (schema[key].min) { + item.min = schema[key].min; + } + if (schema[key].max) { + item.max = schema[key].max; + if (item.unit) { + item.unit = schema[key].min + '..' + schema[key].max + ' ' + item.unit; + } else { + item.unit = schema[key].min + '..' + schema[key].max; + } + } + + + item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item); + item.description = schema[key].description; + if (item.description === undefined || item.description === '') { + item.description = 'No description available.'; + } + // hide complex types for now -> TODO + if (item.type === 'array' || item.type === 'object') { + item.visible = false; + } + return key; + }).sort(function(a,b){ + if (clone[a]['order-number'] < clone[b]['order-number']) return -1; + if (clone[a]['order-number'] > clone[b]['order-number']) return 1; + return 0; + }).map(function(key){ + ordered[key] = clone[key]; + }); + $scope.viewData = ordered; + }, function(error){ + $scope.empty = true; + }); + + }, function (error) { + $scope.configuredData = undefined; + $mwtnLog.error({ component: COMPONENT, message: 'Requesting PTP port ' + JSON.stringify($scope.data) + ' failed!' }); + }); + + $scope.$watch('viewData', function(newValue, oldValue) { + if (oldValue && newValue !== oldValue) { + Object.keys(newValue).filter(function(key){ + return newValue[key]['is-read-only'] !== true && newValue[key].controlType === 'number' ; + }).map(function(key){ + if (newValue[key].value < newValue[key].min) newValue[key].value = newValue[key].min; + if (newValue[key].value > newValue[key].max) newValue[key].value = newValue[key].max; + if (!newValue[key].value) newValue[key].value = newValue[key].min; + }); + } + }, true); + + $scope.newData = {}; + $scope.ok = function () { + $scope.processing = true; + $scope.newData = {}; + Object.keys($scope.viewData).map(function(key){ + $scope.newData[key] = $scope.viewData[key].value; + }); + + $mwtnCommons.setPtpPort($scope.data, $scope.newData).then(function(success){ + $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'}; + $scope.processing = false; + }, function(error){ + $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'}; + $scope.processing = false; + $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)}); + }); + + }; + + $scope.cancel = function () { + $uibModalInstance.close($scope.newData); + }; + + // events + + + }]); + + mwtnBrowserApp.register.controller('mwtnPtpPortsController', ['$scope', '$filter', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnLog', + function ($scope, $filter, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnLog) { + var vm = this; + var COMPONENT = 'mwtnPtpPortsController'; + + $scope.info = false; + var data = JSON.parse(JSON.stringify($scope.data)); + if (!data) { + var message = 'No data to be displayed!";' + $mwtnLog.info({ component: COMPONENT, message: message }); + data = [{'message':message}]; + } + + if ($mwtnGlobal.getType(data) !== 'array') { + var message = 'Data must be of type "array"!'; + $mwtnLog.info({ component: COMPONENT, message: message }); + data = [{'message':message}]; + } + + if (data.length === 0) { + var message = 'Data list must have at least one entry!'; + $mwtnLog.info({ component: COMPONENT, message: message }); + data = [{'message':message}]; + } + + if ($mwtnGlobal.getType(data[0]) !== 'object') { + data = data.map(function(item){ + return {value: item}; + }); + } + + $scope.ptpPorts = []; + + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnCommons.gridOptions)); + $scope.gridOptions.data = 'ptpPorts'; + $scope.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + + // $scope.getTableHeight = function() { + // var rowHeight = 30; + // var headerHeight = 40; + // var maxCount = 12; + // var rowCount = $scope.gridOptions.data.length + 2; + // if (rowCount > maxCount) { + // return { + // height: (maxCount * rowHeight + headerHeight) + 'px' + // }; + // } + // return {}; // use auto-resize feature + // }; + + var getCellTemplate = function(field) { + var object = ['transmission-mode-list', 'performance-data']; + if (object.contains(field)) { + return ['<div class="ui-grid-cell-contents">', + '<i class="fa fa-info-circle pointer" aria-hidden="true"', + ' ng-click="grid.appScope.show(grid.getCellValue(row, col))"></i> ', + '{{grid.getCellValue(row, col)}}</div>'].join(''); + } else if (field === 'action') { + return [ + '<a class="vCenter" ng-class="{attention: grid.appScope.hover, hidden: onfAirInterfaceRevision}" >', + ' <i class="fa fa-pencil-square-o pointer" aria-hidden="true" ng-click="grid.appScope.show(row.entity)"></i>', + '</a>' ].join('<span> </span>'); + } else { + return '<div class="ui-grid-cell-contents">{{grid.getCellValue(row, col)}}</div>'; + } + }; + + $scope.show = function(value){ + var type = $mwtnGlobal.getType(value); + // if (type === 'object') + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnBrowser/templates/ptpPortConfigView.tpl.html', + controller: 'ptpPortConfigViewController', + size: 'huge', + resolve: { + valueData: function () { + return {networkElement: $scope.networkElement, value:value}; + } + } + }); + modalInstance.result.then(function(object) { + console.warn(JSON.stringify(object)); + $scope.ptpPorts.map(function(row, index){ + if (row['port-number'] === object['port-number']) { + console.log($scope.ptpPorts[index]['onf-ptp-dataset:master-only']); + $scope.ptpPorts[index] = object; + console.log($scope.ptpPorts[index]['onf-ptp-dataset:master-only']); + }; + }); + }, function () { + // ignore; + }); + }; + + var enable = data.length > 10; + $scope.gridOptions.columnDefs = Object.keys(data[0]).map(function (field) { + var type = $mwtnGlobal.getType(data[0][field]); + var labelId = $mwtnGlobal.getLabelId(field); + var displayName = $filter('translate')(labelId); + var visible = $mwtnGlobal.getVisibilityOf(field); + if (labelId.contains('$$') || labelId === 'MWTN_SPEC') { + visible = false; + } + return { + field: field, + type: type, + displayName: displayName, + enableSorting: true, + enableFiltering: enable, + headerCellClass: $scope.highlightFilteredHeader, + cellTemplate: getCellTemplate(field), + cellClass: type, + visible: visible + }; + }); + $scope.gridOptions.columnDefs.push({ + field: 'action', + displayName: 'Action', + enableSorting: false, + enableFiltering: false, + headerCellClass: $scope.highlightFilteredHeader, + cellTemplate: getCellTemplate('action'), + width: 100, + visible: true, + pinnedRight : true + + }); + if ($scope.gridOptions.data.length < 10) { + $scope.gridOptions.minRowsToShow = data.length; // 10 is default + } + $scope.ptpPorts = data.map(function(item){ + item.action = ''; + return item; + }); + // .sort(function(a, b){ + // if (a.type === 'object') return -1; + // if (a.type === 'array' ) return -2; + // return 0; + // }) + + $scope.myClipboard = { + data: $scope.data, + supported: true, + getJson: function () { + return JSON.stringify(this.data, null, ' '); + }, + copyToClipboard: function () { + var message = 'Copied to clipboard! ' + this.getJson(); + $mwtnLog.info({ component: COMPONENT, message: message }); + }, + error: function (err) { + $mwtnLog.error({ component: COMPONENT, message: err }); + } + }; + }]); + + mwtnBrowserApp.register.directive('mwtnPtpPorts', function () { + return { + restrict: 'E', + scope: { + data: '=', + path: '=', + networkElement: '=' + }, + controller: 'mwtnPtpPortsController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnBrowser/templates/mwtnPtpPorts.tpl.html' + }; + }); + + mwtnBrowserApp.register.controller('mwtnPtpClockViewerController', ['$scope', '$timeout', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', '$mwtnBrowser', + function ($scope, $timeout, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, $mwtnBrowser) { + var vm = this; + var COMPONENT = 'mwtnPtpClockViewerController'; + if ($scope.data) { + $scope.replace = false; + if ($scope.path && $scope.path.endsWith('-configuration') ) { + $scope.replace = true; + } + $scope.viewData = $mwtnGlobal.getViewData($scope.data, $scope.ne); + var path = [undefined, undefined, undefined]; + if ($scope.path) { + path = $scope.path.split($mwtnCommons.separator); + } + + var processData = function(schema) { + var ordered = {}; + var clone = JSON.parse(JSON.stringify($scope.viewData)); + var keys = Object.keys(clone).map(function(key){ + if ($mwtnGlobal.getType(key) !== 'string') { + console.log('key', key); + return; + } + var item = clone[key]; + if (!schema[key]) { + var message = 'No schema information for ' + key; + $mwtnLog.warning({ component: COMPONENT, message: message }); + item['order-number'] = $mwtnCommons.getOrderNumber(97, item); + item.description = 'No description available.'; + item.visible = true; + return key; + } + item.unit = schema[key].unit; + item.description = schema[key].description; + item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item); + if (item.description === undefined || item.description === '') { + item.description = 'No description available.'; + } + return key; + }).sort(function(a,b){ + if (clone[a]['order-number'] < clone[b]['order-number']) return -1; + if (clone[a]['order-number'] > clone[b]['order-number']) return 1; + return 0; + }).map(function(key){ + if ($mwtnGlobal.getType( clone[key].value ) === 'object') { + Object.keys(clone[key].value).filter(function(subKey){ + return subKey.endsWith('-identity'); + }).map(function(subKey){ + var clockId = clone[key].value[subKey]; + if ($mwtnGlobal.getType(clockId) === 'object') { + if (clockId['clock-identity']) { + var ascii = clockId['clock-identity'].base64ToHex(); + clone[key].value[subKey]['clock-identity'] = [clone[key].value[subKey]['clock-identity'], '(ascii:', ascii, ')'].join(' '); + } + } else { + var ascii = clone[key].value[subKey].base64ToHex(); + clone[key].value[subKey] = [clone[key].value[subKey], '(ascii:', ascii, ')'].join(' '); + } + }); + ordered[key] = clone[key]; + } else { + ordered[key] = clone[key]; + } + }); + $scope.info = false; + if (Object.keys(ordered).length === 0) { + $scope.info = 'An empty object is displayed. Please check if the NetConf server has send an empty object.'; + } + return ordered; + }; + + + $mwtnDatabase.getSchema().then(function(schema){ + $scope.schema = schema; + $scope.viewData = processData($scope.schema); + }, function(error){ + // ignore; + }); + } + + $scope.show = function(value){ + var type = $mwtnGlobal.getType(value); + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnBrowser/templates/ptpDefaultDsConfigView.tpl.html', + controller: 'ptpDefaultDsViewController', + size: 'huge', + resolve: { + defaultDs: function () { + return {networkElement: $scope.networkElement, value:value}; + } + } + }); + modalInstance.result.then(function(object) { + $mwtnBrowser.refreshPTP(); + }, function () { + // ignore; + }); + }; + }]); + + mwtnBrowserApp.register.directive('mwtnPtpClockViewer', function () { + return { + restrict: 'E', + scope: { + data: '=', + path: '=', + ne: '=', // flag if ne class + networkElement: '=' + }, + controller: 'mwtnPtpClockViewerController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnBrowser/templates/mwtnPtpClockViewer.tpl.html' + }; + }); + + + mwtnBrowserApp.register.controller('mwtnBrowserCtrl', ['$scope', '$rootScope', '$mwtnLog', '$mwtnCommons', '$mwtnEthernet', '$mwtnBrowser', '$translate', 'OnfNetworkElement', 'PtpClock', 'LogicalTerminationPoint', + function($scope, $rootScope, $mwtnLog, $mwtnCommons, $mwtnEthernet, $mwtnBrowser, $translate, OnfNetworkElement, PtpClock, LogicalTerminationPoint) { + + var COMPONENT = 'mwtnBrowserCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'mwtnBrowserCtrl started!'}); + $rootScope.section_logo = 'src/app/mwtnBrowser/images/mwtnBrowser.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + var pacTemplate = { + 'layer-protocol': 'unknown' + }; + + $scope.fcDeletion = { + nodeId: $scope.networkElementId, + ltp:'', + info: 'handle with care, no further warning, qualified user expected ;)' + }; + $scope.deleteForwardingConstruct = function() { + $scope.fcDeletion.nodeId = $scope.networkElementId; + $scope.fcDeletion.info = 'Processing ...'; + $scope.fcDeletion.error = undefined; + if ($scope.fcDeletion.ltp === undefined || $scope.fcDeletion.ltp === '') { + $scope.fcDeletion.error = 'Please select a valid LTP#1.!'; + return; + } + $mwtnEthernet.deleteForwardingConstruct($scope.fcDeletion).then(function(success){ + console.log(success); + $scope.fcDeletion.info = success; + }, function(error){ + console.log(error); + $scope.fcDeletion.error = error; + }); + } + + $scope.fcCreation = { + nodeId: $scope.networkElementId, + ltp1:'', + ltp2:'', + vlan:42, + info:'handle with care, no further warning, qualified user expected ;)' + }; + $scope.createForwardingConstruct = function() { + console.warn(JSON.stringify($scope.networkElementId)); + console.warn(JSON.stringify($scope.networkElement)); + $scope.fcCreation.nodeId = $scope.networkElementId; + $scope.fcCreation.info = 'Processing ...'; + $scope.fcCreation.error = undefined; + if ($scope.fcCreation.ltp1 === undefined || $scope.fcCreation.ltp1 === '') { + $scope.fcCreation.error = 'Please select a valid LTP#1!'; + return; + } + if ($scope.fcCreation.ltp2 === undefined || $scope.fcCreation.ltp2 === '') { + $scope.fcCreation.error = 'Please select a valid LTP#2!'; + return; + } + if ($scope.fcCreation.vlan === undefined) { + $scope.fcCreation.error = 'Please select a valid vlan-id!'; + return; + } + if ($scope.fcCreation.ltp1 === $scope.fcCreation.ltp2) { + $scope.fcCreation.error = 'Please select different LTPs. Loopback is not supported yet!'; + return; + } + $mwtnEthernet.createForwardingConstruct($scope.fcCreation).then(function(success){ + console.log(success); + $scope.fcCreation.info = success; + }, function(error){ + console.log(error); + $scope.fcCreation.error = error; + }); + } + + // get important infromation from yang modules + console.error('help'); + $mwtnBrowser.getModules().then(function(success){ + + var pacOrder = [ + 'onf-otn-odu-conditional-packages:otn-odu-termination-pac', + 'onf-otn-odu-conditional-packages:otn-odu-connection-pac', + 'onf-ethernet-conditional-packages:ethernet-pac', + 'microwave-model:mw-air-interface-diversity-pac', + 'microwave-model:mw-air-interface-hsb-end-point-pac', + 'microwave-model:mw-air-interface-hsb-fc-switch-pac', + 'onf-core-model-conditional-packages:holder-pac', + 'onf-core-model-conditional-packages:connector-pac', + 'onf-core-model-conditional-packages:equipment-pac', + 'microwave-model:mw-ethernet-container-pac', + 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac', + 'microwave-model:mw-ethernet-container-pac', + 'microwave-model:mw-tdm-container-pac', + 'microwave-model:mw-pure-ethernet-structure-pac', + 'microwave-model:mw-hybrid-mw-structure-pac', + 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac', + 'microwave-model:mw-air-interface-pac', + 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac' + ]; + + $scope.modules = success; + $scope.orderedPacs = []; + $scope.parts = []; + Object.keys(success).map(function(module){ + Object.keys(success[module]).filter(function(key){ + return key.endsWith('-pac') || key.endsWith('_Pac'); + }).map(function(pacName){ + $scope.orderedPacs.push([module, pacName].join(':')); + // sort + $scope.orderedPacs.sort(function(a, b) { + if (!pacOrder.indexOf(a)) console.warn(a); + if (!pacOrder.indexOf(b)) console.warn(b); + if(pacOrder.indexOf(a) > pacOrder.indexOf(b)) return 1; + if(pacOrder.indexOf(a) < pacOrder.indexOf(b)) return -1; + return 0; + }) + + if (pacName === 'mw-air-interface-pac') { + $scope.parts = Object.keys(success[module][pacName]).filter(function(conditionalPackage){ + return success[module][pacName][conditionalPackage]['local-name']; + }).map(function(conditionalPackage){ + return success[module][pacName][conditionalPackage]['local-name']; + }); + } + }); + }); + }, function(error){ + $scope.modules = undefined; + $scope.orderedPacs = undefined; + $scope.parts = undefined; + }); + + /** + * @function updateNe + * A function, which updates onfNetworkElement by new data. + * @param {*} data New data recieved from OpenDaylight via RestConf + */ + var updateNe = function(data) { + if (!data) return; + // update onfNetworkElement + switch ($scope.mountpoint.onfCoreModelRevision) { + case '2016-03-23': + $scope.onfNetworkElement = JSON.parse(JSON.stringify(data['network-element'][0])); + $scope.onfLtps = data['network-element'][0].ltp; + $scope.onfNetworkElement.ltp = undefined; + break; + case '2016-08-09': + case '2016-08-11': + case '2017-02-17': + case '2017-03-20': + case '2017-10-20': + // console.log(JSON.stringify(data)); + $scope.onfNetworkElement = new OnfNetworkElement(data['network-element']); + var fd = $scope.onfNetworkElement.getForwardingDomain(); + $scope.forwardingDomain = undefined; + $scope.forwardingConstructs = undefined; + if (fd && fd.length > 0) { + $scope.forwardingDomain = fd[0]; // $mwtnBrowser.getViewData(fd[0]); + $scope.forwardingConstructs = []; + if (fd[0].fc) { + fd[0].fc.map(function(id){ + $mwtnBrowser.getForwardingConstruct($scope.networkElement, id).then(function(fc){ + + // TODO make robust + if (fc['forwarding-construct'] && fc['forwarding-construct'][0]) { + var item = fc['forwarding-construct'][0]; + if (item['fc-port'] && + item['fc-port'][0] && item['fc-port'][0].ltp && item['fc-port'][0].ltp[0] && + item['fc-port'][1] && item['fc-port'][1].ltp && item['fc-port'][1].ltp[0]) { + $scope.forwardingConstructs.push( { + uuid: item.uuid, + 'fc-port#1': $scope.onfNetworkElement.getLtp( item['fc-port'][0].ltp[0] ).getLabel(), + 'fc-port#2': $scope.onfNetworkElement.getLtp( item['fc-port'][1].ltp[0] ).getLabel() + }); + } + } + }); + }); + } + } + $scope.onfLtps = $scope.onfNetworkElement.getLogicalTerminationPoints(); + // $scope.onfNetworkElement.ltp = undefined; + break; + default: + $mwtnLog.info({component: COMPONENT, message: ['The ONF CoreModel revision', $scope.mountpoint.onfCoreModelRevision, ' is not supported (yet)!'].join(' ')}); + $scope.onfNetworkElement = {}; + $scope.onfLtps = {}; + } + + var order = $mwtnBrowser.layerProtocolNameOrder; + // update onfLTPs + $scope.onfLtps.sort(function(a, b){ + if(order[a.getLayer()] < order[b.getLayer()]) return -1; + if(order[a.getLayer()] > order[b.getLayer()]) return 1; + if(a.getId() < b.getId()) return -1; + if(a.getId() > b.getId()) return 1; + return 0; + }); + + // calculate conditional packages + $scope.pacs = {}; + $scope.onfLtps.map(function(ltp) { + ltp.getLayerProtocols().map( + /** + * A function processing a layer-protocol object + * @param {LayerProtocol} lp A layer-protocol object + */ + function(lp) { + var template = JSON.parse(JSON.stringify(pacTemplate)); + template['layer-protocol'] = lp.getId(); + var conditionalPackage = lp.getConditionalPackage(true); + // console.log(conditionalPackage); + if (conditionalPackage !== '') { + if ($scope.pacs[conditionalPackage] === undefined) { + // create missing pac array + $scope.pacs[conditionalPackage] = []; + } + $scope.pacs[conditionalPackage].push(template); + console.error(conditionalPackage, JSON.stringify(template)); + } else { + $mwtnLog.info({component: COMPONENT, message: 'No conditional package for ' + ltp.getLabel() }); + } + }); + }); + + // sort the conditional packages + if ($scope.orderedPacs) { + $scope.orderedPacs.filter(function(item){ + return $scope.pacs[item] !== undefined; + }).map(function(item){ + $scope.pacs[item].sort(function(a, b){ + if(a['layer-protocol'] < b['layer-protocol']) return -1; + if(a['layer-protocol'] > b['layer-protocol']) return 1; + return 0; + }); + }); + } + data.revision = undefined; + }; + + var updateNetworkElementCurrentProblems = function(data) { + if (data && data['network-element-current-problems'] && data['network-element-current-problems']['current-problem-list'] ) { + data.revision = undefined; + $scope.neCurrentProblems = data['network-element-current-problems']['current-problem-list']; + } else { + $scope.neCurrentProblems = []; + } + }; + + var updateLtp = function(data) { + $scope.onfLtps.map(function(ltp){ + if (ltp.getData().uuid === data.data.ltp[0].uuid) { + ltp = new LogicalTerminationPoint(data.data.ltp[0]); + } + }); + }; + + /** + * @deprecated since all conditaional packages are handle the same way even for + * 3rd and 4th PoC model - 2nd PoC model not supported any more. + * @param {*} lpId + * @param {*} part + * @param {*} data + */ + var updateAirInterface = function(lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + $scope.airinterfaces.map(function(airinterface){ + // console.log(JSON.stringify(airinterface)); + if (airinterface['layer-protocol'] === lpId) { + if (Object.keys(data)[0].startsWith('air-interface')) { + airinterface[part] = data; + } else if (part === 'Capability') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + airinterface[part] = data['mw-air-interface-pac'][0]['air-interface-capability-list']; + } else if (part === 'CurrentProblems') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + airinterface[part] = data['mw-air-interface-pac'][0]['air-interface-current-problem-list']; + } + } + }); + data.revision = undefined; + }; + + /** + * @deprecated since all conditaional packages are handle the same way even for + * 3rd and 4th PoC model - 2nd PoC model not supported any more. + * @param {*} lpId + * @param {*} part + * @param {*} data + */ + var updateStructure = function(lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + $scope.structures.map(function(structure){ + // console.log(JSON.stringify(structure)); + if (structure['layer-protocol'] === lpId) { + if (Object.keys(data)[0].contains('tructure')) { + structure[part] = data; + } else if (part === 'Capability') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + structure[part] = data['mw-structure-pac'][0]['structure.capability-list']; + } else if (part === 'CurrentProblems') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + structure[part] = data['mw-structure-pac'][0]['structure-current-problem-list']; + } + } + }); + data.revision = undefined; + }; + + /** + * @deprecated since all conditaional packages are handle the same way even for + * 3rd and 4th PoC model - 2nd PoC model not supported any more. + * @param {*} lpId + * @param {*} part + * @param {*} data + */ + var updateContainer = function(lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + $scope.containers.map(function(container){ + // console.log(JSON.stringify(container)); + if (container['layer-protocol'] === lpId) { + if (Object.keys(data)[0].contains('ontainer') ) { + container[part] = data; + } else if (part === 'Capability') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + container[part] = data['mw-container-pac'][0]['container-capability-list']; + } else if (part === 'CurrentProblems') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + container[part] = data['mw-container-pac'][0]['container-current-problem-list']; + } + } + }); + data.revision = undefined; + }; + + /** + * Creates a template of a conditional packages with its subclasses + * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass + */ + var initPac = function(spec) { + $scope.pacs[spec.pacId].filter(function(conditionalPackage){ + return conditionalPackage['layer-protocol'] === spec.layerProtocolId; + }).map(function(pac){ + $scope.parts.map(function(localName){ + pac[localName] = {id:$mwtnBrowser.getPartGlobalId(spec, localName),localName: localName, data:'No data available'} + }); + }); + }; + + /** + * Updates an existing template of a conditional packages with its subclasses + * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass + */ + var updateSubClassData = function(spec, data) { + $scope.pacs[spec.pacId].filter(function(conditionalPackage){ + return conditionalPackage['layer-protocol'] === spec.layerProtocolId; + }).map(function(conditionalPackage){ + conditionalPackage[$mwtnBrowser.getPartLocalId(spec)].data = data[$mwtnBrowser.yangify(spec.partId)]; + }); + }; + + var updatePart = function(spec, data) { + switch (spec.pacId) { + case 'ne': + updateNe(data); + break; + case 'forwardingDomain': + // TODO $scope.forwardingDomain = new ForwardingDomain(data); + break; + case 'neCurrentProblems': + updateNetworkElementCurrentProblems(data); + break; + case 'clock': + if (data) { + $scope.clock = new PtpClock(data); + } else { + $scope.clock = undefined; + } + break; + case 'ltp': + updateLtp(data); + break; + case 'airinterface': + console.warn(JSON.stringify(spec, JSON.stringify(data))); + updateAirInterface(spec.layerProtocolId, spec.partId, data); + break; + case 'structure': + console.warn(JSON.stringify(data)); + updateStructure(spec.layerProtocolId, spec.partId, data); + break; + case 'container': + console.warn(JSON.stringify(data)); + updateContainer(spec.layerProtocolId, spec.partId, data); + break; + // 3rd Poc + case 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac': + case 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac': + case 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac': + // 4th Poc + case 'microwave-model:mw-air-interface-pac': + case 'microwave-model:mw-air-interface-diversity-pac': + case 'microwave-model:mw-pure-ethernet-structure-pac': + case 'microwave-model:mw-hybrid-mw-structure-pac': + case 'microwave-model:mw-tdm-container-pac': + case 'microwave-model:mw-ethernet-container-pac': + case 'onf-ethernet-conditional-packages:ethernet-pac': + if (!spec.partId) { + initPac(spec); + } else { + updateSubClassData(spec, data); + } + break; + } + }; + + // events + $scope.status = {ne:false}; + $scope.spinner = {ne:false}; + $scope.separator = $mwtnBrowser.separator; //' ' + + $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; + }); + }; + + $scope.$watch('status', function(status, oldValue) { + Object.keys(status).filter(function(key){ + return $scope.networkElementId && status[key] && status[key] !== oldValue[key]; + }).map(function(key){ + $scope.spinner[key] = true; + var info = key.split($scope.separator); + var spec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: info[0], + layerProtocolId: info[1], + partId: info[2] + }; + $mwtnBrowser.getPacParts(spec).then(function(success){ + success = $mwtnBrowser.yangifyObject(success) + updatePart(spec, success); + $scope.spinner[key] = false; + }, function(error){ + updatePart(spec, error); + $scope.spinner[key] = false; + }); + }); + }, true); + + $scope.$watch('networkElement', function(neId, oldValue) { + if (neId && neId !== '' && neId !== oldValue) { + + $scope.collapseAll(); + + // clear old data + $scope.airinterfaces = []; + $scope.structures = []; + $scope.containers = []; + $scope.onfLtps = []; + $scope.clock = undefined; + + $scope.networkElementId = neId; + $scope.revision = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === neId; + }).map(function(mountpoint){ + $scope.mountpoint = mountpoint; + return mountpoint.onfCoreModelRevision; + })[0]; + + var spec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: 'ne' + }; + $mwtnBrowser.getPacParts(spec).then(function(success){ + updatePart(spec, $mwtnBrowser.yangifyObject(success)); + }, function(error){ + updatePart(spec, error); + }); + + // network element alarms + var neAlarms = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === neId; + }).map(function(mountpoint){ + return mountpoint.onfCapabilities.filter(function(cap){ + return cap.module === 'MicrowaveModel-NetworkElement-CurrentProblemList' || cap.module === 'onf-core-model-conditional-packages'; + }); + }); + + if (neAlarms.length === 1 && neAlarms[0].length === 1 ) { + $translate('MWTN_LOADING').then(function (translation) { + $scope.neCurrentProblems = translation; + }); + } else { + $scope.neCurrentProblems = undefined; + } + + // ptp-clock + var ptpClock = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === neId; + }).map(function(mountpoint){ + return mountpoint.onfCapabilities.filter(function(cap){ + return cap.module === 'onf-ptp-dataset'; + }); + }); + if (ptpClock.length === 1 && ptpClock[0].length === 1 ) { + $translate('MWTN_LOADING').then(function (translation) { + $scope.clock = {'translation': translation}; + }); + } else { + $scope.clock = undefined; + } + + } + }); + + }]); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.module.js new file mode 100644 index 00000000..d529ca2f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.module.js @@ -0,0 +1,53 @@ +/* + * 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', + 'app/mwtnCommons/bower_components/angular-clipboard/angular-clipboard'], function(ng) { + var mwtnBrowserApp = angular.module('app.mwtnBrowser', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'angular-clipboard']); + + mwtnBrowserApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnBrowserApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + NavHelperProvider.addControllerUrl('app/mwtnBrowser/mwtnBrowser.controller'); + NavHelperProvider.addToMenu('mwtnBrowser', { + "link" : "#/pnfBrowser/", + "active" : "main.mwtnBrowser", + "title" : "pnf Config", + "icon" : "fa fa-cogs", // Add navigation icon css class here + "page" : { + "title" : "pnf Config", + "description" : "mwtnBrowser" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnBrowser', { + url: 'pnfBrowser/:nodeId', + access: access.admin, + views : { + content : { + templateUrl: 'src/app/mwtnBrowser/templates/frame.tpl.html', + controller: 'mwtnBrowserCtrl' + } + } + }); + + }); + + return mwtnBrowserApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.services.js new file mode 100644 index 00000000..7cd9dc07 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/mwtnBrowser.services.js @@ -0,0 +1,37 @@ +/* + * @copyright 2017 highstreet technologies 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/mwtnCommons/mwtnCommons.module', 'app/mwtnBrowser/mwtnBrowser.module'],function(mwtnBrowserApp) { + + mwtnBrowserApp.register.factory('$mwtnBrowser', function($mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var COMPONENT = '$mwtnBrowser'; + $mwtnLog.info({component: COMPONENT, message: '$mwtnBrowser started!'}); + + var service = {}; + + service.separator = $mwtnCommons.separator; + + service.parts = $mwtnCommons.parts; + service.getPacParts = $mwtnCommons.getPacParts; + service.getModules = $mwtnDatabase.getModules; + service.getPartGlobalId = $mwtnCommons.getPartGlobalId; + service.getPartLocalId = $mwtnCommons.getPartLocalId; + service.getViewData = $mwtnCommons.getViewData; + service.getForwardingConstruct = $mwtnCommons.getForwardingConstruct; + service.layerProtocolNameOrder = $mwtnCommons.layerProtocolNameOrder; + service.yangify = $mwtnCommons.yangify; + service.yangifyObject = $mwtnCommons.yangifyObject; + + service.refreshPTP = function() { + console.error('refresh ptp'); + } + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/frame.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/frame.tpl.html new file mode 100644 index 00000000..6d43dbd8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/frame.tpl.html @@ -0,0 +1,191 @@ +<ht-header help-link='sdnr/pnfConfig/0.4.0/README.md'></ht-header> +<mwtn-select-network-element></mwtn-select-network-element> + +<div class="owl container" ng-if="networkElements.length !== 0 && networkElement" style="width: 100%;"> + <div class="row"> + <uib-accordion close-others="oneAtATime"> + <div class="col-md-12"> + <div uib-accordion-group class="panel-primary" is-open="status.ne"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status.ne, 'fa-chevron-right': !status.ne}"></i> + <span>{{'MWTN_NETWORKELEMENT' | translate}} '{{onfNetworkElement.getName()}}' </span> + <span> (#{{'MWTN_LTPS' | translate}}: {{onfNetworkElement.getLogicalTerminationPoints().length}})</span> + <i class="fa fa-spinner fa-pulse" ng-show="spinner.ne"></i> + </uib-accordion-heading> + <mwtn-json-viewer network-element="networkElement" data="onfNetworkElement.getData()" ne="true" ng-if="status.ne"></mwtn-json-viewer> + <br/> + + <uib-accordion close-others="oneAtATime"> + <div uib-accordion-group class="panel-default" is-open="status.neCurrentProblems" ng-if="neCurrentProblems"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status.neCurrentProblems, 'fa-chevron-right': !status.neCurrentProblems}"></i> + <span>{{'MWTN_CURRENT_PROBLEM_LIST' | translate}}</span> + <i class="fa fa-spinner fa-pulse" ng-show="spinner.neCurrentProblems"></i> + </uib-accordion-heading> + + <mwtn-grid network-element="networkElement" data="neCurrentProblems" ng-if="neCurrentProblems && !spinner.neCurrentProblems"></mwtn-grid> + </div> + + <div uib-accordion-group class="panel-default" is-open="status.forwardingDomain" ng-show="forwardingDomain"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status.forwardingDomain, 'fa-chevron-right': !status.forwardingDomain}"></i> + <span>{{'MWTN_FORWARDING_DOMAIN' | translate}}</span> + <i class="fa fa-spinner fa-pulse" ng-show="spinner.forwardingDomain"></i> + </uib-accordion-heading> + + <mwtn-json-viewer network-element="networkElement" data="forwardingDomain" ng-if="status.forwardingDomain"></mwtn-json-viewer> + </div> + + <div uib-accordion-group class="panel-default" is-open="status.forwardingConstructs" ng-show="forwardingConstructs"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status.forwardingConstructs, 'fa-chevron-right': !status.forwardingConstructs}"></i> + <span>{{'MWTN_FORWARDING_CONSTRUCTS' | translate}}</span> + <i class="fa fa-spinner fa-pulse" ng-show="spinner.forwardingConstructs"></i> + </uib-accordion-heading> + + <mwtn-grid network-element="networkElement" data="forwardingConstructs" ng-if="forwardingConstructs && !spinner.forwardingConstructs"></mwtn-grid> + + <!-- create fc --> + <div class="row"> + <div class="col col-md-3"> + <label class="owl-dark" for="vlan">{{'MWTN_LTP1' | translate}}</label><br/> + <select class="form-control" ng-model="fcCreation.ltp1"> + <option ng-repeat="ltp in forwardingDomain.ltp" value="{{ltp}}">{{ltp}}</option> + </select> + </div> + <div class="col col-md-3"> + <label class="owl-dark" for="vlan">{{'MWTN_LTP2' | translate}}</label><br/> + <select class="form-control" ng-model="fcCreation.ltp2"> + <option ng-repeat="ltp in forwardingDomain.ltp" value="{{ltp}}">{{ltp}}</option> + </select> + </div> + <div class="col col-md-1 form-group"> + <label class="owl-dark" for="vlan">{{'MWTN_SERVICE_ID' | translate}}</label><br/> + <input class="form-control" type="number" value="42" id="example-number-input" ng-model="fcCreation.vlan"> + </div> + <div class="col col-md-2"> + <label style="color:white;" for="create">create</label><br/> + <button type="button" class="btn btn-warning" ng-click="createForwardingConstruct()"> + <i class="fa fa-plus" aria-hidden="true"></i> + <span style="color:white;">{{'MWTN_CREATE' | translate}}</span> + </button> + </div> + <div class="col col-md-3"> + <span class="owl-dark" ng-if="!fcCreation.error">{{fcCreation.info}}</span> + <span class="error" ng-if="fcCreation.error">{{fcCreation.error}}</span> + </div> + </div> + + <!-- delete fc --> + <div class="row"> + <div class="col col-md-6 form-group"> + <label class="owl-dark" for="vlan">{{'MWTN_FC_UUID' | translate}}</label><br/> + <select class="form-control" ng-model="fcDeletion.ltp"> + <option ng-repeat="fc in forwardingConstructs" value="{{fc.uuid}}">{{fc.uuid}}</option> + </select> + </div> + <div class="col col-md-2 col-md-offset-1" > + <label style="color:white;" for="delete">delete</label><br/> + <button type="button" class="btn btn-danger" ng-click="deleteForwardingConstruct()"> + <i class="fa fa-times" aria-hidden="true"></i> + <span style="color:white;">{{'MWTN_DELETE' | translate}}</span> + </button> + </div> + <div class="col col-md-3"> + <span class="owl-dark" ng-if="!fcDeletion.error">{{fcDeletion.info}}</span> + <span class="error" ng-if="fcDeletion.error">{{fcDeletion.error}}</span> + </div> + </div> + + </div> + + <div ng-repeat="ltp in onfLtps" ng-show="status.ne" uib-accordion-group class="panel-default" is-open="status['ltp' + separator + ltp.getData().uuid]"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status['ltp' + separator + ltp.getData().uuid], 'fa-chevron-right': !status['ltp' + separator + ltp.getData().uuid]}"></i> + <span>{{'MWTN_LTP' | translate}}(</span> + <b>{{ltp.getLayerProtocols()[0].getItuLabel().toUpperCase()}}</b> + <span>): {{ltp.getName()}} (ID: {{ltp.getId()}})</span> + </uib-accordion-heading> + + <mwtn-json-viewer network-element="networkElement" data="ltp.getData()" ng-if="status['ltp' + separator + ltp.getData().uuid]"></mwtn-json-viewer> + </div> + </uib-accordion> + </div> + + <div uib-accordion-group class="panel-default" is-open="status.clock" ng-if="clock"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status.clock, 'fa-chevron-right': !status.clock}"></i> + <span>{{'MWTN_CLOCK' | translate}}</span> + <i class="fa fa-spinner fa-pulse" ng-show="spinner.clock"></i> + </uib-accordion-heading> + + <!-- <mwtn-json-viewer network-element="networkElement" data="clock.getData()" ng-if="clock.getData() && !spinner.clock"></mwtn-json-viewer> --> + <mwtn-ptp-clock-viewer network-element="networkElement" data="clock.getData()" ng-if="clock.getData() && !spinner.clock"></mwtn-ptp-clock-viewer> + </div> + + + </div> + + + </uib-accordion> + </div> + + <div class="row" ng-repeat="orderedPac in orderedPacs" ng-if="pacs[orderedPac]"> + <uib-accordion close-others="oneAtATime"> + <div ng-class="{ 'col-md-12': pacs[orderedPac].length === 1, 'col-md-6': pacs[orderedPac].length !== 1 }" style="margin-top: 5px;" + ng-repeat="pac in pacs[orderedPac]"> + <div uib-accordion-group class="panel-primary" is-open="status[ [orderedPac, pac['layer-protocol']].join(separator) ]"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status[ [orderedPac, pac['layer-protocol']].join(separator) ], 'fa-chevron-right': !status[ [orderedPac, pac['layer-protocol']].join(separator) ]}"></i> + <span>{{ ['mwtn', orderedPac].join('-').replaceAll('-', '_').toUpperCase() | translate }} '{{pac['layer-protocol']}}'</span> + </uib-accordion-heading> + + <div ng-repeat="part in parts" uib-accordion-group class="panel-default" is-open="status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"> + <uib-accordion-heading> + <i class="fa" ng-class="{'fa-chevron-down': status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ], 'fa-chevron-right': !status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]}"></i> + <span>{{ ['mwtn', part].join('-').replaceAll('-', '_').toUpperCase() | translate}}</span> + <i class="fa fa-spinner fa-pulse" ng-show="spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></i> + </uib-accordion-heading> + + + <!-- current-problem-list --> + <mwtn-grid network-element="networkElement" data="pac[part].data['current-problem-list']" ng-if="pac[part].data['current-problem-list'] && !spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></mwtn-grid> + <div ng-if="pac[part].data['current-problem-list'].length === 0">Alarm free ;)</div> + + <!-- PM Current --> + <mwtn-json-viewer network-element="networkElement" data="pac[part].data['current-performance-data-list'][0]" + path="[orderedPac, pac['layer-protocol'], pac[part].id].join(separator)" + ng-if="part === 'current-performance' && pac[part].data && !spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></mwtn-json-viewer> + <hr ng-if="part === 'current-performance' && pac[part].data && !spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"> + <mwtn-json-viewer network-element="networkElement" data="pac[part].data['current-performance-data-list'][1]" + path="[orderedPac, pac['layer-protocol'], pac[part].id].join(separator)" + ng-if="part === 'current-performance' && pac[part].data && !spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></mwtn-json-viewer> + + <!-- PM history --> + <mwtn-grid network-element="networkElement" data="pac[part].data['historical-performance-data-list']" + path="[orderedPac, pac['layer-protocol'], pac[part].id].join(separator)" + ng-if="pac[part].data['historical-performance-data-list'] && !spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></mwtn-grid> + + <!-- else --> + <mwtn-json-viewer network-element="networkElement" data="pac[part].data" + path="[orderedPac, pac['layer-protocol'], pac[part].id].join(separator)" + ng-if="status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator)] && + pac[part].data && + part !== 'current-problems' && + part !== 'current-performance' && + part !== 'historical-performances' && + !spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></mwtn-json-viewer> + + </div> + </div> + </div> + <hr class="white"> + </uib-accordion> + </div> + +</div> + +<hr /> +<div class="owl"> + <span class="white">ONAP SDN-R | ONF Wireless for @distversion@ - Build: @buildtime@</span> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/mwtnPtpClockViewer.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/mwtnPtpClockViewer.tpl.html new file mode 100644 index 00000000..1a6849df --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/mwtnPtpClockViewer.tpl.html @@ -0,0 +1,66 @@ +<div class="owl"> + <div class="row text-right"> + <div class="form-group"> + <button class="btn btn-default" type="button" clipboard supported="myClipboard.supported" text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + <button class="btn btn-default" type="button" ng-if="replace"> + <i class="fa fa-pencil-square-o pointer" aria-hidden="true" ng-click="openConfigView()" ></i> + </button> + <div> + </div> +</div> +<div class="owl"> + +<!-- + <div class="row" ng-repeat="(key, value) in viewData track by $index" ng-show="value.value !== undefined"> + <span class="owl-dark">{{key | json}}</span><br/> + <span class="owl-dark">{{value | json}}</span><br/> + <span class="owl-dark">{{viewData[key].labelId | translate}}</span> + <span class="owl-dark">{{viewData['instance-number'].labelId | translate}}</span> + </div> --> + + <!-- instance-number - -> + <div class="row"> + <div class="col col-md-3 text-right" title="{{viewData['instance-number'].description}}"> + <span class="owl-dark">{{viewData['instance-number'].labelId | translate}}</span> + </div> + <div class="col col-md-4"> + <b>{{viewData['instance-number'].value}}</b> + </div> + </div> --> + + <!-- current-ds --> + <div class="row"> + <div class="column col-md-6 text-left" title="{{viewData['default-ds'].description}}"> + <b>{{viewData['default-ds'].labelId | translate}}</b> + <i class="fa fa-pencil-square-o pointer" aria-hidden="true" ng-click="show(viewData['default-ds'].value)"></i> + <br/> + <mwtn-json-viewer network-element="networkElement" data="viewData['default-ds'].value" no-buttons="true" ng-if="viewData['default-ds'].value"></mwtn-json-viewer> + <hr/> + </div> + + <div class="column col-md-6 text-left" title="{{viewData['parent-ds'].description}}"> + <b>{{viewData['parent-ds'].labelId | translate}}</b> + <br/> + <mwtn-json-viewer network-element="networkElement" data="viewData['parent-ds'].value" no-buttons="true" ng-if="viewData['parent-ds'].value"></mwtn-json-viewer> + <hr/> + </div> + + <div class="column col-md-6 text-left" ng-repeat="key in ['current-ds', 'time-properties-ds']" title="{{viewData[key].description}}"> + <b>{{viewData[key].labelId | translate}}</b> + <br/> + <mwtn-json-viewer network-element="networkElement" data="viewData[key].value" no-buttons="true" ng-if="viewData[key].value"></mwtn-json-viewer> + <hr/> + </div> + </div> + + <div class="row"> + <div class="col col-md-12 text-left" > + <b>{{'MWTN_PORT_DS_LIST' | translate}}</b> + <br/> + <mwtn-ptp-ports network-element="networkElement" data="viewData['port-ds-list'].value" path="path"></mwtn-ptp-ports> + </div> + </div> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/mwtnPtpPorts.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/mwtnPtpPorts.tpl.html new file mode 100644 index 00000000..2751ffcb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/mwtnPtpPorts.tpl.html @@ -0,0 +1,23 @@ +<div class="owl co1ntainer" > + + <div class="row"> + <div class="col-md-12"> + + <div ng-if="info !== false"> + <span class="owl-dark">{{info}}</span> + </div> + + <div ui-grid="gridOptions" + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + ui-grid-auto-resize + class="mwtn-grid" + ng-style="getTableHeight()"></div> + + </div> + </div> + +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/ptpDefaultDsConfigView.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/ptpDefaultDsConfigView.tpl.html new file mode 100644 index 00000000..cb0e40c2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/ptpDefaultDsConfigView.tpl.html @@ -0,0 +1,45 @@ +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{'MWTN_PTP_DEFAULT_DS_CONFIGURATION' | translate}}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="container" style="width:100%"> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_NETWORKELEMENT' | translate}} + </div> + <div class="col-md-9"> + <b>{{data.networkElement}}</b> + </div> + </div> + <hr/> + <div class="row"> + + <div ng-repeat="(key, item) in viewData" ng-if="item.visible === true"> + + <!-- text, number, combo --> + <div class="col-md-3 text-right radio">{{item.labelId | translate}}</div> + <div ng-class="{'col-md-2':item.unit, 'col-md-3':!item.unit}" class="form-group" ng-if="item.controlType !== 'checkbox' && getType(item.controlType) !== 'array'"> + <input class="form-control" type="{{item.controlType}}" ng-model="item.value" ng-disabled="item['is-read-only'] === true" min="{{item.min}}" max="{{item.max}}"></input> + </div> + + <div class="col-md-3 checkbox" ng-if="item.controlType === 'checkbox' "><input type="checkbox" ng-model="item.value" ng-disabled="item['is-read-only'] === true" /></div> + <div ng-class="{'col-md-2':item.unit, 'col-md-3':!item.unit}" class="form-group" ng-if="getType(item.controlType) === 'array'"> + <select class="form-control" ng-model="item.value" ng-disabled="item['is-read-only'] === true"> + <option ng-repeat="option in item.controlType track by $index" value="{{option}}">{{option}}</option> + </select> + </div> + <div class="col-md-1 radio" ng-if="item.unit"> + <span class="owl-dark">{{item.unit}}</span> + </div> + + </div> + </div> +</div> +<div class="modal-footer"> + <div class="{{applied.class}}", ng-show="applied">{{applied.text}}</div> + <button class="btn btn-primary" type="button" ng-click="ok()"> + <span style="color: white;">{{'MWTN_APPLY' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="processing"></i> + </button> + <button class="btn btn-warning" type="button" ng-click="cancel()">{{'MWTN_CLOSE' | translate}}</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/ptpPortConfigView.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/ptpPortConfigView.tpl.html new file mode 100644 index 00000000..5d7d9df5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/mwtnBrowser-module/src/main/resources/mwtnBrowser/templates/ptpPortConfigView.tpl.html @@ -0,0 +1,53 @@ +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{'MWTN_PTP_PORT_CONFIGURATION' | translate}}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="container" style="width:100%"> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_NETWORKELEMENT' | translate}} + </div> + <div class="col-md-9"> + <b>{{data.networkElement}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_PORT_IDENTITY' | translate}} + </div> + <div class="col-md-9"> + <b>{{data.value['port-identity']['clock-identity']}}#{{data.value['port-identity']['port-number']}}</b> + </div> + </div> + <hr/> + <div class="row"> + + <div ng-repeat="(key, item) in viewData" ng-if="item.visible === true"> + + <!-- text, number, combo --> + <div class="col-md-3 text-right radio">{{item.labelId | translate}}</div> + <div ng-class="{'col-md-2':item.unit, 'col-md-3':!item.unit}" class="form-group" ng-if="item.controlType !== 'checkbox' && getType(item.controlType) !== 'array'"> + <input class="form-control" type="{{item.controlType}}" ng-model="item.value" ng-disabled="item['is-read-only'] === true" min="{{item.min}}" max="{{item.max}}"></input> + </div> + + <div class="col-md-3 checkbox" ng-if="item.controlType === 'checkbox'"><input type="checkbox" ng-model="item.value" /></div> + <div ng-class="{'col-md-2':item.unit, 'col-md-3':!item.unit}" class="form-group" ng-if="getType(item.controlType) === 'array'"> + <select class="form-control" ng-model="item.value" ng-disabled="item['is-read-only'] === true"> + <option ng-repeat="option in item.controlType track by $index" value="{{option}}">{{option}}</option> + </select> + </div> + <div class="col-md-1 radio" ng-if="item.unit"> + <span class="owl-dark">{{item.unit}}</span> + </div> + + </div> + </div> +</div> +<div class="modal-footer"> + <div class="{{applied.class}}", ng-show="applied">{{applied.text}}</div> + <button class="btn btn-primary" type="button" ng-click="ok()"> + <span style="color: white;">{{'MWTN_APPLY' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="processing"></i> + </button> + <button class="btn btn-warning" type="button" ng-click="cancel()">{{'MWTN_CLOSE' | translate}}</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/pom.xml new file mode 100644 index 00000000..7584afdc --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnBrowser/pom.xml @@ -0,0 +1,22 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnBrowser</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + <packaging>pom</packaging> + + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <modules> + <module>mwtnBrowser-module</module> + <module>mwtnBrowser-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-bundle/pom.xml new file mode 100644 index 00000000..b7993d31 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-bundle/pom.xml @@ -0,0 +1,118 @@ +<?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>mwtnClosedLoop</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnClosedLoop-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnClosedLoop-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnClosedLoop-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..8187f7fe --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnClosedLoop"/> + <property name="url" value="/src/app/mwtnClosedLoop"/> + <property name="directory" value="/mwtnClosedLoop"/> + <property name="requireJs" value="app/mwtnClosedLoop/mwtnClosedLoop.module"/> + <property name="angularJs" value="app.mwtnClosedLoop"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnClosedLoop/mwtnClosedLoop-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/pom.xml new file mode 100644 index 00000000..aadd37ce --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-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>mwtnClosedLoop</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>mwtnClosedLoop-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/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/images/mwtnClosedLoop.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/images/mwtnClosedLoop.png Binary files differnew file mode 100755 index 00000000..b4ed3d5c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/images/mwtnClosedLoop.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop-custom.css new file mode 100644 index 00000000..6e9a480c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop-custom.css @@ -0,0 +1,26 @@ +/** + * Add your application related css here + */ + +.mwtnClosedLoopGrid { + height: 600px; + background-color: white; +} + +.mwtnClosedLoopGrid span { + color: #393939; +} + +.mwtnClosedLoopGrid span.mismatch { + font-weight: bold; + color: #428bca; +} + +.mwtnClosedLoopGrid .green { + color: darkgreen; +} +.mwtnClosedLoopGrid .green span { + color: darkgreen; +} + +
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.controller.js new file mode 100644 index 00000000..99ad48b7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.controller.js @@ -0,0 +1,160 @@ +/* + * 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/mwtnClosedLoop/mwtnClosedLoop.module','app/mwtnClosedLoop/mwtnClosedLoop.services','app/mwtnCommons/mwtnCommons.services'], function(mwtnClosedLoopApp) { + + mwtnClosedLoopApp.register.controller('mwtnClosedLoopCtrl', ['$scope', '$rootScope', 'uiGridConstants', '$mwtnClosedLoop', '$mwtnCommons', '$mwtnLog', 'OnfNetworkElement', 'MicrowavePhysicalSection', + function($scope, $rootScope, uiGridConstants, $mwtnClosedLoop, $mwtnCommons, $mwtnLog, OnfNetworkElement, MicrowavePhysicalSection) { + + var COMPONENT = 'mwtnClosedLoopCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'Started!'}); + + $rootScope.section_logo = 'src/app/mwtnClosedLoop/images/mwtnClosedLoop.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.timerOptionList = [ + {id : '5seconds', name : "5 seconds"}, + {id : '30seconds', name : "30 seconds"}, + {id : '1minute', name : "One minute"}, + {id : '2minutes', name : "Two minutes"}, + {id : '30minutes', name : "30 minutes"}, + {id : '1hour', name : "One hour"}]; + + var clearMessages = function() { + $scope.info = undefined; + $scope.error = undefined; + }; + + $scope.executeNow = function() { + clearMessages(); + $mwtnCommons.executeClosedLoopAutomation().then(function(message){ + $mwtnLog.info({component: 'mwtnClosedLoopCtrl', message: 'Closed loop automation was started'}); + $scope.info = 'Closed loop automation was executed: ' + new Date().toISOString().toHumanReadableTimeFormat(); + $scope.refresh(); + }, function(error){ + $mwtnLog.error({component: 'mwtnClosedLoopCtrl', message: 'Cannot execute Closed Loop Automation'}); + $scope.error = 'Cannot execute Closed Loop Automation'; + $scope.refresh(); + }); + }; + + $scope.save = function() { + clearMessages(); + $mwtnCommons.saveClosedLoopAutomation($scope.timerEnabled, $scope.timerOption).then(function(message){ + $mwtnLog.info({component: 'mwtnClosedLoopCtrl', message: 'Timer was changed'}); + $scope.info = 'Timer was changed'; + $scope.refresh(); + }, function(error){ + $mwtnLog.error({component: 'mwtnClosedLoopCtrl', message: 'Cannot save timer'}); + $scope.error = 'Cannot save timer'; + $scope.refresh(); + }); + }; + + $scope.read = function() { + clearMessages(); + $mwtnCommons.readClosedLoopAutomation().then(function(message){ + $scope.timerEnabled = message.data.output.enabled; + $scope.timerOption = message.data.output.option; + $scope.refresh(); + }, function(error){ + $mwtnLog.error({component: 'mwtnClosedLoopCtrl', message: 'Cannot read configuration data from the server'}); + $scope.error = 'Cannot read configuration data from the server'; + $scope.refresh(); + }); + }; + + $scope.read(); + + var updateAirInterface = function(spec, data) { + if (data) { + var radioSignalID = data.airInterfaceConfiguration.radioSignalID; + $scope.gridOptions.data.map(function(row){ + if (row.name === spec.nodeId && row.radioSignalID === radioSignalID) { + row.actualAirInterfaceName = data.airInterfaceConfiguration.airInterfaceName; + } + }); + } else { + $scope.gridOptions.data.map(function(row){ + if (row.nodeId === spec.nodeId) { + row.actualAirInterfaceName = '?'; + } + }); + } + }; + + $scope.processing = false; + $scope.refresh = function() { + $scope.processing = true; + $mwtnClosedLoop.refresh().then(function(success){ + $scope.processing = false; + $scope.gridOptions.data = success.airInterfaces; + success.actualNodes.map(function(actualNode){ + if (actualNode.connectionStatus !== 'connected') { + return; + } + var revision = '2016-09-01'; + $mwtnClosedLoop.getActualNetworkElement(actualNode.id, revision).then(function(onfNe){ + var aOnfNe = new OnfNetworkElement(onfNe.NetworkElement); + aOnfNe.getLTPMwpsList().map(function(ltp){ + var spec = { + nodeId: actualNode.id, + revision: revision, + pacId: 'airinterface', + layerProtocolId: ltp._lpList[0].uuid, + partId: 'Configuration' + }; + $mwtnClosedLoop.getPacParts(spec).then(function(success){ + updateAirInterface(spec, success); + }, function(error){ + updateAirInterface(spec, error); + }); + }); + }, function(error){ + // do nothing + }); + }); + }, function(error){ + $scope.processing = false; + $scope.gridOptions.data = []; + }); + }; + + $scope.highlightFilteredHeader = $mwtnClosedLoop.highlightFilteredHeader; + + var requiredNesConnectionStatusCellTemplate = [ + '<div class="ui-grid-cell-contents" ng-class="{ \'green\': grid.getCellValue(row, col) === \'connected\'}"}>', + ' <i ng-show="grid.getCellValue(row, col) === \'connected\'" class="fa fa-link" aria-hidden="true"></i>', + ' <span>{{grid.getCellValue(row, col)}}</span>', + '</div>'].join(''); + + // ng-class="{\'mismatch\': {{row.entity.plannedAirInterfaceName}} !== grid.getCellValue(row, col) }" + var actualAirinterfaceNameTemplate = [ + '<div class="ui-grid-cell-contents">', + ' <span>{{grid.getCellValue(row, col)}}</span>', + '</div>'].join(''); + + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnClosedLoop.gridOptions)); + $scope.gridOptions.columnDefs = [ + { 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 : 140 }, + { field: 'connectionStatus', type: 'string', displayName: 'Connection status', headerCellClass: $scope.highlightFilteredHeader, width : 150, cellTemplate: requiredNesConnectionStatusCellTemplate }, + { field: 'radioSignalID', type: 'string', displayName: 'Radio signal id', headerCellClass: $scope.highlightFilteredHeader, width : 130 }, + { field: 'plannedAirInterfaceName', type: 'string', displayName: 'Planned airinterface name', headerCellClass: $scope.highlightFilteredHeader, width : 200 }, + { field: 'actualAirInterfaceName', type: 'string', displayName: 'Actual airinterface name', headerCellClass: $scope.highlightFilteredHeader, width : 250, cellTemplate: actualAirinterfaceNameTemplate}, + ]; + + $scope.refresh(); + + }]); + + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.module.js new file mode 100644 index 00000000..cec6f69b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.module.js @@ -0,0 +1,51 @@ +/* + * 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 mwtnClosedLoopApp = angular.module('app.mwtnClosedLoop', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state','config']); + + mwtnClosedLoopApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnClosedLoopApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + + NavHelperProvider.addControllerUrl('app/mwtnClosedLoop/mwtnClosedLoop.controller'); + NavHelperProvider.addToMenu('mwtnClosedLoop', { + "link" : "#/mwtnClosedLoop", + "active" : "main.mwtnClosedLoop", + "title" : "MWTN Closed Loop Automation", + "icon" : "fa fa-circle-o", // Add navigation icon css class here + "page" : { + "title" : "MWTN Closed Loop Automation", + "description" : "mwtnClosedLoop" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnClosedLoop', { + url: 'mwtnClosedLoop', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnClosedLoop/mwtnClosedLoop.tpl.html', + controller: 'mwtnClosedLoopCtrl' + } + } + }); + + }); + + return mwtnClosedLoopApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.services.js new file mode 100644 index 00000000..96c8c3e7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.services.js @@ -0,0 +1,74 @@ +/* + * 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/mwtnClosedLoop/mwtnClosedLoop.module'],function(mwtnClosedLoopApp) { + + + mwtnClosedLoopApp.register.factory('$mwtnClosedLoop', function($q, $mwtnCommons, $mwtnLog) { + var service = {}; + + service.gridOptions = $mwtnCommons.gridOptions; + service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + service.getActualNetworkElement = $mwtnCommons.getActualNetworkElement; + service.getPacParts = $mwtnCommons.getPacParts; + + + service.refresh = function() { + var deferred = $q.defer(); + $mwtnCommons.getRequiredNetworkElements(true).then(function(pNes){ + var neIds = pNes.map(function(pNe){ + pNe._source.connectionStatus = 'disconnected'; + return pNe._id; + }); + $mwtnCommons.getMountPoints(). then(function(mountpoints){ + var actualNodes = mountpoints.map(function(mountpoint){ + var pIndex = neIds.indexOf(mountpoint['node-id']); + if (pIndex > -1) { + pNes[pIndex]._source.connectionStatus = mountpoint['netconf-node-topology:connection-status']; + } + return { + id: mountpoint['node-id'], + connectionStatus: mountpoint['netconf-node-topology:connection-status'] + }; + }); + var airInterfaces = []; + pNes.map(function(hit){ + hit._source.MW_AirInterface_Pac.map(function(airinterface){ + return airinterface.airInterfaceConfiguration; + }).map(function(airinterface){ + airInterfaces.push({ + id: $mwtnCommons.getNodeIntIdFromNodeId(hit._source.nodeId), + name: hit._source.nodeId, + connectionStatus: hit._source.connectionStatus, + radioSignalID: airinterface.airInterfaceConfiguration.radioSignalID, + plannedAirInterfaceName: airinterface.airInterfaceConfiguration.airInterfaceName, + actualAirInterfaceName: '?' + }); + }); + }); + + airInterfaces.sort(function(a, b){ + if(a.radioSignalID < b.radioSignalID) return -1; + if(a.radioSignalID > b.radioSignalID) return 1; + return 0; + }); + deferred.resolve({airInterfaces: airInterfaces, actualNodes: actualNodes}); + }, function(error){ + deferred.reject([]); + }); + + }, function(error){ + deferred.reject([]); + }); + return deferred.promise; + }; + + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.tpl.html new file mode 100644 index 00000000..62a2aca0 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/mwtnClosedLoop-module/src/main/resources/mwtnClosedLoop/mwtnClosedLoop.tpl.html @@ -0,0 +1,64 @@ +<ht-header help-link='sdnr/mwtn/mwtnClosedLoop/0.4.0/README.md'></ht-header> +<div class="owl container"> + <div class="row"> + <div class="col-md-2 text-right"> + <span class="white">{{'Timer ON/OFF' | translate}}</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <input type="checkbox" ng-model="timerEnabled"> + </div> + </div> + </div> + + <div class="row"> + <div class="col-md-2 text-right"> + <span class="white">{{'Timer Option' | translate}}</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <select class="form-control" ng-model="timerOption" ng-disabled="!timerEnabled"> + <option ng-repeat="timerOption in timerOptionList" value="{{timerOption.id}}">{{timerOption.name}}</option> + </select> + </div> + </div> + + <div class="col-md-6 text-right"> + <div class="form-group"> + <button type="button" class="btn btn-primary" ng-click="save()">{{'Save' | translate}}</button> + </div> + </div> + </div> + <div class="row"> + <hr /> + <div class="col-md-2"> + <div class="form-group"> + <button type="button" class="btn btn-primary" ng-click="executeNow()">{{'Execute now' | translate}}</button> + </div> + </div> + <div class="col-md-8"> + <div class="form-group"> + <span class="white" ng-show="info">{{ info }}</span> + <span ng-show="error" class="mwtnError">{{ error }}</span> + </div> + </div> + <div clase="col-md-2 text-right"> + <button class="btn btn-primary pull-right" ng-click="refresh()"> + <i class="fa fa-refresh" ng-class="{'fa-spin':processing == true}" aria-hidden="true"></i> + <span>{{'MWTN_REFRESH' | translate}}</span> + </button> + </div> + </div> + <div class="row"> + <div clase="col-md-12"> + <div id="mwtnClosedLoopGrid" ui-grid="gridOptions" ui-grid-exporter + ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnClosedLoopGrid"></div> + </div> + </div> + +</div> +<hr /> +<div class="owl"> + <span class="white">ONAP SDN-R | ONF Wireless for @distversion@ - Build: @buildtime@</span> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/pom.xml new file mode 100644 index 00000000..fc75d742 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnClosedLoop/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnClosedLoop</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnClosedLoop-module</module> + <module>mwtnClosedLoop-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-bundle/pom.xml new file mode 100644 index 00000000..e9f85e05 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-bundle/pom.xml @@ -0,0 +1,117 @@ +<?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>mwtnCommons</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnCommons-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnCommons-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnCommons-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..5a693e16 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,23 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnCommons"/> + <property name="url" value="/src/app/mwtnCommons"/> + <property name="directory" value="/mwtnCommons"/> + <property name="requireJs" value="app/mwtnCommons/mwtnCommons.module"/> + <property name="angularJs" value="app.mwtnCommons"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnCommons/mwtnCommons-custom.css</value> + <value>src/app/mwtnCommons/bower_components/font-awesome/css/font-awesome.css</value> + <value>src/app/mwtnCommons/bower_components/angular-ui-grid/ui-grid.min.css</value> + <value>src/app/mwtnCommons/bower_components/json-formatter/dist/json-formatter.min.css</value> +<!-- <value>src/app/mwtnCommons/bower_components/angular-bootstrap/ui-bootstrap-csp.css</value> --> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/pom.xml new file mode 100644 index 00000000..b031831f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/pom.xml @@ -0,0 +1,69 @@ +<?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>mwtnCommons</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnCommons-module</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>jar</packaging> + + <build> + <pluginManagement> + <plugins> + <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence + on the Maven build itself. --> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>1.0.0</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <versionRange>[1.0.0,)</versionRange> + <goals> + <goal>exec</goal> + </goals> + </pluginExecutionFilter> + <action> + <execute/> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.6.0</version> + <executions> + <execution> + <phase>generate-sources</phase> + <goals> + <goal>exec</goal> + </goals> + </execution> + </executions> + <configuration> + <executable>./bowerInstall.sh</executable> + <arguments> + <argument>install</argument> + </arguments> + <workingDirectory>${basedir}/src/main/resources/mwtnCommons/</workingDirectory> + </configuration> + </plugin> + </plugins> + </build> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/README.md b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/README.md new file mode 100644 index 00000000..3c254917 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/README.md @@ -0,0 +1,34 @@ +# MTWN Comments + +This component offers services for MTWN specific ODL DLUX application development. +It should ensure, that common functionality of ODL DLUX applications is implemented and tested only once, but reused by several applications. + +All MWTN ODL DLUX application should have a dependency to 'mtwnCommons'. +However, it is a case by case decision by developers, whether such dependency is needed for their application of not. + +Common functions are: +* A centralized service ($mwtnLog), which stores application logs in a centralized database. It should simplify failure analysis and debugging. +* Communication with the RestConf API of OpenDaylight. +* WebSocket subscription for notification handling +* Implementation of common object classes as defined by the Microwave Information model (e.g. NetConfServer, NetworkElement, LogicalTerminationPoint, LayerProtocol, MW_AirInterface_Pac, MW_PureEthernetStructure_Pac, MW_EthernetContainer_Pac) +* Enhanced [angular.js](https://angularjs.org/) features for web development, which are not native in [ODL DLUX](https://wiki.opendaylight.org/view/OpenDaylight_dlux:Main). + +## Installation + +Additional [angular.js](https://angularjs.org/) feature and implementations are listed in the file [bower.json](./bower.json). + +``` +bower install +``` +Please see [bower.io](https://bower.io/) for further information about bower. + +## angular-chart.js + +* Open app/mwtnCommons/bower_components/angular-chart.js/dist/angular-chart +* Locate + else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['angular', 'chart'], factory); + } + + * change define(['angular', 'chart'], factory); to define(['angular', 'app/mwtnCommons/bower_components/chart.js/dist/Chart'], factory); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bower.json b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bower.json new file mode 100644 index 00000000..77aed945 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bower.json @@ -0,0 +1,39 @@ +{ + "name": "mwtn-commons", + "homepage": "https://github.com/OpenNetworkingFoundation/CENTENNIAL/tree/master/03-WTP-PoC/code", + "authors": [ + "Martin Skorupski <martin.skorupski@highstreet-technologies.com>" + ], + "description": "bower components for microwave transport network specific opendaylight dlux applications", + "main": "", + "version": "0.5.1-SNAPSHOT", + "dependencies": { + "bootstrap": "~3.3.7", + "font-awesome": "~4.6.3", + "angular-ui-grid": "3.2.9", + "angular-clipboard": "~1.5.0", + "angular-chart.js": "~1.1.1", + "chart.js": "^2.5.0", + "lodash": "^4.17.4", + "json-formatter": "^0.6.0", + "cytoscape": "^3.1.1" + }, + "keywords": [ + "Microwave", + "Millimeterwave", + "MWTN", + "ONF", + "SDN", + "Transport", + "Wireless", + "xHaul" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bowerInstall.sh b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bowerInstall.sh new file mode 100755 index 00000000..054cf683 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bowerInstall.sh @@ -0,0 +1,18 @@ +echo "---------------------------------" +echo "Install bower and adapt to ODL UX" +echo "---------------------------------" +echo "Step1: Install bower" +bower install -q + +echo "Step2: Install Bower patches to adapt to ODL-DLUX" + +FileToPatch="angular-chart.js" +FileToPatchDestination="bower_components/angular-chart.js/dist" +FileToPatchOrigination="bower_components_patches" + +echo "- File to handle: $FileToPatch" +mv $FileToPatchDestination/$FileToPatch $FileToPatchDestination/$FileToPatch.orig +cp $FileToPatchOrigination/$FileToPatch.patch $FileToPatchDestination +mv $FileToPatchDestination/$FileToPatch.patch $FileToPatchDestination/$FileToPatch + +echo "Install bower script ends" diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bower_components_patches/angular-chart.js.patch b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bower_components_patches/angular-chart.js.patch new file mode 100644 index 00000000..23a4b361 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/bower_components_patches/angular-chart.js.patch @@ -0,0 +1,400 @@ +/*! + * angular-chart.js - An angular.js wrapper for Chart.js + * http://jtblin.github.io/angular-chart.js/ + * Version: 1.1.1 + * + * Copyright 2016 Jerome Touffe-Blin + * Released under the BSD-2-Clause license + * https://github.com/jtblin/angular-chart.js/blob/master/LICENSE + */ +(function (factory) { + 'use strict'; + if (typeof exports === 'object') { + // Node/CommonJS + module.exports = factory( + typeof angular !== 'undefined' ? angular : require('angular'), + typeof Chart !== 'undefined' ? Chart : require('chart.js')); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['angular', 'app/mwtnCommons/bower_components/chart.js/dist/Chart'], factory); + } else { + // Browser globals + if (typeof angular === 'undefined') { + throw new Error('AngularJS framework needs to be included, see https://angularjs.org/'); + } else if (typeof Chart === 'undefined') { + throw new Error('Chart.js library needs to be included, see http://jtblin.github.io/angular-chart.js/'); + } + factory(angular, Chart); + } +}(function (angular, Chart) { + 'use strict'; + + Chart.defaults.global.multiTooltipTemplate = '<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>'; + Chart.defaults.global.tooltips.mode = 'label'; + Chart.defaults.global.elements.line.borderWidth = 2; + Chart.defaults.global.elements.rectangle.borderWidth = 2; + Chart.defaults.global.legend.display = false; + Chart.defaults.global.colors = [ + '#97BBCD', // blue + '#DCDCDC', // light grey + '#F7464A', // red + '#46BFBD', // green + '#FDB45C', // yellow + '#949FB1', // grey + '#4D5360' // dark grey + ]; + + var useExcanvas = typeof window.G_vmlCanvasManager === 'object' && + window.G_vmlCanvasManager !== null && + typeof window.G_vmlCanvasManager.initElement === 'function'; + + if (useExcanvas) Chart.defaults.global.animation = false; + + return angular.module('chart.js', []) + .provider('ChartJs', ChartJsProvider) + .factory('ChartJsFactory', ['ChartJs', '$timeout', ChartJsFactory]) + .directive('chartBase', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory(); }]) + .directive('chartLine', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('line'); }]) + .directive('chartBar', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('bar'); }]) + .directive('chartHorizontalBar', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('horizontalBar'); }]) + .directive('chartRadar', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('radar'); }]) + .directive('chartDoughnut', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('doughnut'); }]) + .directive('chartPie', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('pie'); }]) + .directive('chartPolarArea', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('polarArea'); }]) + .directive('chartBubble', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('bubble'); }]) + .name; + + /** + * Wrapper for chart.js + * Allows configuring chart js using the provider + * + * angular.module('myModule', ['chart.js']).config(function(ChartJsProvider) { + * ChartJsProvider.setOptions({ responsive: false }); + * ChartJsProvider.setOptions('Line', { responsive: true }); + * }))) + */ + function ChartJsProvider () { + var options = { responsive: true }; + var ChartJs = { + Chart: Chart, + getOptions: function (type) { + var typeOptions = type && options[type] || {}; + return angular.extend({}, options, typeOptions); + } + }; + + /** + * Allow to set global options during configuration + */ + this.setOptions = function (type, customOptions) { + // If no type was specified set option for the global object + if (! customOptions) { + customOptions = type; + options = angular.merge(options, customOptions); + } else { + // Set options for the specific chart + options[type] = angular.merge(options[type] || {}, customOptions); + } + + angular.merge(ChartJs.Chart.defaults, options); + }; + + this.$get = function () { + return ChartJs; + }; + } + + function ChartJsFactory (ChartJs, $timeout) { + return function chart (type) { + return { + restrict: 'CA', + scope: { + chartGetColor: '=?', + chartType: '=', + chartData: '=?', + chartLabels: '=?', + chartOptions: '=?', + chartSeries: '=?', + chartColors: '=?', + chartClick: '=?', + chartHover: '=?', + chartDatasetOverride: '=?' + }, + link: function (scope, elem/*, attrs */) { + if (useExcanvas) window.G_vmlCanvasManager.initElement(elem[0]); + + // Order of setting "watch" matter + scope.$watch('chartData', watchData, true); + scope.$watch('chartSeries', watchOther, true); + scope.$watch('chartLabels', watchOther, true); + scope.$watch('chartOptions', watchOther, true); + scope.$watch('chartColors', watchOther, true); + scope.$watch('chartDatasetOverride', watchOther, true); + scope.$watch('chartType', watchType, false); + + scope.$on('$destroy', function () { + destroyChart(scope); + }); + + scope.$on('$resize', function () { + if (scope.chart) scope.chart.resize(); + }); + + function watchData (newVal, oldVal) { + if (! newVal || ! newVal.length || (Array.isArray(newVal[0]) && ! newVal[0].length)) { + destroyChart(scope); + return; + } + var chartType = type || scope.chartType; + if (! chartType) return; + + if (scope.chart && canUpdateChart(newVal, oldVal)) + return updateChart(newVal, scope); + + createChart(chartType, scope, elem); + } + + function watchOther (newVal, oldVal) { + if (isEmpty(newVal)) return; + if (angular.equals(newVal, oldVal)) return; + var chartType = type || scope.chartType; + if (! chartType) return; + + // chart.update() doesn't work for series and labels + // so we have to re-create the chart entirely + createChart(chartType, scope, elem); + } + + function watchType (newVal, oldVal) { + if (isEmpty(newVal)) return; + if (angular.equals(newVal, oldVal)) return; + createChart(newVal, scope, elem); + } + } + }; + }; + + function createChart (type, scope, elem) { + var options = getChartOptions(type, scope); + if (! hasData(scope) || ! canDisplay(type, scope, elem, options)) return; + + var cvs = elem[0]; + var ctx = cvs.getContext('2d'); + + scope.chartGetColor = getChartColorFn(scope); + var data = getChartData(type, scope); + // Destroy old chart if it exists to avoid ghost charts issue + // https://github.com/jtblin/angular-chart.js/issues/187 + destroyChart(scope); + + scope.chart = new ChartJs.Chart(ctx, { + type: type, + data: data, + options: options + }); + scope.$emit('chart-create', scope.chart); + bindEvents(cvs, scope); + } + + function canUpdateChart (newVal, oldVal) { + if (newVal && oldVal && newVal.length && oldVal.length) { + return Array.isArray(newVal[0]) ? + newVal.length === oldVal.length && newVal.every(function (element, index) { + return element.length === oldVal[index].length; }) : + oldVal.reduce(sum, 0) > 0 ? newVal.length === oldVal.length : false; + } + return false; + } + + function sum (carry, val) { + return carry + val; + } + + function getEventHandler (scope, action, triggerOnlyOnChange) { + var lastState = { + point: void 0, + points: void 0 + }; + return function (evt) { + var atEvent = scope.chart.getElementAtEvent || scope.chart.getPointAtEvent; + var atEvents = scope.chart.getElementsAtEvent || scope.chart.getPointsAtEvent; + if (atEvents) { + var points = atEvents.call(scope.chart, evt); + var point = atEvent ? atEvent.call(scope.chart, evt)[0] : void 0; + + if (triggerOnlyOnChange === false || + (! angular.equals(lastState.points, points) && ! angular.equals(lastState.point, point)) + ) { + lastState.point = point; + lastState.points = points; + scope[action](points, evt, point); + } + } + }; + } + + function getColors (type, scope) { + var colors = angular.copy(scope.chartColors || + ChartJs.getOptions(type).chartColors || + Chart.defaults.global.colors + ); + var notEnoughColors = colors.length < scope.chartData.length; + while (colors.length < scope.chartData.length) { + colors.push(scope.chartGetColor()); + } + // mutate colors in this case as we don't want + // the colors to change on each refresh + if (notEnoughColors) scope.chartColors = colors; + return colors.map(convertColor); + } + + function convertColor (color) { + // Allows RGB and RGBA colors to be input as a string: e.g.: "rgb(159,204,0)", "rgba(159,204,0, 0.5)" + if (typeof color === 'string' && color[0] === 'r') return getColor(rgbStringToRgb(color)); + // Allows hex colors to be input as a string. + if (typeof color === 'string' && color[0] === '#') return getColor(hexToRgb(color.substr(1))); + // Allows colors to be input as an object, bypassing getColor() entirely + if (typeof color === 'object' && color !== null) return color; + return getRandomColor(); + } + + function getRandomColor () { + var color = [getRandomInt(0, 255), getRandomInt(0, 255), getRandomInt(0, 255)]; + return getColor(color); + } + + function getColor (color) { + var alpha = color[3] || 1; + color = color.slice(0, 3); + return { + backgroundColor: rgba(color, 0.2), + pointBackgroundColor: rgba(color, alpha), + pointHoverBackgroundColor: rgba(color, 0.8), + borderColor: rgba(color, alpha), + pointBorderColor: '#fff', + pointHoverBorderColor: rgba(color, alpha) + }; + } + + function getRandomInt (min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + function rgba (color, alpha) { + // rgba not supported by IE8 + return useExcanvas ? 'rgb(' + color.join(',') + ')' : 'rgba(' + color.concat(alpha).join(',') + ')'; + } + + // Credit: http://stackoverflow.com/a/11508164/1190235 + function hexToRgb (hex) { + var bigint = parseInt(hex, 16), + r = (bigint >> 16) & 255, + g = (bigint >> 8) & 255, + b = bigint & 255; + + return [r, g, b]; + } + + function rgbStringToRgb (color) { + var match = color.match(/^rgba?\(([\d,.]+)\)$/); + if (! match) throw new Error('Cannot parse rgb value'); + color = match[1].split(','); + return color.map(Number); + } + + function hasData (scope) { + return scope.chartData && scope.chartData.length; + } + + function getChartColorFn (scope) { + return typeof scope.chartGetColor === 'function' ? scope.chartGetColor : getRandomColor; + } + + function getChartData (type, scope) { + var colors = getColors(type, scope); + return Array.isArray(scope.chartData[0]) ? + getDataSets(scope.chartLabels, scope.chartData, scope.chartSeries || [], colors, scope.chartDatasetOverride) : + getData(scope.chartLabels, scope.chartData, colors, scope.chartDatasetOverride); + } + + function getDataSets (labels, data, series, colors, datasetOverride) { + return { + labels: labels, + datasets: data.map(function (item, i) { + var dataset = angular.extend({}, colors[i], { + label: series[i], + data: item + }); + if (datasetOverride && datasetOverride.length >= i) { + angular.merge(dataset, datasetOverride[i]); + } + return dataset; + }) + }; + } + + function getData (labels, data, colors, datasetOverride) { + var dataset = { + labels: labels, + datasets: [{ + data: data, + backgroundColor: colors.map(function (color) { + return color.pointBackgroundColor; + }), + hoverBackgroundColor: colors.map(function (color) { + return color.backgroundColor; + }) + }] + }; + if (datasetOverride) { + angular.merge(dataset.datasets[0], datasetOverride); + } + return dataset; + } + + function getChartOptions (type, scope) { + return angular.extend({}, ChartJs.getOptions(type), scope.chartOptions); + } + + function bindEvents (cvs, scope) { + cvs.onclick = scope.chartClick ? getEventHandler(scope, 'chartClick', false) : angular.noop; + cvs.onmousemove = scope.chartHover ? getEventHandler(scope, 'chartHover', true) : angular.noop; + } + + function updateChart (values, scope) { + if (Array.isArray(scope.chartData[0])) { + scope.chart.data.datasets.forEach(function (dataset, i) { + dataset.data = values[i]; + }); + } else { + scope.chart.data.datasets[0].data = values; + } + + scope.chart.update(); + scope.$emit('chart-update', scope.chart); + } + + function isEmpty (value) { + return ! value || + (Array.isArray(value) && ! value.length) || + (typeof value === 'object' && ! Object.keys(value).length); + } + + function canDisplay (type, scope, elem, options) { + // TODO: check parent? + if (options.responsive && elem[0].clientHeight === 0) { + $timeout(function () { + createChart(type, scope, elem); + }, 50, false); + return false; + } + return true; + } + + function destroyChart(scope) { + if(! scope.chart) return; + scope.chart.destroy(); + scope.$emit('chart-destroy', scope.chart); + } + } +})); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/locale/locale-en_US.json b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/locale/locale-en_US.json new file mode 100644 index 00000000..eb0ef3b5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/locale/locale-en_US.json @@ -0,0 +1,924 @@ +{ + + "PNF_NAME": "Name", + "PNF_IDENTIFIER":"Identifier", + "PNF_EQUIPMENT_TYPE":"Equipment type", + "PNF_EQUIPMENT_MODEL": "Equipment model", + "PNF_EQUIPMENT_VENDOR": "Equipment vendor", + "PNF_IPv4ADDRESS": "IPv4 address", + "PNF_MAINTENANCE_MODE": "Maintenace mode", + "PNF_CREATE_IN_AAI": "Create PNF in Active and Available Inventory", + "PNF_DELETE_IN_AAI": "Delete PNF in Active and Available Inventory", + "PNF_RESOURCE_VERSION": "Resource version", + + "MWTN_AMSL_GRD": "Above mean sea level (ground)", + "MWTN_APPCOMMAND": "Application command", + "MWTN_AIR_INTERFACE_LINKS": "Air interface links", + "MWTN_BAND": "Band", + "MWTN_CLIADDRESS": "CLI address", + "MWTN_CONNECTED_LTP_REF": "Connected LTP", + "MWTN_CURRENT_PROBLEMS": "Current problem list", + "MWTN_CURRENT_PERFORMANCE": "Current performance", + "MWTN_DURATION": "Duration", + "MWTN_END_TIME": "End time", + "MWTN_FORWARDING_DOMAIN": "Forwarding domain (ETH switch)", + "MWTN_FORWARDING_CONSTRUCTS":"Forwarding constructs", + "MWTN_FC": "Forwarding constructs", + "MWTN_FC_PORT#1": "Port #1", + "MWTN_FC_PORT#2": "Port #2", + "MWTN_FC_UUID": "Forwarding construct UUID", + "MWTN_FD_EX":"Extension", + "MWTN_HISTORICAL_PERFORMANCES": "Performance history", + "MWTN_HTMEDIATOR": "Has mediator", + "MWTN_INFORMATION_RATE_CUR":"Current infromation rate", + "MWTN_LAT_LON":"Lat/Lon", + "MWTN_LTP1":"LTP#1", + "MWTN_LTP2":"LTP#2", + "MWTN_LTPEXTENSION": "Extension", + "MWTN_LINK_IDENTIFIER": "Link identifier", + "MWTN_LINKS": "Links", + "MWTN_LOWER_LEVEL_LINK": "Lower level link", + "MWTN_LOOP_BACK_IS_AVAIL": "Loopback support", + "MWTN_LOOP_BACK_IS_ON": "Loop-back is on", + "MWTN_LOOP_BACK_IS_UP": "Loopback", + "MWTN_MED_ADD": "Add", + "MWTN_MED_START":"Start", + "MWTN_MED_STOP":"Stop", + "MWTN_MED_CLOSE":"Close", + "MWTN_MED_DELETE":"Delete", + "MWTN_NEIPADDRESS": "IP address", + "MWTN_NEEXTENSION": "Extension", + "MWTN_NE_EXTENSION":"Extension", + "MWTN_NETYPE": "Network element type", + "MWTN_ONF_PTP_DATASET:MULTICAST_MAC_ADDRESS": "Multicast MAC address", + "MWTN_ONF_PTP_DATASET:MAX_STEPS_REMOVED": "Max. steps removed", + "MWTN_PEER_LTP_REF": "Peer LTP", + "MWTN_PHYSICAL_PORT_REFERENCE": "Physical port", + "MWTN_PTP_DEFAULT_DS_CONFIGURATION": "PTP default dataset configuration", + "MWTN_PTP_PORT_CONFIGURATION":"PTP port configuration", + "MWTN_RADIO": "Radio", + "MWTN_REQUIRED_NETWORK_ELEMENTS": "Required network elements", + "MWTN_REVISION": "Revision", + "MWTN_ROOTEQUIPMENT": "Equipment", + "MWTN_SERVICE_ID":"Service ID", + "MWTN_SCANNING": "Scanning...", + "MWTN_SCAN_NETWORK": "Scan network", + "MWTN_START_TIME": "Start time", + "MWTN_SITE_ID": "Site identifier", + "MWTN_SITE_NAME": "Site-name", + "MWTN_SUPPORTED_LOOP_BACK_KIND_LIST":"Supported loopback types", + "MWTN_STATUS": "Status", + "MWTN_TOP_LEVEL_EQUIPMENT":"Main equipment", + "MWTN_TYPE": "Type", + "MWTN_UNKNOWN_NETWORK_ELEMENTS": "Unknown network elements", + "MWTN_VEXTENSION": "Extension", + "MWTN_WEBURI": "Web UI", + + "MWTN_$$HASHKEY": "Key", + "MWTN_ACTION_VERB": "action-verb", + "MWTN_ACTUAL_EQUIPMENT": "actual-equipment", + "MWTN_ACTUAL_HOLDER": "actual-holder", + "MWTN_ADAPTIVEMODULATIONISAVAIL": "adaptiveModulationIsAvail", + "MWTN_ADAPTIVEMODULATIONISON": "adaptiveModulationIsOn", + "MWTN_ADAPTIVE_MODULATION_IS_AVAIL": "adaptive-modulation-is-avail", + "MWTN_ADAPTIVE_MODULATION_IS_ON": "adaptive-modulation-is-on", + "MWTN_ADDRESS_ELEMENT": "address-element", + "MWTN_ADDRESS_ELEMENT_NAME": "address-element-name", + "MWTN_ADDRESS_NAME": "address-name", + "MWTN_ADD_TO_REQUIRED_NETWORKELEMENTS": "Add to required Network Elements", + "MWTN_ADMINISTRATIVECONTROL": "administrativeControl", + "MWTN_ADMINISTRATIVESTATE": "administrativeState", + "MWTN_ADMINISTRATIVE_CONTROL": "administrative-control", + "MWTN_ADMINISTRATIVE_STATE": "administrative-state", + "MWTN_AGGREGATE_FUNCTION": "aggregate-function", + "MWTN_AIRINTERFACECAPABILITY": "airInterfaceCapability", + "MWTN_AIRINTERFACECONFIGURATION": "AirInterfaceConfiguration", + "MWTN_AIRINTERFACECURRENTPERFORMANCE": "AirInterfaceCurrentPerformance", + "MWTN_AIRINTERFACECURRENTPROBLEMS": "airInterfaceCurrentProblems", + "MWTN_AIRINTERFACEDIVERSITY": "airInterfaceDiversity", + "MWTN_AIRINTERFACEDIVERSITYCAPABILITY": "airInterfaceDiversityCapability", + "MWTN_AIRINTERFACEDIVERSITYCONFIGURATION": "airInterfaceDiversityConfiguration", + "MWTN_AIRINTERFACEDIVERSITYCURRENTPERFORMANCE": "AirInterfaceDiversityCurrentPerformance", + "MWTN_AIRINTERFACEDIVERSITYCURRENTPROBLEMS": "AirInterfaceDiversityCurrentProblems", + "MWTN_AIRINTERFACEDIVERSITYHISTORICALPERFORMANCES": "airInterfaceDiversityHistoricalPerformances", + "MWTN_AIRINTERFACEDIVERSITYSTATUS": "AirInterfaceDiversityStatus", + "MWTN_AIRINTERFACEHISTORICALPERFORMANCES": "airInterfaceHistoricalPerformances", + "MWTN_AIRINTERFACEHSBCONFIGURATIONISFAULTYSEVERITY": "airInterfaceHsbConfigurationIsFaultySeverity", + "MWTN_AIRINTERFACEHSBISDOWNSEVERITY": "airInterfaceHsbIsDownSeverity", + "MWTN_AIRINTERFACEHSBISPARTLYDOWNSEVERITY": "airInterfaceHsbIsPartlyDownSeverity", + "MWTN_AIRINTERFACEID": "Air interface identifier", + "MWTN_AIRINTERFACELIST": "airInterfaceList", + "MWTN_AIRINTERFACELTPLIST": "airInterfaceLtpList", + "MWTN_AIRINTERFACENAME": "Air interface name", + "MWTN_AIRINTERFACESTATUS": "airInterfaceStatus", + "MWTN_AIR_INTERFACE": "Air interface", + "MWTN_AIR_INTERFACES": "Air interfaces", + "MWTN_AIR_INTERFACE_CAPABILITY": "air-interface-capability", + "MWTN_AIR_INTERFACE_CONFIGURATION": "air-interface-configuration", + "MWTN_AIR_INTERFACE_CURRENT_PERFORMANCE": "air-interface-current-performance", + "MWTN_AIR_INTERFACE_CURRENT_PROBLEMS": "air-interface-current-problems", + "MWTN_AIR_INTERFACE_DIVERSITY": "air-interface-diversity", + "MWTN_AIR_INTERFACE_DIVERSITY_CAPABILITY": "air-interface-diversity-capability", + "MWTN_AIR_INTERFACE_DIVERSITY_CONFIGURATION": "air-interface-diversity-configuration", + "MWTN_AIR_INTERFACE_DIVERSITY_CURRENT_PERFORMANCE": "air-interface-diversity-current-performance", + "MWTN_AIR_INTERFACE_DIVERSITY_CURRENT_PROBLEMS": "air-interface-diversity-current-problems", + "MWTN_AIR_INTERFACE_DIVERSITY_HISTORICAL_PERFORMANCES": "air-interface-diversity-historical-performances", + "MWTN_AIR_INTERFACE_DIVERSITY_STATUS": "air-interface-diversity-status", + "MWTN_AIR_INTERFACE_HISTORICAL_PERFORMANCES": "air-interface-historical-performances", + "MWTN_AIR_INTERFACE_HSB_CONFIGURATION_IS_FAULTY_SEVERITY": "air-interface-hsb-configuration-is-faulty-severity", + "MWTN_AIR_INTERFACE_HSB_IS_DOWN_SEVERITY": "air-interface-hsb-is-down-severity", + "MWTN_AIR_INTERFACE_HSB_IS_PARTLY_DOWN_SEVERITY": "air-interface-hsb-is-partly-down-severity", + "MWTN_AIR_INTERFACE_NAME": "air-interface-name", + "MWTN_AIR_INTERFACE_STATUS": "air-interface-status", + "MWTN_ALARMS": "Alarms", + "MWTN_ALARM_LOG": "Alarm log", + "MWTN_ALARM_NOTIFICATIONS": "Alarm notifications", + "MWTN_ALARM_STATUS": "Alarm status", + "MWTN_ALICISAVAIL": "alicIsAvail", + "MWTN_ALICISON": "alicIsOn", + "MWTN_ALICISUP": "alicIsUp", + "MWTN_ALIC_IS_AVAIL": "alic-is-avail", + "MWTN_ALIC_IS_ON": "alic-is-on", + "MWTN_ALIC_IS_UP": "alic-is-up", + "MWTN_AMDOWNSHIFTLEVEL": "AM downshift level", + "MWTN_AMUPSHIFTLEVEL": "AM upshift level", + "MWTN_AM_DOWNSHIFT_LEVEL": "am-downshift-level", + "MWTN_AM_UPSHIFT_LEVEL": "am-upshift-level", + "MWTN_ANNOUNCE_RECEIPT_TIMEOUT": "announce-receipt-timeout", + "MWTN_APPLY": "Apply", + "MWTN_ARBITRARY_ELEMENT": "arbitrary-element", + "MWTN_ASSET_INSTANCE_IDENTIFIER": "asset-instance-identifier", + "MWTN_ASSET_TYPE_IDENTIFIER": "asset-type-identifier", + "MWTN_ATPCISAVAIL": "atpcIsAvail", + "MWTN_ATPCISON": "atpcIsOn", + "MWTN_ATPCISUP": "atpcIsUp", + "MWTN_ATPCRANGE": "atpcRange", + "MWTN_ATPCTHRESHLOWER": "atpcThreshLower", + "MWTN_ATPCTHRESHUPPER": "atpcThreshUpper", + "MWTN_ATPC_IS_AVAIL": "atpc-is-avail", + "MWTN_ATPC_IS_ON": "atpc-is-on", + "MWTN_ATPC_IS_UP": "atpc-is-up", + "MWTN_ATPC_RANGE": "atpc-range", + "MWTN_ATPC_THRESH_LOWER": "atpc-thresh-lower", + "MWTN_ATPC_THRESH_UPPER": "atpc-thresh-upper", + "MWTN_ATTRIBUTE": "Attribute", + "MWTN_ATTRIBUTE_NAME": "attribute-name", + "MWTN_ATTRIBUTE_VALUE_CHANGED": "Attribute value changed", + "MWTN_AUTOFREQSELECTISAVAIL": "Automatic frequency selection", + "MWTN_AUTOFREQSELECTISON": "autoFreqSelectIsOn", + "MWTN_AUTOFREQSELECTISUP": "autoFreqSelectIsUp", + "MWTN_AUTOFREQSELECTRANGE": "autoFreqSelectRange", + "MWTN_AUTO_FREQ_SELECT_IS_AVAIL": "auto-freq-select-is-avail", + "MWTN_AUTO_FREQ_SELECT_IS_ON": "auto-freq-select-is-on", + "MWTN_AUTO_FREQ_SELECT_IS_UP": "auto-freq-select-is-up", + "MWTN_AUTO_FREQ_SELECT_RANGE": "auto-freq-select-range", + "MWTN_AVAILABLEKINDSOFCONTAINERLIST": "Supported clients", + "MWTN_AVAILABLEKINDSOFDIVERSITY": "availableKindsOfDiversity", + "MWTN_AVAILABLE_KINDS_OF_DIVERSITY": "available-kinds-of-diversity", + "MWTN_BUNDLINGISAVAIL": "bundlingIsAvail", + "MWTN_BUNDLING_IS_AVAIL": "bundling-is-avail", + "MWTN_CANCEL": "Cancel", + "MWTN_CAPABILITY": "Capability", + "MWTN_CATEGORY": "category", + "MWTN_CHANNELBANDWIDTH": "Channel bandwidth", + "MWTN_CHANNEL_BANDWIDTH": "channel-bandwidth", + "MWTN_CLASS_OF_INSTANCE": "class-of-instance", + "MWTN_CLEAR": "Clear", + "MWTN_CLIENT_LTP": "Client LTPs", + "MWTN_CLOCK": "Clock (IEEE 1588v2)", + "MWTN_CLOCK_ACCURACY": "clock-accuracy", + "MWTN_CLOCK_CLASS": "clock-class", + "MWTN_CLOCK_IDENTITY": "clock-identity", + "MWTN_CLOCK_QUALITY": "clock-quality", + "MWTN_CLOSE": "Close", + "MWTN_COCHANNELGROUP": "CoChannelGroup", + "MWTN_COCHANNELGROUPID": "coChannelGroupId", + "MWTN_CODE_RATE": "code-rate", + "MWTN_CODE_RATE_CUR": "code-rate-cur", + "MWTN_COLLAPSE_ALL": "Collapse all", + "MWTN_CONDITIONALPACKAGE": "Conditional package", + "MWTN_CONDITIONAL_PACKAGE": "Conditional package", + "MWTN_CONFIGURATION": "Configuration", + "MWTN_CONFIGUREDCLIENTCAPACITY": "configuredClientCapacity", + "MWTN_CONFIGURED_CLIENT_CAPACITY": "configured-client-capacity", + "MWTN_CONFIG_AND_SWITCH_CONTROLLER": "config-and-switch-controller", + "MWTN_CONNECTED_LTP": "connected-ltp", + "MWTN_CONNECTIONSTATUS": "Connection status", + "MWTN_CONNECTION_STATUS_LOG": "Connection status log", + "MWTN_CONNECTOR": "connector", + "MWTN_CONNECTOR_CABLE_END": "connector-cable-end", + "MWTN_CONNECTOR_CAPABILITY": "connector-capability", + "MWTN_CONNECTOR_CONFIGURATION": "connector-configuration", + "MWTN_CONNECTOR_CURRENT_PROBLEMS": "connector-current-problems", + "MWTN_CONNECTOR_IN_HOLDER": "connector-in-holder", + "MWTN_CONNECTOR_ON_EQUIPMENT_FOR_CABLE": "connector-on-equipment-for-cable", + "MWTN_CONNECTOR_ON_EQUIPMENT_FOR_HOLDER": "connector-on-equipment-for-holder", + "MWTN_CONNECTOR_PAC": "connector-pac", + "MWTN_CONNECTOR_STATUS": "connector-status", + "MWTN_CONNECTOR_TYPE": "connector-type", + "MWTN_CONTAINED_HOLDER": "contained-holder", + "MWTN_CONTAINER": "Client", + "MWTN_CONTAINERID": "containerID", + "MWTN_CONTAINERTYPE": "containerType", + "MWTN_CONTAINER_ID": "container-id", + "MWTN_CONTAINER_NAME": "container-name", + "MWTN_CONTAINER_TYPE": "container-type", + "MWTN_CONTROL_PARAMETERS": "control-parameters", + "MWTN_COUNTER": "counter", + "MWTN_CO_CHANNEL_GROUP": "co-channel-group", + "MWTN_CO_CHANNEL_GROUP_ID": "co-channel-group-id", + "MWTN_CREATE": "Create", + "MWTN_CRYPTOGRAPHICKEY": "cryptographicKey", + "MWTN_CRYPTOGRAPHIC_KEY": "cryptographic-key", + "MWTN_CSES": "CSES", + "MWTN_CURRENTPERFORMANCEDATALIST": "currentPerformanceDataList", + "MWTN_CURRENTPROBLEMLIST": "currentProblemList", + "MWTN_CURRENT_DS": "current-ds", + "MWTN_CURRENT_PERFORMANCE_DATA_LIST": "current-performance-data", + "MWTN_CURRENT_PROBLEM_LIST": "Current problem list", + "MWTN_CURRENT_UTC_OFFSET": "current-utc-offset", + "MWTN_CURRENT_UTC_OFFSET_VALID": "current-utc-offset-valid", + "MWTN_CUT_THROUGH_COMMANDS": "Cut-through commands", + "MWTN_DEFAULT_DS": "default-ds", + "MWTN_DEFECTBLOCKSSUM": "Defect blocks (sum)", + "MWTN_DEFECT_BLOCKS_SUM": "defect-blocks-sum", + "MWTN_DELAY_ASYMMETRY": "delay-asymmetry", + "MWTN_ONF_PTP_DATASET:DELAY_ASYMMETRY": "delay-asymmetry", + "MWTN_DELAY_MECHANISM": "delay-mechanism", + "MWTN_DELETE": "Delete", + "MWTN_DESCRIPTION": "description", + "MWTN_DESIGNATED_ENABLED": "designated-enabled", + "MWTN_ONF_PTP_DATASET:DESIGNATED_ENABLED": "designated-enabled", + "MWTN_DIRECTIONALITY": "Directionality", + "MWTN_DIVERSITY_NAME": "diversity-name", + "MWTN_DOMAIN_NUMBER": "domain-number", + "MWTN_DUPLEXDISTANCE": "Duplex distance", + "MWTN_DUPLEXDISTANCEISVARIABLE": "Variable duplex distance", + "MWTN_DUPLEX_DISTANCE": "duplex-distance", + "MWTN_DUPLEX_DISTANCE_IS_VARIABLE": "duplex-distance-is-variable", + "MWTN_EFFORT_AND_ACTION": "effort-and-action", + "MWTN_ELAPSEDTIME": "elapsedTime", + "MWTN_ELAPSED_TIME": "elapsed-time", + "MWTN_ENCRYPTIONISAVAIL": "encryptionIsAvail", + "MWTN_ENCRYPTIONISON": "encryptionIsOn", + "MWTN_ENCRYPTION_IS_AVAIL": "encryption-is-avail", + "MWTN_ENCRYPTION_IS_ON": "encryption-is-on", + "MWTN_ENDPOINT": "endpoint", + "MWTN_EQUIPMENT": "equipment", + "MWTN_EQUIPMENT_CAPABILITY": "equipment-capability", + "MWTN_EQUIPMENT_CONFIGURATION": "equipment-configuration", + "MWTN_EQUIPMENT_CURRENT_PROBLEMS": "equipment-current-problems", + "MWTN_EQUIPMENT_INSTANCE": "equipment-instance", + "MWTN_EQUIPMENT_LOCATION": "equipment-location", + "MWTN_EQUIPMENT_PAC": "equipment-pac", + "MWTN_EQUIPMENT_STATUS": "equipment-status", + "MWTN_EQUIPMENT_TYPE": "equipment-type", + "MWTN_ES": "ES", + "MWTN_ETH": "Ethernet (ETH)", + "MWTN_ETH-CTP": "Ethernet connection termination point (ETH-CTP)", + "MWTN_ETHERNETCONTAINERCAPABILITY": "EthernetContainerCapability", + "MWTN_ETHERNETCONTAINERCONFIGURATION": "ethernetContainerConfiguration", + "MWTN_ETHERNETCONTAINERCURRENTPERFORMANCE": "ethernetContainerCurrentPerformance", + "MWTN_ETHERNETCONTAINERCURRENTPROBLEMS": "ethernetContainerCurrentProblems", + "MWTN_ETHERNETCONTAINERHISTORICALPERFORMANCES": "ethernetContainerHistoricalPerformances", + "MWTN_ETHERNETCONTAINERSTATUS": "ethernetContainerStatus", + "MWTN_ETHERNET_CAPABILITY": "ethernet-capability", + "MWTN_ETHERNET_CONFIGURATION": "ethernet-configuration", + "MWTN_ETHERNET_CONTAINER_CAPABILITY": "ethernet-container-capability", + "MWTN_ETHERNET_CONTAINER_CONFIGURATION": "ethernet-container-configuration", + "MWTN_ETHERNET_CONTAINER_CURRENT_PERFORMANCE": "ethernet-container-current-performance", + "MWTN_ETHERNET_CONTAINER_CURRENT_PROBLEMS": "ethernet-container-current-problems", + "MWTN_ETHERNET_CONTAINER_HISTORICAL_PERFORMANCES": "ethernet-container-historical-performances", + "MWTN_ETHERNET_CONTAINER_STATUS": "ethernet-container-status", + "MWTN_ETHERNET_CURRENT_PERFORMANCE": "ethernet-current-performance", + "MWTN_ETHERNET_CURRENT_PROBLEMS": "ethernet-current-problems", + "MWTN_ETHERNET_HISTORICAL_PERFORMANCES": "ethernet-historical-performances", + "MWTN_ETHERNET_PAC": "ethernet-pac", + "MWTN_ETHERNET_STATUS": "ethernet-status", + "MWTN_EXPECTED_EQUIPMENT": "expected-equipment", + "MWTN_EXPECTED_HOLDER": "expected-holder", + "MWTN_EXPOSED_CABLE": "exposed-cable", + "MWTN_EXTENSION": "Extension", + "MWTN_EXTENSIONLIST": "extensionList", + "MWTN_FAULTY_FLAG": "faulty-flag", + "MWTN_FCPORT": "FcPort", + "MWTN_FCPORTDIRECTION": "fcPortDirection", + "MWTN_FCSWITCH": "fcswitch", + "MWTN_FC_BLOCKS_SIGNAL_TO_LP": "fc-blocks-signal-to-lp", + "MWTN_FC_PORT": "fc-port", + "MWTN_FC_PORT_DIRECTION": "fc-port-direction", + "MWTN_FC_SWITCH": "fc-switch", + "MWTN_FD": "fd", + "MWTN_FIRE_CHARACTERISTICS": "fire-characteristics", + "MWTN_FORWARDINGCONSTRUCT": "ForwardingConstruct", + "MWTN_FORWARDINGDIRECTION": "forwardingDirection", + "MWTN_FORWARDINGDOMAIN": "ForwardingDomain", + "MWTN_FORWARDING_CONSTRUCT": "forwarding-construct", + "MWTN_FORWARDING_DIRECTION": "forwarding-direction", + "MWTN_FREQUENCY_TRACEABLE": "frequency-traceable", + "MWTN_FUNCTION_ENABLERS": "function-enablers", + "MWTN_GENERALDIRECTIVES": "generaldirectives", + "MWTN_GEOGRAPHICAL_LOCATION": "geographical-location", + "MWTN_GLOBALCLASS": "GlobalClass", + "MWTN_GLOBAL_PAC": "global-pac", + "MWTN_GRAPH": "Graph", + "MWTN_GRANDMASTER_CLOCK_QUALITY": "grandmaster-clock-quality", + "MWTN_GRANDMASTER_IDENTITY": "grandmaster-identity", + "MWTN_GRANDMASTER_PRIORITY1": "grandmaster-priority1", + "MWTN_GRANDMASTER_PRIORITY2": "grandmaster-priority2", + "MWTN_GRANULARITYPERIOD": "granularityPeriod", + "MWTN_GRANULARITY_PERIOD": "granularity-period", + "MWTN_HEIGHT": "height", + "MWTN_HIDE": "Hide", + "MWTN_HISTORICALPERFORMANCEDATALIST": "historicalPerformanceDataList", + "MWTN_HISTORICAL_PERFORMANCE_DATA_LIST": "historical-performance-data", + "MWTN_HISTORYDATAID": "historyDataId", + "MWTN_HISTORY_DATA_ID": "history-data-id", + "MWTN_HOLDER": "holder", + "MWTN_HOLDER_CAPABILITY": "holder-capability", + "MWTN_HOLDER_CATEGORY": "holder-category", + "MWTN_HOLDER_CONFIGURATION": "holder-configuration", + "MWTN_HOLDER_CURRENT_PROBLEMS": "holder-current-problems", + "MWTN_HOLDER_LOCATION": "holder-location", + "MWTN_HOLDER_MONITORS": "holder-monitors", + "MWTN_HOLDER_PAC": "holder-pac", + "MWTN_HOLDER_STATUS": "holder-status", + "MWTN_HOLDER_STRUCTURE": "holder-structure", + "MWTN_HOLDOFFTIME": "holdOffTime", + "MWTN_HOLD_OFF_TIME": "hold-off-time", + "MWTN_HYBRIDMWSTRUCTURECAPABILITY": "hybridMwStructureCapability", + "MWTN_HYBRIDMWSTRUCTURECONFIGURATION": "HybridMwStructureConfiguration", + "MWTN_HYBRIDMWSTRUCTURECURRENTPERFORMANCE": "HybridMwStructureCurrentPerformance", + "MWTN_HYBRIDMWSTRUCTURECURRENTPROBLEMS": "hybridMwStructureCurrentProblems", + "MWTN_HYBRIDMWSTRUCTUREHISTORICALPERFORMANCES": "hybridMwStructureHistoricalPerformances", + "MWTN_HYBRIDMWSTRUCTURESTATUS": "hybridMwStructureStatus", + "MWTN_HYBRID_MW_STRUCTURE_CAPABILITY": "hybrid-mw-structure-capability", + "MWTN_HYBRID_MW_STRUCTURE_CONFIGURATION": "hybrid-mw-structure-configuration", + "MWTN_HYBRID_MW_STRUCTURE_CURRENT_PERFORMANCE": "hybrid-mw-structure-current-performance", + "MWTN_HYBRID_MW_STRUCTURE_CURRENT_PROBLEMS": "hybrid-mw-structure-current-problems", + "MWTN_HYBRID_MW_STRUCTURE_HISTORICAL_PERFORMANCES": "hybrid-mw-structure-historical-performances", + "MWTN_HYBRID_MW_STRUCTURE_STATUS": "hybrid-mw-structure-status", + "MWTN_ID": "Identifier", + "MWTN_INFORMATIONRATE": "Information rate", + "MWTN_INFORMATIONRATECUR": "informationRateCur", + "MWTN_INSTANCE_LIST": "instances", + "MWTN_INSTANCE_NUMBER": "instance-number", + "MWTN_INTERFACE": "Interface", + "MWTN_INTERFERENCE_ALARM!": "INTERFERENCE ALARM!!!", + "MWTN_INTERFERENCE_ALARM?": "Interference alarm?", + "MWTN_INTERFERENCE_ALARM_STATUS": "Interferance alarm status", + "MWTN_INTERNAL_CONFIGURATION_AND_SWITCH_CONTROL": "internal-configuration-and-switch-control", + "MWTN_IPADDRESS": "IP address", + "MWTN_IPV4COMPRESSIONISAVAIL": "ipv4CompressionIsAvail", + "MWTN_IPV4COMPRESSIONISON": "ipv4CompressionIsOn", + "MWTN_IPV4_COMPRESSION_IS_AVAIL": "ipv4-compression-is-avail", + "MWTN_IPV4_COMPRESSION_IS_ON": "ipv4-compression-is-on", + "MWTN_IPV6COMPRESSIONISAVAIL": "ipv6CompressionIsAvail", + "MWTN_IPV6COMPRESSIONISON": "ipv6CompressionIsOn", + "MWTN_IPV6_COMPRESSION_IS_AVAIL": "ipv6-compression-is-avail", + "MWTN_IPV6_COMPRESSION_IS_ON": "ipv6-compression-is-on", + "MWTN_IS_ACTIVE": "is-active", + "MWTN_IS_ACTUAL_MISMATCH_WITH_EXPECTED": "is-actual-mismatch-with-expected", + "MWTN_IS_CAPTIVE": "is-captive", + "MWTN_IS_COORDINATED_SWITCHING_BOTH_ENDS": "is-coordinated-switching-both-ends", + "MWTN_IS_FIELD_REPLACEABLE": "is-field-replaceable", + "MWTN_IS_FROZEN": "is-frozen", + "MWTN_IS_GUIDED": "is-guided", + "MWTN_IS_HOT_SWAPPABLE": "is-hot-swappable", + "MWTN_IS_INTERNAL_PORT": "is-internal-port", + "MWTN_IS_NOT": "is-not", + "MWTN_IS_PROTECTION_LOCK_OUT": "is-protection-lock-out", + "MWTN_IS_QUANTIZED_SPACE": "is-quantized-space", + "MWTN_IS_SHORT_LIVED": "is-short-lived", + "MWTN_ITEMS": "items", + "MWTN_LABEL": "Label", + "MWTN_LABELLIST": "labelList", + "MWTN_LASTSTATUSCHANGE": "lastStatusChange", + "MWTN_LAST_STATUS_CHANGE": "last-status-change", + "MWTN_LAYER": "Layer", + "MWTN_LAYER2COMPRESSIONISAVAIL": "layer2CompressionIsAvail", + "MWTN_LAYER2COMPRESSIONISON": "layer2CompressionIsOn", + "MWTN_LAYER2_COMPRESSION_IS_AVAIL": "layer2-compression-is-avail", + "MWTN_LAYER2_COMPRESSION_IS_ON": "layer2-compression-is-on", + "MWTN_LAYER4COMPRESSIONISAVAIL": "layer4CompressionIsAvail", + "MWTN_LAYER4COMPRESSIONISON": "layer4CompressionIsOn", + "MWTN_LAYER4_COMPRESSION_IS_AVAIL": "layer4-compression-is-avail", + "MWTN_LAYER4_COMPRESSION_IS_ON": "layer4-compression-is-on", + "MWTN_LAYERPROTOCOL": "LayerProtocol", + "MWTN_LAYERPROTOCOLNAME": "layerProtocolName", + "MWTN_LAYERPROTOCOLNAMELIST": "layerProtocolNameList", + "MWTN_LAYER_PROTOCOL": "layer-protocol", + "MWTN_LAYER_PROTOCOL_NAME": "layer-protocol-name", + "MWTN_LEAP59": "leap59", + "MWTN_LEAP61": "leap61", + "MWTN_LENGTH": "length", + "MWTN_LIFECYCLESTATE": "lifecycleState", + "MWTN_LIFECYCLE_STATE": "lifecycle-state", + "MWTN_LINKISUP": "linkIsUp", + "MWTN_LINK_IS_UP": "link-is-up", + "MWTN_LOADING": "Loading...", + "MWTN_LOCALCLASS": "LocalClass", + "MWTN_LOCALENDPOINTID": "localEndPointId", + "MWTN_LOCALIDLIST": "localIdList", + "MWTN_LOCAL_END_POINT": "local-end-point", + "MWTN_LOCAL_END_POINT_ID": "local-end-point-id", + "MWTN_LOCAL_ID": "local-id", + "MWTN_LOCAL_PAC": "local-pac", + "MWTN_LOCAL_PRIORITY": "local-priority", + "MWTN_ONF_PTP_DATASET:LOCAL_PRIORITY": "local-priority", + "MWTN_LOCATION": "location", + "MWTN_LOGICALTERMINATIONPOINT": "LogicalTerminationPoint", + "MWTN_LOGICAL_TERMINATION_POINT": "logical-termination-point", + "MWTN_ONF_PTP_DATASET:LOGICAL_TERMINATION_POINT": "logical-termination-point", + "MWTN_LOG_ANNOUNCE_INTERVAL": "log-announce-interval", + "MWTN_LOG_MIN_DELAY_REQ_INTERVAL": "log-min-delay-req-interval", + "MWTN_LOG_MIN_PDELAY_REQ_INTERVAL": "log-min-pdelay-req-interval", + "MWTN_LOG_SYNC_INTERVAL": "log-sync-interval", + "MWTN_LOOPBACKISAVAIL": "loopBackIsAvail", + "MWTN_LOOPBACKISON": "loopBackIsOn", + "MWTN_LOOPBACKISUP": "loopBackIsUp", + "MWTN_LOOP_BACK_KIND_ON": "loop-back-kind-on", + "MWTN_LOOP_BACK_KIND_UP": "loop-back-kind-up", + "MWTN_LP": "Layer protocol", + "MWTN_LPDIRECTION": "lpDirection", + "MWTN_LP_DIRECTION": "lp-direction", + "MWTN_LTP": "LTP", + "MWTN_LTPS": "LTPs", + "MWTN_LTPDIRECTION": "ltpDirection", + "MWTN_LTP_DIRECTION": "ltp-direction", + "MWTN_MAINTENANCETIMER": "maintenanceTimer", + "MWTN_MAINTENANCETIMERRANGE": "maintenanceTimerRange", + "MWTN_MAINTENANCE_TIMER": "maintenance-timer", + "MWTN_MAINTENANCE_TIMER_RANGE": "maintenance-timer-range", + "MWTN_MAKE_KNOWN": "To required NEs...", + "MWTN_MANUFACTURED_THING": "manufactured-thing", + "MWTN_MANUFACTURER_IDENTIFIER": "manufacturer-identifier", + "MWTN_MANUFACTURER_NAME": "manufacturer-name", + "MWTN_MANUFACTURER_PROPERTIES": "manufacturer-properties", + "MWTN_MANUFACTURE_DATE": "manufacture-date", + "MWTN_MASTER_ONLY": "master-only", + "MWTN_ONF_PTP_DATASET:MASTER_ONLY": "master-only", + "MWTN_MATERIALS": "materials", + "MWTN_MAX_NUMBER_OF_SEGMENTS_RESERVABLE": "max-number-of-segments-reservable", + "MWTN_MAX_STEPS_REMOVED": "max-steps-removed", + "MWTN_MEAN_PATH_DELAY": "mean-path-delay", + "MWTN_MECHANICAL_FEATURES": "mechanical-features", + "MWTN_MECHANICAL_FUNCTIONS": "mechanical-functions", + "MWTN_MESSAGE": "Message", + "MWTN_MICROWAVEMODEL_OBJECTCLASSES_AIRINTERFACE:MW_AIRINTERFACE_PAC": "Airinterface", + "MWTN_MICROWAVEMODEL_OBJECTCLASSES_ETHERNETCONTAINER:MW_ETHERNETCONTAINER_PAC": "Ethernet container", + "MWTN_MICROWAVEMODEL_OBJECTCLASSES_PUREETHERNETSTRUCTURE:MW_PUREETHERNETSTRUCTURE_PAC": "Structure (pure ethernet)", + "MWTN_MICROWAVE_MODEL:MW_AIR_INTERFACE_DIVERISTY_PAC": "Diversity", + "MWTN_MICROWAVE_MODEL:MW_AIR_INTERFACE_PAC": "Airinterface", + "MWTN_MICROWAVE_MODEL:MW_ETHERNET_CONTAINER_PAC": "Ethernet container", + "MWTN_MICROWAVE_MODEL:MW_HYBRID_MW_STRUCTURE_PAC": "Structure (hybrid)", + "MWTN_MICROWAVE_MODEL:MW_PURE_ETHERNET_STRUCTURE_PAC": "Structure (pure ethernet)", + "MWTN_MICROWAVE_MODEL:MW_TDM_CONTAINER_PAC": "TDM container", + "MWTN_MIMOCHANNELS": "mimoChannels", + "MWTN_MIMOISAVAIL": "mimoIsAvail", + "MWTN_MIMOISON": "mimoIsOn", + "MWTN_MIMOISUP": "mimoIsUp", + "MWTN_MIMO_CHANNELS": "mimo-channels", + "MWTN_MIMO_IS_AVAIL": "mimo-is-avail", + "MWTN_MIMO_IS_ON": "mimo-is-on", + "MWTN_MIMO_IS_UP": "mimo-is-up", + "MWTN_MODEL_IDENTIFIER": "model-identifier", + "MWTN_MODULATIONCUR": "modulationCur", + "MWTN_MODULATIONISON": "modulationIsOn", + "MWTN_MODULATIONMAX": "modulationMax", + "MWTN_MODULATIONMIN": "modulationMin", + "MWTN_MODULATIONSCHEME": "Modulation scheme", + "MWTN_MODULATION_CUR": "modulation-cur", + "MWTN_MODULATION_IS_ON": "modulation-is-on", + "MWTN_MODULATION_MAX": "modulation-max", + "MWTN_MODULATION_MIN": "modulation-min", + "MWTN_MODULATION_SCHEME": "modulation-scheme", + "MWTN_MOUNT": "Mount", + "MWTN_MOUNTPOINT": "Mountpoint", + "MWTN_MPLSCOMPRESSIONISAVAIL": "mplsCompressionIsAvail", + "MWTN_MPLSCOMPRESSIONISON": "mplsCompressionIsOn", + "MWTN_MPLS_COMPRESSION_IS_AVAIL": "mpls-compression-is-avail", + "MWTN_MPLS_COMPRESSION_IS_ON": "mpls-compression-is-on", + "MWTN_MULTICAST_MAC_ADDRESS": "multicast-mac-address", + "MWTN_MWCURRENTPROBLEM": "MwCurrentProblem", + "MWTN_MWPS": "Microwave Physical Section (MWPS)", + "MWTN_MWS": "Microwave Section (MWS)", + "MWTN_MW_AIRINTERFACEDIVERSITY_PAC": "MW_AirInterfaceDiversity_Pac", + "MWTN_MW_AIRINTERFACEHSBENDPOINT_PAC": "MW_AirInterfaceHsbEndPoint_Pac", + "MWTN_MW_AIRINTERFACEHSBFCSWITCH_PAC": "MW_AirInterfaceHsbFcSwitch_Pac", + "MWTN_MW_AIRINTERFACE_PAC": "MW_AirInterface_Pac", + "MWTN_MW_AIR_INTERFACE_DIVERSITY_PAC": "mw-air-interface-diversity-pac", + "MWTN_MW_AIR_INTERFACE_HSB_END_POINT_PAC": "mw-air-interface-hsb-end-point-pac", + "MWTN_MW_AIR_INTERFACE_HSB_FC_SWITCH_PAC": "mw-air-interface-hsb-fc-switch-pac", + "MWTN_MW_AIR_INTERFACE_PAC": "mw-air-interface-pac", + "MWTN_MW_ETHERNETCONTAINER_PAC": "MW_EthernetContainer_Pac", + "MWTN_MW_ETHERNET_CONTAINER_PAC": "mw-ethernet-container-pac", + "MWTN_MW_HYBRIDMWSTRUCTURE_PAC": "MW_HybridMwStructure_Pac", + "MWTN_MW_HYBRID_MW_STRUCTURE_PAC": "mw-hybrid-mw-structure-pac", + "MWTN_MW_PUREETHERNETSTRUCTURE_PAC": "MW_PureEthernetStructure_Pac", + "MWTN_MW_PURE_ETHERNET_STRUCTURE_PAC": "mw-pure-ethernet-structure-pac", + "MWTN_MW_TDMCONTAINER_PAC": "MW_TdmContainer_Pac", + "MWTN_MW_TDM_CONTAINER_PAC": "mw-tdm-container-pac", + "MWTN_NAME": "Name", + "MWTN_NAMEANDVALUEAUTHORITY": "NameAndValueAuthority", + "MWTN_NAMEBINDING": "nameBinding", + "MWTN_NAMELIST": "nameList", + "MWTN_NAME_BINDING": "name-binding", + "MWTN_NECESSARY_INITIALCONDITION_CONSTRAINTS": "necessary-initialcondition-constraints", + "MWTN_NETCONF_PORT": "NetConf port", + "MWTN_NETWORKELEMENT": "Network element", + "MWTN_NETWORK_ELEMENT": "network-element", + "MWTN_NETWORK_ELEMENT_CAPABILITY": "network-element-capability", + "MWTN_NETWORK_ELEMENT_CONFIGURATION": "network-element-configuration", + "MWTN_NETWORK_ELEMENT_CURRENT_PROBLEMS": "network-element-current-problems", + "MWTN_NETWORK_ELEMENT_PAC": "network-element-pac", + "MWTN_NETWORK_ELEMENT_STATUS": "network-element-status", + "MWTN_NETWORK_SCHEME_SPECIFICATION": "network-scheme-specification", + "MWTN_NEW_VALUE": "new-value", + "MWTN_NICKNAME": "Nickname", + "MWTN_NODES": "Nodes", + "MWTN_NO_DEVICES_CONNECTED": "Sorry, no Microwave devices connected to OpenDaylight.", + "MWTN_NUMBEROFLTPS": "# of LTPs", + "MWTN_NUMBEROFTDMSEGMENTSTOBERESERVED": "numberOfTdmSegmentsToBeReserved", + "MWTN_NUMBER_OF_AIR_INTERFACES_MAX": "number-of-air-interfaces-max", + "MWTN_NUMBER_OF_TDM_SEGMENTS_TO_BE_RESERVED": "number-of-tdm-segments-to-be-reserved", + "MWTN_NUMBER_OF_TIME_SLOTS_REQUIRED": "number-of-time-slots-required", + "MWTN_NUMBER_PORTS": "number-ports", + "MWTN_OBJECTCLASS": "objectClass", + "MWTN_OBJECTIDREF": "Object", + "MWTN_OBJECT_CLASS": "object-class", + "MWTN_OBJECT_DELETION_CREATION": "Object deletion or creation", + "MWTN_OBJECT_ID_REF": "object-id-ref", + "MWTN_OBJECT_REFERENCE": "object-reference", + "MWTN_OBJECT_TYPE": "object-type", + "MWTN_OBSERVED_PARENT_CLOCK_PHASE_CHANGE_RATE": "observed-parent-clock-phase-change-rate", + "MWTN_OBSERVED_PARENT_OFFSET_SCALED_LOG_VARIANCE": "observed-parent-offset-scaled-log-variance", + "MWTN_OBSOLETE_DROP_ORDER_RANK": "obsolete-drop-order-rank", + "MWTN_OBSOLETE_PRIORITY_CLASS": "obsolete-priority-class", + "MWTN_OCCUPYING_FRU": "occupying-fru", + "MWTN_OFFSET_FROM_MASTER": "offset-from-master", + "MWTN_OFFSET_SCALED_LOG_VARIANCE": "offset-scaled-log-variance", + "MWTN_OK": "Ok", + "MWTN_ONF_ETHERNET_CONDITIONAL_PACKAGES:ETHERNET_PAC": "Ethernet", + "MWTN_OPERATIONALSTATE": "operationalState", + "MWTN_OPERATIONALSTATUS": "Operational status", + "MWTN_OPERATIONAL_STATE": "operational-state", + "MWTN_OPERATIONAL_STATUS": "operational-status", + "MWTN_OPERATIONIDENTIFIERS": "operationidentifiers", + "MWTN_OPERATION_DETAILS": "operation-details", + "MWTN_OPERATION_ENVELOPE": "operation-envelope", + "MWTN_OPERATION_SET": "operation-set", + "MWTN_OPERATOR_AUGMENTED_EQUIPMENT_TYPE": "operator-augmented-equipment-type", + "MWTN_OPERTYPE": "operType", + "MWTN_ORIENTATION": "orientation", + "MWTN_OTN_CURRENTDATA": "OTN_CurrentData", + "MWTN_OTN_HISTORYDATA": "OTN_HistoryData", + "MWTN_PACKETCOMPRESSIONISAVAIL": "packetCompressionIsAvail", + "MWTN_PACKETCOMPRESSIONISON": "packetCompressionIsOn", + "MWTN_PACKET_COMPRESSION_IS_AVAIL": "packet-compression-is-avail", + "MWTN_PACKET_COMPRESSION_IS_ON": "packet-compression-is-on", + "MWTN_PARENT_DS": "parent-ds", + "MWTN_PARENT_PORT_IDENTITY": "parent-port-identity", + "MWTN_PARENT_STATS": "parent-stats", + "MWTN_PART_TYPE_IDENTIFIER": "part-type-identifier", + "MWTN_PASSWORD": "Password", + "MWTN_PAUSE_RESUME_RULE": "pause-resume-rule", + "MWTN_PEER_LTP": "peer-ltp", + "MWTN_PEER_MEAN_PATH_DELAY": "peer-mean-path-delay", + "MWTN_PERFORMANCEDATA": "Performance data", + "MWTN_PERFORMANCE_DATA": "Performance-data", + "MWTN_PERIODENDTIME": "period-end-time", + "MWTN_PERIOD_END_TIME": "period-end-time", + "MWTN_PHYSICALPORTREFERENCE": "physical-port-reference", + "MWTN_PHYSICAL_CHARACTERISTICS": "physical-characteristics", + "MWTN_PHYSICAL_PROPERTIES": "physical-properties", + "MWTN_PHYSICAL_RATING": "physical-rating", + "MWTN_PIN": "pin", + "MWTN_PIN_GROUP": "pin-group", + "MWTN_PIN_LAYOUT": "pin-layout", + "MWTN_POLARIZATION": "Polarization", + "MWTN_PORT": "Port", + "MWTN_PORT_DS_LIST": "ptp-ports", + "MWTN_PORT_IDENTITY": "port-identity", + "MWTN_PORT_NUMBER": "port-number", + "MWTN_PORT_STATE": "port-state", + "MWTN_POSITION": "position", + "MWTN_POWERISON": "powerIsOn", + "MWTN_POWER_IS_ON": "power-is-on", + "MWTN_POWER_RATING": "power-rating", + "MWTN_POWER_STATE": "power-state", + "MWTN_PRIMARY_DOMAIN": "primary-domain", + "MWTN_PRIORITY1": "priority1", + "MWTN_PRIORITY2": "priority2", + "MWTN_PROBLEM": "problem", + "MWTN_PROBLEMKINDNAME": "Alarm", + "MWTN_PROBLEMKINDSEVERITY": "Severity", + "MWTN_PROBLEMKINDSEVERITYLIST": "Severity list", + "MWTN_PROBLEMNAME": "Problem name", + "MWTN_PROBLEMSEVERITY": "Severity", + "MWTN_PROBLEM_KIND_NAME": "problem-type", + "MWTN_PROBLEM_KIND_SEVERITY": "severity", + "MWTN_PROBLEM_KIND_SEVERITY_LIST": "severities", + "MWTN_PROBLEM_NAME": "problem-name", + "MWTN_PROBLEM_SEVERITY": "problem-severity", + "MWTN_PROBLEM_TYPE_NAME": "problem-type-name", + "MWTN_PROBLEM_TYPE_SEVERITY": "problem-type-severity", + "MWTN_PROBLEM_TYPE_SEVERITY_LIST": "problem-severities", + "MWTN_PROTTYPE": "protType", + "MWTN_PROT_TYPE": "prot-type", + "MWTN_PTP_TIMESCALE": "ptp-timescale", + "MWTN_PUREETHERNETSTRUCTURECAPABILITY": "pureEthernetStructureCapability", + "MWTN_PUREETHERNETSTRUCTURECONFIGURATION": "pureEthernetStructureConfiguration", + "MWTN_PUREETHERNETSTRUCTURECURRENTPERFORMANCE": "PureEthernetStructureCurrentPerformance", + "MWTN_PUREETHERNETSTRUCTURECURRENTPROBLEMS": "PureEthernetStructureCurrentProblems", + "MWTN_PUREETHERNETSTRUCTUREHISTORICALPERFORMANCES": "PureEthernetStructureHistoricalPerformances", + "MWTN_PUREETHERNETSTRUCTURESTATUS": "PureEthernetStructureStatus", + "MWTN_PURE_ETHERNET_STRUCTURE_CAPABILITY": "pure-ethernet-structure-capability", + "MWTN_PURE_ETHERNET_STRUCTURE_CONFIGURATION": "pure-ethernet-structure-configuration", + "MWTN_PURE_ETHERNET_STRUCTURE_CURRENT_PERFORMANCE": "pure-ethernet-structure-current-performance", + "MWTN_PURE_ETHERNET_STRUCTURE_CURRENT_PROBLEMS": "pure-ethernet-structure-current-problems", + "MWTN_PURE_ETHERNET_STRUCTURE_HISTORICAL_PERFORMANCES": "pure-ethernet-structure-historical-performances", + "MWTN_PURE_ETHERNET_STRUCTURE_STATUS": "pure-ethernet-structure-status", + "MWTN_QINQCOMPRESSIONISAVAIL": "qInQCompressionIsAvail", + "MWTN_QINQCOMPRESSIONISON": "qInQCompressionIsOn", + "MWTN_Q_IN_Q_COMPRESSION_IS_AVAIL": "q-in-q-compression-is-avail", + "MWTN_Q_IN_Q_COMPRESSION_IS_ON": "q-in-q-compression-is-on", + "MWTN_RADIOPOWERISUP": "radioPowerIsUp", + "MWTN_RADIOSIGNALID": "Radio signal identifier", + "MWTN_RADIOSIGNALIDS": "Radio signal identifiers", + "MWTN_RADIO_POWER_IS_UP": "radio-power-is-up", + "MWTN_RADIO_SIGNAL_ID": "radio-signal-id", + "MWTN_RECEIVERISON": "receiverIsOn", + "MWTN_RECEIVER_IS_ON": "receiver-is-on", + "MWTN_REFRESH": "Refresh", + "MWTN_REFRESH_STATUS": "refresh-status", + "MWTN_RELATIVE_POSITION": "relative-position", + "MWTN_REMOTEENDPOINTID": "remoteEndPointId", + "MWTN_REMOTE_END_POINT": "remote-end-point", + "MWTN_REMOTE_END_POINT_ID": "remote-end-point-id", + "MWTN_REVERSION_MODE": "reversion-mode", + "MWTN_REVISON": "Revision", + "MWTN_RFTEMPAVG": "Temerature (avg)", + "MWTN_RFTEMPCUR": "rfTempCur", + "MWTN_RFTEMPMAX": "Temerature (max)", + "MWTN_RFTEMPMIN": "Temerature (min)", + "MWTN_RF_TEMP_AVG": "rf-temp-avg", + "MWTN_RF_TEMP_CUR": "rf-temp-cur", + "MWTN_RF_TEMP_MAX": "rf-temp-max", + "MWTN_RF_TEMP_MIN": "rf-temp-min", + "MWTN_ROLE": "role", + "MWTN_ROTATION_SPEED": "rotation-speed", + "MWTN_RXCHANNELBANDWIDTH": "rxChannelBandwidth", + "MWTN_RXFREQUENCY": "Receive frequency", + "MWTN_RXFREQUENCYCUR": "rxFrequencyCur", + "MWTN_RXFREQUENCYMAX": "rxFrequencyMax", + "MWTN_RXFREQUENCYMIN": "rxFrequencyMin", + "MWTN_RXLEVELAVG": "Receive level (avg)", + "MWTN_RXLEVELCUR": "rxLevelCur", + "MWTN_RXLEVELMAX": "Receive level (min)", + "MWTN_RXLEVELMIN": "Receive level (max)", + "MWTN_RXTHRESHOLD": "RX threshold", + "MWTN_RX_CHANNEL_BANDWIDTH": "rx-channel-bandwidth", + "MWTN_RX_FREQUENCY": "rx-frequency", + "MWTN_RX_FREQUENCY_CUR": "rx-frequency-cur", + "MWTN_RX_FREQUENCY_MAX": "rx-frequency-max", + "MWTN_RX_FREQUENCY_MIN": "rx-frequency-min", + "MWTN_RX_LEVEL_AVG": "rx-level-avg", + "MWTN_RX_LEVEL_CUR": "rx-level-cur", + "MWTN_RX_LEVEL_MAX": "rx-level-max", + "MWTN_RX_LEVEL_MIN": "rx-level-min", + "MWTN_RX_THRESHOLD": "rx-threshold", + "MWTN_SCANNERID": "scannerId", + "MWTN_SCANNER_ID": "scanner-id", + "MWTN_SCRIPTID": "Script id", + "MWTN_SCRIPTLIST": "Scripts", + "MWTN_SEGMENTID": "segmentID", + "MWTN_SEGMENTSIDLIST": "segmentsIDList", + "MWTN_SEGMENTSTATUSLIST": "segmentStatusList", + "MWTN_SEGMENTS_ID_LIST": "segments-ids", + "MWTN_SEGMENT_ID": "segment-id", + "MWTN_SEGMENT_ID_REF": "segment-id-ref", + "MWTN_SEGMENT_IS_RESERVED_FOR_TDM": "segment-is-reserved-for-tdm", + "MWTN_SEGMENT_STATUS_LIST": "segment-status", + "MWTN_SEGMENT_STATUS_TYPE_ID": "segment-status-type-id", + "MWTN_SELECTION_PRIORITY": "selection-priority", + "MWTN_SELECT_LTP": "Select LTP", + "MWTN_SELECT_NETWORK_ELEMENT": "Select network element", + "MWTN_SEND": "Send", + "MWTN_SEQUENCENUMBER": "sequenceNumber", + "MWTN_SEQUENCE_NUMBER": "sequence-number", + "MWTN_SERIAL_NUMBER": "serial-number", + "MWTN_SERVERID": "Server identifier", + "MWTN_SERVER_LTP": "Server LTPs", + "MWTN_SERVICE_PRIORITY": "service-priority", + "MWTN_SES": "SES", + "MWTN_SEVERITY": "severity", + "MWTN_SHOWLIST": "Show list", + "MWTN_SHOWOBJECT": "Show object", + "MWTN_SINR": "Signal-to-interference-plus-noise ratio (SINR)", + "MWTN_SITE": "Site", + "MWTN_SLAVE_ONLY": "slave-only", + "MWTN_SNIRAVG": "SINR (avg)", + "MWTN_SNIRCUR": "SINR (current)", + "MWTN_SNIRMAX": "SINR (max)", + "MWTN_SNIRMIN": "SINR (min)", + "MWTN_SNIR_AVG": "SINR (avg)", + "MWTN_SNIR_CUR": "SINR (current)", + "MWTN_SNIR_MAX": "SINR (max)", + "MWTN_SNIR_MIN": "SINR (min)", + "MWTN_SORTOFCOCHANNELGROUP": "sortOfCoChannelGroup", + "MWTN_SORT_OF_CO_CHANNEL_GROUP": "sort-of-co-channel-group", + "MWTN_SPATIAL_PROPERTIES_OF_TYPE": "spatial-properties-of-type", + "MWTN_STATE_PAC": "State_Pac", + "MWTN_STEPS_REMOVED": "steps-removed", + "MWTN_STRUCTUREID": "structureId", + "MWTN_STRUCTURETYPE": "structureType", + "MWTN_STRUCTURE_ID": "structure-id", + "MWTN_STRUCTURE_ID_REF": "structure-id-ref", + "MWTN_STRUCTURE_TYPE": "structure-type", + "MWTN_SUBOBJECT": "Subobject", + "MWTN_SUM": "Sum", + "MWTN_SUPPORTEDALARMS": "supportedAlarms", + "MWTN_SUPPORTEDCHANNELPLAN": "Channnel plan", + "MWTN_SUPPORTEDCHANNELPLANLIST": "supportedChannelPlanList", + "MWTN_SUPPORTEDCHANNELPLANS": "Supported channel plans", + "MWTN_SUPPORTEDTDMCONTAINERTYPESLIST": "supportedTdmContainerTypesList", + "MWTN_SUPPORTEDTDMSTRUCTURETYPESLIST": "supportedTdmStructureTypesList", + "MWTN_SUPPORTED_ALARMS": "supported-alarms", + "MWTN_SUPPORTED_CHANNEL_PLAN": "supported-channel-plan", + "MWTN_SUPPORTED_CHANNEL_PLAN_LIST": "supported-channel-plans", + "MWTN_SUPPORTED_TDM_CONTAINER_TYPES_LIST": "supported-tdm-container-types", + "MWTN_SUPPORTED_TDM_STRUCTURE_TYPES_LIST": "supported-tdm-structure-types", + "MWTN_SUSPECTINTERVALFLAG": "suspectIntervalFlag", + "MWTN_SUSPECT_INTERVAL_FLAG": "suspect-interval-flag", + "MWTN_SWAPABILITY": "swapability", + "MWTN_SWITCH_CONTROL": "switch-control", + "MWTN_SWITCH_RULE": "switch-rule", + "MWTN_SWITCH_SELECTION_REASON": "switch-selection-reason", + "MWTN_SWITCH_SELECTS_PORTS": "switch-selects-ports", + "MWTN_TDMCONTAINERCAPABILITY": "tdmContainerCapability", + "MWTN_TDMCONTAINERCONFIGURATION": "tdmContainerConfiguration", + "MWTN_TDMCONTAINERCURRENTPERFORMANCE": "TdmContainerCurrentPerformance", + "MWTN_TDMCONTAINERCURRENTPROBLEMS": "tdmContainerCurrentProblems", + "MWTN_TDMCONTAINERHISTORICALPERFORMANCES": "TdmContainerHistoricalPerformances", + "MWTN_TDMCONTAINERSTATUS": "tdmContainerStatus", + "MWTN_TDM_CONTAINER_CAPABILITY": "tdm-container-capability", + "MWTN_TDM_CONTAINER_CONFIGURATION": "tdm-container-configuration", + "MWTN_TDM_CONTAINER_CURRENT_PERFORMANCE": "tdm-container-current-performance", + "MWTN_TDM_CONTAINER_CURRENT_PROBLEMS": "tdm-container-current-problems", + "MWTN_TDM_CONTAINER_HISTORICAL_PERFORMANCES": "tdm-container-historical-performances", + "MWTN_TDM_CONTAINER_NAME": "tdm-container-name", + "MWTN_TDM_CONTAINER_SIZE": "tdm-container-size", + "MWTN_TDM_CONTAINER_STATUS": "tdm-container-status", + "MWTN_TDM_SEGMENT_SIZE": "tdm-segment-size", + "MWTN_TDM_STRUCTURE_NAME": "tdm-structure-name", + "MWTN_TDM_TIME_SLOTS_IS_REQUIRED": "tdm-time-slots-is-required", + "MWTN_TEMPERATURE": "temperature", + "MWTN_TERMINATIONSTATE": "terminationState", + "MWTN_TERMINATION_STATE": "Termination state", + "MWTN_THERMAL_RATING": "thermal-rating", + "MWTN_TIME1024SYMBOLS": "Time 1024 QAM", + "MWTN_TIME1024SYMBOLSL": "Time 1024 QAM (light)", + "MWTN_TIME1024_STATES": "time1024-states", + "MWTN_TIME1024_STATES_L": "time1024-states-l", + "MWTN_TIME128SYMBOLS": "Time 128 QAM", + "MWTN_TIME128_STATES": "time128-states", + "MWTN_TIME16SYMBOLS": "Time 16 QAM", + "MWTN_TIME16SYMBOLSS": "Time 16 QAM (strong)", + "MWTN_TIME16_STATES": "time16-states", + "MWTN_TIME16_STATES_S": "time16-states-s", + "MWTN_TIME2048SYMBOLS": "Time 2048 QAM", + "MWTN_TIME2048SYMBOLSL": "Time 2048 QAM (light)", + "MWTN_TIME2048_STATES": "time2048-states", + "MWTN_TIME2048_STATES_L": "time2048-states-l", + "MWTN_TIME256SYMBOLS": "Time 256 QAM", + "MWTN_TIME256_STATES": "time256-states", + "MWTN_TIME2SYMBOLS": "Time 2 QAM", + "MWTN_TIME2_STATES": "time2-states", + "MWTN_TIME32SYMBOLS": "Time 32 QAM", + "MWTN_TIME32_STATES": "time32-states", + "MWTN_TIME4096SYMBOLS": "Time 4096 QAM", + "MWTN_TIME4096SYMBOLSL": "Time 4096 QAM (light)", + "MWTN_TIME4096_STATES": "time4096-states", + "MWTN_TIME4096_STATES_L": "time4096-states-l", + "MWTN_TIME4SYMBOLS": "Time 4 QAM", + "MWTN_TIME4SYMBOLSS": "Time 4 QAM (strong)", + "MWTN_TIME4_STATES": "time4-states", + "MWTN_TIME4_STATES_S": "time4-states-s", + "MWTN_TIME512SYMBOLS": "Time 512 QAM", + "MWTN_TIME512SYMBOLSL": "Time 512 QAM (light)", + "MWTN_TIME512_STATES": "time512-states", + "MWTN_TIME512_STATES_L": "time512-states-l", + "MWTN_TIME64SYMBOLS": "Time 64 QAM", + "MWTN_TIME64_STATES": "time64-states", + "MWTN_TIME8192SYMBOLS": "Time 8192 QAM", + "MWTN_TIME8192SYMBOLSL": "Time 8192 QAM (light)", + "MWTN_TIME8192_STATES": "time8192-states", + "MWTN_TIME8192_STATES_L": "time8192-states-l", + "MWTN_TIME8SYMBOLS": "Time 8 QAM", + "MWTN_TIME8_STATES": "time8-states", + "MWTN_TIMEPERIOD": "Period", + "MWTN_TIMESLOTCAPACITY": "Time slot capacity", + "MWTN_TIMESLOTID": "Time slot", + "MWTN_TIMESLOTIDLIST": "Time slot identifiers", + "MWTN_TIMESLOTSTATUSLIST": "Time slot status list", + "MWTN_TIMESTAMP": "timestamp", + "MWTN_TIME_PERIOD": "time-period", + "MWTN_TIME_PROPERTIES_DS": "time-properties-ds", + "MWTN_TIME_SOURCE": "time-source", + "MWTN_TIME_STAMP": "time-stamp", + "MWTN_TIME_TRACEABLE": "time-traceable", + "MWTN_TOTALNUMBEROFTIMESLOTS": "Total number of time slots", + "MWTN_TRAFFIC": "Traffic (Logical termination points)", + "MWTN_TRANSMISSIONMODEID": "Transmission mode identifier", + "MWTN_TRANSMISSIONMODELIST": "Transmission modes", + "MWTN_TRANSMISSION_MODE_ID": "transmission-mode-id", + "MWTN_TRANSMISSION_MODE_LIST": "transmission-mode", + "MWTN_TRANSMITTERISON": "transmitterIsOn", + "MWTN_TRANSMITTER_IS_ON": "transmitter-is-on", + "MWTN_TRANSPARENT_CLOCK_DEFAULT_DS": "transparent-clock-default-ds", + "MWTN_TRANSPARENT_CLOCK_PORT_DS_LIST": "transparent-clock-port", + "MWTN_TRIGGER_REFRESH": "trigger-refresh", + "MWTN_TWO_STEP_FLAG": "two-step-flag", + "MWTN_TXCHANNELBANDWIDTH": "txChannelBandwidth", + "MWTN_TXFREQUENCY": "Transmit frequency", + "MWTN_TXFREQUENCYCUR": "txFrequencyCur", + "MWTN_TXFREQUENCYMAX": "txFrequencyMax", + "MWTN_TXFREQUENCYMIN": "txFrequencyMin", + "MWTN_TXLEVELAVG": "Transmit level (avg)", + "MWTN_TXLEVELCUR": "txLevelCur", + "MWTN_TXLEVELMAX": "Transmit level (max)", + "MWTN_TXLEVELMIN": "Transmit level (min)", + "MWTN_TXPOWER": "txPower", + "MWTN_TXPOWERMAX": "Max tx power", + "MWTN_TXPOWERMIN": "Min tx power", + "MWTN_TX_CHANNEL_BANDWIDTH": "tx-channel-bandwidth", + "MWTN_TX_ETHERNET_BYTES_MAX_M": "tx-ethernet-bytes-max-m", + "MWTN_TX_ETHERNET_BYTES_MAX_S": "tx-ethernet-bytes-max-s", + "MWTN_TX_ETHERNET_BYTES_SUM": "tx-ethernet-bytes-sum", + "MWTN_TX_FREQUENCY": "tx-frequency", + "MWTN_TX_FREQUENCY_CUR": "tx-frequency-cur", + "MWTN_TX_FREQUENCY_MAX": "tx-frequency-max", + "MWTN_TX_FREQUENCY_MIN": "tx-frequency-min", + "MWTN_TX_LEVEL_AVG": "tx-level-avg", + "MWTN_TX_LEVEL_CUR": "tx-level-cur", + "MWTN_TX_LEVEL_MAX": "tx-level-max", + "MWTN_TX_LEVEL_MIN": "tx-level-min", + "MWTN_TX_POWER": "tx-power", + "MWTN_TX_POWER_MAX": "tx-power-max", + "MWTN_TX_POWER_MIN": "tx-power-min", + "MWTN_TYPEOFEQUIPMENT": "typeOfEquipment", + "MWTN_TYPE_NAME": "type-name", + "MWTN_TYPE_OF_EQUIPMENT": "type-of-equipment", + "MWTN_UNAVAILABILITY": "unavailability", + "MWTN_UNIVERSALIDAUTHORITY": "UniversalIdAuthority", + "MWTN_USERNAME": "User name", + "MWTN_UUID": "UUID", + "MWTN_VALUE": "value", + "MWTN_VALUE_NAME": "value-name", + "MWTN_VERSION": "version", + "MWTN_VERSION_NUMBER": "version-number", + "MWTN_VLANCOMPRESSIONISAVAIL": "vlanCompressionIsAvail", + "MWTN_VLANCOMPRESSIONISON": "vlanCompressionIsOn", + "MWTN_VLAN_COMPRESSION_IS_AVAIL": "vlan-compression-is-avail", + "MWTN_VLAN_COMPRESSION_IS_ON": "vlan-compression-is-on", + "MWTN_VLAN_ID": "vlan-id", + "MWTN_WAITTORESTORETIME": "waitToRestoreTime", + "MWTN_WAIT_TO_RESTORE_TIME": "wait-to-restore-time", + "MWTN_WAIT_TO_REVERT_TIME": "wait-to-revert-time", + "MWTN_WEIGHT_CHARACTERISTICS": "weight-characteristics", + "MWTN_WIDTH": "width", + "MWTN_X_CONNECTIONS": "Cross connections", + "MWTN_XPDAVG": "Cross polarization discrimination (avg)", + "MWTN_XPDCUR": "xpdCur", + "MWTN_XPDMAX": "Cross polarization discrimination (max)", + "MWTN_XPDMIN": "Cross polarization discrimination (min)", + "MWTN_XPD_AVG": "xpd-avg", + "MWTN_XPD_CUR": "xpd-cur", + "MWTN_XPD_MAX": "xpd-max", + "MWTN_XPD_MIN": "xpd-min", + "MWTN_XPICISAVAIL": "xPic", + "MWTN_XPICISON": "xpicIsOn", + "MWTN_XPICISUP": "xpicIsUp", + "MWTN_XPIC_IS_AVAIL": "xpic-is-avail", + "MWTN_XPIC_IS_ON": "xpic-is-on", + "MWTN_XPIC_IS_UP": "xpic-is-up", + "MWTN_YANG_CAPABILITIES": "Yang capabilities", + "MWTN__CLIENTLTPREFLIST": "_clientLtpRefList", + "MWTN__CONNECTEDLTPREF": "_connectedLtpRef", + "MWTN__FCPORTLIST": "_fcPortList", + "MWTN__FCREFLIST": "_fcRefList", + "MWTN__FCSWITCHLIST": "_fcSwitchList", + "MWTN__FDREFLIST": "_fdRefList", + "MWTN__LOWERLEVELFCREFLIST": "_lowerLevelFcRefList", + "MWTN__LOWERLEVELFDREFLIST": "_lowerLevelFdRefList", + "MWTN__LPLIST": "_lpList", + "MWTN__LTPREFLIST": "_ltpRefList", + "MWTN__PEERLTPREF": "_peerLtpRef", + "MWTN__SELECTEDFCPORTREFLIST": "_selectedFcPortRefList", + "MWTN__SERVERLTPREFLIST": "_serverLtpRefList", + "MWTN_«Q.822»-CURRENTDATA": "«Q.822»-CurrentData", + "MWTN_«Q.822»-HISTORYDATA": "«Q.822»-HistoryData", + "MWTN_«X.721»-TOP": "«X.721»-Top", + "MWTN_«X.739»-SCANNER": "«X.739»-Scanner" +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons-custom.css new file mode 100644 index 00000000..cf22c146 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons-custom.css @@ -0,0 +1,108 @@ +/** + * Add your application related css here + */ + .ht-header { + display: block; + height: 32px; +} +.ht-header-right { + float: right; +} + +.owl { + padding:5px; +} +.owl-dark { + color: #414042; +} + +.owl .owl-dark { + color: #414042; +} + +.owl span { + color: white; +} + +.owl a span { + color: white; +} + +.owl .panel-default span { + color: #414042; +} + +.owl .panel-default a span.owl-dark { + color: #414042; +} + +.owl .panel-default .mwtn-json-viewer span.owl-dark { + color: #414042; +} + +.owl .panel-default .json-formatter-row .string{color:green;white-space:pre;word-wrap:break-word} +.owl .panel-default .json-formatter-row .number{color:#00f} +.owl .panel-default .json-formatter-row .boolean{color:red} +.owl .panel-default .json-formatter-row .null{color:#855A00} +.owl .panel-default .json-formatter-row .undefined{color:#ca0b69} +.owl .panel-default .json-formatter-row .function{color:#FF20ED} +.owl .panel-default .json-formatter-row .date{background-color:rgba(0,0,0,.05)} +.owl .panel-default .json-formatter-row .url{text-decoration:underline;color:#00f;cursor:pointer} +.owl .panel-default .json-formatter-row a span.bracket{color:#00f} +.owl .panel-default .json-formatter-row a span.key{color:#00008B;cursor:pointer} +.owl .panel-default .json-formatter-row a span.constructor-name{color: #888888; cursor:pointer} + +.mwtn-grid { + background-color: white; + color:black; +} + +@media (min-width: 1296px) { + .modal-huge { + width: 1200px; + } +} + + +.form-group span.mwtnError { + color: red; +} + +.mwtnLight { + color: white; +} + +.panel-group .panel-default span .mwtnError { + color: red; +} + +.mwtnSuccess { + color: darkgreen; +} + +.panel-group .panel-default span .mwtnSuccess { + color: darkgreen; +} + +.number { + text-align: right; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +.vCenter { + margin: 5px 30px 5px 0px; + display: inline-block; + vertical-align: middle; + float: none; +} + +a.vCenter { + text-decoration: none; +} diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.controller.js new file mode 100644 index 00000000..872c2aa8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.controller.js @@ -0,0 +1,25 @@ +/* + * 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/mwtnCommons/mwtnCommons.module', + 'app/mwtnCommons/mwtnCommons.services'], function(mwtnCommonsApp) { + + mwtnCommonsApp.register.controller('mwtnCommonsCtrl', ['$scope', '$rootScope', '$mwtnCommons', '$mwtnLog', 'FileReader', + function($scope, $rootScope, $mwtnCommons, $mwtnLog, FileReader) { + + $rootScope.section_logo = ''; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.mwtnCommonsInfo = {}; + + $mwtnCommons.getData(function(data){ + $scope.data = data; + }); + + }]); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.module.js new file mode 100755 index 00000000..ebc515ca --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.module.js @@ -0,0 +1,622 @@ +/* + * 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/bower_components/angular-ui-grid/ui-grid.min', + 'app/mwtnCommons/bower_components/chart.js/dist/Chart', + 'app/mwtnCommons/bower_components/angular-chart.js/dist/angular-chart', + 'app/mwtnCommons/bower_components/angular-clipboard/angular-clipboard', + 'ui-bootstrap', + 'app/mwtnCommons/bower_components/json-formatter/dist/json-formatter.min'], + function(ng) { + var mwtnCommonsApp = angular.module('app.mwtnCommons', ['app.core','chart.js', 'ui.router.state', 'ui.grid', 'ui.bootstrap', 'jsonFormatter', 'config', 'pascalprecht.translate', 'angular-clipboard']); + + mwtnCommonsApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + mwtnCommonsApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + $translatePartialLoaderProvider.addPart('app/mwtnCommons/locale/locale'); + + var access = routingConfig.accessLevels; + + }); + + mwtnCommonsApp.directive('htHeader', [ '$injector' ,function ($injector) { + return { + template: '<div class="ht-header"><div class="ht-header-right"><alarm-status ng-if="mwtnFaultExists"></alarm-status><help ng-if="helpExists" link="{{helpLink}}" ></help></div></div>', + controller: ['$scope', function ($scope) { + $scope.helpExists = $injector.has('helpDirective'); + $scope.mwtnFaultExists = $injector.has('alarmStatusDirective'); + }], + restict: "EA", + replace: true, + scope: { + helpLink: "@" + } + }; + }]); + + + return mwtnCommonsApp; +}); + + +/* + Copyright 2011-2013 Abdulla Abdurakhmanov + Original sources are available at https://code.google.com/p/x2js/ + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +function X2JS(config) { + 'use strict'; + + var VERSION = "1.1.5"; + + config = config || {}; + initConfigDefaults(); + initRequiredPolyfills(); + + function initConfigDefaults() { + if(config.escapeMode === undefined) { + config.escapeMode = true; + } + config.attributePrefix = config.attributePrefix || "_"; + config.arrayAccessForm = config.arrayAccessForm || "none"; + config.emptyNodeForm = config.emptyNodeForm || "text"; + if(config.enableToStringFunc === undefined) { + config.enableToStringFunc = true; + } + config.arrayAccessFormPaths = config.arrayAccessFormPaths || []; + if(config.skipEmptyTextNodesForObj === undefined) { + config.skipEmptyTextNodesForObj = true; + } + if(config.stripWhitespaces === undefined) { + config.stripWhitespaces = true; + } + config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || []; + } + + var DOMNodeTypes = { + ELEMENT_NODE : 1, + TEXT_NODE : 3, + CDATA_SECTION_NODE : 4, + COMMENT_NODE : 8, + DOCUMENT_NODE : 9 + }; + + function initRequiredPolyfills() { + function pad(number) { + var r = String(number); + if ( r.length === 1 ) { + r = '0' + r; + } + return r; + } + // Hello IE8- + if(typeof String.prototype.trim !== 'function') { + String.prototype.trim = function() { + return this.replace(/^\s+|^\n+|(\s|\n)+$/g, ''); + } + } + if(typeof Date.prototype.toISOString !== 'function') { + // Implementation from http://stackoverflow.com/questions/2573521/how-do-i-output-an-iso-8601-formatted-string-in-javascript + Date.prototype.toISOString = function() { + return this.getUTCFullYear() + + '-' + pad( this.getUTCMonth() + 1 ) + + '-' + pad( this.getUTCDate() ) + + 'T' + pad( this.getUTCHours() ) + + ':' + pad( this.getUTCMinutes() ) + + ':' + pad( this.getUTCSeconds() ) + + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 ) + + 'Z'; + }; + } + } + + function getNodeLocalName( node ) { + var nodeLocalName = node.localName; + if(nodeLocalName == null) // Yeah, this is IE!! + nodeLocalName = node.baseName; + if(nodeLocalName == null || nodeLocalName=="") // =="" is IE too + nodeLocalName = node.nodeName; + return nodeLocalName; + } + + function getNodePrefix(node) { + return node.prefix; + } + + function escapeXmlChars(str) { + if(typeof(str) == "string") + return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); + else + return str; + } + + function unescapeXmlChars(str) { + return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(///g, '\/'); + } + + function toArrayAccessForm(obj, childName, path) { + switch(config.arrayAccessForm) { + case "property": + if(!(obj[childName] instanceof Array)) + obj[childName+"_asArray"] = [obj[childName]]; + else + obj[childName+"_asArray"] = obj[childName]; + break; + /*case "none": + break;*/ + } + + if(!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) { + var idx = 0; + for(; idx < config.arrayAccessFormPaths.length; idx++) { + var arrayPath = config.arrayAccessFormPaths[idx]; + if( typeof arrayPath === "string" ) { + if(arrayPath == path) + break; + } + else + if( arrayPath instanceof RegExp) { + if(arrayPath.test(path)) + break; + } + else + if( typeof arrayPath === "function") { + if(arrayPath(obj, childName, path)) + break; + } + } + if(idx!=config.arrayAccessFormPaths.length) { + obj[childName] = [obj[childName]]; + } + } + } + + function fromXmlDateTime(prop) { + // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object + // Improved to support full spec and optional parts + var bits = prop.split(/[-T:+Z]/g); + + var d = new Date(bits[0], bits[1]-1, bits[2]); + var secondBits = bits[5].split("\."); + d.setHours(bits[3], bits[4], secondBits[0]); + if(secondBits.length>1) + d.setMilliseconds(secondBits[1]); + + // Get supplied time zone offset in minutes + if(bits[6] && bits[7]) { + var offsetMinutes = bits[6] * 60 + Number(bits[7]); + var sign = /\d\d-\d\d:\d\d$/.test(prop)? '-' : '+'; + + // Apply the sign + offsetMinutes = 0 + (sign == '-'? -1 * offsetMinutes : offsetMinutes); + + // Apply offset and local timezone + d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset()) + } + else + if(prop.indexOf("Z", prop.length - 1) !== -1) { + d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds())); + } + + // d is now a local time equivalent to the supplied time + return d; + } + + function checkFromXmlDateTimePaths(value, childName, fullPath) { + if(config.datetimeAccessFormPaths.length > 0) { + var path = fullPath.split("\.#")[0]; + var idx = 0; + for(; idx < config.datetimeAccessFormPaths.length; idx++) { + var dtPath = config.datetimeAccessFormPaths[idx]; + if( typeof dtPath === "string" ) { + if(dtPath == path) + break; + } + else + if( dtPath instanceof RegExp) { + if(dtPath.test(path)) + break; + } + else + if( typeof dtPath === "function") { + if(dtPath(obj, childName, path)) + break; + } + } + if(idx!=config.datetimeAccessFormPaths.length) { + return fromXmlDateTime(value); + } + else + return value; + } + else + return value; + } + + function parseDOMChildren( node, path ) { + if(node.nodeType == DOMNodeTypes.DOCUMENT_NODE) { + var result = new Object; + var nodeChildren = node.childNodes; + // Alternative for firstElementChild which is not supported in some environments + for(var cidx=0; cidx <nodeChildren.length; cidx++) { + var child = nodeChildren.item(cidx); + if(child.nodeType == DOMNodeTypes.ELEMENT_NODE) { + var childName = getNodeLocalName(child); + result[childName] = parseDOMChildren(child, childName); + } + } + return result; + } + else + if(node.nodeType == DOMNodeTypes.ELEMENT_NODE) { + var result = new Object; + result.__cnt=0; + + var nodeChildren = node.childNodes; + + // Children nodes + for(var cidx=0; cidx <nodeChildren.length; cidx++) { + var child = nodeChildren.item(cidx); // nodeChildren[cidx]; + var childName = getNodeLocalName(child); + + if(child.nodeType!= DOMNodeTypes.COMMENT_NODE) { + result.__cnt++; + if(result[childName] == null) { + result[childName] = parseDOMChildren(child, path+"."+childName); + toArrayAccessForm(result, childName, path+"."+childName); + } + else { + if(result[childName] != null) { + if( !(result[childName] instanceof Array)) { + result[childName] = [result[childName]]; + toArrayAccessForm(result, childName, path+"."+childName); + } + } + (result[childName])[result[childName].length] = parseDOMChildren(child, path+"."+childName); + } + } + } + + // Attributes + for(var aidx=0; aidx <node.attributes.length; aidx++) { + var attr = node.attributes.item(aidx); // [aidx]; + result.__cnt++; + result[config.attributePrefix+attr.name]=attr.value; + } + + // Node namespace prefix + var nodePrefix = getNodePrefix(node); + if(nodePrefix!=null && nodePrefix!="") { + result.__cnt++; + result.__prefix=nodePrefix; + } + + if(result["#text"]!=null) { + result.__text = result["#text"]; + if(result.__text instanceof Array) { + result.__text = result.__text.join("\n"); + } + if(config.escapeMode) + result.__text = unescapeXmlChars(result.__text); + if(config.stripWhitespaces) + result.__text = result.__text.trim(); + delete result["#text"]; + if(config.arrayAccessForm=="property") + delete result["#text_asArray"]; + result.__text = checkFromXmlDateTimePaths(result.__text, childName, path+"."+childName); + } + if(result["#cdata-section"]!=null) { + result.__cdata = result["#cdata-section"]; + delete result["#cdata-section"]; + if(config.arrayAccessForm=="property") + delete result["#cdata-section_asArray"]; + } + + if( result.__cnt == 1 && result.__text!=null ) { + result = result.__text; + } + else + if( result.__cnt == 0 && config.emptyNodeForm=="text" ) { + result = ''; + } + else + if ( result.__cnt > 1 && result.__text!=null && config.skipEmptyTextNodesForObj) { + if( (config.stripWhitespaces && result.__text=="") || (result.__text.trim()=="")) { + delete result.__text; + } + } + delete result.__cnt; + + if( config.enableToStringFunc && (result.__text!=null || result.__cdata!=null )) { + result.toString = function() { + return (this.__text!=null? this.__text:'')+( this.__cdata!=null ? this.__cdata:''); + }; + } + + return result; + } + else + if(node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) { + return node.nodeValue; + } + } + + function startTag(jsonObj, element, attrList, closed) { + var resultStr = "<"+ ( (jsonObj!=null && jsonObj.__prefix!=null)? (jsonObj.__prefix+":"):"") + element; + if(attrList!=null) { + for(var aidx = 0; aidx < attrList.length; aidx++) { + var attrName = attrList[aidx]; + var attrVal = jsonObj[attrName]; + if(config.escapeMode) + attrVal=escapeXmlChars(attrVal); + resultStr+=" "+attrName.substr(config.attributePrefix.length)+"='"+attrVal+"'"; + } + } + if(!closed) + resultStr+=">"; + else + resultStr+="/>"; + return resultStr; + } + + function endTag(jsonObj,elementName) { + return "</"+ (jsonObj.__prefix!=null? (jsonObj.__prefix+":"):"")+elementName+">"; + } + + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + + function jsonXmlSpecialElem ( jsonObj, jsonObjField ) { + if((config.arrayAccessForm=="property" && endsWith(jsonObjField.toString(),("_asArray"))) + || jsonObjField.toString().indexOf(config.attributePrefix)==0 + || jsonObjField.toString().indexOf("__")==0 + || (jsonObj[jsonObjField] instanceof Function) ) + return true; + else + return false; + } + + function jsonXmlElemCount ( jsonObj ) { + var elementsCnt = 0; + if(jsonObj instanceof Object ) { + for( var it in jsonObj ) { + if(jsonXmlSpecialElem ( jsonObj, it) ) + continue; + elementsCnt++; + } + } + return elementsCnt; + } + + function parseJSONAttributes ( jsonObj ) { + var attrList = []; + if(jsonObj instanceof Object ) { + for( var ait in jsonObj ) { + if(ait.toString().indexOf("__")== -1 && ait.toString().indexOf(config.attributePrefix)==0) { + attrList.push(ait); + } + } + } + return attrList; + } + + function parseJSONTextAttrs ( jsonTxtObj ) { + var result =""; + + if(jsonTxtObj.__cdata!=null) { + result+="<![CDATA["+jsonTxtObj.__cdata+"]]>"; + } + + if(jsonTxtObj.__text!=null) { + if(config.escapeMode) + result+=escapeXmlChars(jsonTxtObj.__text); + else + result+=jsonTxtObj.__text; + } + return result; + } + + function parseJSONTextObject ( jsonTxtObj ) { + var result =""; + + if( jsonTxtObj instanceof Object ) { + result+=parseJSONTextAttrs ( jsonTxtObj ); + } + else + if(jsonTxtObj!=null) { + if(config.escapeMode) + result+=escapeXmlChars(jsonTxtObj); + else + result+=jsonTxtObj; + } + + return result; + } + + function parseJSONArray ( jsonArrRoot, jsonArrObj, attrList ) { + var result = ""; + if(jsonArrRoot.length == 0) { + result+=startTag(jsonArrRoot, jsonArrObj, attrList, true); + } + else { + for(var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) { + result+=startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false); + result+=parseJSONObject(jsonArrRoot[arIdx]); + result+=endTag(jsonArrRoot[arIdx],jsonArrObj); + } + } + return result; + } + + function parseJSONObject ( jsonObj ) { + var result = ""; + + var elementsCnt = jsonXmlElemCount ( jsonObj ); + + if(elementsCnt > 0) { + for( var it in jsonObj ) { + + if(jsonXmlSpecialElem ( jsonObj, it) ) + continue; + + var subObj = jsonObj[it]; + + var attrList = parseJSONAttributes( subObj ) + + if(subObj == null || subObj == undefined) { + result+=startTag(subObj, it, attrList, true); + } + else + if(subObj instanceof Object) { + + if(subObj instanceof Array) { + result+=parseJSONArray( subObj, it, attrList ); + } + else if(subObj instanceof Date) { + result+=startTag(subObj, it, attrList, false); + result+=subObj.toISOString(); + result+=endTag(subObj,it); + } + else { + var subObjElementsCnt = jsonXmlElemCount ( subObj ); + if(subObjElementsCnt > 0 || subObj.__text!=null || subObj.__cdata!=null) { + result+=startTag(subObj, it, attrList, false); + result+=parseJSONObject(subObj); + result+=endTag(subObj,it); + } + else { + result+=startTag(subObj, it, attrList, true); + } + } + } + else { + result+=startTag(subObj, it, attrList, false); + result+=parseJSONTextObject(subObj); + result+=endTag(subObj,it); + } + } + } + result+=parseJSONTextObject(jsonObj); + + return result; + } + + this.parseXmlString = function(xmlDocStr) { + var isIEParser = window.ActiveXObject || "ActiveXObject" in window; + if (xmlDocStr === undefined) { + return null; + } + var xmlDoc; + if (window.DOMParser) { + var parser=new window.DOMParser(); + var parsererrorNS = null; + // IE9+ now is here + if(!isIEParser) { + try { + parsererrorNS = parser.parseFromString("INVALID", "text/xml").childNodes[0].namespaceURI; + } + catch(err) { + parsererrorNS = null; + } + } + try { + xmlDoc = parser.parseFromString( xmlDocStr, "text/xml" ); + if( parsererrorNS!= null && xmlDoc.getElementsByTagNameNS(parsererrorNS, "parsererror").length > 0) { + //throw new Error('Error parsing XML: '+xmlDocStr); + xmlDoc = null; + } + } + catch(err) { + xmlDoc = null; + } + } + else { + // IE :( + if(xmlDocStr.indexOf("<?")==0) { + xmlDocStr = xmlDocStr.substr( xmlDocStr.indexOf("?>") + 2 ); + } + xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async="false"; + xmlDoc.loadXML(xmlDocStr); + } + return xmlDoc; + }; + + this.asArray = function(prop) { + if(prop instanceof Array) + return prop; + else + return [prop]; + }; + + this.toXmlDateTime = function(dt) { + if(dt instanceof Date) + return dt.toISOString(); + else + if(typeof(dt) === 'number' ) + return new Date(dt).toISOString(); + else + return null; + }; + + this.asDateTime = function(prop) { + if(typeof(prop) == "string") { + return fromXmlDateTime(prop); + } + else + return prop; + }; + + this.xml2json = function (xmlDoc) { + return parseDOMChildren ( xmlDoc ); + }; + + this.xml_str2json = function (xmlDocStr) { + var xmlDoc = this.parseXmlString(xmlDocStr); + if(xmlDoc!=null) + return this.xml2json(xmlDoc); + else + return null; + }; + + this.json2xml_str = function (jsonObj) { + return parseJSONObject ( jsonObj ); + }; + + this.json2xml = function (jsonObj) { + var xmlDocStr = this.json2xml_str (jsonObj); + return this.parseXmlString(xmlDocStr); + }; + + this.getVersion = function () { + return VERSION; + }; + +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.services.js new file mode 100644 index 00000000..9a713436 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.services.js @@ -0,0 +1,3826 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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 {@link http://www.eclipse.org/legal/epl-v10.html} + */ + +if (!String.prototype.toHumanReadableTimeFormat) { + String.prototype.toHumanReadableTimeFormat = function () { + return this.replace(/T/g, ' ').replace(/Z/g, ' UTC').replace(/\+00:00/g, ' UTC'); + }; +} + +if (!String.prototype.base64ToHex) { + String.prototype.base64ToHex = function () { + var raw = atob(this); + var result = []; + for ( i = 0; i < raw.length; i++ ) { + var _hex = raw.charCodeAt(i).toString(16) + result.push('0x' + ( _hex.length === 2 ? _hex:'0' + _hex)); + } + return result.join(' '); + }; +} + +if (!String.prototype.contains) { + /** + * An extension to String, which checks whether another string is contained. + * @param {string} find A string to be checked, whether it is contained in 'this'. + * @return {boolean} True, if 'this' contains param 'find', otherwise false. + */ + String.prototype.contains = function (find) { + return this.indexOf(find) > -1; + }; +} + +if (!String.prototype.format) { + /** + * An extension to String, which replaces certain patterns by arguments. + * @see {@link https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format|javascript-equivalent-to-printf-string-format} + * @return {string} Formated string. + */ + String.prototype.format = function () { + var args = arguments; + return this.replace(/{(\d+)}/g, function (match, number) { + return typeof args[number] !== 'undefined' ? args[number] : match + ; + }); + }; +} + +if (!String.prototype.replaceAll) { + /** + * An extension to String, which replaces certain patterns by arguments. + * @see {@link https://stackoverflow.com/questions/1144783/how-to-replace-all-occurrences-of-a-string-in-javascript|how-to-replace-all-occurrences-of-a-string-in-javascript} + * @param {string} find - The string which should be replaced. + * @param {string} replace - The string which should replace 'find'. + * @return {string} String where 'find' is replaced by 'replace'. + */ + String.prototype.replaceAll = function (find, replace) { + return this.replace(new RegExp(find, 'g'), replace); + } +} + +if (!Array.prototype.contains) { + /** + * An extension to Array checking whether an array of primitive types contains a given value. + * @param {string|number|boolean|null|undefined} find An object which should be removed from the array. + * @return {boolean} True, if 'this' contains param 'find', otherwise false.. + */ + Array.prototype.contains = function (find) { + return this.indexOf(find) > -1; + }; +} + +if (!Array.prototype.clean) { + /** + * An extension to Array removing defined values from an array. + * @see {@link https://gist.github.com/waynegraham/3684627|Array.clean()} + * @param {Object} deleteValue An object which should be removed from the array. + * @return {Array} An array without 'deleteValue'. + */ + Array.prototype.clean = function (deleteValue) { + for (var i = 0; i < this.length; i++) { // TODO swtich to .map() ? + if (this[i] === deleteValue) { + this.splice(i, 1); + i--; + } + } + return this; + }; +} + +define( + ['app/mwtnCommons/mwtnCommons.module'], + function (mwtnCommonsApp) { + + mwtnCommonsApp.register.controller('mwtnFooterController', ['$scope', function ($scope) { + var vm = this; + $scope.prefix = 'ONF Wireless for OpenDaylight Boron-SR3'; + }]); + + mwtnCommonsApp.register.directive('mwtnFooter', function () { + return { + restrict: 'E', + controller: 'mwtnFooterController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnCommons/templates/mwtnFooter.tpl.html' + }; + }); + + mwtnCommonsApp.register.controller('openConfigViewController', ['$scope', '$uibModalInstance', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', 'valueData', + function ($scope, $uibModalInstance, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, data) { + + var vm = this; + var COMPONENT = 'openConfigViewController'; + + $scope.getType = $mwtnGlobal.getType; + $scope.spec = data.spec; + $mwtnCommons.getConditionalPackagePart($scope.spec).then(function (success) { + + var getControlType = function(type) { + var result = 'text' + switch (type) { + case 'boolean': + result = 'checkbox'; + break; + case 'number': + result = 'number'; + break; + case 'string': + case 'array': + case 'object': + break; + default: + var message = 'Check control type for ' + type; + $mwtnLog.warning({ component: COMPONENT, message: message }); + } + return result; + }; + + success.layerProtocol = $scope.spec.layerProtocolId; + $scope.configuredData = success; + $scope.newData = $scope.configuredData[$scope.spec.partId]; + + $scope.viewData = $mwtnGlobal.getViewData($scope.configuredData[$scope.spec.partId], $scope.ne); + $mwtnDatabase.getSchema().then(function(schema){ + var ordered = {}; + var clone = JSON.parse(JSON.stringify($scope.viewData)); + var keys = Object.keys(clone).map(function(key){ + if ($mwtnGlobal.getType(key) !== 'string') { + console.log('key', key); + return; + } + var item = clone[key]; + if (!schema[key]) { + + var message = 'No schema information for ' + key; + console.error(key, schema[key]); + $mwtnLog.warning({ component: COMPONENT, message: message }); + item['order-number'] = $mwtnCommons.getOrderNumber(97, item); + item.description = 'No description available.'; + item.visible = true; + return key; + } + if (schema[key].controlType === undefined) { + item.controlType = getControlType(item.type); + } else { + item.controlType = schema[key].controlType; + } + item.unit = schema[key].unit; + item.description = schema[key].description; + item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item); + if (item.description === undefined || item.description === '') { + item.description = 'No description available.'; + } + // hide complex types for now -> TODO + if (item.type === 'array' || item.type === 'object') { + item.visible = false; + } + return key; + }).sort(function(a,b){ + if (clone[a]['order-number'] < clone[b]['order-number']) return -1; + if (clone[a]['order-number'] > clone[b]['order-number']) return 1; + return 0; + }).map(function(key){ + ordered[key] = clone[key]; + }); + $scope.viewData = ordered; + }, function(error){ + $scope.empty = true; + }); + + }, function (error) { + $scope.configuredData = undefined; + $mwtnLog.error({ component: COMPONENT, message: 'Requesting conditional package of ' + JSON.stringify($scope.spec) + ' failed!' }); + }); + + $scope.ok = function () { + $scope.processing = true; + Object.keys($scope.viewData).map(function(key){ + $scope.newData[key] = $scope.viewData[key].value; + }); + + $mwtnCommons.setConditionalPackagePart($scope.spec, $scope.newData).then(function(success){ + $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'}; + $scope.processing = false; + }, function(error){ + $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'}; + $scope.processing = false; + $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)}); + }); + + }; + + $scope.cancel = function () { + $uibModalInstance.close($scope.newData); + }; + + }]); + + mwtnCommonsApp.register.controller('mwtnJsonViewerController', ['$scope', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', + function ($scope, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + var vm = this; + var COMPONENT = 'mwtnJsonViewerController'; + $scope.getType = $mwtnGlobal.getType; + + if ($scope.data) { + $scope.replace = false; + if ($scope.path && $scope.path.endsWith('-configuration') ) { + $scope.replace = true; + } + $scope.viewData = $mwtnGlobal.getViewData($scope.data, $scope.ne); + var path = [undefined, undefined, undefined]; + if ($scope.path) { + path = $scope.path.split($mwtnCommons.separator); + } + $scope.spec = { + nodeId: $scope.networkElement, + revision: '2017-03-20', + pacId: path[0], + layer: '???', + layerProtocolId: path[1], + partId: path[2], + config: true + }; + + $scope.openConfigView = function(){ + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnCommons/templates/openConfigView.html', + controller: 'openConfigViewController', + size: 'huge', + resolve: { + valueData: function () { + return {spec:$scope.spec}; + } + } + }); + modalInstance.result.then(function(object) { + // update fetch new data from ODL + $mwtnCommons.getPacParts($scope.spec).then(function(success){ + // intermedite step to display something, even processing fails or takes time + $scope.viewData = $mwtnGlobal.getViewData(success[$scope.spec.partId], $scope.ne); + // now the nice way ;) + $scope.viewData = processData($scope.schema); + }, function(error){ + // ignore; + }); + }, function () { + // ignore; + }); + }; + + $scope.myClipboard = { + data: [$scope.data], + supported: true, + getJson: function () { + return JSON.stringify(this.data, null, ' '); + }, + copyToClipboard: function () { + var message = 'Copied to clipboard! ' + this.getJson(); + $mwtnLog.info({ component: COMPONENT, message: message }); + }, + error: function (err) { + $mwtnLog.error({ component: COMPONENT, message: err }); + } + }; + + var processData = function(schema) { + var ordered = {}; + var clone = JSON.parse(JSON.stringify($scope.viewData)); + var keys = Object.keys(clone).map(function(key){ + if ($mwtnGlobal.getType(key) !== 'string') { + console.log('key', key); + return; + } + var item = clone[key]; + if (!schema[key]) { + var message = 'No schema information for ' + key; + $mwtnLog.warning({ component: COMPONENT, message: message }); + item['order-number'] = $mwtnCommons.getOrderNumber(97, item); + item.description = 'No description available.'; + item.visible = true; + return key; + } + item.unit = schema[key].unit; + item.description = schema[key].description; + item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item); + if (item.description === undefined || item.description === '') { + item.description = 'No description available.'; + } + return key; + }).sort(function(a,b){ + if (clone[a]['order-number'] < clone[b]['order-number']) return -1; + if (clone[a]['order-number'] > clone[b]['order-number']) return 1; + return 0; + }).map(function(key){ + ordered[key] = clone[key]; + }); + $scope.info = false; + if (Object.keys(ordered).length === 0) { + $scope.info = 'An empty object is displayed. Please check if the NetConf server has send an empty object.'; + } + return ordered; + }; + + $mwtnDatabase.getSchema().then(function(schema){ + $scope.schema = schema; + $scope.viewData = processData($scope.schema); + }, function(error){ + // ignore; + }); + } + }]); + + mwtnCommonsApp.register.directive('mwtnJsonViewer', function () { + return { + restrict: 'E', + scope: { + data: '=', + path: '=', + ne: '=', // flag if ne class + networkElement: '=', + noButtons: '=' + }, + controller: 'mwtnJsonViewerController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnCommons/templates/mwtnJsonViewer.tpl.html' + }; + }); + + mwtnCommonsApp.register.controller('showGridCellDetailController', ['$scope', '$uibModalInstance', '$mwtnGlobal', 'valueData', + function ($scope, $uibModalInstance, $mwtnGlobal, valueData) { + + $scope.networkElement = valueData.networkElement; + $scope.path = valueData.path; + $scope.type = $mwtnGlobal.getType(valueData.value); + $scope.value = valueData.value; + // $scope.gridOptions = JSON.parse(JSON.stringify($mwtnCommons.gridOptions)); + // $scope.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + + console.log('valueData', JSON.stringify(valueData)); + + // $scope.ok = function () { + // $scope.processing = true; + // $mwtnCommons.setPacPartLists($scope.path, $scope.listData).then(function(success){ + // $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'}; + // $scope.processing = false; + // }, function(error){ + // $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'}; + // $scope.processing = false; + // $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)}); + // }); + + // }; + + $scope.cancel = function () { + $uibModalInstance.dismiss('cancel'); + }; + + }]); + + mwtnCommonsApp.register.controller('mwtnGridController', ['$scope', '$filter', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnLog', + function ($scope, $filter, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnLog) { + var vm = this; + var COMPONENT = 'mwtnGridController'; + + $scope.info = false; + + var data = JSON.parse(JSON.stringify($scope.data)); + if (!data) { + var message = 'No data to be displayed!";' + $mwtnLog.info({ component: COMPONENT, message: message }); + data = [{'message':message}]; + } + + if ($mwtnGlobal.getType(data) !== 'array') { + var message = 'Data must be of type "array"!'; + $mwtnLog.info({ component: COMPONENT, message: message }); + data = [{'message':message}]; + } + + if (data.length === 0) { + var message = 'Data list must have at least one entry!'; + $mwtnLog.info({ component: COMPONENT, message: message }); + data = [{'message':message}]; + } + + if ($mwtnGlobal.getType(data[0]) !== 'object') { + data = data.map(function(item){ + return {value: item}; + }); + } + + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnCommons.gridOptions)); + $scope.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + + $scope.getTableHeight = function() { + var rowHeight = 30; + var headerHeight = 40; + var maxCount = 12; + var rowCount = $scope.gridOptions.data.length + 2; + var count = rowCount; + if (rowCount > maxCount) { + count = maxCount; + headerHeight = 31; + } + return { + height: (count * rowHeight + headerHeight) + 'px' + }; + }; + + var getCellTemplate = function(field) { + var object = ['transmission-mode-list', 'performance-data']; + if (object.contains(field)) { + console.warn(JSON.stringify(field)); + return ['<div class="ui-grid-cell-contents">', + '<i class="fa fa-info-circle" aria-hidden="true"', + ' ng-click="grid.appScope.show(grid.getCellValue(row, col))"', + ' style="color: rgb(66, 139, 202); cursor: pointer;"></i> ', + '{{grid.getCellValue(row, col)}}</div>'].join(''); + } + return '<div class="ui-grid-cell-contents">{{grid.getCellValue(row, col)}}</div>'; + }; + $scope.show = function(value){ + // console.warn(JSON.stringify(value)); + var type = $mwtnGlobal.getType(value); + // if (type === 'object') + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnCommons/templates/showGridCellDetail.html', + controller: 'showGridCellDetailController', + size: 'huge', + resolve: { + valueData: function () { + return {networkElement: $scope.networkElement, path:$scope.path, value:value}; + } + } + }); + }; + var enable = data.length > 10; + $scope.gridOptions.columnDefs = Object.keys(data[0]).map(function (field) { + var type = $mwtnGlobal.getType(data[0][field]); + var labelId = $mwtnGlobal.getLabelId(field); + var displayName = $filter('translate')(labelId); + var visible = $mwtnGlobal.getVisibilityOf(field); + if (labelId.contains('$$') || labelId === 'MWTN_SPEC') { + visible = false; + } + return { + field: field, + type: type, + displayName: displayName, + enableSorting: true, + enableFiltering: enable, + headerCellClass: $scope.highlightFilteredHeader, + cellTemplate: getCellTemplate(field), + cellClass: type, + visible: visible + }; + }); + if ($scope.gridOptions.data.length < 10) { + $scope.gridOptions.minRowsToShow = data.length; // 10 is default + } + $scope.gridOptions.data = data; + // .sort(function(a, b){ + // if (a.type === 'object') return -1; + // if (a.type === 'array' ) return -2; + // return 0; + // }) + + $scope.myClipboard = { + data: $scope.data, + supported: true, + getJson: function () { + return JSON.stringify(this.data, null, ' '); + }, + copyToClipboard: function () { + var message = 'Copied to clipboard! ' + this.getJson(); + $mwtnLog.info({ component: COMPONENT, message: message }); + }, + error: function (err) { + $mwtnLog.error({ component: COMPONENT, message: err }); + } + }; + }]); + + mwtnCommonsApp.register.directive('mwtnGrid', function () { + return { + restrict: 'E', + scope: { + data: '=', + path: '=', + networkElement: '=' + }, + controller: 'mwtnGridController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnCommons/templates/mwtnGrid.tpl.html' + }; + }); + + mwtnCommonsApp.register.controller('mwtnSelectNetworkElementController', ['$scope', '$state','$mwtnCommons', function ($scope, $state, $mwtnCommons) { + var vm = this; + + /** + * A function which scanns the mountpoints for connected network-elements and adds it to networkElements. + * @param {{"onfAirInterfaceRevision": string, "node-id": string, "netconf-node-topology:connection-status": string}[]} mountpoints An array of mountpoints from OpenDaylight. + */ + var initNodeList = function (mountpoints) { + $scope.loading = true; + $scope.mountPoints = mountpoints; + $scope.networkElements = mountpoints.filter(function (mountpoint) { + return mountpoint['netconf-node-topology:connection-status'] === 'connected'; + }).map(function (mountpoint) { + return { id: mountpoint['node-id'], revision: mountpoint.onfAirInterfaceRevision }; + }).sort(function (a, b) { + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; + return 0; + }); + + + $scope.networkElement = undefined; + if ($state.params.nodeId) { + + } + + console.error('nodeId', $state.params.nodeId); + + // select one of the nodes + /* dont do it in field applications!!!! + var select = parseInt(Math.random() * $scope.networkElements.length); + if (select !== undefined && $scope.networkElements[select]) { + $scope.networkElement = $scope.networkElements[select].id; + $scope.mountpoint = $scope.mountPoints.filter(function (mountpoint) { + return mountpoint['node-id'] === $scope.networkElement; + })[0]; + } + */ + $scope.loading = false; + }; + + $mwtnCommons.getMountPoints().then(function (mountpoints) { + initNodeList(mountpoints); + }, function (error) { + $scope.networkElements = []; + }); + }]); + + mwtnCommonsApp.register.directive('mwtnSelectNetworkElement', function () { + return { + restrict: 'E', + controller: 'mwtnSelectNetworkElementController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnCommons/templates/mwtnSelectNetworkElement.tpl.html' + }; + }); + + // mwtnCommonsApp.register.factory('$notifying', function($rootScope) { + // return { + // subscribe: function(scope, callback) { + // var handler = $rootScope.$on('notifying-service-event', callback); + // scope.$on('$destroy', handler); + // }, + + // notify: function(text) { + // $rootScope.$emit('notifying-service-event', text); + // } + // }; + // }); + + mwtnCommonsApp.register.factory('$mwtnGlobal', function () { + var service = {}; + + /** + * Returns false, if parameter/attribute should be in visible + * @param {string} field - a json to be analyzed + * @return {boolean} true, if the parameter should be visible, otherwise false. + */ + service.getVisibilityOf = function(field) { + var hide = ['name-binding', 'object-class']; + return !hide.contains(field); + }; + + /** + * Returns the (json) type of a value + * @param {*} value - a json to be analyzed + * @return type of json + */ + service.getType = function (value) { + var result = typeof value; + if (result === 'object' && JSON.stringify(value).substring(0, 1) === '[') { + result = 'array'; + } else if (result === 'object' && value === null) { + result = 'null'; + } else if (result === 'object' && value['value-name'] && value.value) { + result = 'name-value'; + } + return result; + }; + + service.getLabelId = function (string) { + return ['mwtn', string].join('_').replaceAll('-', '_').toUpperCase(); + }; + + var isIntesting = function(key) { + var instesting = ['name', 'local-id', 'label', 'extension', 'physical-port-reference', 'lp', 'server-ltp', 'client-ltp', 'layer-protocol-name']; + return instesting.contains(key); + } + /** + * Returns a simplfies json for display + * @param {*} data - the json to be simplified + * @param {boolean} ne - control parameter for finetuning + * @return a simplfied json for display + */ + service.getViewData = function (data, ne) { + var viewData = JSON.parse(JSON.stringify(data)); + if (ne) { + viewData.ltp = undefined; + viewData.fd = undefined; + } + Object.keys(viewData).map(function (key) { + var type = service.getType(viewData[key]); + var viewValue = { + value: viewData[key], + type: type, + labelId: service.getLabelId(key), + visible: service.getVisibilityOf(key) + }; + viewData[key] = viewValue; + if (type === 'array') { + if (key === 'extension') { + viewValue.value.map(function (item) { + viewData[item['value-name']] = { value: item.value, type: 'string', labelId:service.getLabelId(item['value-name']) }; + }); + viewData[key] = undefined; + } else if (viewValue.value.length === 1 && isIntesting(key)) { + // console.warn(key, JSON.stringify(viewData[key])); + var valueType = service.getType(viewValue.value[0]); + viewData[key].value = viewValue.value[0]; + viewData[key].type = valueType; + + if (valueType === 'object') { + viewData[key].value = service.getViewData(viewValue.value); + } else if (valueType === 'name-value') { + viewData[key].value = viewValue.value.value; + //viewData[key].type = 'string'; + } + } else if (type === 'object') { + viewData[key].value = service.getViewData(viewValue.value); + } + } + }); + return viewData; + }; + return service; + }); + + /** + * Process an array of data synchronously. + * Please see https://gist.github.com/KevinTCoughlin/6901825 + * @param {Array} data An array of data. + * @param {function} processData A function that processes an item of data. + * Signature: function(item, i, callback), where {@code item} is the i'th item, + * {@code i} is the loop index value and {@code calback} is the + * parameterless function to call on completion of processing an item. + * @param {function} done A callback function indecating that all items are processed. + */ + var doSynchronousLoop = function (data, processData, done) { + if (data && data.length > 0) { + var loop = function (data, i, processData, done) { + processData(data[i], i, function () { + if (++i < data.length) { + loop(data, i, processData, done); + } else { + done(); + } + }); + }; + loop(data, 0, processData, done); + } else { + done(); + } + }; + + mwtnCommonsApp.register.factory('$mwtnCommons', function ($http, $q, $mwtnGlobal, $mwtnLog, $mwtnDatabase, LogicalTerminationPoint, PtpClock) { + + var COMPONENT = '$mwtnCommons'; + + var service = { + base: window.location.origin + "/restconf/", + database: {}, + 'sdn-controller': [], + modules: {}, + layerProtocolNameOrder: { + 'MWPS': 6, + 'MWS': 5, + 'ETC': 4, + 'TDM': 3, + 'ETY': 2, + 'ETH-CTP': 1, + 'ETH': 1, + } + }; + + service.getOrderNumber = function(proposal, item){ + var result = proposal; + if (item.type === 'array') { + proposal = 99; + } else if (item.type === 'object') { + proposal = 98; + } else if (item.labelId === 'MWTN_LOCAL_ID') { + proposal = -1; + } else if (item.labelId === 'MWTN_LABEL') { + proposal = -2; + } else if (item.labelId === 'MWTN_NAME') { + proposal = -3; + } else if (item.labelId === 'MWTN_UUID') { + proposal = -4; + } + return proposal; + } + + /** + * A function to get the global-identifier of a condtional package subClass by a specifcation object of such subClass and a local-name. + * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass. + * @param {string} local-name (e.g. current-problems) + * @return {string} globel-identifier of a conditional packages subClass (e.g. 'air-interface-diversity-current-problems') + */ + service.getPartGlobalId = function (spec, localName) { + var address = spec.pacId.split(':'); + var module = address[0]; + var pacName = address[1]; + + // check for unexpected issues + if (!module) { + console.error('not module', module, JSON.stringify(spec)); + return; + } + if (!pacName) { + console.error('not pacName', pacName, JSON.stringify(spec)); + return; + } + if (!service.modules[module]) { + console.error('not service.modules[module]', service.modules[module], JSON.stringify(spec)); + return; + } + if (!service.modules[module][pacName]) { + console.error('not service.modules[module][pacName]', service.modules[module][pacName], JSON.stringify(spec)); + return; + } + if (!service.modules[module]) { + console.error('not ervice.modules[module][pacName][subClass]', service.modules[module][pacName][subClass], JSON.stringify(spec)); + return; + } + + return Object.keys(service.modules[module][pacName]).filter(function (subClass) { + return service.modules[module][pacName][subClass]['local-name'] === localName; + }).map(function (subClass) { + return service.modules[module][pacName][subClass].name; + })[0]; + + }; + + /** + * A function to get the local-name of a condtional package subClass by a specifcation object of such subClass. + * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass + * @return {string} local-name of a conditional packages subClass (e.g. 'current-problems') + */ + service.getPartLocalId = function (spec) { + var result; + Object.keys(service.modules).map(function (module) { + Object.keys(service.modules[module]).filter(function (pacName) { + return spec.pacId === [module, pacName].join(':') && service.modules[module][pacName][spec.partId].name === spec.partId; + }).map(function (pacName) { + result = service.modules[module][pacName][spec.partId]['local-name']; + }); + }); + return result; + }; + + var init = function () { + var deferred = $q.defer(); + var databaseRequest = { + base: $mwtnDatabase.base, + index: 'config', + docType: 'sdn-controller', + command: '_search', + method: 'GET', + from: 0, + size: 10 + }; + $mwtnDatabase.genericRequest(databaseRequest).then(function (success) { + // console.log('sc', JSON.stringify(success.data.hits.hits)); + service['sdn-controller'] = success.data.hits.hits; + $mwtnDatabase.getModules().then(function (success) { + service.modules = success; + }, function (error) { + service.modules = []; + console.error('modules', JSON.stringify(error)); + deferred.reject(error); + }); + deferred.resolve(); + }, function (error) { + service['sdn-controller'] = []; + console.error('sc', JSON.stringify(error)); + deferred.reject(error); + }); + + return deferred.promise; + }; + + service.getMainConroller = function () { + var deferred = $q.defer(); + if (service['sdn-controller'].length === 0) { + init().then(function (success) { + service['sdn-controller'].map(function (controller) { + result = controller; + }); + deferred.resolve(result); + }, function (error) { + deferred.reject(error); + }); + } else { + service['sdn-controller'].map(function (controller) { + result = controller; + }); + deferred.resolve(result); + } + return deferred.promise; + }; + + var createStream = function (streamName, callback) { + service.getMainConroller().then(function (success) { + var src = success._source; + var ip = src.host; + if (ip === 'localhost') { + ip = service.base.split('//')[1].split(':')[0]; + } + var url = [src['transport-protocol'], '://', ip, ':', src.port, '/restconf/streams/stream/', streamName].join(''); + var request = { + method: 'GET', + url: url + }; + $http(request).then(function (response) { + // console.log(response.headers('Location')); + callback(response.headers('Location')); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + callback(); + }); + }, function (error) { + console.error('mainController', error); + callback(); + }); + }; + + service.getMwtnWebSocketUrl = function () { + var deferred = $q.defer(); + service.getMainConroller().then(function (success) { + + var protocol = window.location.protocol.replace(/http/g, 'ws'); + var host = window.location.hostname; + var user = window.localStorage.odlUser; + if (user === undefined) user = 'admin' // ODL default user + var pw = window.localStorage.odlPass; + if (pw === undefined) pw = 'admin' // ODL default password + + var url = [protocol, '//', user, ':',pw, '@', host, ':8085/websocket'].join(''); + console.info('url', url); + + deferred.resolve(url); + }, function (error) { + console.error('mainController', error); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.formatTimeStamp = function (t) { + // t: time in ONF format, e.g. 20161020081633.7Z, 20161025235946.0+0000 + if (t.length !== '20161020081633.7Z'.length || t.length !== '20161025221822.0+0000') { + if (t.endsWith('Z') || t.endsWith('+0000')) { + if (!t.contains('-')) { + return [[t.slice(0, 4), t.slice(4, 6), t.slice(6, 8)].join('-'), + [t.slice(8, 10), t.slice(10, 12), t.slice(12, 16)].join(':')].join(' ') + ' UTC'; + } + } + } + // console.info('check', t); + // return new Date().toISOString().toHumanReadableTimeFormat(); + return t.toHumanReadableTimeFormat(); + }; + + service.formatData = function (event) { + var deferred = $q.defer(); + + var x2js = new X2JS(); + var jsonObj = x2js.xml_str2json(event.data); + // console.info('a', service.getType(jsonObj), JSON.stringify(jsonObj)); + if (jsonObj === null || service.getType(jsonObj) !== 'object') { + deferred.reject('ignore'); + } else { + notifType = Object.keys(jsonObj)[0]; + var formated = jsonObj[notifType]; + formated.timeStamp = service.formatTimeStamp(formated.timeStamp); + formated.notifType = notifType; + formated.myMessage = 'someMessage'; + formated.time = new Date().toISOString(); + deferred.resolve(formated); + } + + return deferred.promise; + }; + + service.getData = function (callback) { + return callback('$mwtnCommons registered to this application.'); + }; + + service.getType = $mwtnGlobal.getType; + service.getViewData = $mwtnGlobal.getViewData; + + service.getLayer = function (pacId) { + console.warn('@depricated', '$mwtnCommons.getLayer()'); + switch (pacId) { + case 'airinterface': + case 'air-interface': + return 'MWPS'; + case 'structure': + case 'pureEthernetStructure': + case 'hybridStructure': + case 'pure-ethernet-structure': + case 'hybrid-structure': + return 'MWS'; + case 'container': + case 'ethernetContainer': + case 'ethernet-container': + return 'ETC'; + case 'tdmContainer': + case 'tdm-container': + return 'TDM'; + default: + return (pacId); + } + }; + + /** @deprecated */ + service.parts = ['Capability', 'Configuration', 'Status', 'CurrentProblems', 'CurrentPerformance', 'HistoricalPerformances']; + + service.getLabelId = function (key, callback) { + return callback(['mwtn', key].join('_').toUpperCase()); + }; + + service.checkModules = function (names) { + // accepts a list of module names and + // attempts to load them, in order. + // attempt to load the module into m + var m; + var result = {}; + names.map(function (name) { + try { + m = angular.module(name); + result[name] = true; + } catch (err) { + result[name] = false; + } + }); + return result; + }; + + service.mount = function (mp) { + // mp: mounting point + var url = [service.base, service.url.mount(mp.name)].join(''); + /* deprecated + var xml = [ + '<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">', + '<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">prefix:sal-netconf-connector</type>', + '<name>{0}</name>', + '<address xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{1}</address>', + '<port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{2}</port>', + '<username xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{3}</username>', + '<password xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{4}</password>', + '<tcp-only xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">false</tcp-only>', + '<event-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">', + ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>', + ' <name>global-event-executor</name>', + '</event-executor>', + '<binding-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">', + ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>', + ' <name>binding-osgi-broker</name>', + '</binding-registry>', + '<dom-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">', + ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>', + ' <name>dom-broker</name>', + '</dom-registry>', + '<client-dispatcher xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">', + ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>', + ' <name>global-netconf-dispatcher</name>', + '</client-dispatcher>', + '<processing-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">', + ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>', + ' <name>global-netconf-processing-executor</name>', + '</processing-executor>', + '<keepalive-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">', + ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:scheduled-threadpool</type>', + ' <name>global-netconf-ssh-scheduled-executor</name>', + '</keepalive-executor>', + '</module>' ].join('').format(mp.name, mp.ipaddress, mp.port, mp.username, mp.password); */ + var xml = [ + '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">', + ' <node-id>{0}</node-id>', + ' <host xmlns="urn:opendaylight:netconf-node-topology">{1}</host>', + ' <port xmlns="urn:opendaylight:netconf-node-topology">{2}</port>', + ' <username xmlns="urn:opendaylight:netconf-node-topology">{3}</username>', + ' <password xmlns="urn:opendaylight:netconf-node-topology">{4}</password>', + ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>', + + ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->', + ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>', + ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>', + ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>', + ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>', + ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>', + + ' <!-- keepalive-delay set to 0 turns off keepalives-->', + ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>', + '</node>'].join('').format(mp.name, mp.ipaddress, mp.port, mp.username, mp.password); + + var request = { + method: 'PUT', + url: url, + headers: { + 'Content-Type': 'application/xml', + 'Accept': 'application/xml' + }, + data: xml + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + deferred.resolve(success.data); + }, function (error) { + $mwtnLog.error({ component: '$mwtnCommons.mount', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise to unmount netconf devices the old way from OpenDaylight Lithium. + * This is needed in case Netconf devices from 3rd ONF Wireless PoC were mounted. + * @param {string} nodeId - The mountpoint identifier which should be unmounted the old way. + */ + var unmountDeprecated = function (nodeId) { + var url = [service.base, + 'config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-sal-netconf-connector-cfg:sal-netconf-connector/', + nodeId].join(''); + var request = { + method: 'DELETE', + url: url + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + $mwtnLog.info({ component: COMPONENT, message: 'Mounting Point deleted: ' + nodeId }); + deferred.resolve(success.data); + }, function (error) { + $mwtnLog.info({ component: '$mwtnCommons.unmount', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + } + + /** + * A promise to unmount netconf devices from OpenDaylight Beryllium and higher. + * @param {string} nodeId - The mountpoint identifier which unmounted/disconnected from OpenDaylight. + */ + service.unmount = function (nodeId) { + var url = [service.base, service.url.unmount(nodeId)].join(''); + var request = { + method: 'DELETE', + url: url + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + $mwtnLog.info({ component: COMPONENT, message: 'Mounting Point deleted: ' + nodeId }); + deferred.resolve(success.data); + }, function (error) { + // try the old way + unmountDeprecated(nodeId).then( + function (success) { + $mwtnLog.info({ component: COMPONENT, message: 'Mounting Point deleted: ' + nodeId }); + deferred.resolve(success.data); + }, + function (error) { + $mwtnLog.info({ component: '$mwtnCommons.unmount', message: JSON.stringify(error.data) }); + deferred.reject(error); + } + ); + }); + return deferred.promise; + }; + + service.getPacParts = function (spec) { + var errorMsg = { info: 'No data received' }; + var deferred = $q.defer(); + switch (spec.pacId) { + case 'ne': + service.getActualNetworkElement(spec.nodeId, spec.revision).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!' }); + deferred.reject(error); + }); + break; + case 'clock': + service.getPtpClockData(spec.nodeId, spec.revision).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Requesting clock for ' + spec.nodeId + ' failed!' }); + deferred.reject(); + }); + break; + case 'forwardingDomain': + console.warn('fd', JSON.stringify(spec)); + service.getForwardingDomain(spec.nodeId, 'eth-switch').then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Requesting forwarding domain for ' + spec.nodeId + ' failed!' }); + deferred.reject(error); + }); + break; + case 'ltp': + var ltpKey = 'ltp'; + switch (spec.revision) { + case '2017-02-17': + case '2017-03-20': + case '2017-03-24': + case '2017-10-20': + ltpKey = 'ltp'; + break; + default: + ltpKey = '_ltpRefList'; + } + var odlRequest = { + method: 'GET', + url: [service.url.actualNetworkElement(spec.nodeId, spec.revision), ltpKey, spec.layerProtocolId].join('/') + }; + // console.info(odlRequest.url); + service.genericRequest(odlRequest).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Requesting LTPs of ' + spec.nodeId + ' failed!' }); + deferred.reject(errorMsg); + }); + break; + case 'MWPS': + case 'MWS': + case 'ETH-CTP': + case 'ETC': + case 'airinterface': + case 'structure': + case 'container': + // 3rd PoC + case 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac': + case 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac': + case 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac': + // 4th PoC + case 'microwave-model:mw-air-interface-pac': + case 'microwave-model:mw-air-interface-diversity-pac': + case 'microwave-model:mw-pure-ethernet-structure-pac': + case 'microwave-model:mw-hybrid-mw-structure-pac': + case 'microwave-model:mw-tdm-container-pac': + case 'microwave-model:mw-ethernet-container-pac': + case 'onf-ethernet-conditional-packages:ethernet-pac': + // PoC 4.1 + case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac': + case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac': + if (spec.partId) { + service.getConditionalPackagePart(spec).then(function (success) { + success.layerProtocol = spec.layerProtocolId; + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Requesting conditional package of ' + JSON.stringify(spec) + ' failed!' }); + deferred.reject(errorMsg); + }); + } else { + deferred.resolve(); + } + break; + case 'neCurrentProblems': + service.getNetworkElementCurrentProblemList(spec.nodeId, spec.revision).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!' }); + deferred.reject(error); + }); + break; + case 'mountpoint': + case 'forwardingConstructs': + // not needed (currently) + deferred.resolve(); + break; + default: + $mwtnLog.error({ component: COMPONENT, message: 'Requesting ' + spec.pacId + ' is not supported!' }); + deferred.reject(errorMsg); + } + return deferred.promise; + }; + service.setPacParts = function (spec, data) { + var errorMsg = { info: 'No data received' }; + var deferred = $q.defer(); + switch (spec.pacId) { + // case 'ne': + // service.getActualNetworkElement(spec.nodeId, spec.revision).then(function(success){ + // deferred.resolve(success); + // }, function(error){ + // $mwtnLog.error({component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!'}); + // deferred.reject(errorMsg); + // }); + // break; + // case 'ltp': + // var odlRequest = { + // method: 'GET', + // url: [service.url.actualNetworkElement(spec.nodeId, spec.revision), '_ltpRefList', spec.layerProtocolId].join('/') + // }; + // service.genericRequest(odlRequest).then(function(success){ + // deferred.resolve(success); + // }, function(error){ + // $mwtnLog.error({component: COMPONENT, message: 'Requesting LTPs of ' + spec.nodeId + ' failed!'}); + // deferred.reject(errorMsg); + // }); + // break; + case 'airinterface': + case 'structure': + case 'container': + // 4th PoC + case 'microwave-model:mw-air-interface-pac': + case 'microwave-model:mw-air-interface-diversity-pac': + case 'microwave-model:mw-pure-ethernet-structure-pac': + case 'microwave-model:mw-hybrid-mw-structure-pac': + case 'microwave-model:mw-tdm-container-pac': + case 'microwave-model:mw-ethernet-container-pac': + case 'onf-ethernet-conditional-packages:ethernet-pac': + // PoC 4.1 + case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac': + case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac': + service.setConditionalPackagePart(spec, data).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + JSON.stringify(spec) + ' failed!' }); + deferred.reject(errorMsg); + }); + break; + default: + $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + spec.pacId + ' not supported!' }); + deferred.reject(errorMsg); + } + return deferred.promise; + }; + service.setPacPartLists = function (spec, listData) { + var errorMsg = { info: 'No data received' }; + var deferred = $q.defer(); + switch (spec.pacId) { + // case 'ne': + // service.getActualNetworkElement(spec.nodeId, spec.revision).then(function(success){ + // deferred.resolve(success); + // }, function(error){ + // $mwtnLog.error({component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!'}); + // deferred.reject(errorMsg); + // }); + // break; + // case 'ltp': + // var odlRequest = { + // method: 'GET', + // url: [service.url.actualNetworkElement(spec.nodeId, spec.revision), '_ltpRefList', spec.layerProtocolId].join('/') + // }; + // service.genericRequest(odlRequest).then(function(success){ + // deferred.resolve(success); + // }, function(error){ + // $mwtnLog.error({component: COMPONENT, message: 'Requesting LTPs of ' + spec.nodeId + ' failed!'}); + // deferred.reject(errorMsg); + // }); + // break; + case 'airinterface': + case 'structure': + case 'container': + // 4th PoC + case 'microwave-model:mw-air-interface-pac': + case 'microwave-model:mw-air-interface-diversity-pac': + case 'microwave-model:mw-pure-ethernet-structure-pac': + case 'microwave-model:mw-hybrid-mw-structure-pac': + case 'microwave-model:mw-tdm-container-pac': + case 'microwave-model:mw-ethernet-container-pac': + case 'onf-ethernet-conditional-packages:ethernet-pac': + // PoC 4.1 + case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac': + case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac': + service.setConditionalPackagePartList(spec, listData).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + JSON.stringify(spec) + ' failed!' }); + deferred.reject(errorMsg); + }); + break; + default: + $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + spec.pacId + ' not supported!' }); + deferred.reject(errorMsg); + } + return deferred.promise; + }; + var nodeIntId = 100; + service.getNodeIntIdFromNodeId = function (nodeId) { + nodeIntId = nodeIntId + 1; + if (nodeId.contains('-')) { + return nodeId.split('-')[1]; + } + return nodeIntId; + }; + + service.getRequiredNetworkElements = function (complete) { + var sort = [{ _id: { order: 'asc' } }];; + var query = { + match: { + required: true + } + }; + var deferred = $q.defer(); + $mwtnDatabase.getFilteredSortedData('mwtn', 'required-networkelement', 0, 10000, sort, query).then( + function (success) { + if (complete) { + deferred.resolve(success.data.hits.hits); + } + var result = success.data.hits.hits.map(function (ne) { + var yangifiedObj = service.yangifyObject(ne._source); + var pacKey = 'microwave-model:mw-air-interface-pac'; + if (yangifiedObj['microwave-model-object-classes-air-interface:mw-air-interface-pac']) { + pacKey = 'microwave-model-object-classes-air-interface:mw-air-interface-pac'; + } + var configKey = 'air-interface-configuration'; + var radioSignalIds = []; + if (yangifiedObj[pacKey]) { + radioSignalIds = yangifiedObj[pacKey].filter( + function (mwps) { + return mwps[configKey] && mwps[configKey]['radio-signal-id']; + } + ).map( + function (mwps) { + return mwps[configKey]['radio-signal-id']; + } + ).sort(); + } + return { + id: service.getNodeIntIdFromNodeId(yangifiedObj['node-id']), + name: yangifiedObj['node-id'], + ipaddress: yangifiedObj.connect.host, + port: yangifiedObj.connect.port, + username: yangifiedObj.connect.username, + password: yangifiedObj.connect.password, + radioSignalIds: JSON.stringify(radioSignalIds), + connectionStatus: 'disconnected' + }; + }); + deferred.resolve(result); + }, + function (error) { + $mwtnLog.error({ component: COMPONENT, message: 'Problems in retrieving required network elements.' }); + deferred.reject(error); + } + ); + return deferred.promise; + }; + + service.getConnectionStatus = function (neId) { + var url = service.base + service.url.connectionStatus(neId); + var request = { + method: 'GET', + url: url + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + // console.log(JSON.stringify(success)); + deferred.resolve(success.data.node[0]['netconf-node-topology:connection-status']); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + service.executeClosedLoopAutomation = function () { + var url = service.base + 'operations/closedLoopAutomation:start'; + var request = { + method: 'POST', + url: url + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + service.saveClosedLoopAutomation = function (enabled, option) { + var url = service.base + 'operations/closedLoopAutomation:save-timer'; + var request = { + method: 'POST', + url: url, + data: { + "input": { + "enabled": enabled, + "option": option + } + } + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + service.readClosedLoopAutomation = function () { + var url = service.base + 'operations/closedLoopAutomation:read-timer'; + var request = { + method: 'POST', + url: url, + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise inquiring the a single mountpoint from topology-netconf. + * @param {string} nodeId - The mountpoint identifier. + * @return {{'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}} - The mountpoint from topology-netconf. + */ + service.getMountPoint = function (nodeId) { + var odlRequest = { + method: 'GET', + url: service.url.mount(nodeId) + }; + var deferred = $q.defer(); + service.genericRequest(odlRequest).then( + function (success) { + deferred.resolve(success.data.node[0]); + }, + function (error) { + deferred.reject(error); + } + ); + return deferred.promise; + }; + + service.getMountPoints = function () { + var url = service.base + service.url.actualNetworkElements(); + var request = { + method: 'GET', + url: url + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + var requiredTopology = 'topology-netconf'; + var topo = success.data.topology.filter(function (topo) { + return topo['topology-id'] === requiredTopology; + }); + // console.log('topo', JSON.stringify(topo)); + if (topo.length === 0) { + var message = ['ODL', requiredTopology, 'not found!'].join(' '); + $mwtnLog.error({ component: COMPONENT, message: message }); + deferred.reject(message); + } else if (topo[0].node) { + var mwMountPoints = topo[0].node.filter(function (mountpoint) { + return mountpoint['node-id'] !== 'controller-config'; + }).map(function (mountpoint) { + // console.info('mountpoint', JSON.stringify(mountpoint)); + var capId = 'netconf-node-topology:available-capabilities'; + if (mountpoint[capId] && mountpoint[capId]['available-capability']) { + var caps = mountpoint[capId]['available-capability'].filter(function (cap) { + // console.info(JSON.stringify(cap)); + return cap.capability.contains('?revision='); + }).map(function (cap) { + return { + module: cap.capability.split(')')[1], + revision: cap.capability.split('?revision=')[1].substring(0, 10) + }; + }).sort(function (a, b) { + if (a.module < b.module) return -1; + if (a.module > b.module) return 1; + return 0; + }); + // console.log('mountpoint', JSON.stringify(caps)); + mountpoint.onfCapabilities = caps; + mountpoint.onfCoreModelRevision = caps.filter(function (cap) { + return cap.module === 'core-model' || cap.module === 'CoreModel-CoreNetworkModule-ObjectClasses'; + }).map(function (cap) { + return cap.revision; + }); + if (mountpoint.onfCoreModelRevision.length === 1) { + mountpoint.onfCoreModelRevision = mountpoint.onfCoreModelRevision[0]; + } else { + $mwtnLog.error({ component: COMPONENT, message: mountpoint.onfCoreModelRevision.length + ' CoreModels supported by ' + mountpoint['node-id'] }); + } + + // console.log('caps', JSON.stringify(caps)); + mountpoint.onfAirInterfaceRevision = caps.filter(function (cap) { + return cap.module === 'microwave-model' || cap.module === 'MicrowaveModel-ObjectClasses-AirInterface'; + }).map(function (cap) { + return cap.revision; + }); + // console.log('onfAirInterfaceRevision', mountpoint.onfAirInterfaceRevision); + if (mountpoint.onfAirInterfaceRevision.length === 1) { + mountpoint.onfAirInterfaceRevision = mountpoint.onfAirInterfaceRevision[0]; + } else { + $mwtnLog.error({ component: COMPONENT, message: 'More than 1 or no MicrowaveModel supported by ' + mountpoint['node-id'] }); + } + } + var clusterConneactionStatus = 'netconf-node-topology:clustered-connection-status'; + if (mountpoint[clusterConneactionStatus] && mountpoint[clusterConneactionStatus]['netconf-master-node']) { + var value = mountpoint[clusterConneactionStatus]['netconf-master-node']; + value = value.substring(value.indexOf('@')); + mountpoint.client = value.substring(1, value.indexOf(':')); + } else { + mountpoint.client = window.location.hostname; + } + return mountpoint; + }); + // console.log('mwMountPoints', JSON.stringify(mwMountPoints)); + deferred.resolve(mwMountPoints); + } + }, function (error) { + $mwtnLog.error({ component: COMPONENT, message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + service.separator = ' '; + // grid settings + service.highlightFilteredHeader = function (row, rowRenderIndex, + col, colRenderIndex) { + if (col.filters[0].term) { + return 'header-filtered'; + } else { + return ''; + } + }; + service.gridOptions = { + data: [], + enableColumnResizing: true, + enableSorting: true, + enableFiltering: true, + enableGridMenu: true, + exporterMenuPdf: false, + showGridFooter: true, + // showColumnFooter: true, + fastWatch: true, + enableRowSelection: true, + enableRowHeaderSelection: true, + multiSelect: false + }; + service.gridOptions.gridMenuCustomItems = [{ + title: 'Rotate Grid', + action: function ($event) { + this.grid.element.toggleClass('rotated'); + }, + order: 210 + }]; + service.url = { + actualNetworkElements: function () { + return 'operational/network-topology:network-topology/topology/topology-netconf'; + }, + connectionStatus: function (neId) { + return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId; + }, + mount: function (neId) { + return 'config/network-topology:network-topology/topology/topology-netconf/node/' + neId; + // return 'config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules'; // depricated + }, + unmount: function (neId) { + // return 'config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-sal-netconf-connector-cfg:sal-netconf-connector/' + neId; // depricated + return 'config/network-topology:network-topology/topology/topology-netconf/node/' + neId; + }, + forwardingDomain: function (neId, fdUuid) { + return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId + '/yang-ext:mount/core-model:network-element/fd/' +fdUuid; + }, + forwardingConstruct: function (neId, fcUuid) { + return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId + '/yang-ext:mount/core-model:forwarding-construct/' +fcUuid; + }, + clock: function (neId, revision) { + return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1'; + }, + actualNetworkElement: function (neId, revision) { + switch (revision) { + case "2016-03-23": + return [ + 'operational/network-topology:network-topology/topology/topology-netconf/node/', + neId, + '/yang-ext:mount/CoreModel-CoreNetworkModule-ObjectClasses:NetworkElement/', + neId].join(''); + case "2017-02-17": + case "2017-03-20": + case "2017-03-24": + case "2017-10-20": + return [ + 'operational/network-topology:network-topology/topology/topology-netconf/node/', + neId, + '/yang-ext:mount/core-model:network-element'].join(''); + default: // 2016-08-11 + return [ + 'operational/network-topology:network-topology/topology/topology-netconf/node/', + neId, + '/yang-ext:mount/CoreModel-CoreNetworkModule-ObjectClasses:NetworkElement'].join(''); + } + }, + networkElementCurrentProblemList: function (neId, revision) { + console.log(neId, revision); + switch (revision) { + case "2016-08-11": + return [ + 'operational/network-topology:network-topology/topology/topology-netconf/node/', + neId, + '/yang-ext:mount/MicrowaveModel-NetworkElement-CurrentProblemList:NetworkElementCurrentProblems'].join(''); + case "2017-02-17": + case "2017-03-20": // TODO sko equipmentAlarms check new yang file if agreed + return [ + 'operational/network-topology:network-topology/topology/topology-netconf/node/', + neId, + '/yang-ext:mount/onf-core-model-conditional-packages:network-element-pac/network-element-current-problems'].join(''); + default: + return [ + 'operational/network-topology:network-topology/topology/topology-netconf/node/', + neId, + '/yang-ext:mount/onf-core-model-conditional-packages:network-element-pac/network-element-current-problems'].join(''); + } + } + }; + /* + * Changes different time formats to a common time fromat + * TODO currently not implemented! + */ + service.normalizeTimeFormat = function (time, format) { + return time; + }; + /* + * Changing a string according to yang naming conventions. + * The function should be alinged with the ONF Eagle project. + */ + service.yangify = function (str) { + var result = str + .replace(/RefList+$/, '') // endling "List" was removed + .replace(/List+$/, '') // endling "List" was removed + .replace(/([a-z])([A-Z])/g, '$1-$2') // insert dashes + .replace(/([0-9])([a-zA-Z])/g, '$1-$2') // insert dashes + .replace(/([A-Z])([A-Z])([a-z])/g, '$1-$2$3') // insert dashes + .toLowerCase() // lowercase everything + .replace(/^_/, '') // remove leading underscore + .replace(/:_/g, ':') // and leading underscores in path segments + .replace(/_/g, '-'); // convert underscore to dashes + + // catch "wrong" UML labels + var exceptions = { + 'air-interface':'air-interface-list', + 'air-interface-ltp':'air-interface-ltp-list', + 'air-interface-capability': 'air-interface-capability-list', + 'air-interface-current-problem': 'air-interface-current-problem-list', + 'container-capability': 'container-capability-list', + 'current-performance-data':'current-performance-data-list', + 'current-problem':'current-problem-list', + 'historical-performance-data':'historical-performance-data-list', + 'problem-kind-severity':'problem-kind-severity-list', + 'pure-ethernet-structure-capability':'pure-ethernet-structure-capability-list', + 'segment-status':'segment-status-list', + 'segments-id':'segments-id-list', + 'structure-capability': 'structure-capability-list', + 'structure-current-problem': 'structure-current-problem-list', + 'supported-tdm-container-types':'supported-tdm-container-types-list', + 'supported-tdm-structure-types':'supported-tdm-structure-types-list', + 'supported-channel-plan':'supported-channel-plan-list', + 'supported-loop-back-kind':'transmission-mode-list', + 'transmission-mode':'transmission-mode-list' + }; + if (exceptions[result]) { + console.warn(result, '.>', exceptions[result]); + result=exceptions[result]; + } + + // catch modulation value difference + if (result.startsWith('time') && result.endsWith('symbols') + || result.startsWith('time') && result.contains('-symbols-') && result.endsWith('-s') + || result.startsWith('time') && result.contains('-symbols-') && result.endsWith('-l')) { + result = result.replace('symbols', 'states'); + } + return result; + }; + + /* + * Checking, whether a jsonObject should be yangifyed + */ + service.isCamelCase = function (jsonObject) { + if (jsonObject === undefined || jsonObject === null) { + return true; + } + var result; + var type = service.getType(jsonObject); + switch (type) { + case 'object': + result = false; + Object.keys(jsonObject).map(function (key) { + result = result || key !== [service.yangify(key)]; + }); + break; + case 'array': + case 'boolean': + case 'function': + case 'string': + case 'number': + case 'null': + case 'undefined': + result = true; + break; + default: + console.error('Type1:', type, ' is not supported!'); + result = true; + } + return result; + }; + /* + * Yangifies a names/keys of a jsonOject + */ + service.yangifyObject = function (jsonObject) { + if (jsonObject === undefined || jsonObject === null) { + return jsonObject; + } + var result; + var type = service.getType(jsonObject); + switch (type) { + case 'object': + case 'name-value': + result = {}; + Object.keys(jsonObject).map(function (key) { + result[service.yangify(key)] = service.yangifyObject(jsonObject[key]); + }); + break; + case 'array': + result = jsonObject.map(function (item, index) { + return service.yangifyObject(item); + }); + break; + case 'boolean': + case 'function': + case 'string': + case 'number': + case 'null': + case 'undefined': + result = jsonObject; + break; + default: + console.error('Type:', type, ' is not supported!'); + result = jsonObject; + } + return result; + }; + /* + * Send a restconf request to OpenDayligth. + * All ODL restconf requests should pass this function. + */ + service.genericRequest = function (odlRequest) { + var url = [service.base, odlRequest.url].join(''); + var request = { + method: odlRequest.method, + url: url, + data: odlRequest.data + }; + var deferred = $q.defer(); + $http(request).then(function (success) { + // yangifing the response is required until all NEs has switch to CoreModel 1.2 (ONF-TR-532) + // deferred.resolve(service.yangifyObject(success)); + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: COMPONENT + '.genericRequest', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + service.getMountedNetConfServers = function (callback) { + var url = service.base + service.url.actualNetworkElements(); + var request = { + method: 'GET', + url: url + }; + $http(request).then(function (success) { + return callback(success.data); + }, function (error) { + console.error(JSON.stringify(error)); + return callback(); + }); + }; + + service.getActualNetworkElement = function (neId, revision) { + var url = [service.base, + service.url.actualNetworkElement(neId, revision)].join(''); + var request = { + method: 'GET', + url: url + }; + var taskId = [neId, 'ONF:CoreModel:NetworkElement data received'].join(' '); + + var deferred = $q.defer(); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + success.data.revision = revision; + // deferred.resolve(service.yangifyObject(success.data)); + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getActualNetworkElement', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getForwardingDomain = function(neId, fdUuid) { + var url = [service.base, + service.url.forwardingDomain(neId, fdUuid)].join(''); + var request = { + method: 'GET', + url: url + }; + var taskId = [neId, 'ONF:ForwardingDomain received'].join(' '); + + var deferred = $q.defer(); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + // deferred.resolve(service.yangifyObject(success.data)); + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getForwardingDomain', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getForwardingConstruct = function(neId, fcUuid) { + var url = [service.base, + service.url.forwardingConstruct(neId, fcUuid)].join(''); + var request = { + method: 'GET', + url: url + }; + var taskId = [neId, fcUuid, 'ONF:ForwardingConstruct received'].join(' '); + + var deferred = $q.defer(); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + // deferred.resolve(service.yangifyObject(success.data)); + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getForwardingConstruct', message: JSON.stringify(error.data) }); + deferred.reject(); + }); + return deferred.promise; + }; + + service.getPtpClockData = function(neId, revision) { + var url = [service.base, + service.url.clock(neId, revision)].join(''); + var request = { + method: 'GET', + url: url + }; + var taskId = [neId, 'ONF:PTP:DataSet received'].join(' '); + + var deferred = $q.defer(); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + success.data.revision = revision; + // deferred.resolve(service.yangifyObject(success.data)); + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getPtpClockData', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getNetworkElementCurrentProblemList = function (neId, revision) { + var url = [service.base, + service.url.networkElementCurrentProblemList(neId, revision)].join(''); + var request = { + method: 'GET', + url: url + }; + var taskId = [neId, 'ONF:CoreModel:NetworkElement data received'].join(' '); + + var deferred = $q.defer(); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + success.data.revision = revision; + // deferred.resolve(service.yangifyObject(success.data)); TODO: check if correct + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getActualNetworkElement', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + var getIdsByRevision = function (revision, pacId, partId) { + + switch (revision) { + case '2016-03-23': + switch (pacId) { + case 'MWPS': + case 'AirInterface': + case 'airinterface': + case 'airInterface': + pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_AirInterface_Pac'; + partId = 'airInterface' + partId; + if (partId === 'airInterfaceCapability' || partId === 'airInterfaceCurrentProblems') { + partId = undefined; + } + break; + case 'MWS': + case 'Structure': + case 'structure': + pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_Structure_Pac'; + partId = 'structure' + partId; + break; + case 'ETH-CTP': + case 'ETH': + case 'Container': + case 'container': + pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_Container_Pac'; + partId = 'container' + partId; + break; + case 'TDM': + pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_Container_Pac'; + partId = 'container' + partId; + break; + } + break; + case '2017-02-17': + case '2017-03-20': + case '2017-03-24': + switch (pacId) { + case 'MWPS': + case 'AirInterface': + case 'airinterface': + case 'airInterface': + case 'air-interface': + pacId = 'microwave-model:mw-air-interface-pac'; + partId = 'air-interface-' + service.yangify(partId); + break; + case 'MWS': + case 'Structure': + case 'structure': + var isHybrid = false; // TODO How do I know this? + if (isHybrid) { + pacId = 'microwave-model:mw-hybrid-mw-structure-pac'; + partId = 'hybrid-mw-structure-' + service.yangify(partId); + } else { + pacId = 'microwave-model:mw-pure-ethernet-structure-pac'; + partId = 'pure-ethernet-structure-' + service.yangify(partId); + } + break; + case 'ETH-CTP': + case 'ETC': + case 'Container': + case 'container': + pacId = 'microwave-model:mw-ethernet-container-pac'; + partId = 'ethernet-container-' + service.yangify(partId); + break; + case 'TDM': + pacId = 'microwave-model:mw-tdm-container-pac'; + partId = 'tdm-container-' + service.yangify(partId); + break; + } + break; + default: + switch (pacId) { + case 'MWPS': + case 'AirInterface': + case 'airinterface': + case 'airInterface': + pacId = 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac'; + partId = 'airInterface' + partId; + break; + case 'MWS': + case 'Structure': + case 'structure': + pacId = 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac'; + partId = 'pureEthernetStructure' + partId; + break; + case 'ETH-CTP': + case 'ETH': + case 'Container': + case 'container': + pacId = 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac'; + partId = 'ethernetContainer' + partId; + break; + case 'TDM': + pacId = 'microwave-model:mw-tdm-container-pac'; + partId = 'tdm-container-' + service.yangify(partId); + break; + } + } + return { + pacId: pacId, + partId: partId + }; + }; + + service.getConditionalPackagePart = function (spec) { + // console.log(JSON.stringify(spec)); + var deferred = $q.defer(); + if (!spec.partId) { + deferred.reject('ignore'); + return deferred.promise; + } + + var ids = getIdsByRevision(spec.revision, spec.pacId, spec.partId); + var operation = 'operational'; + if (spec.config === true) { + operation = 'config'; + } + + var url = [service.base, operation, + '/network-topology:network-topology/topology/topology-netconf/node/', + spec.nodeId, + '/yang-ext:mount/', ids.pacId, '/', + spec.layerProtocolId, '/', + ids.partId].join(''); + var request = { + method: 'GET', + url: url + }; + // console.log(JSON.stringify(request)); + + var taskId = [spec.nodeId, spec.layerProtocolId, spec.pacId, 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + success.data.revision = spec.revision; + deferred.resolve(success.data); + // console.log(JSON.stringify(service.yangifyObject(success.data))); + // [sko] not now - later after all apps are updated to the new model: deferred.resolve(service.yangifyObject(success.data)); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getConditionalPackagePart', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getPtpPort = function (spec) { + var deferred = $q.defer(); + if (!spec.networkElement || !spec.value) { + deferred.reject('ignore'); + return deferred.promise; + } + + var operation = 'config'; + var url = [service.base, operation, + '/network-topology:network-topology/topology/topology-netconf/node/', + spec.networkElement, + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/port-ds-list/', + spec.value['port-number']].join(''); + var request = { + method: 'GET', + url: url + }; + console.warn(JSON.stringify(request)); + + var taskId = [spec.networkElement, spec.value['port-number'], 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + console.warn(JSON.stringify(success.data)); + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getPtpPort', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.setPtpPort = function (spec, data) { + var deferred = $q.defer(); + if (!spec.networkElement || !spec.value) { + deferred.reject('ignore'); + return deferred.promise; + } + + var operation = 'config'; + var url = [service.base, operation, + '/network-topology:network-topology/topology/topology-netconf/node/', + spec.networkElement, + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/port-ds-list/', + spec.value['port-number']].join(''); + + var body = {'port-ds-list': data}; + + var request = { + method: 'PUT', + url: url, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + data: body + }; + + var taskId = [spec.networkElement, spec.value['port-number'], 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + deferred.resolve(success.data); + // deferred.resolve(service.yangifyObject(success.data)); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.error({ component: '$mwtnCommons.setPtpPort', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + + service.getPtpDefaultDs = function (spec) { + var deferred = $q.defer(); + if (!spec.networkElement || !spec.value) { + deferred.reject('ignore'); + return deferred.promise; + } + + var operation = 'config'; + var url = [service.base, operation, + '/network-topology:network-topology/topology/topology-netconf/node/', + spec.networkElement, + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/default-ds/'].join(''); + var request = { + method: 'GET', + url: url + }; + console.warn(JSON.stringify(request)); + + var taskId = [spec.networkElement, 'default-ds', 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + console.warn(JSON.stringify(success.data)); + deferred.resolve(success.data); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.info({ component: '$mwtnCommons.getPtpPort', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.setPtpDefaultDs = function (spec, data) { + var deferred = $q.defer(); + if (!spec.networkElement || !spec.value) { + deferred.reject('ignore'); + return deferred.promise; + } + + var operation = 'config'; + var url = [service.base, operation, + '/network-topology:network-topology/topology/topology-netconf/node/', + spec.networkElement, + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/default-ds/'].join(''); + + var body = {'default-ds': data}; + + var request = { + method: 'PUT', + url: url, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + data: body + }; + + var taskId = [spec.networkElement, 'default-ds', 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + deferred.resolve(success.data); + // deferred.resolve(service.yangifyObject(success.data)); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.error({ component: '$mwtnCommons.setPtpPort', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + + service.setConditionalPackagePart = function (spec, data) { + var deferred = $q.defer(); + if (!spec.partId) { + deferred.reject('ignore'); + return deferred.promise; + } + + var ids = getIdsByRevision(spec.revision, spec.pacId, spec.partId); + var body = {}; + body[ids.partId] = data; + + var url = [service.base, + 'config/network-topology:network-topology/topology/topology-netconf/node/', + spec.nodeId, + '/yang-ext:mount/', ids.pacId, '/', + spec.layerProtocolId, '/', + ids.partId].join(''); + var request = { + method: 'PUT', + url: url, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + data: body + }; + + var taskId = [spec.nodeId, spec.layerProtocolId, spec.pacId, 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + success.data.revision = spec.revision; + deferred.resolve(success.data); + // deferred.resolve(service.yangifyObject(success.data)); + }, function (error) { + console.timeEnd(taskId); + $mwtnLog.error({ component: '$mwtnCommons.setConditionalPackagePart', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + // pureEthernetStructureConfiguration/problemKindSeverityList/value1 + // { + // "problemKindSeverityList": [ + // { + // "problemKindName": "severity1", + // "problemKindSeverity": "warning" + // } + // ] + // } + + var processData = function (item, i, callback) { + var spec = item.spec; + var ids = getIdsByRevision(spec.revision, spec.pacId, + spec.partId); + item.spec = undefined; + var body = {}; + body[spec.attribute] = [item]; + $mwtnDatabase.getSchema().then(function (schema) { + + var key; + Object.keys(item).map(function (k) { + // works currently only for single key lists + if (schema[k] && schema[k]['is-key']) { + key = k; + } + }); + + var url = [ + service.base.slice(0, -1), + 'config/network-topology:network-topology/topology/topology-netconf/node', + spec.nodeId, 'yang-ext:mount', ids.pacId, + spec.layerProtocolId, ids.partId, + spec.attribute, item[key]].join('/'); + var request = { + method: 'PUT', + url: url, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + data: body + }; + // console.log(JSON.stringify(request)); + var taskId = [spec.nodeId, spec.layerProtocolId, + spec.pacId, item.problemKindName, + 'data received'].join(' '); + console.time(taskId); + $http(request).then(function (success) { + console.timeEnd(taskId); + success.data.revision = spec.revision; + return callback(); + }, + function (error) { + console.timeEnd(taskId); + $mwtnLog + .error({ + component: '$mwtnCommons.setConditionalPackagePart', + message: JSON + .stringify(error.data) + }); + return callback(); + }); + }); + }; + + service.setConditionalPackagePartList = function (spec, data) { + var deferred = $q.defer(); + if (!spec.partId) { + deferred.reject('ignore'); + return deferred.promise; + } + + data.map(function (item) { + item.spec = spec; + }); + + doSynchronousLoop(data, processData, function () { + deferred.resolve(); + }); + return deferred.promise; + }; + + var saveRequiredNetworkElement = function (requiredNode) { + var url = [$mwtnDatabase.base, $mwtnDatabase.index, 'required-networkelement', + requiredNode.nodeId].join('/'); + var bodyString = JSON.stringify(requiredNode); + var headers = { + 'Content-Type': 'application/json', + 'Content-Length': bodyString.length + }; + var request = { + method: 'PUT', + url: url, + data: requiredNode + }; + + var deferred = $q.defer(); + console.time('database:' + url); + $http(request).then(function (success) { + console.timeEnd('database:' + url); + // console.log(JSON.stringify(success)); + deferred.resolve(success); + }, function (error) { + console.timeEnd('database:' + url); + $mwtnLog.error({ component: '$mwtnCommons.saveRequiredNetworkElement', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * 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, site:string, onfCoreModelRevision: string, onfAirInterfaceRevision: string}} netconfServer - A netConf server object with all connectivity parameters. + */ + service.addRequiredNetworkElement = function (netconfServer) { + /** {Object} requiredNode - Data set to be stored in database */ + var requiredNode = { + nodeId: netconfServer['node-id'], + siteRef: netconfServer.site, + onfCoreModelRevision: netconfServer.onfCoreModelRevision, + onfAirInterfaceRevision: netconfServer.onfAirInterfaceRevision, + required: true, + connect: { + mountId: netconfServer['node-id'], + host: netconfServer['netconf-node-topology:host'], + port: netconfServer['netconf-node-topology:port'], + username: netconfServer.username, + password: netconfServer.password + }, + 'core-model:network-element': {}, + }; + + var deferred = $q.defer(); + saveRequiredNetworkElement(requiredNode).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: '$mwtnCommons.saveRequiredNetworkElement', message: JSON.stringify(error.data) }); + deferred.reject(error); + }); + + // [sko] much simplified du to ONAP concepts, no device configuration needs to be stored in database. + + // // get NetworkElement object from node + // var spec = { + // nodeId: requiredNode.nodeId, + // revision: requiredNode.onfCoreModelRevision, + // pacId: 'ne' + // }; + + // var updatePart = function (spec, data) { + // data.layerProtocol = spec.layerProtocolId; + // requiredNode[spec.pacId].push(data); + // }; + + // var numberOfLtps = -1; + // var processLTPs = function (item, i, callback) { + // var ltp = new LogicalTerminationPoint(item); + // ltp.getLayerProtocols().map( + // /** + // * A function processing a layer-protocol object + // * @param {LayerProtocol} lp A layer-protocol object + // */ + // function (lp) { + // var conditionalPackage = lp.getConditionalPackage(true); + // if (conditionalPackage !== '') { + // if (requiredNode[conditionalPackage] === undefined) { + // // create missing pac array + // requiredNode[conditionalPackage] = []; + // } + // var spec = { + // nodeId: requiredNode.nodeId, + // revision: requiredNode.onfCoreModelRevision, + // pacId: conditionalPackage, + // layer: lp.getLayer(), + // layerProtocolId: lp.getId() + // }; + // spec.partId = service.getPartGlobalId(spec, 'configuration'); + // // console.info(JSON.stringify(spec)); + // service.getPacParts(spec).then(function (success) { + // // console.log(JSON.stringify(success)); + // spec.message = ['Process LTP', i+1, 'of', numberOfLtps].join(' '); + // $notifying.notify(spec); + // updatePart(spec, service.yangifyObject(success)); + // return callback(); + // }, function (error) { + // spec.message = ['Process LTP', i+1, 'of', numberOfLtps].join(' '); + // $notifying.notify(spec); + // $mwtnLog.error({ component: '$mwtnCommons.processLTPs bad data', message: JSON.stringify(error) }); + // return callback(); + // }); + // } else { + // $mwtnLog.info({ component: COMPONENT, message: 'No condtional package found: ' + ltp.getId() }); + // return callback(); + // } + // }); + + // // console.log(JSON.stringify(ltp.getData())); + // }; + + // service.getPacParts(spec).then(function (success) { + // success = service.yangifyObject(success); + // requiredNode['core-model:network-element'] = success['network-element']; + // var id = success['network-element']['node-id']; + // numberOfLtps = success['network-element'].ltp.length; + // doSynchronousLoop(success['network-element'].ltp, processLTPs, function () { + // saveRequiredNetworkElement(requiredNode).then(function (success) { + // $notifying.notify( { nodeId: id, message: 'finish'} ); + // deferred.resolve(success); + // }, function (error) { + // $mwtnLog.error({ component: '$mwtnCommons.saveRequiredNetworkElement', message: JSON.stringify(error.data) }); + // deferred.reject(error); + // }); + // }); + + // }, function (error) { + // $mwtnLog.error({ component: '$mwtnCommons.getPacParts', message: JSON.stringify(error.data) }); + // deferred.reject(error); + // }); + return deferred.promise; + }; + + service.registerForOdlEvents = function (path, callback) { + var request = { + method: 'POST', + url: [service.base, + 'operations/sal-remote:create-data-change-event-subscription'] + .join(''), + data: { + "input": { + "path": path, + "sal-remote-augment:datastore": "CONFIGURATION", + "sal-remote-augment:scope": "SUBTREE" + } + } + }; + $http(request).then( + function successCallback(response) { + // this callback will be called asynchronously + // when the response is available + // console.log(JSON.stringify(response)); + createStream(response.data.output['stream-name'], + function (socketLocation) { + callback(socketLocation); + }); + }, function errorCallback(response) { + // called asynchronously if an error occurs + // or server returns response with an error status. + console.error(JSON.stringify(response)); + }); + }; + + return service; + }); + + // Precision Time Protocol PTP + mwtnCommonsApp.register.factory('$mwtnPtp', function ($http, $q, $mwtnCommons, PtpClock) { + var key1 = 'netconf-node-topology:available-capabilities'; + var key2 = 'available-capability'; + var filterActivePtpClocks = function(mountpoints) { + return mountpoints.filter(function(mountpoint) { + if (!mountpoint) return false; + if (!mountpoint[key1]) return false; + if (!mountpoint[key1][key2]) return false; + if (mountpoint['netconf-node-topology:connection-status'] !== 'connected') return false; + var ptpCapability = mountpoint[key1][key2].filter(function(capability){ + return capability.contains('ietf-ptp-dataset'); + }); + return ptpCapability.length > 0; + }).map(function(mountpoint){ + return mountpoint['node-id']; + }); + }; + var ptpClocks = {}; + var processData = function (nodeId, i, callback) { + $mwtnCommons.getPtpClockData(nodeId).then( + function (success) { + ptpClocks[nodeId] = new PtpClock(success); + callback(); + }, + function (error) { + console.error(error); + callback(); + } + ); + }; + + var service = {}; + service.getPtpClocks = function() { + var deferred = $q.defer(); + + $mwtnCommons.getMountPoints().then(function (mountpoints) { + var ptpClockNodeIds = filterActivePtpClocks(mountpoints); + doSynchronousLoop(ptpClockNodeIds, processData, function () { + deferred.resolve(ptpClocks); + }); + }, function (error) { + console.log(error); + deferred.reject(); + }); + + return deferred.promise; + }; + + service.getParent = function(nodeId) { + var deferred = $q.defer(); + var request = { + method: 'GET', + url: 'operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/parent-ds/parent-port-identity' + }; + + $mwtnCommons.genericRequest(request).then(function(success){ + console.warn(JSON.stringify(success)); + deferred.resolve(success.data['parent-port-identity']); + }, function(error) { + console.error(JSon.stringify(error)); + deferred.reject(); + }); + return deferred.promise; + }; + + return service; + }); + + // Service log + mwtnCommonsApp.register.factory('$mwtnLog', function ($http, $q, $mwtnDatabase) { + var writeLogToDB = function (data, callback) { + var url = [$mwtnDatabase.base, $mwtnDatabase.index, 'log'].join('/'); + var request = { + method: 'POST', + url: url, + data: { + timestamp: data.timestamp ? data.timestamp : new Date().toISOString(), + type: data.type ? data.type : 'info', + component: data.component ? data.component : 'unkonwn', + message: data.message + } + }; + $http(request).then(function successCallback(response) { + return callback(true); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + return callback(false); + }); + }; + + var createIndex = function (index, callback) { + var url = [$mwtnDatabase.base, index].join('/'); + var request = { + method: 'POST', + url: url, + data: { + timestamp: new Date().toISOString(), + type: 'info', + component: '$mwtnLog', + message: 'init log' + } + }; + $http(request).then(function (success) { + return callback(true); + }, function (error) { + console.error(JSON.stringify(error)); + return callback(false); + }); + }; + var checkIndex = function (index, callback) { + var url = [$mwtnDatabase.base, index].join('/'); + var request = { + method: 'HEAD', + url: url + }; + $http(request).then(function successCallback(response) { + return callback(true); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + createIndex(index, function (created) { + return callback(created); + }); + }); + }; + var checkDatabase = function (callback) { + var url = $mwtnDatabase.base; + var request = { + method: 'GET', + url: url + }; + $http(request).then(function successCallback(response) { + checkIndex($mwtnDatabase.index, function (exists) { + return callback(exists); + }); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + return callback(false); + }); + }; + var getData = function (type, log) { + var data = {}; + data.timestamp = new Date().toISOString(); + switch (typeof log) { + case 'string': + data.type = type; + data.component = 'unknown'; + data.message = log; + break; + case 'object': + data.type = type; + data.component = log.component; + data.message = log.message; + break; + default: + data.type = 'error'; + data.component = '$mwtnLog'; + data.message = 'pnf log service is called with wrong parameters.'; + } + // console.log(JSON.stringify(data)); + return data; + }; + var service = { + base: $mwtnDatabase.base + }; + service.debug = function (log) { + var data = getData('debug', log); + checkDatabase(function (isRunning) { + if (isRunning) { + writeLogToDB(data, function () { + // console.log('log stored'); + }); + } else { + console.error(data.timestamp, service.base, + 'Database (ElasticSerach) not reachable!?'); + } + }); + console.log(data.timestamp, JSON.stringify(log)); + }; + service.error = function (log) { + var data = getData('error', log); + checkDatabase(function (isRunning) { + if (isRunning) { + writeLogToDB(data, function () { + // console.log('log stored'); + }); + } else { + console.error(data.timestamp, service.base, + 'Database (ElasticSerach) not reachable!?'); + } + }); + console.error(data.timestamp, JSON.stringify(log)); + }; + service.info = function (log) { + var data = getData('info', log); + checkDatabase(function (isRunning) { + if (isRunning) { + writeLogToDB(data, function () { + // console.log('log stored'); + }); + } else { + console.error(data.timestamp, service.base, 'Database (ElasticSerach) not reachable!?'); + } + }); + console.info(data.timestamp, JSON.stringify(log)); + }; + service.warning = function (log) { + var data = getData('warning', log); + checkDatabase(function (isRunning) { + if (isRunning) { + writeLogToDB(data, function () { + // console.log('log stored'); + }); + } else { + console.error(data.timestamp, service.base, 'Database (ElasticSerach) not reachable!?'); + } + }); + console.warn(data.timestamp, JSON.stringify(log)); + }; + return service; + }); + + // Service log + mwtnCommonsApp.register.factory('$mwtnEthernet', function ($http, $q) { + var service = {}; + + service.base = window.location.origin + '/restconf'; + service.url = { + create: service.base + '/operations/route:create', + delete: service.base + '/operations/route:delete' + }; + + service.createForwardingConstruct = function(spec) { + var deferred = $q.defer(); + + var request = { + method: 'POST', + url: service.url.create, + data: { + input: { + vlanid: spec.vlan, + fc: [{ + nodeName: spec.nodeId, + aEnd: spec.ltp1, + zEnd: spec.ltp2 + } + ] + } + } + }; + console.log(JSON.stringify(spec)); + console.log(JSON.stringify(request)); + + var consoleId = 'create-forwarding-consturuct: '; + console.time(consoleId); + $http(request).then(function (success) { + console.timeEnd(consoleId); + console.log(JSON.stringify(success)); + deferred.resolve(success.data.output.status); + }, function (error) { + console.timeEnd(consoleId); + // console.error(JSON.stringify(error.statusText)); + deferred.reject(error.statusText); + }); + return deferred.promise; + }; + + service.deleteForwardingConstruct = function(spec) { + + var deferred = $q.defer(); + var request = { + method: 'POST', + url: service.url.delete, + data: {input:{vlanid:spec.ltp.slice(-2)}} + }; + console.log(JSON.stringify(spec)); + console.log(JSON.stringify(request)); + + var consoleId = 'delete-forwarding-consturuct: '; + console.time(consoleId); + $http(request).then(function (success) { + console.timeEnd(consoleId); + console.log(JSON.stringify(success)); + deferred.resolve(success.data.output.status); + }, function (error) { + console.timeEnd(consoleId); + // console.error(JSON.stringify(error.statusText)); + deferred.reject(error.statusText); + }); + return deferred.promise; + }; + + return service; + }); + + // Service Database (ElasticSerach) + mwtnCommonsApp.register.factory('$mwtnDatabase', function ($http, $q) { + var service = { + base: window.location.origin + '/database', + index: 'mwtn', + command: '_search', + mwtn: 'todo' + }; + + // TODO getBase is not needed anymore + service.getBase = function (functionId) { + var deferred = $q.defer(); + + deferred.resolve({ + base: service.base, + index: functionId + }); + + return deferred.promise; + }; + + service.genericRequest = function (databaseRequest) { + var url = [databaseRequest.base, databaseRequest.index, databaseRequest.docType, + databaseRequest.command].join('/'); + var request = { + method: databaseRequest.method, + url: url, + data: { + from: databaseRequest.from, + size: databaseRequest.size, + sort: databaseRequest.sort, + filter: databaseRequest.filter, + query: databaseRequest.query + } + }; + // overwrite request data if given + if (databaseRequest.data) { + request.data = databaseRequest.data; + } + var deferred = $q.defer(); + var consoleId = 'database: ' + url; + console.time(consoleId); + $http(request).then(function (success) { + console.timeEnd(consoleId); + // console.log(JSON.stringify(success)); + deferred.resolve(success); + }, function (error) { + console.timeEnd(consoleId); + console.warn(JSON.stringify(error)); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.aggregationRequest = function (databaseRequest) { + var url = [databaseRequest.base, databaseRequest.index, databaseRequest.docType, + databaseRequest.command].join('/'); + var request = { + method: databaseRequest.method, + url: url, + data: databaseRequest.aggregation + }; + var deferred = $q.defer(); + var consoleId = 'database: ' + url; + console.time(consoleId); + $http(request).then(function (success) { + console.timeEnd(consoleId); + deferred.resolve(success); + }, function (error) { + console.timeEnd(consoleId); + console.warn(JSON.stringify(error)); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAllData = function (functionId, docType, from, size, sort) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'POST', + base: success.base, + index: success.index, + command: '_search', + docType: docType, + from: from, + size: size, + sort: sort, + query: { + match_all: {} + } + }; + service.genericRequest(databaseRequest).then(function (success) { + // console.log('getAllData', success); + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getFilteredData = function (functionId, docType, from, size, query) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'POST', + base: success.base, + index: success.index, + command: '_search', + docType: docType, + from: from, + size: size, + sort: [], + query: query + }; + service.genericRequest(databaseRequest).then(function (success) { + // console.log('getAllData', success); + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getFilteredSortedData = function (functionId, docType, from, size, sort, query) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'POST', + base: success.base, + index: success.index, + command: '_search', + docType: docType, + from: from, + size: size, + sort: sort, + query: query + }; + service.genericRequest(databaseRequest).then(function (success) { + // console.log('getAllData', success); + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAggregatedData = function (functionId, docType, aggregation) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'POST', + base: success.base, + index: success.index, + command: '_search', + docType: docType, + aggregation: aggregation + }; + service.aggregationRequest(databaseRequest).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAggregations = function (functionId, docType, aggregations) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'POST', + base: success.base, + index: success.index, + command: '_search', + docType: docType, + aggregation: aggregations + }; + service.aggregationRequest(databaseRequest).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getData = function (docType, from, size, sort, filter, query) { + var deferred = $q.defer(); + service.getBase('mwtn').then(function (success) { + var databaseRequest = { + method: 'POST', + base: success.base, + index: success.index, + docType: docType, + from: from, + size: size, + sort: sort, + filter: filter, + query: query + }; + service.genericRequest(databaseRequest).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.deleteDocType = function (spec) { + var deferred = $q.defer(); + service.getBase(spec.functionId).then(function (success) { + var databaseRequest = { + method: 'DELETE', + base: success.base, + index: success.index, + docType: spec.docType, + command: '_query', + query: spec.query + }; + + service.genericRequest(databaseRequest).then(function (success) { + deferred.resolve(status); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise, which inquires a single document from database. + * @param {string} functionId - An identifier of an SDN function (e.g 'mwtn'). + * @param {string} docType - The document type of the document to be deleted. + * @param {string} id - An identifier of the document to be deleted. + */ + service.getSingleDocument = function (functionId, docType, id) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'GET', + base: success.base, + index: success.index, + docType: docType, + command: id + }; + + service.genericRequest(databaseRequest).then(function (success) { + deferred.resolve(success.data._source); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise, creating or updateing a single document of the database. + * @param {string} functionId - An identifier of an SDN function (e.g 'mwtn'). + * @param {string} docType - The document type of the document to be deleted. + * @param {string} id - An identifier of the document to be deleted. + * @param {Object} data - A json object to be stored in the database + */ + service.createSingleDocument = function (functionId, docType, id, data) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'PUT', + base: success.base, + index: success.index, + docType: docType, + command: id, + data: data + }; + + service.genericRequest(databaseRequest).then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise, which deletes one document within the database. + * @param {string} functionId - An identifier of an SDN function (e.g 'mwtn'). + * @param {string} docType - The document type of the document to be deleted. + * @param {string} id - An identifier of the document to be deleted. + */ + service.deleteSingleDocument = function (functionId, docType, id) { + var deferred = $q.defer(); + service.getBase(functionId).then(function (success) { + var databaseRequest = { + method: 'DELETE', + base: success.base, + index: success.index, + docType: docType, + command: id, + }; + + service.genericRequest(databaseRequest).then(function (success) { + deferred.resolve({ status: success.status, logId: success.data._id }); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + var moduleInformation; + var inquireModuleInformation = function () { + var deferred = $q.defer(); + service.getBase('mwtn').then(function (success) { + var databaseRequest = { + method: 'GET', + base: success.base, + index: success.index, + from: 0, + size: 999 + }; + service.getAllData('mwtn', 'module', 0, 999, undefined).then(function (success) { + // console.log(JSON.stringify(data.data.hits.hits)); + moduleInformation = {}; + success.data.hits.hits.map(function (hit) { + moduleInformation[hit._id] = hit._source; + }); + // console.log('got moduleInformation', Object.keys(moduleInformation).length); + return deferred.resolve(moduleInformation); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise which returns object yang class and attribute descriptions + */ + service.getModules = function () { + var deferred = $q.defer(); + if (moduleInformation) { + deferred.resolve(moduleInformation); + } else { + inquireModuleInformation().then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + } + return deferred.promise; + }; + + var schemaInformation; + var inquireSchemaInformation = function () { + var deferred = $q.defer(); + service.getBase('mwtn').then(function (success) { + var databaseRequest = { + method: 'GET', + base: success.base, + index: success.index, + from: 0, + size: 999 + }; + service.getAllData('mwtn', 'schema-information', 0, 9999, undefined).then(function (success) { + // console.log(JSON.stringify(data.data.hits.hits)); + schemaInformation = {}; + success.data.hits.hits.map(function (hit) { + schemaInformation[hit._id] = hit._source; + }); + // console.log('got schemaInformation', Object.keys(schemaInformation).length); + return deferred.resolve(schemaInformation); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + /** + * A promise which returns object yang class and attribute descriptions + */ + service.getSchema = function () { + var deferred = $q.defer(); + if (schemaInformation) { + deferred.resolve(schemaInformation); + } else { + inquireSchemaInformation().then(function (success) { + deferred.resolve(success); + }, function (error) { + deferred.reject(error); + }); + } + return deferred.promise; + }; + + return service; + }); + // Class NetConfServer + mwtnCommonsApp.register.factory('NetConfServer', function () { + // Classes + // Class NetConfServer + var NetConfServer = function (data) { + this.data = data; + this.getData = function () { + return this.data; + }; + this.getRadioSignalId = function () { + return this.data.airInterfaceConfiguration.radioSignalId; + }; + this.isLinkUp = function () { + return this.data.airInterfaceStatus.linkIsUp; + }; + this.isPowerOn = function () { + return this.data.airInterfaceConfiguration.powerIsOn; + }; + this.isActive = function () { + return this.isPowerOn() && this.isLinkUp(); + }; + }; + return NetConfServer; + }); + + mwtnCommonsApp.register.factory('ActualNetworkElement', function () { + // Classes + // Class ActualNetworkElement + var ActualNetworkElement = function (data) { + this.data = data; + this.data.layerProtocols = {}; + this.setOnfNetworkElement = function (onfNe) { + this.data.onfNetworkElement = onfNe; + }; + this.getLpByRadioSignalId = function (radioSignalId) { + //console.log('getLP', JSON.stringify(this.data.ltp)); + var layerProtocol; + for (var layerProtocolKey in this.data.layerProtocols) { + if (this.data.layerProtocols[layerProtocolKey].getRadioSignalId && + radioSignalId === parseInt(this.data.layerProtocols[layerProtocolKey].getRadioSignalId())) { + layerProtocol = this.data.layerProtocols[layerProtocolKey]; + } + } + return layerProtocol; + }; + this.getLpByRadioSignalIds = function (radioSignalIds) { + //console.log('getLP', JSON.stringify(this.data.ltp)); + var layerProtocol; + if (radioSignalIds !== undefined) { + for (var layerProtocolKey in this.data.layerProtocols) { + if (this.data.layerProtocols[layerProtocolKey].getRadioSignalIds && + radioSignalIds.toString() === this.data.layerProtocols[layerProtocolKey].getRadioSignalIds(this).toString()) { + layerProtocol = this.data.layerProtocols[layerProtocolKey]; + } + } + } + return layerProtocol; + }; + this.setLP = function (onfPac) { + this.data.layerProtocols[onfPac.data.layerProtocol] = onfPac; + }; + this.getLpPac = function (lpRef) { + return this.data.layerProtocols[lpRef]; + }; + this.getName = function () { + return this.data.name; + }; + this.getConnectionStatus = function () { + return this.data.connectionStatus; + }; + this.isConnected = function () { + return this.data.name !== 'controller-config' && this.data.connectionStatus == 'connected'; + }; + this.setConnectionStatus = function (status) { + this.data.connectionStatus = status; + }; + }; + return ActualNetworkElement; + }); + + mwtnCommonsApp.register.factory('LogicalTerminationPoint', function ($mwtnGlobal, $mwtnLog) { + // Sub-Class LayerProtocol + /** + * An object representing an LP. + * @typedef {Object} LayerProtocol + */ + var LayerProtocol = function (data) { + // take a guess, if termiation-state is not exposed + if (data['termination-state'] === undefined) { + + data['termination-state'] = 'terminated-bidirectional'; + if (data['layer-protocol-name'] === "ETH") { + data['termination-state'] = 'lp-can-never-terminate'; + } + $mwtnLog.warning({ component: 'LTP.getTerminationState', message: 'Check whether NE provided mandatory termination state. ' + data.uuid }); + } else if (data['termination-state'] === false || data['termination-state'] === 'false' ) { + data['termination-state'] = 'terminated-bidirectional'; + } + + // console.log('in', JSON.stringify(data)); + var defaultMapping = { + 'ety-ttp': {}, + // [FFA 1709] 'etc-ttp': { 'capability': 'urn:onf:params:xml:ns:yang:microwave-model?module=microwave-model', 'revision': '2017-03-24', 'conditional-package': 'mw-ethernet-container-pac' }, + 'etc-ttp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-EthernetContainerl?module=MicrowaveModel-ObjectClasses-EthernetContainer', 'revision': '2016-09-02', 'conditional-package': 'MW_EthernetContainer_Pac' }, + 'tdm-ctp': { 'capability': 'urn:onf:params:xml:ns:yang:microwave-model?module=microwave-model', 'revision': '2017-03-24', 'conditional-package': 'mw-tdm-container-pac' }, + + // due to E/// + 'mws-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-PureEthernetStructure?module=MicrowaveModel-ObjectClasses-PureEthernetStructure', 'revision': '2016-09-02', 'conditional-package': 'MW_PureEthernetStructure_Pac' }, + 'mwps-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-AirInterface?module=MicrowaveModel-ObjectClasses-AirInterface', 'revision': '2016-09-01', 'conditional-package': 'MW_AirInterface_Pac' }, + // 'mws-ctp': { 'capability': 'urn:onf:params:xml:ns:yang:microwave-model?module=microwave-model', 'revision': '2017-03-24', 'conditional-package': 'mw-air-interface-diversity-pac' }, + + 'eth-ctp': { 'capability': 'urn:onf:params:xml:ns:yang:onf-ethernet-conditional-packages?module=onf-ethernet-conditional-packages', 'revision': '2017-04-02', 'conditional-package': 'ethernet-pac' }, + // 3rd PoC + 'mwps-ttp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-AirInterface?module=MicrowaveModel-ObjectClasses-AirInterface', 'revision': '2016-09-01', 'conditional-package': 'MW_AirInterface_Pac' }, + 'mws-ttp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-PureEthernetStructure?module=MicrowaveModel-ObjectClasses-PureEthernetStructure', 'revision': '2016-09-02', 'conditional-package': 'MW_PureEthernetStructure_Pac' }, + 'eth-ctp-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-EthernetContainerl?module=MicrowaveModel-ObjectClasses-EthernetContainer', 'revision': '2016-09-02', 'conditional-package': 'MW_EthernetContainer_Pac' }, + 'etc-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-EthernetContainerl?module=MicrowaveModel-ObjectClasses-EthernetContainer', 'revision': '2016-09-02', 'conditional-package': 'MW_EthernetContainer_Pac' }, + + }; + // create empty extension, if not exists + if (!data.extension) { + data.extension = []; + } + this.data = data; + + // methods + this.getData = function () { + return this.data; + }; + this.getId = function () { + return this.getData().uuid; + }; + this.getLabel = function () { + return ['LP(', this.getItuLabel(true).toUpperCase(), '): ', this.getId()].join(''); + }; + this.getLayer = function () { + var layer = this.getData()['layer-protocol-name']; + if (layer === 'ETH-CTP') { + layer = 'ETC'; + } + return layer; + }; + this.getTerminationState = function (abstract) { + // 3th PoC termination state is of type boolean + if (this.getData()['termination-state'] === true) { + return 'ttp'; + } else if (this.getData()['termination-state'] === false) { + return 'ctp'; + } + // 4th PoC termination state is of type enum + if (abstract !== true) { + return this.getData()['termination-state']; + } + var mapping = { + 'lp-can-never-terminate': 'ctp', + 'lt-not-terminated': 'ctp', + 'terminated-server-to-client-flow': 'ttp', + 'terminated-client-to-server-flow': 'ttp', + 'terminated-bidirectional': 'ttp', + 'lt-permenantly-terminated': 'ttp', + 'termination-state-unknown': 'ttp' + }; + return mapping[this.getData()['termination-state']]; + }; + this.getItuLabel = function () { + return [this.getLayer(), this.getTerminationState(true)].join('-').toLowerCase(); + }; + this.getExtension = function (key) { + var result = this.getData().extension.filter(function (ex) { + return ex['value-name'] === key; + }).map(function (ex) { + return ex.value; + }); + if (result && result.length > 0) { + return result[0]; + } + // check hardcoded alternatives + var ituLabel = this.getItuLabel(); + if (!defaultMapping[ituLabel]) { + return ''; + } + return defaultMapping[ituLabel][key]; + }; + /** + * A getter for the yang-capability of the LayerProtocol + * @param {boolean|undefined} moduleOnly - Defines, whether the result should contain only yang-module-name. + * @return {string} The conditional package name of the LayerProtocol + */ + this.getCapability = function (moduleOnly) { + var cap = this.getExtension('capability'); + if (!cap) return ''; + + // workaround bug in spec + if (cap.contains('onf-ethernet-conditional-package') && !cap.contains('onf-ethernet-conditional-packages')) { + console.warn('Inform vendor about spec error and updates'); + cap = cap.replaceAll('onf-ethernet-conditional-package', 'onf-ethernet-conditional-packages'); + } + if (cap !== '' && moduleOnly === true) { + return cap.split('?module=')[1]; + } + return cap; + }; + this.getRevision = function () { + return this.getExtension('revision'); + }; + /** + * A getter for the conditional package name of the LayerProtocol + * @param {boolean|undefined} addModule - Defines, whether the result should include the yang-module-name. + * @return {string} The conditional package name of the LayerProtocol + */ + this.getConditionalPackage = function (addModule) { + var cp = this.getExtension('conditional-package'); + if (!cp) { + return ''; + } + if (addModule === true) { + return [this.getCapability(true), cp].join(':'); + } + return cp; + }; + }; + + // Sub-Class LogicalTerminationPoint + /** + * An object representing an LTP. + * @typedef {Object} LogicalTerminationPoint + */ + var LogicalTerminationPoint = function (data) { + this.data = data; + this.layerProtocols = this.data.lp.map(function (layerProtocol) { + return new LayerProtocol(layerProtocol); + }); + // console.log(this.layerProtocols); + this.getData = function () { + return this.data; + }; + this.getId = function () { + return this.getData().uuid; + }; + this.getName = function () { + return this.getData().name[0].value; + }; + this.getDirectionality = function () { + return this.getData()['ltp-direction']; + }; + this.getServerLtps = function () { + return this.getData()['server-ltp']; + }; + this.getClientLtps = function () { + return this.getData()['client-ltp']; + }; + this.getLayer = function () { + return this.getLayerProtocols()[0].getLayer(); + }; + this.getLabel = function () { + return ['LTP(', this.getLayerProtocols()[0].getItuLabel(true).toUpperCase(), '): ', this.getId()].join(''); + }; + this.getLayerProtocols = function () { + return this.layerProtocols; + }; + this.getConditionalPackages = function () { + console.error(JSON.stringifythis.getLayerProtocols()()); + return this.getLayerProtocols().map(function (lp) { + return lp.getConditionalPackage(); + }); + }; + } + return LogicalTerminationPoint; + }); + + mwtnCommonsApp.register.factory('PtpClock', function (PtpPort) { + var PtpClock = function (data) { + var COMPONENT = "PtpClock"; + this.data = {}; + if (data && data['instance-list'] && data['instance-list'][0]) { + this.data = data['instance-list'][0]; + } + if (!this.data['port-ds-list'] || this.data['port-ds-list'].length === 0) { + this.ptpPorts = []; + var message = ['The PTP clock', data['instance-number'], 'dose not support a single PTP port.'].join(' '); + console.info({ component: COMPONENT, message: message }); + } else { + this.ptpPorts = this.data['port-ds-list'].map(function(ptpPort) { + return new PtpPort(ptpPort); + }); + } + + this.getData = function () { + return this.data; + // return JSON.parse(JSON.stringify(this.data).replaceAll('onf-ptp-dataset:', '')); + }; + this.getIdentity = function(hex) { + var defaultDs = this.getData()['default-ds']; + var result = 'ERROR: no clock identity found'; + if (defaultDs && defaultDs['clock-identity']) { + result = defaultDs['clock-identity']; + if (hex) { + result = result.base64ToHex(); + } + } + return result; + }; + this.getParent = function(hex) { + var parentDs = this.getData()['parent-ds']; + var key = 'parent-port-identity'; + var result = ''; + if (parentDs && parentDs[key] && parentDs[key]['clock-identity'] && parentDs[key]['port-number']) { + result = parentDs[key]['clock-identity']; + if (hex) { + result = result.base64ToHex(); + } + result = [result, parentDs[key]['port-number']].join('#'); + } + return result; + }; + this.getGrandMaster = function(hex) { + var parentDs = this.getData()['parent-ds']; + // console.warn(JSON.stringify(parentDs)); + var key = 'parent-port-identity'; + var result = ''; + if (parentDs && parentDs['grandmaster-identity']) { + result = parentDs['grandmaster-identity']; + if (hex) { + result = result.base64ToHex(); + } + } + return result; + }; + this.getPtpPorts = function () { + return this.ptpPorts; + }; + }; + return PtpClock; + }); + + mwtnCommonsApp.register.factory('PtpPort', function () { + var PtpPort = function (data) { + this.data = data; + this.getData = function () { + return this.data; + }; + this.getId = function() { + return this.getData()['port-number']; + }; + this.getNumber = function() { + return this.getData()['port-number']; + }; + this.getState = function() { + return this.getData()['port-state']; + }; + this.isSlave = function() { + return this.getData()['port-state'] === 'SLAVE'; + }; + this.isMaster = function() { + return this.getData()['port-state'] === 'MASTER'; + }; + this.getLogicalTerminationPointReference = function() { + return this.getData()['onf-ptp-dataset:logical-termination-point']; + }; + }; + return PtpPort; + }); + + mwtnCommonsApp.register.factory('OnfNetworkElement', function ($mwtnGlobal, LogicalTerminationPoint) { + // Classes + // Class OnfNetworkElement + var OnfNetworkElement = function (data) { + var COMPONENT = "OnfNetworkElement"; + + this.data = data; + if (!this.data) { + var message = ['No data received.'].join(' '); + console.warn({ component: COMPONENT, message: message }); + return; + } + + // console.log(JSON.stringify(data)); + if (!this.data.ltp || this.data.ltp.length === 0) { + this.logicalTerminationPoints = []; + var message = ['The network-element', data.uuid, 'does not support a single LTP. No LTP -> no SDN integration via ONF core-model.'].join(' '); + // TODO $mwtnLog -> Unknown provider: $mwtnlogProvider <- $mwtnlog <- OnfNetworkElement [sko] Dont get it ;( + console.warn({ component: COMPONENT, message: message }); + } else { + this.logicalTerminationPoints = this.data.ltp.map(function (logicalTerminationPoint) { + return new LogicalTerminationPoint(logicalTerminationPoint); + }); + } + + this.getData = function () { + return this.data; + }; + this.getId = function () { + return this.getData().uuid; + }; + this.getForwardingDomain = function () { + return this.getData().fd; + }; + this.getName = function () { + return this.getData().name[0].value || this.getData().uuid; + }; + this.getLogicalTerminationPoints = function () { + return this.logicalTerminationPoints; + }; + this.getLtp = function (id) { + var result = this.getLogicalTerminationPoints().filter(function (ltp) { + return ltp.getId() === id; + }); + if (result.length === 1) { + return result[0]; + } + return undefined; + }; + this.getLpById = function (id) { + var result = {}; + this.getLogicalTerminationPoints().map(function (ltp) { + ltp.getLayerProtocols().map(function (lp) { + if (lp.getData().uuid === id) { + result = lp; + } + }); + }); + return result; + }; + this.getNumberOfLtps = function () { + return this.logicalTerminationPoints.length; + }; + this.getServerLtps = function (layerProtocolRef) { + var result = []; + if (this.data._ltpRefList) { + var ltpList = this.data._ltpRefList.map(function (ltp) { + if (ltp.lp[0].uuid === layerProtocolRef) { + result = ltp._serverLtpRefList; + } + }); + } + return result; + }; + this.getClientLtpIds = function (layerProtocolRef) { + var result = []; + if (this.data._ltpRefList) { + var ltpList = this.data._ltpRefList.map(function (ltp) { + if (ltp.lp[0].uuid === layerProtocolRef) { + result = ltp._clientLtpRefList; + } + }); + } + return result; + }; + this.getLpByLtpRef = function (ltpRef) { + var result; + if (this.data._ltpRefList) { + var ltpList = this.data._ltpRefList.map(function (ltp) { + if (ltp.uuid === ltpRef) { + result = ltp.lp[0]; + } + }); + } + return result; + }; + this.getLtpsByLayer = function (layerProtocolName) { + return this.getLogicalTerminationPoints().filter(function (ltp) { + return ltp.getLayer() === layerProtocolName; + }); + }; + this.getLTPMwpsList = function () { + return this.getLtpsByLayer('MWPS'); + }; + this.getLTPMwsList = function () { + return this.getLtpsByLayer('MWS'); + }; + this.getLTPEthCtpList = function () { + return this.getLtpsByLayer('ETH'); + }; + this.getLTPTdmCtpList = function () { + return this.getLtpsByLayer('TDM'); + }; + }; + return OnfNetworkElement; + }); + + mwtnCommonsApp.register.factory('MicrowavePhysicalSection', function () { + // Classes + // Class MicrowavePhysicalSection + var MicrowavePhysicalSection = function (data) { + this.data = data; + this.getData = function () { + return this.data; + }; + this.getLayerProtocolId = function () { + return this.getData().layerProtocol; + }; + this.getRadioSignalId = function () { + return this.getData()['air-interface-configuration'] ? this.data['air-interface-configuration']['radio-signal-id'] : -1; + }; + this.isLinkUp = function () { + return this.getData()['air-interface-status']['link-is-up']; + }; + this.isPowerOn = function () { + return this.getData()['air-interface-configuration']['power-is-on']; + }; + this.isActive = function () { + return this.isPowerOn() && this.isLinkUp(); + }; + }; + return MicrowavePhysicalSection; + }); + + mwtnCommonsApp.register.factory('MicrowaveSection', function () { + // Classes + // Class MicrowaveSection + var MicrowaveSection = function (data) { + this.data = data; + this.getData = function () { + return this.data; + }; + this.getId = function () { + return this.data.layerProtocol; + }; + this.getRadioSignalIds = function (actualNe) { + this.data.parent = actualNe; + var result = []; + var onfNe = actualNe.data.onfNetworkElement; + var lpId = this.getId(); + onfNe.getServerLtps(lpId).map(function (mwpsLtpRef) { + var lpRef = onfNe.getLpByLtpRef(mwpsLtpRef).uuid; + var mwps = actualNe.getLpPac(lpRef); + result.push(mwps.getRadioSignalId()); + }); + return result; + }; + this.getTimeSlotCapacity = function () { + return this.data.structureCapability.timeSlotCapacity; + }; + this.getTotalNumberOfTimeSlots = function () { + return this.data.structureCapability.totalNumberOfTimeSlots; + }; + this.getNumberOfEffectiveTimeSlots = function () { + var count = 0; + this.data.structureStatus.timeSlotStatusList.map(function (ts) { + if (ts.operationalStatus === 'ENABLED') { + count = count + 1; + } + }); + return count; + }; + this.getConfiguredCapacity = function () { + return this.getTotalNumberOfTimeSlots() * this.getTimeSlotCapacity(); + }; + this.getEffectiveCapacity = function () { + return this.getNumberOfEffectiveTimeSlots() * this.getTimeSlotCapacity(); + }; + this.isActive = function () { + if (this.data.parent === undefined) { + return false; + } + var actualNe = this.data.parent; + var result = true; + var onfNe = actualNe.data.onfNetworkElement; + var lpId = this.getId(); + onfNe.getServerLtps(lpId).map(function (mwpsLtpRef) { + var lpRef = onfNe.getLpByLtpRef(mwpsLtpRef).uuid; + var mwps = actualNe.getLpPac(lpRef); + result = result && mwps.isActive(); + }); + return result; + }; + }; + return MicrowaveSection; + }); + });
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.tpl.html new file mode 100644 index 00000000..9594bca7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/mwtnCommons.tpl.html @@ -0,0 +1,7 @@ +<!-- This is the landing page of you application, Update the content as per your requirements --> + +<h4>Your {{data}} application is loaded</h4> +<hr /> +<div class="owl"> + <span class="white">ONAP SDN-R | ONF Wireless for @distversion@ - Build: @buildtime@</span> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnFooter.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnFooter.tpl.html new file mode 100644 index 00000000..597bcb98 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnFooter.tpl.html @@ -0,0 +1,4 @@ +<hr /> +<div class="owl"> + <span class="white">{{prefix}} - Build: @buildtime@</span> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnGrid.tpl.html new file mode 100644 index 00000000..2751ffcb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnGrid.tpl.html @@ -0,0 +1,23 @@ +<div class="owl co1ntainer" > + + <div class="row"> + <div class="col-md-12"> + + <div ng-if="info !== false"> + <span class="owl-dark">{{info}}</span> + </div> + + <div ui-grid="gridOptions" + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + ui-grid-auto-resize + class="mwtn-grid" + ng-style="getTableHeight()"></div> + + </div> + </div> + +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnJsonViewer.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnJsonViewer.tpl.html new file mode 100644 index 00000000..5f3cfbf5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnJsonViewer.tpl.html @@ -0,0 +1,110 @@ +<div class="owl"> + <div class="row text-right" > + <div class="form-group" ng-if="noButtons !== true"> + <button class="btn btn-default" type="button" clipboard supported="myClipboard.supported" text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + <button class="btn btn-default" type="button" ng-if="replace" ng-click="openConfigView()"> + <i class="fa fa-pencil-square-o pointer" aria-hidden="true" ></i> + </button> + <div> + </div> +</div> +<div class="owl"> + + <div ng-if="info !== false"> + <span class="owl-dark">{{info}}</span> + </div> + + <div class="row" ng-repeat="(key, value) in viewData track by $index" ng-show="value.value !== undefined"> + + <!-- type- default --> + <div class="col col-md-4 text-right" title="{{value.description}}" ng-if="value.type !== 'array' && value.visible === true"> + <span class="owl-dark">{{value.labelId | translate}}</span> + </div> + <div class="col col-md-4 text-left" ng-if="value.type !== 'boolean' && value.type !== 'number' && value.type !== 'object' && value.type !== 'array' && value.visible === true"> + <b>{{value.value}}</b> + </div> + + <!-- type-boolean --> + + <div class="col col-md-2" ng-if="value.type === 'boolean' && value.visible === true"> + <i class="fa" ng-class="{'fa-square-o': value.value === false, 'fa-check-square-o green': value.value === true}" aria-hidden="true"></i> + </div> + + <!-- type- number --> + <div class="col col-md-2 number" ng-if="value.type === 'number' && value.visible === true"> + <b>{{value.value}}</b> + </div> + <div class="col col-md-2 text-left" ng-if="value.unit && value.visible === true"> + <span class="owl-dark">{{value.unit}}</span> + </div> + + <!-- type- array of objects --> + <div class="col col-md-12" ng-if="value.type === 'array' && value.value.length !== 0 && getType(value.value[0]) === 'object'"> + <span class="owl-dark text-right" style="margin-top: 5px;">{{value.labelId | translate}}</span><br/> + <mwtn-grid network-element="networkElement" data="value.value" path="path"></mwtn-grid> + </div> + <!-- type- array of non objects --> + <div class="col col-md-4 text-right" title="{{value.description}}" ng-if="value.type === 'array' && value.value.length !== 0 && getType(value.value[0]) !== 'object'"> + <span class="owl-dark">{{value.labelId | translate}}</span> + </div> + <div class="col col-md-8 text-left" ng-if="value.type === 'array' && value.value.length !== 0 && getType(value.value[0]) !== 'object'"> + <b>{{value.value}}</b> + </div> + + <!-- type- object --> + <div class="col col-md-7" ng-if="value.type === 'object'"> + +<!-- <pre>{{value | json}}</pre> + ### + <hr> +<mwtn-json-viewer data="value.value"></mwtn-json-viewer> + <hr> + ### --> + + <div class="owl"> + + <!-- TODO exception case: current pm --> + <div class="row" ng-repeat="(oKey, oValue) in value.value track by $index" ng-if="oValue.value === undefined"> + <div class="col col-md-3 text-right"> + <span class="owl-dark">{{oKey | translate}}</span> + </div> + <div class="col col-md-4 text-right" ng-if="oValue.type !== 'object'"> + <b>{{oValue | json}}</b> + </div> + </div> + + <!-- expected case: --> + <div class="row" ng-repeat="(oKey, oValue) in value.value track by $index" ng-if="oValue.value !== undefined"> + <!-- oValue.type !== 'object'' && oValue.type !== 'array' --> + <div class="col col-md-3 text-right" ng-if="oValue.type !== 'object' && oValue.type !== 'array'"> + <span class="owl-dark">{{oValue.labelId || oKey.replace('onf-ptp-dataset:' ,'') | translate}}</span> + </div> + <div class="col col-md-4 text-right" ng-if="oValue.type !== 'object' && oValue.type !== 'array'"> + <b>{{oValue.value || oValue}}</b> + </div> + + + <!-- oValue.type === 'array'' --> + <div class="col col-md-3 text-right" ng-if="oValue.type === 'array'"> + <span class="owl-dark">{{oValue.labelId || oKey.replace('onf-ptp-dataset:' ,'') | translate}}</span> + </div> + <div class="col col-md-4" ng-if="oValue.type === 'array'"> + <json-formatter json="oValue.value" open="1"></json-formatter> + </div> + + <!-- oValue.type === 'object' --> + <div class="col col-md-3 text-right" ng-if="oValue.type === 'object'"> + <span class="owl-dark">{{oValue.labelId || oKey.replace('onf-ptp-dataset:' ,'') | translate}}</span> + </div> + <div class="col col-md-4" ng-if="oValue.type === 'object'"> + <json-formatter json="oValue.value" open="1"></json-formatter> + </div> + </div> + </div> + </div> + </div> + +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnSelectNetworkElement.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnSelectNetworkElement.tpl.html new file mode 100644 index 00000000..58515605 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/mwtnSelectNetworkElement.tpl.html @@ -0,0 +1,33 @@ +<div class="owl container" ng-hide="networkElements.lenght !== 0" style="width: 100%"> + <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="owl container" ng-show="networkElements.lenght !== 0" style="width: 100%"> + <div class="row"> + <div class="col-md-3 form-group" ng-show="networkElements.length > 30"> + <input list="networkElements" class="form-control" ng-model="networkElement"> + <datalist id="networkElements"> + <option ng-repeat="ne in networkElements" value="{{ne.id}}">{{ne.id}}</option> + </datalist> + </div> + <div class="col-md-3 form-group" ng-hide="networkElements.length > 30"> + <select class="form-control" ng-model="networkElement"> + <option ng-repeat="ne in networkElements" value="{{ne.id}}">{{ne.id}}</option> + </select> + </div> + <div class="col-md-2"> + <span class="white">{{'MWTN_SELECT_NETWORK_ELEMENT' | translate}}</span> + </div> + <div class="col-md-7 text-right"> + <div class="form-group"> + <button type="button" class="btn btn-default" ng-click="collapseAll()">{{'MWTN_COLLAPSE_ALL' | translate}}</button> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/openConfigView.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/openConfigView.html new file mode 100644 index 00000000..64c06e96 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/openConfigView.html @@ -0,0 +1,69 @@ + +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{'MWTN_CONFIGURATION' | translate}}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="container" style="width:100%"> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_NETWORKELEMENT' | translate}} + </div> + <div class="col-md-9"> + <b>{{spec.nodeId}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_CONDITIONAL_PACKAGE' | translate}} + </div> + <div class="col-md-9"> + <b>{{spec.pacId}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_LP' | translate}} + </div> + <div class="col-md-9"> + <b>{{spec.layerProtocolId}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_SUBOBJECT' | translate}} + </div> + <div class="col-md-9"> + <b>{{spec.partId}}</b> + </div> + <hr /> + </div> + <div class="row"> + + <div ng-repeat="(key, item) in viewData" ng-if="item.visible === true"> + + <!-- text, number, combo --> + <div class="col-md-3 text-right radio">{{item.labelId | translate}}</div> + <div ng-class="{'col-md-2':item.unit, 'col-md-3':!item.unit}" class="form-group" ng-if="item.controlType !== 'checkbox' && getType(item.controlType) !== 'array'"> + <input class="form-control" type="{{item.controlType}}" ng-model="item.value"></input> + </div> + <div class="col-md-3 checkbox" ng-if="item.controlType === 'checkbox'"><input type="checkbox" ng-model="item.value" /></div> + <div ng-class="{'col-md-2':item.unit, 'col-md-3':!item.unit}" class="form-group" ng-if="getType(item.controlType) === 'array'"> + <select class="form-control" ng-model="item.value"> + <option ng-repeat="option in item.controlType track by $index" value="{{option}}">{{option}}</option> + </select> + </div> + <div class="col-md-1 radio" ng-if="item.unit"> + <span class="owl-dark">{{item.unit}}</span> + </div> + + </div> + </div> +</div> +<div class="modal-footer"> + <div class="{{applied.class}}", ng-show="applied">{{applied.text}}</div> + <button class="btn btn-primary" type="button" ng-click="ok()"> + <span style="color: white;">{{'MWTN_APPLY' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="processing"></i> + </button> + <button class="btn btn-warning" type="button" ng-click="cancel()">{{'MWTN_CLOSE' | translate}}</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/showGridCellDetail.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/showGridCellDetail.html new file mode 100644 index 00000000..ab449bbc --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/templates/showGridCellDetail.html @@ -0,0 +1,54 @@ + +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{'MWTN_CONFIGURATION' | translate}}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="container" style="width:100%"> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_NETWORKELEMENT' | translate}} + </div> + <div class="col-md-9"> + <b>{{networkElement}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_CONDITIONAL_PACKAGE' | translate}} + </div> + <div class="col-md-9"> + <b>{{path.split('&nbsp;')[0]}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_LP' | translate}} + </div> + <div class="col-md-9"> + <b>{{path.split('&nbsp;')[1]}}</b> + </div> + </div> + <div class="row"> + <div class="col-md-3 text-right" > + {{'MWTN_SUBOBJECT' | translate}} + </div> + <div class="col-md-9"> + <b>{{path.split('&nbsp;')[2]}}</b> + </div> + <hr /> + </div> + <div class="row"> + <mwtn-json-viewer network-element="networkElement" data="value" ng-if="type === 'object'"></mwtn-json-viewer> + <mwtn-grid network-element="networkElement" data="value" ng-if="type === 'array'"></mwtn-grid> + </div> + </div> +</div> +<div class="modal-footer"> + <div class="{{applied.class}}", ng-show="applied">{{applied.text}}</div> +<!-- + <button class="btn btn-primary" type="button" ng-click="ok()"> + <span>{{'MWTN_APPLY' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="processing"></i> + </button> --> + <button class="btn btn-warning" type="button" ng-click="cancel()">{{'MWTN_CLOSE' | translate}}</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/xml2json.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/xml2json.js new file mode 100644 index 00000000..5ff7e578 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/mwtnCommons-module/src/main/resources/mwtnCommons/xml2json.js @@ -0,0 +1,567 @@ +/*
+ Copyright 2011-2013 Abdulla Abdurakhmanov
+ Original sources are available at https://code.google.com/p/x2js/
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+function X2JS(config) {
+ 'use strict';
+
+ var VERSION = "1.1.5";
+
+ config = config || {};
+ initConfigDefaults();
+ initRequiredPolyfills();
+
+ function initConfigDefaults() {
+ if(config.escapeMode === undefined) {
+ config.escapeMode = true;
+ }
+ config.attributePrefix = config.attributePrefix || "_";
+ config.arrayAccessForm = config.arrayAccessForm || "none";
+ config.emptyNodeForm = config.emptyNodeForm || "text";
+ if(config.enableToStringFunc === undefined) {
+ config.enableToStringFunc = true;
+ }
+ config.arrayAccessFormPaths = config.arrayAccessFormPaths || [];
+ if(config.skipEmptyTextNodesForObj === undefined) {
+ config.skipEmptyTextNodesForObj = true;
+ }
+ if(config.stripWhitespaces === undefined) {
+ config.stripWhitespaces = true;
+ }
+ config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || [];
+ }
+
+ var DOMNodeTypes = {
+ ELEMENT_NODE : 1,
+ TEXT_NODE : 3,
+ CDATA_SECTION_NODE : 4,
+ COMMENT_NODE : 8,
+ DOCUMENT_NODE : 9
+ };
+
+ function initRequiredPolyfills() {
+ function pad(number) {
+ var r = String(number);
+ if ( r.length === 1 ) {
+ r = '0' + r;
+ }
+ return r;
+ }
+ // Hello IE8-
+ if(typeof String.prototype.trim !== 'function') {
+ String.prototype.trim = function() {
+ return this.replace(/^\s+|^\n+|(\s|\n)+$/g, '');
+ }
+ }
+ if(typeof Date.prototype.toISOString !== 'function') {
+ // Implementation from http://stackoverflow.com/questions/2573521/how-do-i-output-an-iso-8601-formatted-string-in-javascript
+ Date.prototype.toISOString = function() {
+ return this.getUTCFullYear()
+ + '-' + pad( this.getUTCMonth() + 1 )
+ + '-' + pad( this.getUTCDate() )
+ + 'T' + pad( this.getUTCHours() )
+ + ':' + pad( this.getUTCMinutes() )
+ + ':' + pad( this.getUTCSeconds() )
+ + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
+ + 'Z';
+ };
+ }
+ }
+
+ function getNodeLocalName( node ) {
+ var nodeLocalName = node.localName;
+ if(nodeLocalName == null) // Yeah, this is IE!!
+ nodeLocalName = node.baseName;
+ if(nodeLocalName == null || nodeLocalName=="") // =="" is IE too
+ nodeLocalName = node.nodeName;
+ return nodeLocalName;
+ }
+
+ function getNodePrefix(node) {
+ return node.prefix;
+ }
+
+ function escapeXmlChars(str) {
+ if(typeof(str) == "string")
+ return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/');
+ else
+ return str;
+ }
+
+ function unescapeXmlChars(str) {
+ return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(///g, '\/');
+ }
+
+ function toArrayAccessForm(obj, childName, path) {
+ switch(config.arrayAccessForm) {
+ case "property":
+ if(!(obj[childName] instanceof Array))
+ obj[childName+"_asArray"] = [obj[childName]];
+ else
+ obj[childName+"_asArray"] = obj[childName];
+ break;
+ /*case "none":
+ break;*/
+ }
+
+ if(!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) {
+ var idx = 0;
+ for(; idx < config.arrayAccessFormPaths.length; idx++) {
+ var arrayPath = config.arrayAccessFormPaths[idx];
+ if( typeof arrayPath === "string" ) {
+ if(arrayPath == path)
+ break;
+ }
+ else
+ if( arrayPath instanceof RegExp) {
+ if(arrayPath.test(path))
+ break;
+ }
+ else
+ if( typeof arrayPath === "function") {
+ if(arrayPath(obj, childName, path))
+ break;
+ }
+ }
+ if(idx!=config.arrayAccessFormPaths.length) {
+ obj[childName] = [obj[childName]];
+ }
+ }
+ }
+
+ function fromXmlDateTime(prop) {
+ // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object
+ // Improved to support full spec and optional parts
+ var bits = prop.split(/[-T:+Z]/g);
+
+ var d = new Date(bits[0], bits[1]-1, bits[2]);
+ var secondBits = bits[5].split("\.");
+ d.setHours(bits[3], bits[4], secondBits[0]);
+ if(secondBits.length>1)
+ d.setMilliseconds(secondBits[1]);
+
+ // Get supplied time zone offset in minutes
+ if(bits[6] && bits[7]) {
+ var offsetMinutes = bits[6] * 60 + Number(bits[7]);
+ var sign = /\d\d-\d\d:\d\d$/.test(prop)? '-' : '+';
+
+ // Apply the sign
+ offsetMinutes = 0 + (sign == '-'? -1 * offsetMinutes : offsetMinutes);
+
+ // Apply offset and local timezone
+ d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset())
+ }
+ else
+ if(prop.indexOf("Z", prop.length - 1) !== -1) {
+ d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()));
+ }
+
+ // d is now a local time equivalent to the supplied time
+ return d;
+ }
+
+ function checkFromXmlDateTimePaths(value, childName, fullPath) {
+ if(config.datetimeAccessFormPaths.length > 0) {
+ var path = fullPath.split("\.#")[0];
+ var idx = 0;
+ for(; idx < config.datetimeAccessFormPaths.length; idx++) {
+ var dtPath = config.datetimeAccessFormPaths[idx];
+ if( typeof dtPath === "string" ) {
+ if(dtPath == path)
+ break;
+ }
+ else
+ if( dtPath instanceof RegExp) {
+ if(dtPath.test(path))
+ break;
+ }
+ else
+ if( typeof dtPath === "function") {
+ if(dtPath(obj, childName, path))
+ break;
+ }
+ }
+ if(idx!=config.datetimeAccessFormPaths.length) {
+ return fromXmlDateTime(value);
+ }
+ else
+ return value;
+ }
+ else
+ return value;
+ }
+
+ function parseDOMChildren( node, path ) {
+ if(node.nodeType == DOMNodeTypes.DOCUMENT_NODE) {
+ var result = new Object;
+ var nodeChildren = node.childNodes;
+ // Alternative for firstElementChild which is not supported in some environments
+ for(var cidx=0; cidx <nodeChildren.length; cidx++) {
+ var child = nodeChildren.item(cidx);
+ if(child.nodeType == DOMNodeTypes.ELEMENT_NODE) {
+ var childName = getNodeLocalName(child);
+ result[childName] = parseDOMChildren(child, childName);
+ }
+ }
+ return result;
+ }
+ else
+ if(node.nodeType == DOMNodeTypes.ELEMENT_NODE) {
+ var result = new Object;
+ result.__cnt=0;
+
+ var nodeChildren = node.childNodes;
+
+ // Children nodes
+ for(var cidx=0; cidx <nodeChildren.length; cidx++) {
+ var child = nodeChildren.item(cidx); // nodeChildren[cidx];
+ var childName = getNodeLocalName(child);
+
+ if(child.nodeType!= DOMNodeTypes.COMMENT_NODE) {
+ result.__cnt++;
+ if(result[childName] == null) {
+ result[childName] = parseDOMChildren(child, path+"."+childName);
+ toArrayAccessForm(result, childName, path+"."+childName);
+ }
+ else {
+ if(result[childName] != null) {
+ if( !(result[childName] instanceof Array)) {
+ result[childName] = [result[childName]];
+ toArrayAccessForm(result, childName, path+"."+childName);
+ }
+ }
+ (result[childName])[result[childName].length] = parseDOMChildren(child, path+"."+childName);
+ }
+ }
+ }
+
+ // Attributes
+ for(var aidx=0; aidx <node.attributes.length; aidx++) {
+ var attr = node.attributes.item(aidx); // [aidx];
+ result.__cnt++;
+ result[config.attributePrefix+attr.name]=attr.value;
+ }
+
+ // Node namespace prefix
+ var nodePrefix = getNodePrefix(node);
+ if(nodePrefix!=null && nodePrefix!="") {
+ result.__cnt++;
+ result.__prefix=nodePrefix;
+ }
+
+ if(result["#text"]!=null) {
+ result.__text = result["#text"];
+ if(result.__text instanceof Array) {
+ result.__text = result.__text.join("\n");
+ }
+ if(config.escapeMode)
+ result.__text = unescapeXmlChars(result.__text);
+ if(config.stripWhitespaces)
+ result.__text = result.__text.trim();
+ delete result["#text"];
+ if(config.arrayAccessForm=="property")
+ delete result["#text_asArray"];
+ result.__text = checkFromXmlDateTimePaths(result.__text, childName, path+"."+childName);
+ }
+ if(result["#cdata-section"]!=null) {
+ result.__cdata = result["#cdata-section"];
+ delete result["#cdata-section"];
+ if(config.arrayAccessForm=="property")
+ delete result["#cdata-section_asArray"];
+ }
+
+ if( result.__cnt == 1 && result.__text!=null ) {
+ result = result.__text;
+ }
+ else
+ if( result.__cnt == 0 && config.emptyNodeForm=="text" ) {
+ result = '';
+ }
+ else
+ if ( result.__cnt > 1 && result.__text!=null && config.skipEmptyTextNodesForObj) {
+ if( (config.stripWhitespaces && result.__text=="") || (result.__text.trim()=="")) {
+ delete result.__text;
+ }
+ }
+ delete result.__cnt;
+
+ if( config.enableToStringFunc && (result.__text!=null || result.__cdata!=null )) {
+ result.toString = function() {
+ return (this.__text!=null? this.__text:'')+( this.__cdata!=null ? this.__cdata:'');
+ };
+ }
+
+ return result;
+ }
+ else
+ if(node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {
+ return node.nodeValue;
+ }
+ }
+
+ function startTag(jsonObj, element, attrList, closed) {
+ var resultStr = "<"+ ( (jsonObj!=null && jsonObj.__prefix!=null)? (jsonObj.__prefix+":"):"") + element;
+ if(attrList!=null) {
+ for(var aidx = 0; aidx < attrList.length; aidx++) {
+ var attrName = attrList[aidx];
+ var attrVal = jsonObj[attrName];
+ if(config.escapeMode)
+ attrVal=escapeXmlChars(attrVal);
+ resultStr+=" "+attrName.substr(config.attributePrefix.length)+"='"+attrVal+"'";
+ }
+ }
+ if(!closed)
+ resultStr+=">";
+ else
+ resultStr+="/>";
+ return resultStr;
+ }
+
+ function endTag(jsonObj,elementName) {
+ return "</"+ (jsonObj.__prefix!=null? (jsonObj.__prefix+":"):"")+elementName+">";
+ }
+
+ function endsWith(str, suffix) {
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ }
+
+ function jsonXmlSpecialElem ( jsonObj, jsonObjField ) {
+ if((config.arrayAccessForm=="property" && endsWith(jsonObjField.toString(),("_asArray")))
+ || jsonObjField.toString().indexOf(config.attributePrefix)==0
+ || jsonObjField.toString().indexOf("__")==0
+ || (jsonObj[jsonObjField] instanceof Function) )
+ return true;
+ else
+ return false;
+ }
+
+ function jsonXmlElemCount ( jsonObj ) {
+ var elementsCnt = 0;
+ if(jsonObj instanceof Object ) {
+ for( var it in jsonObj ) {
+ if(jsonXmlSpecialElem ( jsonObj, it) )
+ continue;
+ elementsCnt++;
+ }
+ }
+ return elementsCnt;
+ }
+
+ function parseJSONAttributes ( jsonObj ) {
+ var attrList = [];
+ if(jsonObj instanceof Object ) {
+ for( var ait in jsonObj ) {
+ if(ait.toString().indexOf("__")== -1 && ait.toString().indexOf(config.attributePrefix)==0) {
+ attrList.push(ait);
+ }
+ }
+ }
+ return attrList;
+ }
+
+ function parseJSONTextAttrs ( jsonTxtObj ) {
+ var result ="";
+
+ if(jsonTxtObj.__cdata!=null) {
+ result+="<![CDATA["+jsonTxtObj.__cdata+"]]>";
+ }
+
+ if(jsonTxtObj.__text!=null) {
+ if(config.escapeMode)
+ result+=escapeXmlChars(jsonTxtObj.__text);
+ else
+ result+=jsonTxtObj.__text;
+ }
+ return result;
+ }
+
+ function parseJSONTextObject ( jsonTxtObj ) {
+ var result ="";
+
+ if( jsonTxtObj instanceof Object ) {
+ result+=parseJSONTextAttrs ( jsonTxtObj );
+ }
+ else
+ if(jsonTxtObj!=null) {
+ if(config.escapeMode)
+ result+=escapeXmlChars(jsonTxtObj);
+ else
+ result+=jsonTxtObj;
+ }
+
+ return result;
+ }
+
+ function parseJSONArray ( jsonArrRoot, jsonArrObj, attrList ) {
+ var result = "";
+ if(jsonArrRoot.length == 0) {
+ result+=startTag(jsonArrRoot, jsonArrObj, attrList, true);
+ }
+ else {
+ for(var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) {
+ result+=startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false);
+ result+=parseJSONObject(jsonArrRoot[arIdx]);
+ result+=endTag(jsonArrRoot[arIdx],jsonArrObj);
+ }
+ }
+ return result;
+ }
+
+ function parseJSONObject ( jsonObj ) {
+ var result = "";
+
+ var elementsCnt = jsonXmlElemCount ( jsonObj );
+
+ if(elementsCnt > 0) {
+ for( var it in jsonObj ) {
+
+ if(jsonXmlSpecialElem ( jsonObj, it) )
+ continue;
+
+ var subObj = jsonObj[it];
+
+ var attrList = parseJSONAttributes( subObj )
+
+ if(subObj == null || subObj == undefined) {
+ result+=startTag(subObj, it, attrList, true);
+ }
+ else
+ if(subObj instanceof Object) {
+
+ if(subObj instanceof Array) {
+ result+=parseJSONArray( subObj, it, attrList );
+ }
+ else if(subObj instanceof Date) {
+ result+=startTag(subObj, it, attrList, false);
+ result+=subObj.toISOString();
+ result+=endTag(subObj,it);
+ }
+ else {
+ var subObjElementsCnt = jsonXmlElemCount ( subObj );
+ if(subObjElementsCnt > 0 || subObj.__text!=null || subObj.__cdata!=null) {
+ result+=startTag(subObj, it, attrList, false);
+ result+=parseJSONObject(subObj);
+ result+=endTag(subObj,it);
+ }
+ else {
+ result+=startTag(subObj, it, attrList, true);
+ }
+ }
+ }
+ else {
+ result+=startTag(subObj, it, attrList, false);
+ result+=parseJSONTextObject(subObj);
+ result+=endTag(subObj,it);
+ }
+ }
+ }
+ result+=parseJSONTextObject(jsonObj);
+
+ return result;
+ }
+
+ this.parseXmlString = function(xmlDocStr) {
+ var isIEParser = window.ActiveXObject || "ActiveXObject" in window;
+ if (xmlDocStr === undefined) {
+ return null;
+ }
+ var xmlDoc;
+ if (window.DOMParser) {
+ var parser=new window.DOMParser();
+ var parsererrorNS = null;
+ // IE9+ now is here
+ if(!isIEParser) {
+ try {
+ parsererrorNS = parser.parseFromString("INVALID", "text/xml").childNodes[0].namespaceURI;
+ }
+ catch(err) {
+ parsererrorNS = null;
+ }
+ }
+ try {
+ xmlDoc = parser.parseFromString( xmlDocStr, "text/xml" );
+ if( parsererrorNS!= null && xmlDoc.getElementsByTagNameNS(parsererrorNS, "parsererror").length > 0) {
+ //throw new Error('Error parsing XML: '+xmlDocStr);
+ xmlDoc = null;
+ }
+ }
+ catch(err) {
+ xmlDoc = null;
+ }
+ }
+ else {
+ // IE :(
+ if(xmlDocStr.indexOf("<?")==0) {
+ xmlDocStr = xmlDocStr.substr( xmlDocStr.indexOf("?>") + 2 );
+ }
+ xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.async="false";
+ xmlDoc.loadXML(xmlDocStr);
+ }
+ return xmlDoc;
+ };
+
+ this.asArray = function(prop) {
+ if(prop instanceof Array)
+ return prop;
+ else
+ return [prop];
+ };
+
+ this.toXmlDateTime = function(dt) {
+ if(dt instanceof Date)
+ return dt.toISOString();
+ else
+ if(typeof(dt) === 'number' )
+ return new Date(dt).toISOString();
+ else
+ return null;
+ };
+
+ this.asDateTime = function(prop) {
+ if(typeof(prop) == "string") {
+ return fromXmlDateTime(prop);
+ }
+ else
+ return prop;
+ };
+
+ this.xml2json = function (xmlDoc) {
+ return parseDOMChildren ( xmlDoc );
+ };
+
+ this.xml_str2json = function (xmlDocStr) {
+ var xmlDoc = this.parseXmlString(xmlDocStr);
+ if(xmlDoc!=null)
+ return this.xml2json(xmlDoc);
+ else
+ return null;
+ };
+
+ this.json2xml_str = function (jsonObj) {
+ return parseJSONObject ( jsonObj );
+ };
+
+ this.json2xml = function (jsonObj) {
+ var xmlDocStr = this.json2xml_str (jsonObj);
+ return this.parseXmlString(xmlDocStr);
+ };
+
+ this.getVersion = function () {
+ return VERSION;
+ };
+
+}
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/pom.xml new file mode 100644 index 00000000..93caaec9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCommons/pom.xml @@ -0,0 +1,26 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtn</artifactId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnCommons</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + <packaging>pom</packaging> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnCommons-module</module> + <module>mwtnCommons-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-bundle/pom.xml new file mode 100644 index 00000000..66e1ee9e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-bundle/pom.xml @@ -0,0 +1,118 @@ +<?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-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnCompare-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnCompare-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..dae4aa40 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/mwtnCompare-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnCompare"/> + <property name="url" value="/src/app/mwtnCompare"/> + <property name="directory" value="/mwtnCompare"/> + <property name="requireJs" value="app/mwtnCompare/mwtnCompare.module"/> + <property name="angularJs" value="app.mwtnCompare"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnCompare/mwtnCompare-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file 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 Binary files differnew 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 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; //' ' + $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 diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/pom.xml new file mode 100644 index 00000000..75cedab1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnCompare/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnCompare</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnCompare-module</module> + <module>mwtnCompare-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-bundle/pom.xml new file mode 100644 index 00000000..2b8c9823 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-bundle/pom.xml @@ -0,0 +1,118 @@ +<?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>mwtnConnect</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnConnect-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnConnect-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnConnect-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..62345db5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,20 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnConnect"/> + <property name="url" value="/src/app/mwtnConnect"/> + <property name="directory" value="/mwtnConnect"/> + <property name="requireJs" value="app/mwtnConnect/mwtnConnect.module"/> + <property name="angularJs" value="app.mwtnConnect"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnConnect/mwtnConnect-custom.css</value> + <value>src/app/mwtnCommons/mwtnCommons-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/pom.xml new file mode 100644 index 00000000..c47134aa --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/mwtnConnect-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnConnect</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnConnect-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/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 Binary files differnew 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 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 Binary files differnew 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 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> </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> </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> </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> </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> </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; //' ' + $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"> / {{ 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> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/pom.xml new file mode 100644 index 00000000..273501d5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnConnect/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnConnect</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnConnect-module</module> + <module>mwtnConnect-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-bundle/pom.xml new file mode 100644 index 00000000..9a9504ac --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>mwtnEvents</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnEvents-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnEvents-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnEvents-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..4cac53b2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnEvents"/> + <property name="url" value="/src/app/mwtnEvents"/> + <property name="directory" value="/mwtnEvents"/> + <property name="requireJs" value="app/mwtnEvents/mwtnEvents.module"/> + <property name="angularJs" value="app.mwtnEvents"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnEvents/mwtnEvents-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/pom.xml new file mode 100644 index 00000000..cf3ec048 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-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>mwtnEvents</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnEvents-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/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/images/mwtnEvents.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/images/mwtnEvents.png Binary files differnew file mode 100755 index 00000000..d93e6df5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/images/mwtnEvents.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents-custom.css new file mode 100644 index 00000000..211adc44 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents-custom.css @@ -0,0 +1,12 @@ +/** + * Add your application related css here + */ +.mwtnEventsGrid { + height: 600px; + background-color: white; +} + +.mwtnEventsGrid span { + color: #393939; +} +
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.controller.js new file mode 100644 index 00000000..1a545adb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.controller.js @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016 Tech Mahindra Ltd. 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/mwtnEvents/mwtnEvents.module', 'app/mwtnEvents/mwtnEvents.services', 'app/mwtnCommons/mwtnCommons.services'], + function(mwtnEventsApp) { + + mwtnEventsApp.register + .controller( + 'mwtnEventsCtrl', + [ + '$scope', + '$rootScope', + '$mwtnEvents', + 'uiGridConstants', + function($scope, $rootScope, $mwtnEvents, uiGridConstants) { + + $rootScope.section_logo = 'src/app/mwtnEvents/images/mwtnEvents.png'; + + $scope.status = {alarms:true}; + $scope.oneATime = true; + + $scope.gridOptionsAlarms = JSON.parse(JSON.stringify($mwtnEvents.gridOptions)); + $scope.gridOptionsAlarms.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + // { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timeStamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200,sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 90 }, + { field: 'nodeName', type: 'string', displayName: 'NetworkElement', headerCellClass: $scope.highlightFilteredHeader, width: 170 }, + { field: 'objectId', type: 'string', displayName: 'Object', headerCellClass: $scope.highlightFilteredHeader, width: 400 }, + + { field: 'problem', type: 'string', displayName: 'Alarm', headerCellClass: $scope.highlightFilteredHeader, width : 140 }, + { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 100 } + ]; + + $scope.gridOptionsAVC = JSON.parse(JSON.stringify($mwtnEvents.gridOptions)); + $scope.gridOptionsAVC.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + // { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timeStamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200,sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 90 }, + { field: 'nodeName', type: 'string', displayName: 'NetworkElement', headerCellClass: $scope.highlightFilteredHeader, width: 170 }, + { field: 'objectId', type: 'string', displayName: 'Object', headerCellClass: $scope.highlightFilteredHeader, width: 400 }, + { field: 'attributeName', type: 'string', displayName: 'Attribute', headerCellClass: $scope.highlightFilteredHeader, width : 140 }, + { field: 'newValue', type: 'string', displayName: 'New value', headerCellClass: $scope.highlightFilteredHeader, width : 140 } + ]; + + $scope.gridOptionsObject = JSON.parse(JSON.stringify($mwtnEvents.gridOptions)); + $scope.gridOptionsObject.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + // { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timeStamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200,sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 90 }, + { field: 'nodeName', type: 'string', displayName: 'NetworkElement', headerCellClass: $scope.highlightFilteredHeader, width: 170 }, + { field: 'objectId', type: 'string', displayName: 'Object', headerCellClass: $scope.highlightFilteredHeader, width: 400 }, + { field: 'objectType', type: 'string', displayName: 'Type', headerCellClass: $scope.highlightFilteredHeader, width: 400 }, + { field: 'action', type: 'string', displayName: 'Action', headerCellClass: $scope.highlightFilteredHeader, width: 100 } + + ]; + + var listenToNotifications = function() { + $mwtnEvents.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("---------------------------"); + $mwtnEvents.formatData(event).then(function(formated) { + switch (formated.notifType) { + case 'ProblemNotification': + $scope.gridOptionsAlarms.data.push(formated); + break; + case 'AttributeValueChangedNotification': + $scope.gridOptionsAVC.data.push(formated); + break; + case 'ObjectCreationNotification': + formated.action = 'created'; + if (formated.nodeName.contains('SDN-Controller')) { + formated.objectType = 'NETCONF session'; + } + $scope.gridOptionsObject.data.push(formated); + break; + case 'ObjectDeletionNotification': + formated.action = 'deleted'; + if (formated.nodeName.contains('SDN-Controller')) { + formated.objectType = 'NETCONF session'; + } + $scope.gridOptionsObject.data.push(formated); + 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."); + console.log("---------------------------"); + + function subscribe() { + if (notificationSocket.readyState === notificationSocket.OPEN) { + var data = { + 'data' : 'scopes', + 'scopes' : [ "ObjectCreationNotification", + "ObjectDeletionNotification", + "AttributeValueChangedNotification", + "ProblemNotification" ] + }; + 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); + }); + }; + listenToNotifications(); + } ]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.module.js new file mode 100644 index 00000000..f059d6d1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.module.js @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Tech Mahindra Ltd. 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 mwtnEventsApp = angular.module('app.mwtnEvents', [ 'app.core', + 'ui.router.state', 'config' ]); + + mwtnEventsApp.config(function($stateProvider, $compileProvider, + $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnEventsApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + NavHelperProvider.addControllerUrl('app/mwtnEvents/mwtnEvents.controller'); + NavHelperProvider.addToMenu('mwtnEvents', { + "link" : "#/pnfEvents", + "active" : "main.mwtnEvents", + "title" : "pnf Events", + "icon" : "fa fa-bolt", // Add navigation icon css class here + "page" : { + "title" : "pnf Events", + "description" : "Events" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnEvents', { + url : 'mwtnEvents', + access : access.admin, + views : { + 'content' : { + templateUrl : 'src/app/mwtnEvents/mwtnEvents.tpl.html', + controller : 'mwtnEventsCtrl' + } + } + }); + + }); + + return mwtnEventsApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.services.js new file mode 100644 index 00000000..1cd41fb7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.services.js @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016 Tech Mahindra Ltd. 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/mwtnEvents/mwtnEvents.module' ], function(mwtnEventsApp) { + + mwtnEventsApp.register.factory('$mwtnEvents', function($mwtnCommons) { + + var service = {}; + + service.gridOptions = $mwtnCommons.gridOptions; + service.getMwtnWebSocketUrl = $mwtnCommons.getMwtnWebSocketUrl; + service.formatData = $mwtnCommons.formatData; + + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.tpl.html new file mode 100644 index 00000000..b0a2ed41 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/mwtnEvents.tpl.html @@ -0,0 +1,45 @@ +<ht-header help-link='sdnr/mwtnEvents/0.4.0/README.md'></ht-header> +<div class="mwtnError">{{error}}</div> + +<uib-accordion close-others="oneATime"> + +<div uib-accordion-group class="panel-primary" is-open="status.alarms"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.alarms, 'fa-chevron-right': !status.alarms}"></i> + <span>{{'MWTN_ALARMS' | translate}} + ({{gridOptionsAlarms.data.length}})</span> </uib-accordion-heading> + + + <div id="mwtnEventsGridAlarms" ui-grid="gridOptionsAlarms" + ui-grid-exporter ui-grid-selection ui-grid-pinning + ui-grid-resize-columns ui-grid-move-columns class="mwtnEventsGrid"></div> +</div> + +<div uib-accordion-group class="panel-primary" is-open="status.avc"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.avc, 'fa-chevron-right': !status.avc}"></i> + <span>{{'MWTN_ATTRIBUTE_VALUE_CHANGED' | translate}} + ({{gridOptionsAVC.data.length}})</span> </uib-accordion-heading> + + + <div id="mwtnEventsGridAVC" ui-grid="gridOptionsAVC" ui-grid-exporter + ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnEventsGrid"></div> +</div> + +<div uib-accordion-group class="panel-primary" is-open="status.object"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.object, 'fa-chevron-right': !status.object}"></i> + <span>{{'MWTN_OBJECT_DELETION_CREATION' | translate}} + ({{gridOptionsObject.data.length}})</span> </uib-accordion-heading> + + <div id="mwtnEventsGridObject" ui-grid="gridOptionsObject" + ui-grid-exporter ui-grid-selection ui-grid-pinning + ui-grid-resize-columns ui-grid-move-columns class="mwtnEventsGrid"></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/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/xml2json.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/xml2json.js new file mode 100644 index 00000000..5ff7e578 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/mwtnEvents-module/src/main/resources/mwtnEvents/xml2json.js @@ -0,0 +1,567 @@ +/*
+ Copyright 2011-2013 Abdulla Abdurakhmanov
+ Original sources are available at https://code.google.com/p/x2js/
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+function X2JS(config) {
+ 'use strict';
+
+ var VERSION = "1.1.5";
+
+ config = config || {};
+ initConfigDefaults();
+ initRequiredPolyfills();
+
+ function initConfigDefaults() {
+ if(config.escapeMode === undefined) {
+ config.escapeMode = true;
+ }
+ config.attributePrefix = config.attributePrefix || "_";
+ config.arrayAccessForm = config.arrayAccessForm || "none";
+ config.emptyNodeForm = config.emptyNodeForm || "text";
+ if(config.enableToStringFunc === undefined) {
+ config.enableToStringFunc = true;
+ }
+ config.arrayAccessFormPaths = config.arrayAccessFormPaths || [];
+ if(config.skipEmptyTextNodesForObj === undefined) {
+ config.skipEmptyTextNodesForObj = true;
+ }
+ if(config.stripWhitespaces === undefined) {
+ config.stripWhitespaces = true;
+ }
+ config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || [];
+ }
+
+ var DOMNodeTypes = {
+ ELEMENT_NODE : 1,
+ TEXT_NODE : 3,
+ CDATA_SECTION_NODE : 4,
+ COMMENT_NODE : 8,
+ DOCUMENT_NODE : 9
+ };
+
+ function initRequiredPolyfills() {
+ function pad(number) {
+ var r = String(number);
+ if ( r.length === 1 ) {
+ r = '0' + r;
+ }
+ return r;
+ }
+ // Hello IE8-
+ if(typeof String.prototype.trim !== 'function') {
+ String.prototype.trim = function() {
+ return this.replace(/^\s+|^\n+|(\s|\n)+$/g, '');
+ }
+ }
+ if(typeof Date.prototype.toISOString !== 'function') {
+ // Implementation from http://stackoverflow.com/questions/2573521/how-do-i-output-an-iso-8601-formatted-string-in-javascript
+ Date.prototype.toISOString = function() {
+ return this.getUTCFullYear()
+ + '-' + pad( this.getUTCMonth() + 1 )
+ + '-' + pad( this.getUTCDate() )
+ + 'T' + pad( this.getUTCHours() )
+ + ':' + pad( this.getUTCMinutes() )
+ + ':' + pad( this.getUTCSeconds() )
+ + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
+ + 'Z';
+ };
+ }
+ }
+
+ function getNodeLocalName( node ) {
+ var nodeLocalName = node.localName;
+ if(nodeLocalName == null) // Yeah, this is IE!!
+ nodeLocalName = node.baseName;
+ if(nodeLocalName == null || nodeLocalName=="") // =="" is IE too
+ nodeLocalName = node.nodeName;
+ return nodeLocalName;
+ }
+
+ function getNodePrefix(node) {
+ return node.prefix;
+ }
+
+ function escapeXmlChars(str) {
+ if(typeof(str) == "string")
+ return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/');
+ else
+ return str;
+ }
+
+ function unescapeXmlChars(str) {
+ return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(///g, '\/');
+ }
+
+ function toArrayAccessForm(obj, childName, path) {
+ switch(config.arrayAccessForm) {
+ case "property":
+ if(!(obj[childName] instanceof Array))
+ obj[childName+"_asArray"] = [obj[childName]];
+ else
+ obj[childName+"_asArray"] = obj[childName];
+ break;
+ /*case "none":
+ break;*/
+ }
+
+ if(!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) {
+ var idx = 0;
+ for(; idx < config.arrayAccessFormPaths.length; idx++) {
+ var arrayPath = config.arrayAccessFormPaths[idx];
+ if( typeof arrayPath === "string" ) {
+ if(arrayPath == path)
+ break;
+ }
+ else
+ if( arrayPath instanceof RegExp) {
+ if(arrayPath.test(path))
+ break;
+ }
+ else
+ if( typeof arrayPath === "function") {
+ if(arrayPath(obj, childName, path))
+ break;
+ }
+ }
+ if(idx!=config.arrayAccessFormPaths.length) {
+ obj[childName] = [obj[childName]];
+ }
+ }
+ }
+
+ function fromXmlDateTime(prop) {
+ // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object
+ // Improved to support full spec and optional parts
+ var bits = prop.split(/[-T:+Z]/g);
+
+ var d = new Date(bits[0], bits[1]-1, bits[2]);
+ var secondBits = bits[5].split("\.");
+ d.setHours(bits[3], bits[4], secondBits[0]);
+ if(secondBits.length>1)
+ d.setMilliseconds(secondBits[1]);
+
+ // Get supplied time zone offset in minutes
+ if(bits[6] && bits[7]) {
+ var offsetMinutes = bits[6] * 60 + Number(bits[7]);
+ var sign = /\d\d-\d\d:\d\d$/.test(prop)? '-' : '+';
+
+ // Apply the sign
+ offsetMinutes = 0 + (sign == '-'? -1 * offsetMinutes : offsetMinutes);
+
+ // Apply offset and local timezone
+ d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset())
+ }
+ else
+ if(prop.indexOf("Z", prop.length - 1) !== -1) {
+ d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()));
+ }
+
+ // d is now a local time equivalent to the supplied time
+ return d;
+ }
+
+ function checkFromXmlDateTimePaths(value, childName, fullPath) {
+ if(config.datetimeAccessFormPaths.length > 0) {
+ var path = fullPath.split("\.#")[0];
+ var idx = 0;
+ for(; idx < config.datetimeAccessFormPaths.length; idx++) {
+ var dtPath = config.datetimeAccessFormPaths[idx];
+ if( typeof dtPath === "string" ) {
+ if(dtPath == path)
+ break;
+ }
+ else
+ if( dtPath instanceof RegExp) {
+ if(dtPath.test(path))
+ break;
+ }
+ else
+ if( typeof dtPath === "function") {
+ if(dtPath(obj, childName, path))
+ break;
+ }
+ }
+ if(idx!=config.datetimeAccessFormPaths.length) {
+ return fromXmlDateTime(value);
+ }
+ else
+ return value;
+ }
+ else
+ return value;
+ }
+
+ function parseDOMChildren( node, path ) {
+ if(node.nodeType == DOMNodeTypes.DOCUMENT_NODE) {
+ var result = new Object;
+ var nodeChildren = node.childNodes;
+ // Alternative for firstElementChild which is not supported in some environments
+ for(var cidx=0; cidx <nodeChildren.length; cidx++) {
+ var child = nodeChildren.item(cidx);
+ if(child.nodeType == DOMNodeTypes.ELEMENT_NODE) {
+ var childName = getNodeLocalName(child);
+ result[childName] = parseDOMChildren(child, childName);
+ }
+ }
+ return result;
+ }
+ else
+ if(node.nodeType == DOMNodeTypes.ELEMENT_NODE) {
+ var result = new Object;
+ result.__cnt=0;
+
+ var nodeChildren = node.childNodes;
+
+ // Children nodes
+ for(var cidx=0; cidx <nodeChildren.length; cidx++) {
+ var child = nodeChildren.item(cidx); // nodeChildren[cidx];
+ var childName = getNodeLocalName(child);
+
+ if(child.nodeType!= DOMNodeTypes.COMMENT_NODE) {
+ result.__cnt++;
+ if(result[childName] == null) {
+ result[childName] = parseDOMChildren(child, path+"."+childName);
+ toArrayAccessForm(result, childName, path+"."+childName);
+ }
+ else {
+ if(result[childName] != null) {
+ if( !(result[childName] instanceof Array)) {
+ result[childName] = [result[childName]];
+ toArrayAccessForm(result, childName, path+"."+childName);
+ }
+ }
+ (result[childName])[result[childName].length] = parseDOMChildren(child, path+"."+childName);
+ }
+ }
+ }
+
+ // Attributes
+ for(var aidx=0; aidx <node.attributes.length; aidx++) {
+ var attr = node.attributes.item(aidx); // [aidx];
+ result.__cnt++;
+ result[config.attributePrefix+attr.name]=attr.value;
+ }
+
+ // Node namespace prefix
+ var nodePrefix = getNodePrefix(node);
+ if(nodePrefix!=null && nodePrefix!="") {
+ result.__cnt++;
+ result.__prefix=nodePrefix;
+ }
+
+ if(result["#text"]!=null) {
+ result.__text = result["#text"];
+ if(result.__text instanceof Array) {
+ result.__text = result.__text.join("\n");
+ }
+ if(config.escapeMode)
+ result.__text = unescapeXmlChars(result.__text);
+ if(config.stripWhitespaces)
+ result.__text = result.__text.trim();
+ delete result["#text"];
+ if(config.arrayAccessForm=="property")
+ delete result["#text_asArray"];
+ result.__text = checkFromXmlDateTimePaths(result.__text, childName, path+"."+childName);
+ }
+ if(result["#cdata-section"]!=null) {
+ result.__cdata = result["#cdata-section"];
+ delete result["#cdata-section"];
+ if(config.arrayAccessForm=="property")
+ delete result["#cdata-section_asArray"];
+ }
+
+ if( result.__cnt == 1 && result.__text!=null ) {
+ result = result.__text;
+ }
+ else
+ if( result.__cnt == 0 && config.emptyNodeForm=="text" ) {
+ result = '';
+ }
+ else
+ if ( result.__cnt > 1 && result.__text!=null && config.skipEmptyTextNodesForObj) {
+ if( (config.stripWhitespaces && result.__text=="") || (result.__text.trim()=="")) {
+ delete result.__text;
+ }
+ }
+ delete result.__cnt;
+
+ if( config.enableToStringFunc && (result.__text!=null || result.__cdata!=null )) {
+ result.toString = function() {
+ return (this.__text!=null? this.__text:'')+( this.__cdata!=null ? this.__cdata:'');
+ };
+ }
+
+ return result;
+ }
+ else
+ if(node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {
+ return node.nodeValue;
+ }
+ }
+
+ function startTag(jsonObj, element, attrList, closed) {
+ var resultStr = "<"+ ( (jsonObj!=null && jsonObj.__prefix!=null)? (jsonObj.__prefix+":"):"") + element;
+ if(attrList!=null) {
+ for(var aidx = 0; aidx < attrList.length; aidx++) {
+ var attrName = attrList[aidx];
+ var attrVal = jsonObj[attrName];
+ if(config.escapeMode)
+ attrVal=escapeXmlChars(attrVal);
+ resultStr+=" "+attrName.substr(config.attributePrefix.length)+"='"+attrVal+"'";
+ }
+ }
+ if(!closed)
+ resultStr+=">";
+ else
+ resultStr+="/>";
+ return resultStr;
+ }
+
+ function endTag(jsonObj,elementName) {
+ return "</"+ (jsonObj.__prefix!=null? (jsonObj.__prefix+":"):"")+elementName+">";
+ }
+
+ function endsWith(str, suffix) {
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ }
+
+ function jsonXmlSpecialElem ( jsonObj, jsonObjField ) {
+ if((config.arrayAccessForm=="property" && endsWith(jsonObjField.toString(),("_asArray")))
+ || jsonObjField.toString().indexOf(config.attributePrefix)==0
+ || jsonObjField.toString().indexOf("__")==0
+ || (jsonObj[jsonObjField] instanceof Function) )
+ return true;
+ else
+ return false;
+ }
+
+ function jsonXmlElemCount ( jsonObj ) {
+ var elementsCnt = 0;
+ if(jsonObj instanceof Object ) {
+ for( var it in jsonObj ) {
+ if(jsonXmlSpecialElem ( jsonObj, it) )
+ continue;
+ elementsCnt++;
+ }
+ }
+ return elementsCnt;
+ }
+
+ function parseJSONAttributes ( jsonObj ) {
+ var attrList = [];
+ if(jsonObj instanceof Object ) {
+ for( var ait in jsonObj ) {
+ if(ait.toString().indexOf("__")== -1 && ait.toString().indexOf(config.attributePrefix)==0) {
+ attrList.push(ait);
+ }
+ }
+ }
+ return attrList;
+ }
+
+ function parseJSONTextAttrs ( jsonTxtObj ) {
+ var result ="";
+
+ if(jsonTxtObj.__cdata!=null) {
+ result+="<![CDATA["+jsonTxtObj.__cdata+"]]>";
+ }
+
+ if(jsonTxtObj.__text!=null) {
+ if(config.escapeMode)
+ result+=escapeXmlChars(jsonTxtObj.__text);
+ else
+ result+=jsonTxtObj.__text;
+ }
+ return result;
+ }
+
+ function parseJSONTextObject ( jsonTxtObj ) {
+ var result ="";
+
+ if( jsonTxtObj instanceof Object ) {
+ result+=parseJSONTextAttrs ( jsonTxtObj );
+ }
+ else
+ if(jsonTxtObj!=null) {
+ if(config.escapeMode)
+ result+=escapeXmlChars(jsonTxtObj);
+ else
+ result+=jsonTxtObj;
+ }
+
+ return result;
+ }
+
+ function parseJSONArray ( jsonArrRoot, jsonArrObj, attrList ) {
+ var result = "";
+ if(jsonArrRoot.length == 0) {
+ result+=startTag(jsonArrRoot, jsonArrObj, attrList, true);
+ }
+ else {
+ for(var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) {
+ result+=startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false);
+ result+=parseJSONObject(jsonArrRoot[arIdx]);
+ result+=endTag(jsonArrRoot[arIdx],jsonArrObj);
+ }
+ }
+ return result;
+ }
+
+ function parseJSONObject ( jsonObj ) {
+ var result = "";
+
+ var elementsCnt = jsonXmlElemCount ( jsonObj );
+
+ if(elementsCnt > 0) {
+ for( var it in jsonObj ) {
+
+ if(jsonXmlSpecialElem ( jsonObj, it) )
+ continue;
+
+ var subObj = jsonObj[it];
+
+ var attrList = parseJSONAttributes( subObj )
+
+ if(subObj == null || subObj == undefined) {
+ result+=startTag(subObj, it, attrList, true);
+ }
+ else
+ if(subObj instanceof Object) {
+
+ if(subObj instanceof Array) {
+ result+=parseJSONArray( subObj, it, attrList );
+ }
+ else if(subObj instanceof Date) {
+ result+=startTag(subObj, it, attrList, false);
+ result+=subObj.toISOString();
+ result+=endTag(subObj,it);
+ }
+ else {
+ var subObjElementsCnt = jsonXmlElemCount ( subObj );
+ if(subObjElementsCnt > 0 || subObj.__text!=null || subObj.__cdata!=null) {
+ result+=startTag(subObj, it, attrList, false);
+ result+=parseJSONObject(subObj);
+ result+=endTag(subObj,it);
+ }
+ else {
+ result+=startTag(subObj, it, attrList, true);
+ }
+ }
+ }
+ else {
+ result+=startTag(subObj, it, attrList, false);
+ result+=parseJSONTextObject(subObj);
+ result+=endTag(subObj,it);
+ }
+ }
+ }
+ result+=parseJSONTextObject(jsonObj);
+
+ return result;
+ }
+
+ this.parseXmlString = function(xmlDocStr) {
+ var isIEParser = window.ActiveXObject || "ActiveXObject" in window;
+ if (xmlDocStr === undefined) {
+ return null;
+ }
+ var xmlDoc;
+ if (window.DOMParser) {
+ var parser=new window.DOMParser();
+ var parsererrorNS = null;
+ // IE9+ now is here
+ if(!isIEParser) {
+ try {
+ parsererrorNS = parser.parseFromString("INVALID", "text/xml").childNodes[0].namespaceURI;
+ }
+ catch(err) {
+ parsererrorNS = null;
+ }
+ }
+ try {
+ xmlDoc = parser.parseFromString( xmlDocStr, "text/xml" );
+ if( parsererrorNS!= null && xmlDoc.getElementsByTagNameNS(parsererrorNS, "parsererror").length > 0) {
+ //throw new Error('Error parsing XML: '+xmlDocStr);
+ xmlDoc = null;
+ }
+ }
+ catch(err) {
+ xmlDoc = null;
+ }
+ }
+ else {
+ // IE :(
+ if(xmlDocStr.indexOf("<?")==0) {
+ xmlDocStr = xmlDocStr.substr( xmlDocStr.indexOf("?>") + 2 );
+ }
+ xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.async="false";
+ xmlDoc.loadXML(xmlDocStr);
+ }
+ return xmlDoc;
+ };
+
+ this.asArray = function(prop) {
+ if(prop instanceof Array)
+ return prop;
+ else
+ return [prop];
+ };
+
+ this.toXmlDateTime = function(dt) {
+ if(dt instanceof Date)
+ return dt.toISOString();
+ else
+ if(typeof(dt) === 'number' )
+ return new Date(dt).toISOString();
+ else
+ return null;
+ };
+
+ this.asDateTime = function(prop) {
+ if(typeof(prop) == "string") {
+ return fromXmlDateTime(prop);
+ }
+ else
+ return prop;
+ };
+
+ this.xml2json = function (xmlDoc) {
+ return parseDOMChildren ( xmlDoc );
+ };
+
+ this.xml_str2json = function (xmlDocStr) {
+ var xmlDoc = this.parseXmlString(xmlDocStr);
+ if(xmlDoc!=null)
+ return this.xml2json(xmlDoc);
+ else
+ return null;
+ };
+
+ this.json2xml_str = function (jsonObj) {
+ return parseJSONObject ( jsonObj );
+ };
+
+ this.json2xml = function (jsonObj) {
+ var xmlDocStr = this.json2xml_str (jsonObj);
+ return this.parseXmlString(xmlDocStr);
+ };
+
+ this.getVersion = function () {
+ return VERSION;
+ };
+
+}
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/pom.xml new file mode 100644 index 00000000..e898be3c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnEvents/pom.xml @@ -0,0 +1,27 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnEvents</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnEvents-module</module> + <module>mwtnEvents-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-bundle/pom.xml new file mode 100644 index 00000000..bceb9084 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>mwtnFault</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnFault-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnFault-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnFault-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..2f89a41c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnFault"/> + <property name="url" value="/src/app/mwtnFault"/> + <property name="directory" value="/mwtnFault"/> + <property name="requireJs" value="app/mwtnFault/mwtnFault.module"/> + <property name="angularJs" value="app.mwtnFault"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnFault/mwtnFault-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/pom.xml new file mode 100644 index 00000000..f0d7215d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-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>mwtnFault</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnFault-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/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/images/mwtnFault.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/images/mwtnFault.png Binary files differnew file mode 100755 index 00000000..47bfc70c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/images/mwtnFault.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault-custom.css new file mode 100644 index 00000000..7e959b1e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault-custom.css @@ -0,0 +1,100 @@ +/** + * Add your application related css here + */ +.global-alarm-status { + float: left; + margin: 5px; + margin-left: 8px; +} + +.global-alarm-status a { + color:azure; + text-decoration: none; +} + +.global-alarm-status a:visited { + color:azure; + text-decoration: none; +} + +.global-alarm-status a:hover { + color:bisque; +} +s +.mwtn span { + color: white; +} +.mwtn a span { + color: white; +} +.Critical { + color: red; +} +.Major { + color: orange; +} +.Minor { + color: yellow; +} +.Warning { + color: #428bca; +} +.cleared { + color: lightgreen; +} + +.mwtnFaultGrid { + height: 600px; + background-color: white; +} + +.mwtnFaultGrid span { + color: #393939; +} +.ht-pagination span { + color: #393939; +} +.ht-pagination span.dark { + color: #393939; +} +.dark { + color: #393939; +} + + + +.mwtnFaultGrid div.debug { + color: #393939; + background-color: white; +} +.mwtnFaultGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.mwtnFaultGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.mwtnFaultGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.controller.js new file mode 100644 index 00000000..d29d547d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.controller.js @@ -0,0 +1,597 @@ +/* + * 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/mwtnFault/mwtnFault.module', + 'app/mwtnFault/mwtnFault.services', + 'app/mwtnFault/mwtnFault.directives'], + function(mwtnFaultApp) { + + mwtnFaultApp.register.controller('mwtnFaultCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$mwtnFault', '$mwtnLog', '$http', + function(uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $mwtnFault, $mwtnLog, $http) { + + + var COMPONENT = 'mwtnFaultCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'mwtnFaultCtrl started!'}); + + $rootScope.section_logo = 'src/app/mwtnFault/images/mwtnFault.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.date = new Date().toISOString().toHumanReadableTimeFormat(); + $scope.highlightFilteredHeader = $mwtnFault.highlightFilteredHeader; + $scope.oneATime = true; + + // var rowTemplate = '<div ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ng-class="[\'ui-grid-cell\', row.entity.type]" ui-grid-cell></div>'; + var iconCell = '<div class="ui-grid-cell-contents tooltip-uigrid" title="TOOLTIP"><i class="fa {{COL_FIELD}}" aria-hidden="true"></i></div>'; + var getIconFromSeverity = function(severity) { + var mapping = { + Cleared : '', + NonAlarmed : '', + Critical : 'fa-exclamation-triangle', + Major : 'fa-exclamation-triangle', + Minor : 'fa-exclamation-triangle', + Warning : 'fa-times-circle' + }; + return mapping[severity]; + }; + + // Current Problem List + $scope.gridOptionsCurrentProblemList = JSON.parse(JSON.stringify($mwtnFault.gridOptions)); + $scope.gridOptionsCurrentProblemList.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timestamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200, sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'node', type: 'string', displayName: 'Node name', headerCellClass: $scope.highlightFilteredHeader, width: 200 }, + { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 70, cellClass: 'number' }, + { field: 'object', type: 'string', displayName: 'Object Id', headerCellClass: $scope.highlightFilteredHeader, width: 300 }, + { field: 'problem', type: 'string', displayName: 'Alarm type', headerCellClass: $scope.highlightFilteredHeader, width : 200 }, + { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 150 } + + ]; + + var processCurrentProblemEntries = function(logEntries) { + if (logEntries.data.hits.hits) { + $scope.gridOptionsCurrentProblemList.data = logEntries.data.hits.hits.map(function(entry){ + return { + id: entry._id, + icon: getIconFromSeverity(entry._source.faultCurrent.severity), + timestamp: $mwtnFault.formatTimeStamp(entry._source.faultCurrent.timeStamp), + node: entry._source.faultCurrent.nodeName, + counter: entry._source.faultCurrent.counter, + object: entry._source.faultCurrent.objectId, + problem: entry._source.faultCurrent.problem, + severity: entry._source.faultCurrent.severity, + }; + }); + $scope.progress.max = logEntries.data.hits.total; + $scope.progress.value = $scope.gridOptionsCurrentProblemList.data.length; + $scope.progress.show = $scope.gridOptionsCurrentProblemList.data.length < logEntries.data.hits.total; + } + }; + + $scope.refreshCurrentProblemList = function() { + // $scope.gridOptionsCurrentProblemList.data = []; + var from = 0; + var size = 10000; + $scope.processing = true; + $mwtnFault.getAllCurrentProblemEntries(from, size).then(function(logEntries){ + $scope.processing = false; + $scope.spinner.currentProblemList = false; + processCurrentProblemEntries(logEntries); + from = from + size; + while (from < $scope.progress.max) { + $mwtnFault.getAllCurrentProblemEntries(from, size).then(function(logEntries){ + processCurrentProblemEntries(logEntries); + }, function(error){ + console.error(JSON.stringify(error)); + }); + from = from + size; + } + }, function(error){ + $scope.processing = false; + $scope.spinner.currentProblemList = false; + console.error(JSON.stringify(error)); + }); + }; + + // Alarm Notifications + $scope.gridOptionsAlarmNotifications = JSON.parse(JSON.stringify($mwtnFault.gridOptions)); + $scope.gridOptionsAlarmNotifications.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timeStamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200,sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 90 }, + { field: 'nodeName', type: 'string', displayName: 'NetworkElement', headerCellClass: $scope.highlightFilteredHeader, width: 170 }, + { field: 'objectId', type: 'string', displayName: 'Object', headerCellClass: $scope.highlightFilteredHeader, width: 400 }, + + { field: 'problem', type: 'string', displayName: 'Alarm', headerCellClass: $scope.highlightFilteredHeader, width : 140 }, + { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 100 } + ]; + var listenToNotifications = function() { + $mwtnFault.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("---------------------------"); + $mwtnFault.formatData(event).then(function(formated) { + switch (formated.notifType) { + case 'ProblemNotification': + formated.icon = getIconFromSeverity(formated.severity); + $scope.gridOptionsAlarmNotifications.data.push(formated); + $timeout(function(){$scope.refreshCurrentProblemList();}, 500); + break; + case 'AttributeValueChangedNotification': + case 'ObjectCreationNotification': + case 'ObjectDeletionNotification': + // ignore + 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' : [ "ProblemNotification" ] + }; + 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); + }); + }; + listenToNotifications(); + + // Alarm Log + // $scope.gridOptionsAlarmLog = JSON.parse(JSON.stringify($mwtnFault.gridOptions)); + + $scope.paginationOptions = { + pageNumber: 1, + pageSize: 25, + sort: null + }; + + $scope.gridOptionsAlarmLog = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: false, + enableFiltering: true, + useExternalFiltering: true, + columnDefs : [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timestamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200, sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'node', type: 'string', displayName: 'Node name', headerCellClass: $scope.highlightFilteredHeader, width: 200 }, + { field: 'counter', type: 'number', displayName: 'Counter', headerCellClass: $scope.highlightFilteredHeader, width: 70, cellClass: 'number' }, + { field: 'object', type: 'string', displayName: 'Object Id', headerCellClass: $scope.highlightFilteredHeader, width: 300 }, + { field: 'problem', type: 'string', displayName: 'Alarm type', headerCellClass: $scope.highlightFilteredHeader, width : 200 }, + { field: 'severity', type: 'string', displayName: 'Severity', headerCellClass: $scope.highlightFilteredHeader, width : 150 } + ], + 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.gridOptionsAlarmLog.columnDefs[1] ] ); + + $scope.gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getPage(); + }); + } +}; + + //stateobject + $scope.state={}; + $scope.state.filter=false; + $scope.state.sort=false; + $scope.state.lastfilter=null; + $scope.state.lastSort=null; + + $scope.maxCount=0; //value shown on screen + + + $scope.seekPage= function(page){ + if(!page){ //catch NaN values + page=1; + return; + } + $scope.gridApi.pagination.seek(parseInt(page)); + }; + + $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.gridOptionsAlarmLog.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.gridOptionsAlarmLog.totalItems, $scope.maxCount); + + } else { + var defaultTpl = 'Showing {0} to {1} of {2} total items'; + return defaultTpl.format( startnum, pagenednum, $scope.maxCount); + } + }; + +//list visible on screen + $scope.data = []; + + var getPage = function() { + //from, how many, sort, filter + getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize, $scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter) + .then(function (data) { + $scope.gridOptionsAlarmLog.totalItems = data.data.hits.total; + processResponseRecreateList(data); + }); + }; + + //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); + if(col==="fault.timeStamp"){ + //convert timestamp to db format + var timestamp= $mwtnFault.TimeStampToONFFormat(value.filters[0].term); + columns.push({ column: col ,value: timestamp }); + } + else + columns.push({ column: col ,value: value.filters[0].term }); //create column object + } + }); + + if(columns.length === 0){ //all filter data cleared away + $scope.state.filter=false; + $scope.state.lastfilter=null; + + //get unfiltered data + getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-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=[]; + for(var obj of columns){ + var prefixObj={}; + prefixObj[obj.column]=obj.value;//add like: {column: "fault.counter", value: "1"} => {"fault.counter":1} + prefixs.push({prefix:prefixObj}); // => {"prefix":{...}} + } + + //add objects to must property + filter.query.bool.must=prefixs; + + //save filter + $scope.state.lastfilter=filter; + $scope.state.filter=true; + + //send data to sdnevents/faultlog/_search + getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-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.gridOptionsAlarmLog.totalItems = response.data.hits.total; + }else{ + //clear data from list + $scope.data=[]; + $scope.gridOptionsAlarmLog.totalItems =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 + getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter).then(function(response) { + if (response.data.hits.hits) { + processResponseRecreateList(response); + } + }); + } + }; + + function sort(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; + + 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; + + 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; + + getData(($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize,$scope.paginationOptions.pageSize,$scope.state.lastSort,$scope.state.lastfilter) + .then(function(response) { + if (response.data.hits.hits) { + processResponseRecreateList(response); + } + }); + + break; + } + } + + var findColumn = function(name) { + + if(name==="Timestamp"){ return "fault.timeStamp"; } + else if(name==="Node name"){ return "fault.nodeName"; } + else if(name==="Counter"){ return "fault.counter"; } + else if(name==="Object Id"){ return "fault.objectId"; } + else if(name==="Alarm type"){return "fault.problem"; } + else if(name==="Severity"){ return "fault.severity"; } + + }; + + var getData = function(from, size, sort, query){ + if(sort === null){ //default sort value + sort = [ { "fault.timeStamp" : {order : 'desc'}}]; + } + if(query === null){ //default filter value + query= {match_all: {}}; + } + return $mwtnFault.getFilteredSortedData(from, size, sort, query); + }; + + var processResponseAddToList=function(response) { + if (response.data.hits.hits) { + response.data.hits.hits.map(function(entry){ + var log = { + id: entry._id, + icon: getIconFromSeverity(entry._source.fault.severity), + timestamp: $mwtnFault.formatTimeStamp(entry._source.fault.timeStamp), + node: entry._source.fault.nodeName, + counter: entry._source.fault.counter, + object: entry._source.fault.objectId, + problem: entry._source.fault.problem, + severity: entry._source.fault.severity, + }; + + $scope.data.push(log); + }); + + $scope.gridOptionsAlarmLog.totalItems = response.data.hits.total; // needed by ui-grid to calculate page number, always update! + if($scope.maxCount<response.data.hits.total){ + $scope.maxCount=response.data.hits.total; //only if total is higher (can be lower due to eg filtering) + } + }}; + + function processResponseRecreateList(response){ + var list=[]; + response.data.hits.hits.map(function(entry){ + var log = { + id: entry._id, + icon: getIconFromSeverity(entry._source.fault.severity), + timestamp: $mwtnFault.formatTimeStamp(entry._source.fault.timeStamp), + node: entry._source.fault.nodeName, + counter: entry._source.fault.counter, + object: entry._source.fault.objectId, + problem: entry._source.fault.problem, + severity: entry._source.fault.severity, + }; + + list.push(log); + }); + $scope.data=list; + $scope.gridOptionsAlarmLog.totalItems = response.data.hits.total; // needed by ui-grid to calculate page number, always update! + if($scope.maxCount<response.data.hits.total){ + $scope.maxCount=response.data.hits.total; //only if total is higher (can be lower due to eg filtering) + } + } + + $scope.refreshLog = function() { + + var from = ($scope.gridOptionsAlarmLog.paginationCurrentPage-1)*$scope.paginationOptions.pageSize; + var size = $scope.paginationOptions.pageSize; + $scope.processing = true; + getData(from, size,$scope.state.lastSort,$scope.state.lastfilter).then(function(logEntries){ + $scope.processing = false; + $scope.spinner.alarmLog = false; + processResponseRecreateList(logEntries); + + }, function(error){ + $scope.processing = false; + $scope.spinner.alarmLog = false; + console.error(JSON.stringify(error)); + }); + }; + + // [sko] TODO check from here on + $scope.progress = { + show: true + }; + + $scope.clearLog = function () { + + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnFault/templates/clearLogConfirmation.tpl.html', + controller: 'ClearFaultLogCtrl', + size: 'lg', + resolve: { + now: function () { + var onfDateAndTime = new Date().toISOString().replace(/-/g, '').replace(/T/g, '').replace(/:/g, '').substring(0,16) + 'Z'; + return {timestamp: onfDateAndTime}; + } + } + }); + + modalInstance.result.then(function (now) { + var spec = { + functionId : 'sdnevents', + docType : 'faultlog', + query: { + match_all: {} + } + }; + $mwtnFault.deleteDocType(spec).then(function(deleted){ + //set all to 'null' (empty) + $scope.data = []; + $scope.maxCount=0; + $scope.gridOptionsAlarmLog.totalItems=0; + + $timeout( function() { $scope.refreshLog(); getPage(); }, 1000); + + $mwtnLog.info({component: COMPONENT, message: 'Fault log cleared!'}); + }, function(error){ + $mwtnLog.error({component: COMPONENT, message:JSON.stringify(error)}); + }); + }, function () { + $mwtnLog.info({component: COMPONENT, message: 'Clear fault log dismissed!'}); + }); + }; + + + // UI events + $scope.status = {currentProblemList: true}; + $scope.spinner = {currentProblemList: false}; + $scope.$watch('status', function(status, oldValue) { + Object.keys(status).map(function(key){ + if (status[key] !== oldValue[key]) { + $scope.spinner[key] = status[key]; + + switch (key) { + case 'currentProblemList': + if (status[key]) { + $scope.refreshCurrentProblemList(); + } + break; + case 'alarmNotifications': + $scope.spinner[key] = false; + break; + case 'alarmLog': + $scope.refreshLog(); + break; + default: + $mwtnLog.error({component: COMPONENT, message: key + ' is not implemented!'}); + } + } + }); + }, true); + + // init + $scope.refreshCurrentProblemList(); + + getPage(); + + }]); + + mwtnFaultApp.register.controller('ClearFaultLogCtrl', ['$scope', '$uibModalInstance', '$mwtnFault', 'now', + function ($scope, $uibModalInstance, $mwtnFault, now) { + + $scope.now = $mwtnFault.formatTimeStamp(now.timestamp); + $scope.processing = false; + + $scope.ok = function () { + $uibModalInstance.close(now); + $scope.processing = true; + }; + + $scope.cancel = function () { + $uibModalInstance.dismiss(); + }; + }]); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.directives.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.directives.js new file mode 100644 index 00000000..ef1c3897 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.directives.js @@ -0,0 +1,163 @@ +/* + * 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/mwtnCommons/mwtnCommons.module'], function(mwtnCommonsApp) { + mwtnCommonsApp.register.directive('alarmStatus', function() { + return { + restrict : 'E', + templateUrl : 'src/app/mwtnFault/templates/alarmStatus.tpl.html', + controller : ['$scope', '$mwtnCommons', '$mwtnDatabase', '$timeout', function($scope, $mwtnCommons, $mwtnDatabase, $timeout){ + + $scope.link = '#/pnfFault/'; + + $scope.nodeCount = 0; + + $scope.alarmStatus = { + Critical:0, + Major:0, + Minor:0, + Warning:0, + }; + + $scope.getAlarmStatusSum = function(){ + var sum = 0; + Object.keys($scope.alarmStatus).map(function(severity) { + sum = sum + $scope.alarmStatus[severity]; + }); + return sum; + }; + + // Update: request the number of alarms in current alarm list per severity + var update = function() { + $mwtnCommons.getMountPoints().then(function(mountpoints) { + $scope.nodeCount = mountpoints.filter(function(mountpoint) { + return mountpoint['netconf-node-topology:connection-status'] === 'connected'; + }).length; + }); + var functionId = 'sdnevents'; + var docType = 'faultcurrent'; + var aggregations = { + "size":0, + "aggregations": { + "severity": { + "terms": { + "field": "faultCurrent.severity" + } + } + } + }; + $mwtnDatabase.getAggregations(functionId, docType, aggregations).then(function (success) { + var found = success.data.aggregations['severity'].buckets.map(function(bucket){ + $scope.alarmStatus[bucket.key] = bucket.doc_count; + return bucket.key; + }); + Object.keys($scope.alarmStatus).map(function(key){ + if (!found.contains(key)) { + $scope.alarmStatus[key] = 0; + } + }); + }, function (error) { + console.error(error); + $scope.alarmStatus = { + Critical:0, + Major:0, + Minor:0, + Warning:0, + }; + }); + + + // Object.keys($scope.alarmStatus).map(function(severity) { + // // usage of the ElasticSearch Count API + // $mwtnDatabase.getBase('sdnevents').then(function(success) { + // var databaseRequest = { + // base : success.base, + // method : 'POST', + // command: '_count', + // index: success.index, + // docType: 'faultcurrent', + // query: { + // match: { + // 'faultCurrent.severity': severity + // } + // } + // }; + // $mwtnDatabase.genericRequest(databaseRequest).then(function(success){ + // $scope.alarmStatus[severity] = success.data.count; + // }, function(error){ + // console.error('severity', severity, error); + // }); + // }, function(error) { + // console.error('severity', severity, error); + // }); + // }); + }; + update(); + + var listenToNotifications = function() { + $mwtnCommons.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); + $mwtnCommons.formatData(event).then(function(formated) { + switch (formated.notifType) { + case 'ProblemNotification': + $timeout(function(){update();}, 500); + break; + case 'AttributeValueChangedNotification': + case 'ObjectCreationNotification': + case 'ObjectDeletionNotification': + // ignore + 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' : [ "ProblemNotification" ] + }; + 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); + }); + }; + listenToNotifications(); + }] + }; + }); + +});
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.module.js new file mode 100644 index 00000000..0da8e76d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.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 mwtnFaultApp = angular.module('app.mwtnFault', ['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', 'ui.grid.infiniteScroll','ui.grid.pagination' ]); + + mwtnFaultApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnFaultApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/mwtnFault/mwtnFault.controller'); + NavHelperProvider.addToMenu('mwtnFault', { + "link" : "#/pnfFault/", + "active" : "main.mwtnFault", + "title" : "pnf Fault", + "icon" : "fa fa-bell", // Add navigation icon css class here + "page" : { + "title" : "pnf Fault", + "description" : "mwtnFault" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnFault', { + url: 'pnfFault/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnFault/mwtnFault.tpl.html', + controller: 'mwtnFaultCtrl' + } + } + }); + + }); + + return mwtnFaultApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.services.js new file mode 100644 index 00000000..f07e4d04 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.services.js @@ -0,0 +1,100 @@ +/* + * 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/mwtnFault/mwtnFault.module','app/mwtnCommons/mwtnCommons.services'],function(mwtnFaultApp) { + + mwtnFaultApp.register.factory('$mwtnFault', function($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.checkModules = $mwtnCommons.checkModules; + service.getMwtnWebSocketUrl = $mwtnCommons.getMwtnWebSocketUrl; + service.gridOptions = $mwtnCommons.gridOptions; + service.formatData = $mwtnCommons.formatData; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.deleteDocType = $mwtnDatabase.deleteDocType; + + + service.TimeStampToONFFormat=function(timestamp){ + + timestamp=timestamp.split('-').join(''); + timestamp=timestamp.split(':').join(''); + timestamp=timestamp.split(' ').join(''); + timestamp=timestamp.replace('UTC','Z'); + return timestamp; + }; + + service.getAllLogEntries = function(from, size) { + var sort = [ { + "fault.timeStamp" : { + order : 'desc' + } + }]; + var deferred = $q.defer(); + $mwtnDatabase.getAllData('sdnevents', 'faultlog', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnFault.getAllLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAllLogEntriesWithSort= function(from, size, sort){ + var deferred = $q.defer(); + $mwtnDatabase.getAllData('sdnevents', 'faultlog', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnFault.getAllLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getFilteredSortedData=function(from, size, sort,query){ + var deferred = $q.defer(); + $mwtnDatabase.getFilteredSortedData('sdnevents', 'faultlog', from, size,sort, query).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnFault.getFilteredSortedData', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + + }; + + service.getFilteredData= function(from, size, query){ + var deferred = $q.defer(); + $mwtnDatabase.getFilteredData('sdnevents', 'faultlog', from, size, query).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnFault.getFilteredData', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAllCurrentProblemEntries = function(from, size) { + var sort = [ { + "faultCurrent.timeStamp" : { + order : 'desc' + } + }]; + var deferred = $q.defer(); + $mwtnDatabase.getAllData('sdnevents', 'faultcurrent', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnFault.getAllCurrentLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.tpl.html new file mode 100644 index 00000000..dd23d262 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/mwtnFault.tpl.html @@ -0,0 +1,119 @@ +<ht-header help-link='sdnr/pnfFault/0.4.0/README.md'></ht-header> +<div class="mwtnError">{{error}}</div> + +<uib-accordion close-others="oneATime"> + +<div uib-accordion-group class="panel-primary" is-open="status.currentProblemList"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.currentProblemList, 'fa-chevron-right': !status.currentProblemList}"></i> + <span>{{'MWTN_CURRENT_PROBLEM_LIST' | translate}} + ({{gridOptionsCurrentProblemList.data.length}})</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.currentProblemList"></i> + </uib-accordion-heading> + + + <div id="mwtnFaultGridCurrentProblemList" ui-grid="gridOptionsCurrentProblemList" ui-grid-exporter + ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnFaultGrid"></div> +</div> + +<div uib-accordion-group class="panel-primary" is-open="status.alarmNotifications"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.alarmNotifications, 'fa-chevron-right': !status.alarmNotifications}"></i> + <span>{{'MWTN_ALARM_NOTIFICATIONS' | translate}} + ({{gridOptionsAlarmNotifications.data.length}} since {{date}})</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.alarmNotifications"></i> + </uib-accordion-heading> + + + <div id="mwtnFaultGridAlarmNotifications" ui-grid="gridOptionsAlarmNotifications" + ui-grid-exporter ui-grid-selection ui-grid-pinning + ui-grid-resize-columns ui-grid-move-columns class="mwtnFaultGrid"></div> +</div> + +<div uib-accordion-group class="panel-primary" is-open="status.alarmLog"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.alarmLog, 'fa-chevron-right': !status.alarmLog}"></i> + <span>{{'MWTN_ALARM_LOG' | translate}} + ({{maxCount}})</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.alarmLog"></i> + </uib-accordion-heading> + + <div id="mwtnFaultGridAlarmLog" + ui-grid="gridOptionsAlarmLog" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns class="mwtnFaultGrid"> + </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="gridOptionsAlarmLog.paginationCurrentPage" + ng-change="seekPage(gridOptionsAlarmLog.paginationCurrentPage)" + type="number" style="width:20px;"/> + <span class="dark"> / {{ gridApi.pagination.getTotalPages() }}</span> + + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsAlarmLog.paginationCurrentPage === gridApi.pagination.getTotalPages()" + ng-click="gridApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsAlarmLog.paginationCurrentPage === 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="gridOptionsAlarmLog.paginationPageSize = gridOptionsAlarmLog.paginationPageSizes[0]" + ng-model="gridOptionsAlarmLog.paginationPageSize" + ng-options="option for option in gridOptionsAlarmLog.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/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/templates/alarmStatus.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/templates/alarmStatus.tpl.html new file mode 100644 index 00000000..b57a614c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/templates/alarmStatus.tpl.html @@ -0,0 +1,21 @@ +<div class="text-right margin5 mwtn global-alarm-status"> + <a href="{{link}}" title="{{'MWTN_NODES' | translate}}"> + <span>{{ 'MWTN_NODES' | translate }}:</span> + <i class="fa fa-link cleared" aria-hidden="true"></i> + <span> {{nodeCount}} </span> + <span> || </span> + </a> + <a href="{{link}}" title="{{'MWTN_NODES' | translate}}"> + <span>{{ 'MWTN_ALARM_STATUS' | translate }}:</span> + </a> + <a href="{{link}}" ng-repeat="(key, value) in alarmStatus" title="{{key}}"> + <span ng-show="$index !== 0"> | </span> + <i class="fa fa-exclamation-triangle" ng-class="{ {{key}} : value !== 0, 'cleared': value === 0}" aria-hidden="true" ></i> + <span> {{value}} </span> + </a> + <a href="{{link}}" title="{{key}}"> + <span> | </span> + <span>{{ 'MWTN_SUM' | translate }}: </span> + <span> {{getAlarmStatusSum()}} </span> + </a> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/templates/clearLogConfirmation.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/templates/clearLogConfirmation.tpl.html new file mode 100644 index 00000000..3e58a3a4 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/mwtnFault-module/src/main/resources/mwtnFault/templates/clearLogConfirmation.tpl.html @@ -0,0 +1,17 @@ + +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{'Clear Log Confirmation' | translate}}</h3> +</div> +<div class="modal-body" id="modal-body"> + <p> + <span>All alarm log entries will be deleted.</span> + </p> + <p>Please make sure, you have exported the log entries, otherwise they will get lost.</p> +</div> +<div class="modal-footer"> + <button class="btn btn-primary" type="button" ng-click="ok()"> + <i class="pull-left fa fa-spinner fa-pulse" ng-show="processing"></i> + <span>{{'Clear log' | translate}}</span> + </button> + <button class="btn btn-warning" type="button" ng-click="cancel()">{{'Cancel' | translate}}</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/pom.xml new file mode 100644 index 00000000..64df3af1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnFault/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnFault</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnFault-module</module> + <module>mwtnFault-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-bundle/pom.xml new file mode 100644 index 00000000..ea013df3 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>mwtnInventory</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnInventory-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnInventory-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnInventory-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..1075069c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnInventory"/> + <property name="url" value="/src/app/mwtnInventory"/> + <property name="directory" value="/mwtnInventory"/> + <property name="requireJs" value="app/mwtnInventory/mwtnInventory.module"/> + <property name="angularJs" value="app.mwtnInventory"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnInventory/mwtnInventory-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/pom.xml new file mode 100644 index 00000000..5a72f5e9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-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>mwtnInventory</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnInventory-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/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipment.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipment.html new file mode 100755 index 00000000..5b0f5f65 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipment.html @@ -0,0 +1,37 @@ +<div uib-accordion-group="" class="panel-primary" template-url="src/app/mwtnInventory/templates/accordeonHeader.tpl.html" + heading="{{equipment.uuid + ' | '+ equipment.name || equipment.label }}"> + <div class="row"> + <div class="col"> + Manufacturer: <br /> <b> {{ equipment.manufacturer.id }} </b> + </div> + <div class="col"> + Serial: <br /> <b> {{ equipment.manufacturer.serial }} </b> + </div> + + <div class="col"> + Version: <br /> <b> {{ equipment.manufacturer.version }} </b> + </div> + <div class="col"> + Date: <br /> <b> {{ equipment.manufacturer.date | date }} </b> + </div> + + <div class="col"> + Description: <br /> <b> {{ equipment.manufacturer.description }} </b> + </div> + <div class="col"> + Part Type Id: <br /> <b> {{ equipment.manufacturer.partTypeIdentifier }} </b> + </div> + + <div class="col"> + Model Identifier: <br /> <b> {{ equipment.manufacturer.modelIdentifier }} </b> + </div> + <div class="col"> + Type Name: <br /> <b> {{ equipment.manufacturer.partTypeIdetypeNamentifier }} </b> + </div> + </div> + <div class="row"> + <mwtn-equipment-group equipments="equipment.children" /> + </div> + <div class="row"> + </div> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipment.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipment.ts new file mode 100755 index 00000000..0ea067c9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipment.ts @@ -0,0 +1,28 @@ +declare var angular: angular.IAngularStatic; + +import { Equipment } from '../models/equipment'; + +const mwtnInventory = angular.module('app.mwtnInventory'); + +const EquipmentDirective = () => { + return { + templateUrl: 'src/app/mwtnInventory/components/equipment.html', + controller: 'mwtnEquipmentCtrl', + controllerAs: 'vm', + scope: { + equipment: "=" + } + } +}; + +mwtnInventory.directive('mwtnEquipment', EquipmentDirective); + +export class EquipmentController { + constructor(private $scope: ng.IScope & { equipment: Equipment }) { + + } + + +} + +mwtnInventory.controller('mwtnEquipmentCtrl', ['$scope', EquipmentController]); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipmentGroup.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipmentGroup.html new file mode 100755 index 00000000..ad43bff9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipmentGroup.html @@ -0,0 +1,5 @@ +<div class="app-mwtnInventory-components-equipmentGroup"> +<uib-accordion close-others="false"> + <mwtn-equipment ng-repeat="eq in equipments" equipment="eq" /> +</uib-accordion> +</div > diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipmentGroup.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipmentGroup.ts new file mode 100755 index 00000000..ee0945d5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/components/equipmentGroup.ts @@ -0,0 +1,41 @@ +declare var angular: angular.IAngularStatic; + +import { Equipment } from '../models/equipment'; + +const mwtnInventory = angular.module('app.mwtnInventory'); + +const EquipmentGroupDirective = ($compile) => { + return { + templateUrl: 'src/app/mwtnInventory/components/equipmentGroup.html', + controller: 'mwtnEquipmentGroupCtrl', + controllerAs: 'vm', + scope: { + equipments: "=" + }, + // HACK: for angular 1.4. compatibility + compile: function (tElement, tAttr, transclude) { + var contents = tElement.contents().remove(); + var compiledContents; + return function (scope, iElement, iAttr) { + if (!compiledContents) { + compiledContents = $compile(contents, transclude); + } + compiledContents(scope, function (clone, scope) { + iElement.append(clone); + }); + }; + } + } +}; + +mwtnInventory.directive('mwtnEquipmentGroup', ['$compile', EquipmentGroupDirective]); + +export class EquipmentGroupController { + constructor(private $scope: ng.IScope & { equipments: Equipment[] }) { + //console.log("EquipmentGroupController", $scope.equipments); + + } + +} + +mwtnInventory.controller('mwtnEquipmentGroupCtrl', ['$scope', EquipmentGroupController]);
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/images/mwtnInventory.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/images/mwtnInventory.png Binary files differnew file mode 100755 index 00000000..02e626d2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/images/mwtnInventory.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/models/equipment.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/models/equipment.ts new file mode 100755 index 00000000..edc4fc5b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/models/equipment.ts @@ -0,0 +1,6 @@ +export class Equipment { + uuid: string; + name: string; + label: string; + children: Equipment[]; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory-custom.css new file mode 100644 index 00000000..2eb9261d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory-custom.css @@ -0,0 +1,31 @@ + +.app-mwtnInventory * { + box-sizing: border-box; +} + +.app-mwtnInventory .col { + height: 70px; + width: 12.5%; + float: left; + padding: 15px; +} + +.app-mwtnInventory .row::after { + content: ""; + clear: both; + display: table; +} + +@media (max-width: 1600px) { + .app-mwtnInventory .col { width: 25%; } + +} + +@media (max-width: 1200px) { + .app-mwtnInventory .col { width: 33.3%; } +} + +.app-mwtnInventory-components-equipmentGroup { + padding-left: 15px; + padding-right: 15px; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.controller.js new file mode 100644 index 00000000..fa6a85f8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.controller.js @@ -0,0 +1,372 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +define("mwtnInventory.service", ["require", "exports", "angularAMD"], function (require, exports, angular) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var mwtnInventory = angular.module('app.mwtnInventory'); + var ExtensionResult = /** @class */ (function () { + function ExtensionResult() { + } + return ExtensionResult; + }()); + var InventoryService = /** @class */ (function () { + function InventoryService($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + var _this = this; + this.$q = $q; + this.$mwtnCommons = $mwtnCommons; + this.$mwtnDatabase = $mwtnDatabase; + this.$mwtnLog = $mwtnLog; + /** + * Helperfunction to detect and convert the 'value-name-group' . + * @param propertyName Name of the object property. + * @param propertyValue Value of the object property. + * @param valueName Optional: The value-name to be used instaed of the propertyName. + * @returns A simplified property value if this is a 'value-name-group' otherwhise the propertyValue. */ + this.convertValue = function (propertyName, propertyValue, valueName) { + if (valueName === void 0) { valueName = ''; } + if (propertyValue && propertyValue instanceof Array && propertyValue.length == 1 && (valueName == null || + propertyValue[0]["value-name"] === propertyName || + propertyValue[0]["value-name"] === valueName)) { + return propertyValue[0]["value"]; + } + return propertyValue; + }; + /** + * Converts an API object to a simplified local object. + * @param apiResult The API object to convert. + * @param valueName Optional: The value-name to be used instaed of the propertyName. + * @returns The simplified local object. + */ + this.convertObject = function (apiResult, valueName) { + if (valueName === void 0) { valueName = ''; } + if (apiResult instanceof Array) { + return apiResult.map(function (elm) { return _this.convertObject(elm, valueName); }); + } + else if (apiResult instanceof Object) { + var keys = Object.keys(apiResult); + var result_1 = {}; + keys.forEach(function (key) { + var value = _this.convertValue(key, apiResult[key], valueName); + result_1[key] = (value instanceof Object || value instanceof Array) + ? _this.convertObject(value) + : value; + }); + return result_1; + } + return apiResult; + }; + } + /** Requests all active moint points */ + InventoryService.prototype.getConnectedMountpoints = function () { + return this.$mwtnCommons.getMountPoints().then(function (mountpoints) { + //console.log(mountpoints); + return mountpoints.reduce(function (acc, cur, ind, arr) { + if (cur['netconf-node-topology:connection-status'] === 'connected') + acc.push(cur["node-id"]); + return acc; + }, []); + }); + }; + /** + * Requests all 'root identifiers' for the given 'node id'. + * @param nodeId The id of the node to request the root identifiers for. + * @returns A q.Promise containing an array of all root identifiers for the requested node id. + * */ + InventoryService.prototype.getRootIdentifiers = function (nodeId) { + var _this = this; + var request = { + url: "operational/network-topology:network-topology/topology/topology-netconf/node/" + nodeId + "/yang-ext:mount/core-model:network-element/extension/top-level-equipment", + method: "GET" + }; + return this.$mwtnCommons.genericRequest(request).then(function (result) { + if (result && result.status == 200 && result.data) { + var topLevelEquipment = _this.convertObject(result.data, 'top-level-equipment'); + var rootIdentifiers = topLevelEquipment && topLevelEquipment.extension && topLevelEquipment.extension.split(','); + return rootIdentifiers && rootIdentifiers.map(function (identifier) { return identifier && identifier.trim(); }); + } + return null; + }, function (err) { return (null); }); + }; + /** + * Requests the detail information for the given combination of 'nodeId' and 'equipmentIdentifier'. + * @param nodeId The id of the root node. + * @param identifier The identifier to request the details for. + * @returns A q.Promise containing an object with all the details. + * */ + InventoryService.prototype.getEquipmentDetails = function (nodeId, identifier) { + var _this = this; + var request = { + url: "operational/network-topology:network-topology/topology/topology-netconf/node/" + nodeId + "/yang-ext:mount/core-model:equipment/" + identifier, + method: "GET" + }; + return this.$mwtnCommons.genericRequest(request).then(function (result) { + if (result && result.status == 200 && result.data) { + return _this.convertObject(result.data); + } + return null; + }, function (err) { return (null); }); + }; + /** + * Requests the conditional information for the given combination of 'nodeId' and 'equipmentIdentifier'. + * @param nodeId The id of the root node. + * @param identifier The identifier to request the conditionals for. + * @returns A q.Promise containing an object with all the conditional informations. + * */ + InventoryService.prototype.getEquipmentConditionals = function (nodeId, identifier) { + var _this = this; + var request = { + url: "operational/network-topology:network-topology/topology/topology-netconf/node/" + nodeId + "/yang-ext:mount/onf-core-model-conditional-packages:equipment-pac/" + identifier, + method: "GET" + }; + return this.$mwtnCommons.genericRequest(request).then(function (result) { + if (result && result.status == 200 && result.data) { + return _this.convertObject(result.data); + } + return {"equipment-pac":[]}; + }, function (err) { return ({"equipment-pac":[]}); }); + }; + return InventoryService; + }()); + exports.InventoryService = InventoryService; + mwtnInventory.service('mwtnInventoryService', ["$q", "$mwtnCommons", "$mwtnDatabase", "$mwtnLog", InventoryService]); +}); +define("models/equipment", ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var Equipment = /** @class */ (function () { + function Equipment() { + } + return Equipment; + }()); + exports.Equipment = Equipment; +}); +define("components/equipment", ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var mwtnInventory = angular.module('app.mwtnInventory'); + var EquipmentDirective = function () { + return { + templateUrl: 'src/app/mwtnInventory/components/equipment.html', + controller: 'mwtnEquipmentCtrl', + controllerAs: 'vm', + scope: { + equipment: "=" + } + }; + }; + mwtnInventory.directive('mwtnEquipment', EquipmentDirective); + var EquipmentController = /** @class */ (function () { + function EquipmentController($scope) { + this.$scope = $scope; + } + return EquipmentController; + }()); + exports.EquipmentController = EquipmentController; + mwtnInventory.controller('mwtnEquipmentCtrl', ['$scope', EquipmentController]); +}); +define("components/equipmentGroup", ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var mwtnInventory = angular.module('app.mwtnInventory'); + var EquipmentGroupDirective = function ($compile) { + return { + templateUrl: 'src/app/mwtnInventory/components/equipmentGroup.html', + controller: 'mwtnEquipmentGroupCtrl', + controllerAs: 'vm', + scope: { + equipments: "=" + }, + // HACK: for angular 1.4. compatibility + compile: function (tElement, tAttr, transclude) { + var contents = tElement.contents().remove(); + var compiledContents; + return function (scope, iElement, iAttr) { + if (!compiledContents) { + compiledContents = $compile(contents, transclude); + } + compiledContents(scope, function (clone, scope) { + iElement.append(clone); + }); + }; + } + }; + }; + mwtnInventory.directive('mwtnEquipmentGroup', ['$compile', EquipmentGroupDirective]); + var EquipmentGroupController = /** @class */ (function () { + function EquipmentGroupController($scope) { + //console.log("EquipmentGroupController", $scope.equipments); + this.$scope = $scope; + } + return EquipmentGroupController; + }()); + exports.EquipmentGroupController = EquipmentGroupController; + mwtnInventory.controller('mwtnEquipmentGroupCtrl', ['$scope', EquipmentGroupController]); +}); +define( ["require", "exports", "mwtnInventory.service", "components/equipment", "components/equipmentGroup"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var mwtnInventory = angular.module('app.mwtnInventory'); + var MwtnInventoryCtrl = /** @class */ (function () { + function MwtnInventoryCtrl($rootScope, $scope, $state, $timeout, mwtnInventoryService) { + var _this = this; + this.$rootScope = $rootScope; + this.$scope = $scope; + this.$state = $state; + this.$timeout = $timeout; + this.mwtnInventoryService = mwtnInventoryService; + // todo: change this + $rootScope.section_logo = 'src/app/mwtnInventory/images/mwtnInventory.png'; + $scope.loading = false; + $scope.message = "Empty"; + $scope.equipments = []; + $scope.selectedMountPoint = null; + $scope.activeMountPoints = []; + var getAllChildEquipments = function (equipmentsRootId, equimentIds) { return __awaiter(_this, void 0, void 0, function () { + var equipmentObjects, equipmentConditionals, results; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!equimentIds || !equimentIds.length) { + return [2 /*return*/, []]; + } + return [4 /*yield*/, Promise.all(equimentIds.map(function (id) { + return mwtnInventoryService.getEquipmentDetails(equipmentsRootId, id); + }))]; + case 1: + equipmentObjects = (_a.sent()).map(function (eq) { return (eq["equipment"][0]); }); + return [4 /*yield*/, Promise.all(equimentIds.map(function (id) { + return mwtnInventoryService.getEquipmentConditionals(equipmentsRootId, id); + }))]; + case 2: + equipmentConditionals = (_a.sent()).map(function (eq) { return (eq["equipment-pac"][0]); }); + return [4 /*yield*/, Promise.all(equipmentObjects.map(function (eq) { + var fruNames = (eq["contained-holder"] || []).map(function (ch) { return ch["occupying-fru"]; }).filter(function (fru) { return !!fru; }); + return getAllChildEquipments(equipmentsRootId, fruNames); + }))]; + case 3: + results = _a.sent(); + return [2 /*return*/, equipmentObjects.reduce(function (acc, cur, ind, arr) { + var conditional = equipmentConditionals[ind] || null; + // ensure EVERY property can be null or undefined + var manufacturedThing = cur['manufactured-thing']; + var equipmentType = manufacturedThing && manufacturedThing['equipment-type']; + var manufacturerProperties = manufacturedThing && manufacturedThing['manufacturer-properties']; + var equipmentInstance = manufacturedThing && manufacturedThing['equipment-instance']; + var card = { + name: cur.name, + label: cur.label, + uuid: cur.uuid, + manufacturer: { + version: equipmentType && equipmentType["version"], + description: equipmentType && equipmentType["description"], + partTypeIdentifier: equipmentType && equipmentType["part-type-identifier"], + modelIdentifier: equipmentType && equipmentType["model-identifier"], + partTypeIdetypeNamentifier: equipmentType && equipmentType["type-name"], + id: manufacturerProperties && manufacturerProperties['manufacturer-identifier'], + date: equipmentInstance && equipmentInstance['manufacture-date'] && Date.parse(equipmentInstance && equipmentInstance['manufacture-date']), + serial: equipmentInstance && equipmentInstance['serial-number'] + }, + conditional: conditional + }; + (results[ind].length ? card['children'] = results[ind] : null); + acc.push(card); + return acc; + }, [])]; + } + }); + }); }; + var pleaseSelect = "... please select a mount point"; + var refresh = function (equipmentsRootId) { return __awaiter(_this, void 0, void 0, function () { + var rootIdentifiers, equipments, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, mwtnInventoryService.getRootIdentifiers(equipmentsRootId)]; + case 1: + rootIdentifiers = _b.sent(); + _a = rootIdentifiers; + if (!_a) return [3 /*break*/, 3]; + return [4 /*yield*/, getAllChildEquipments(equipmentsRootId, rootIdentifiers)]; + case 2: + _a = (_b.sent()); + _b.label = 3; + case 3: + equipments = _a; + $timeout(function () { + $scope.equipments = equipments; + }); + return [2 /*return*/]; + } + }); + }); }; + mwtnInventoryService.getConnectedMountpoints().then(function (res) { + $scope.activeMountPoints = [pleaseSelect].concat(res); + $scope.selectedMountPoint = $scope.selectedMountPoint || pleaseSelect; + }); + $scope.$watch(function () { return ($state.params.nodeId); }, function (newVal, oldVal) { + $scope.selectedMountPoint = newVal; + }); + $scope.$watch("selectedMountPoint", function (newVal, oldVal) { return __awaiter(_this, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!newVal || newVal === pleaseSelect) { + $scope.equipments = []; + return [2 /*return*/]; + } + if ($scope.activeMountPoints[0] === pleaseSelect) { + _a = $scope.activeMountPoints, $scope.activeMountPoints = _a.slice(1); + } + $scope.loading = true; + if ($state.params.nodeId !== newVal) { + $state.go('main.mwtnInventory', { nodeId: newVal }, { notify: false }); + } + return [4 /*yield*/, refresh(newVal).catch(function (err) { + $timeout(function () { $scope.equipments = null; }); + })]; + case 1: + _b.sent(); + $timeout(function () { $scope.loading = false; }); + return [2 /*return*/]; + } + }); + }); }); + } + return MwtnInventoryCtrl; + }()); + mwtnInventory.controller('mwtnInventoryCtrl', ['$rootScope', '$scope', '$state', '$timeout', 'mwtnInventoryService', MwtnInventoryCtrl]); +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXd0bkludmVudG9yeS5jb250cm9sbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2FwcC9td3RuSW52ZW50b3J5L213dG5JbnZlbnRvcnkuc2VydmljZS50cyIsInNyYy9hcHAvbXd0bkludmVudG9yeS9tb2RlbHMvZXF1aXBtZW50LnRzIiwic3JjL2FwcC9td3RuSW52ZW50b3J5L2NvbXBvbmVudHMvZXF1aXBtZW50LnRzIiwic3JjL2FwcC9td3RuSW52ZW50b3J5L2NvbXBvbmVudHMvZXF1aXBtZW50R3JvdXAudHMiLCJzcmMvYXBwL213dG5JbnZlbnRvcnkvbXd0bkludmVudG9yeS5jb250cm9sbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBRUEsSUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBRTFEO1FBQUE7UUFJQSxDQUFDO1FBQUQsc0JBQUM7SUFBRCxDQUFDLEFBSkQsSUFJQztJQW1CRDtRQUNFLDBCQUFvQixFQUFnQixFQUFVLFlBQTJCLEVBQVUsYUFBYSxFQUFVLFFBQVE7WUFBbEgsaUJBRUM7WUFGbUIsT0FBRSxHQUFGLEVBQUUsQ0FBYztZQUFVLGlCQUFZLEdBQVosWUFBWSxDQUFlO1lBQVUsa0JBQWEsR0FBYixhQUFhLENBQUE7WUFBVSxhQUFRLEdBQVIsUUFBUSxDQUFBO1lBSWxIOzs7OztvSEFLd0c7WUFDaEcsaUJBQVksR0FBRyxVQUFDLFlBQW9CLEVBQUUsYUFBa0IsRUFBRSxTQUFzQjtnQkFBdEIsMEJBQUEsRUFBQSxjQUFzQjtnQkFDdEYsRUFBRSxDQUFDLENBQUMsYUFBYSxJQUFJLGFBQWEsWUFBWSxLQUFLLElBQUksYUFBYSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FDbEYsU0FBUyxJQUFJLElBQUk7b0JBQ2pCLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsS0FBSyxZQUFZO29CQUMvQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLEtBQUssU0FBUyxDQUM5QyxDQUFDLENBQUMsQ0FBQztvQkFDRCxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNuQyxDQUFDO2dCQUNELE1BQU0sQ0FBQyxhQUFhLENBQUM7WUFDdkIsQ0FBQyxDQUFBO1lBRUQ7Ozs7O2NBS0U7WUFDTSxrQkFBYSxHQUFHLFVBQUMsU0FBYyxFQUFFLFNBQXNCO2dCQUF0QiwwQkFBQSxFQUFBLGNBQXNCO2dCQUM3RCxFQUFFLENBQUMsQ0FBQyxTQUFTLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDL0IsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsVUFBQSxHQUFHLElBQU0sTUFBTSxDQUFDLEtBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzlFLENBQUM7Z0JBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsWUFBWSxNQUFNLENBQUMsQ0FBQyxDQUFDO29CQUN2QyxJQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUNwQyxJQUFJLFFBQU0sR0FBRyxFQUFFLENBQUM7b0JBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBQSxHQUFHO3dCQUNkLElBQU0sS0FBSyxHQUFHLEtBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQzt3QkFDaEUsUUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxZQUFZLE1BQU0sSUFBSSxLQUFLLFlBQVksS0FBSyxDQUFDOzRCQUMvRCxDQUFDLENBQUMsS0FBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUM7NEJBQzNCLENBQUMsQ0FBQyxLQUFLLENBQUM7b0JBQ1osQ0FBQyxDQUFDLENBQUM7b0JBQ0gsTUFBTSxDQUFDLFFBQU0sQ0FBQztnQkFDaEIsQ0FBQztnQkFDRCxNQUFNLENBQUMsU0FBUyxDQUFDO1lBQ25CLENBQUMsQ0FBQTtRQXhDRCxDQUFDO1FBMENELHVDQUF1QztRQUNoQyxrREFBdUIsR0FBOUI7WUFDRSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQU0sQ0FBQyxJQUFJLENBQUMsVUFBQyxXQUFpQjtnQkFDbkUsMkJBQTJCO2dCQUMzQixNQUFNLENBQVcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFDLEdBQWEsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUc7b0JBQy9ELEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyx5Q0FBeUMsQ0FBQyxLQUFLLFdBQVcsQ0FBQzt3QkFBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO29CQUM3RixNQUFNLENBQUMsR0FBRyxDQUFDO2dCQUNiLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNULENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVEOzs7O2FBSUs7UUFDRSw2Q0FBa0IsR0FBekIsVUFBMEIsTUFBYztZQUF4QyxpQkFlQztZQWJDLElBQU0sT0FBTyxHQUFzQjtnQkFDakMsR0FBRyxFQUFFLGtGQUFnRixNQUFNLDZFQUEwRTtnQkFDckssTUFBTSxFQUFFLEtBQUs7YUFDZCxDQUFDO1lBRUYsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFrQixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQyxNQUFNO2dCQUM1RSxFQUFFLENBQUMsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7b0JBQ2xELElBQU0saUJBQWlCLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUM7b0JBQ2pGLElBQU0sZUFBZSxHQUFHLGlCQUFpQixJQUFJLGlCQUFpQixDQUFDLFNBQVMsSUFBSSxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNuSCxNQUFNLENBQUMsZUFBZSxJQUFJLGVBQWUsQ0FBQyxHQUFHLENBQUMsVUFBQSxVQUFVLElBQUksT0FBQSxVQUFVLElBQUksVUFBVSxDQUFDLElBQUksRUFBRSxFQUEvQixDQUErQixDQUFDLENBQUM7Z0JBQy9GLENBQUM7Z0JBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQztZQUNkLENBQUMsRUFBRSxVQUFBLEdBQUcsSUFBSSxPQUFBLENBQUMsSUFBSSxDQUFDLEVBQU4sQ0FBTSxDQUFDLENBQUM7UUFDcEIsQ0FBQztRQUVEOzs7OzthQUtLO1FBQ0UsOENBQW1CLEdBQTFCLFVBQTJCLE1BQWMsRUFBRSxVQUFrQjtZQUE3RCxpQkFXQztZQVZDLElBQU0sT0FBTyxHQUFzQjtnQkFDakMsR0FBRyxFQUFFLGtGQUFnRixNQUFNLDZDQUF3QyxVQUFZO2dCQUMvSSxNQUFNLEVBQUUsS0FBSzthQUNkLENBQUM7WUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQWtCLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFDLE1BQU07Z0JBQzVFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztvQkFDbEQsTUFBTSxDQUFDLEtBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN6QyxDQUFDO2dCQUNELE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDZCxDQUFDLEVBQUUsVUFBQSxHQUFHLElBQUksT0FBQSxDQUFDLElBQUksQ0FBQyxFQUFOLENBQU0sQ0FBQyxDQUFDO1FBQ3BCLENBQUM7UUFFRDs7Ozs7YUFLSztRQUNFLG1EQUF3QixHQUEvQixVQUFnQyxNQUFjLEVBQUUsVUFBa0I7WUFBbEUsaUJBV0M7WUFWQyxJQUFNLE9BQU8sR0FBc0I7Z0JBQ2pDLEdBQUcsRUFBRSxrRkFBZ0YsTUFBTSwwRUFBcUUsVUFBWTtnQkFDNUssTUFBTSxFQUFFLEtBQUs7YUFDZCxDQUFDO1lBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFrQixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQyxNQUFNO2dCQUM1RSxFQUFFLENBQUMsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7b0JBQ2xELE1BQU0sQ0FBQyxLQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDekMsQ0FBQztnQkFDRCxNQUFNLENBQUMsSUFBSSxDQUFDO1lBQ2QsQ0FBQyxFQUFFLFVBQUEsR0FBRyxJQUFJLE9BQUEsQ0FBQyxJQUFJLENBQUMsRUFBTixDQUFNLENBQUMsQ0FBQztRQUNwQixDQUFDO1FBQ0gsdUJBQUM7SUFBRCxDQUFDLEFBbkhELElBbUhDO0lBbkhZLDRDQUFnQjtJQW9IN0IsYUFBYSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7Ozs7O0lDL0lySDtRQUFBO1FBS0EsQ0FBQztRQUFELGdCQUFDO0lBQUQsQ0FBQyxBQUxELElBS0M7SUFMWSw4QkFBUzs7Ozs7SUNJdEIsSUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBRTFELElBQU0sa0JBQWtCLEdBQUc7UUFDekIsTUFBTSxDQUFDO1lBQ0wsV0FBVyxFQUFFLGlEQUFpRDtZQUM5RCxVQUFVLEVBQUUsbUJBQW1CO1lBQy9CLFlBQVksRUFBRSxJQUFJO1lBQ2xCLEtBQUssRUFBRTtnQkFDTCxTQUFTLEVBQUUsR0FBRzthQUNmO1NBQ0YsQ0FBQTtJQUNILENBQUMsQ0FBQztJQUVGLGFBQWEsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLGtCQUFrQixDQUFDLENBQUM7SUFFN0Q7UUFDRSw2QkFBb0IsTUFBNEM7WUFBNUMsV0FBTSxHQUFOLE1BQU0sQ0FBc0M7UUFFaEUsQ0FBQztRQUdILDBCQUFDO0lBQUQsQ0FBQyxBQU5ELElBTUM7SUFOWSxrREFBbUI7SUFRaEMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7Ozs7O0lDdkIvRSxJQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFMUQsSUFBTSx1QkFBdUIsR0FBRyxVQUFDLFFBQVE7UUFDdkMsTUFBTSxDQUFDO1lBQ0wsV0FBVyxFQUFFLHNEQUFzRDtZQUNuRSxVQUFVLEVBQUUsd0JBQXdCO1lBQ3BDLFlBQVksRUFBRSxJQUFJO1lBQ2xCLEtBQUssRUFBRTtnQkFDTCxVQUFVLEVBQUUsR0FBRzthQUNoQjtZQUNELHVDQUF1QztZQUN2QyxPQUFPLEVBQUUsVUFBVSxRQUFRLEVBQUUsS0FBSyxFQUFFLFVBQVU7Z0JBQzVDLElBQUksUUFBUSxHQUFHLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxnQkFBZ0IsQ0FBQztnQkFDckIsTUFBTSxDQUFDLFVBQVUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLO29CQUNyQyxFQUFFLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQzt3QkFDdEIsZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztvQkFDcEQsQ0FBQztvQkFDRCxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsVUFBVSxLQUFLLEVBQUUsS0FBSzt3QkFDNUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDekIsQ0FBQyxDQUFDLENBQUM7Z0JBQ0wsQ0FBQyxDQUFDO1lBQ0osQ0FBQztTQUNGLENBQUE7SUFDSCxDQUFDLENBQUM7SUFFRixhQUFhLENBQUMsU0FBUyxDQUFDLG9CQUFvQixFQUFFLENBQUMsVUFBVSxFQUFFLHVCQUF1QixDQUFDLENBQUMsQ0FBQztJQUVyRjtRQUNFLGtDQUFvQixNQUErQztZQUNqRSw2REFBNkQ7WUFEM0MsV0FBTSxHQUFOLE1BQU0sQ0FBeUM7UUFHbkUsQ0FBQztRQUVILCtCQUFDO0lBQUQsQ0FBQyxBQU5ELElBTUM7SUFOWSw0REFBd0I7SUFRckMsYUFBYSxDQUFDLFVBQVUsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLFFBQVEsRUFBRSx3QkFBd0IsQ0FBQyxDQUFDLENBQUM7Ozs7O0lDakN6RixJQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFVMUQ7UUFDRSwyQkFBb0IsVUFBVSxFQUFVLE1BQTJCLEVBQVUsTUFBTSxFQUFVLFFBQVEsRUFBVSxvQkFBc0M7WUFBckosaUJBOEZDO1lBOUZtQixlQUFVLEdBQVYsVUFBVSxDQUFBO1lBQVUsV0FBTSxHQUFOLE1BQU0sQ0FBcUI7WUFBVSxXQUFNLEdBQU4sTUFBTSxDQUFBO1lBQVUsYUFBUSxHQUFSLFFBQVEsQ0FBQTtZQUFVLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBa0I7WUFDbkosb0JBQW9CO1lBQ3BCLFVBQVUsQ0FBQyxZQUFZLEdBQUcsZ0RBQWdELENBQUM7WUFFM0UsTUFBTSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDdkIsTUFBTSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7WUFDekIsTUFBTSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7WUFDdkIsTUFBTSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztZQUVqQyxNQUFNLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1lBRTlCLElBQU0scUJBQXFCLEdBQUcsVUFBTyxnQkFBd0IsRUFBRSxXQUFxQjs7Ozs7NEJBQ2xGLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0NBQ3hDLE1BQU0sZ0JBQUMsRUFBRSxFQUFDOzRCQUNaLENBQUM7NEJBQ3lCLHFCQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxVQUFBLEVBQUU7b0NBQzVELE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxtQkFBbUIsQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQztnQ0FDeEUsQ0FBQyxDQUFDLENBQUMsRUFBQTs7NEJBRkcsZ0JBQWdCLEdBQUcsQ0FBQyxTQUV2QixDQUFDLENBQUMsR0FBRyxDQUFDLFVBQUEsRUFBRSxJQUFJLE9BQUEsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBcEIsQ0FBb0IsQ0FBQzs0QkFFTCxxQkFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsVUFBQSxFQUFFO29DQUNqRSxNQUFNLENBQUMsb0JBQW9CLENBQUMsd0JBQXdCLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0NBQzdFLENBQUMsQ0FBQyxDQUFDLEVBQUE7OzRCQUZHLHFCQUFxQixHQUFHLENBQUMsU0FFNUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFBLEVBQUUsSUFBSSxPQUFBLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQXhCLENBQXdCLENBQUM7NEJBRTFCLHFCQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFVBQUEsRUFBRTtvQ0FDckQsSUFBSSxRQUFRLEdBQWEsQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsVUFBQSxFQUFFLElBQUksT0FBQSxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQW5CLENBQW1CLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBQSxHQUFHLElBQUksT0FBQSxDQUFDLENBQUMsR0FBRyxFQUFMLENBQUssQ0FBQyxDQUFDO29DQUM1RyxNQUFNLENBQUMscUJBQXFCLENBQUMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0NBQzNELENBQUMsQ0FBQyxDQUFDLEVBQUE7OzRCQUhDLE9BQU8sR0FBRyxTQUdYOzRCQUVILHNCQUFPLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxVQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUc7b0NBQ2hELElBQUksV0FBVyxHQUFHLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQztvQ0FDckQsa0RBQWtEO29DQUNsRCxJQUFJLGlCQUFpQixHQUFHLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO29DQUNsRCxJQUFJLGFBQWEsR0FBRyxpQkFBaUIsSUFBSSxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO29DQUM3RSxJQUFJLHNCQUFzQixHQUFHLGlCQUFpQixJQUFJLGlCQUFpQixDQUFDLHlCQUF5QixDQUFDLENBQUM7b0NBQy9GLElBQUksaUJBQWlCLEdBQUcsaUJBQWlCLElBQUksaUJBQWlCLENBQUMsb0JBQW9CLENBQUMsQ0FBQztvQ0FFckYsSUFBSSxJQUFJLEdBQUc7d0NBQ1QsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO3dDQUNkLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSzt3Q0FDaEIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO3dDQUNkLFlBQVksRUFBRTs0Q0FDWixPQUFPLEVBQUUsYUFBYSxJQUFJLGFBQWEsQ0FBQyxTQUFTLENBQUM7NENBQ2xELFdBQVcsRUFBRSxhQUFhLElBQUksYUFBYSxDQUFDLGFBQWEsQ0FBQzs0Q0FDMUQsa0JBQWtCLEVBQUUsYUFBYSxJQUFJLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQzs0Q0FDMUUsZUFBZSxFQUFFLGFBQWEsSUFBSSxhQUFhLENBQUMsa0JBQWtCLENBQUM7NENBQ25FLDBCQUEwQixFQUFFLGFBQWEsSUFBSSxhQUFhLENBQUMsV0FBVyxDQUFDOzRDQUN2RSxFQUFFLEVBQUUsc0JBQXNCLElBQUksc0JBQXNCLENBQUMseUJBQXlCLENBQUM7NENBQy9FLElBQUksRUFBRSxpQkFBaUIsSUFBSSxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLElBQUksaUJBQWlCLENBQUMsa0JBQWtCLENBQUMsQ0FBQzs0Q0FDMUksTUFBTSxFQUFFLGlCQUFpQixJQUFJLGlCQUFpQixDQUFDLGVBQWUsQ0FBQzt5Q0FDaEU7d0NBQ0QsV0FBVyxFQUFFLFdBQVc7cUNBQ3pCLENBQUM7b0NBQ0YsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQ0FDL0QsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztvQ0FDZixNQUFNLENBQUMsR0FBRyxDQUFDO2dDQUNiLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBQzs7O2lCQUNSLENBQUE7WUFFRCxJQUFNLFlBQVksR0FBRyw2QkFBNkIsQ0FBQztZQUVuRCxJQUFNLE9BQU8sR0FBRyxVQUFPLGdCQUF3Qjs7OztnQ0FDdkIscUJBQU0sb0JBQW9CLENBQUMsa0JBQWtCLENBQUMsZ0JBQWdCLENBQUMsRUFBQTs7NEJBQWpGLGVBQWUsR0FBRyxTQUErRDs0QkFDcEUsS0FBQSxlQUFlLENBQUE7cUNBQWYsd0JBQWU7NEJBQUkscUJBQU0scUJBQXFCLENBQUMsZ0JBQWdCLEVBQUUsZUFBZSxDQUFDLEVBQUE7O2tDQUE5RCxTQUE4RDs7OzRCQUE5RixVQUFVLEtBQW9GOzRCQUNsRyxRQUFRLENBQUM7Z0NBQ1AsTUFBTSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7NEJBQ2pDLENBQUMsQ0FBQyxDQUFDOzs7O2lCQUNKLENBQUM7WUFFRixvQkFBb0IsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFBLEdBQUc7Z0JBQ3JELE1BQU0sQ0FBQyxpQkFBaUIsSUFBSSxZQUFZLFNBQUssR0FBRyxDQUFDLENBQUU7Z0JBQ25ELE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxNQUFNLENBQUMsa0JBQWtCLElBQUksWUFBWSxDQUFDO1lBQ3hFLENBQUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFNLE9BQUEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUF0QixDQUFzQixFQUFFLFVBQUMsTUFBYyxFQUFFLE1BQWM7Z0JBQ3pFLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxNQUFNLENBQUM7WUFDckMsQ0FBQyxDQUFDLENBQUM7WUFFSCxNQUFNLENBQUMsTUFBTSxDQUFDLG9CQUFvQixFQUFFLFVBQU8sTUFBYyxFQUFFLE1BQWM7Ozs7OzRCQUN2RSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxNQUFNLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQztnQ0FDdkMsTUFBTSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7Z0NBQ3ZCLE1BQU0sZ0JBQUM7NEJBQ1QsQ0FBQzs0QkFDRCxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQztnQ0FDakQsNkJBQTBELEVBQXZELHNDQUEyQixDQUE2Qjs0QkFDN0QsQ0FBQzs0QkFDRCxNQUFNLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQzs0QkFDdEIsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQztnQ0FDcEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDOzRCQUN6RSxDQUFDOzRCQUNELHFCQUFNLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQSxHQUFHO29DQUM3QixRQUFRLENBQUMsY0FBUSxNQUFNLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dDQUNoRCxDQUFDLENBQUMsRUFBQTs7NEJBRkYsU0FFRSxDQUFDOzRCQUNILFFBQVEsQ0FBQyxjQUFRLE1BQU0sQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Ozs7aUJBQzdDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDSCx3QkFBQztJQUFELENBQUMsQUFoR0QsSUFnR0M7SUFFRCxhQUFhLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLHNCQUFzQixFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFuZ3VsYXIgZnJvbSAnYW5ndWxhckFNRCc7XG5cbmNvbnN0IG13dG5JbnZlbnRvcnkgPSBhbmd1bGFyLm1vZHVsZSgnYXBwLm13dG5JbnZlbnRvcnknKTtcblxuY2xhc3MgRXh0ZW5zaW9uUmVzdWx0IHtcbiAgcHVibGljIGV4dGVuc2lvbjogW1xuICAgIHsgXCJ2YWx1ZS1uYW1lXCI6IHN0cmluZywgXCJ2YWx1ZVwiOiBzdHJpbmcgfVxuICBdXG59XG5cbmludGVyZmFjZSBHZW5lcmljR2V0UmVxdWVzdCB7XG4gIHVybDogc3RyaW5nO1xuICBtZXRob2Q6IFwiR0VUXCI7XG59XG5cbmludGVyZmFjZSBHZW5lcmljUG9zdFJlcXVlc3Q8VD4ge1xuICB1cmw6IHN0cmluZztcbiAgbWV0aG9kOiBcIlBPU1RcIjtcbiAgZGF0YTogVFxufVxuXG5pbnRlcmZhY2UgQ29tbW9uU2VydmljZSB7XG4gIGdlbmVyaWNSZXF1ZXN0PFRSZXN1bHQ+KHJlcXVlc3Q6IEdlbmVyaWNHZXRSZXF1ZXN0KTogbmcuSVByb21pc2U8bmcuSUh0dHBSZXNwb25zZTxUUmVzdWx0Pj47XG4gIGdlbmVyaWNSZXF1ZXN0PFRSZXF1ZXN0LCBUUmVzdWx0PihyZXF1ZXN0OiBHZW5lcmljUG9zdFJlcXVlc3Q8VFJlcXVlc3Q+KTogbmcuSVByb21pc2U8bmcuSUh0dHBSZXNwb25zZTxUUmVzdWx0Pj47XG4gIGdldE1vdW50UG9pbnRzPFRSZXN1bHQ+KCk6IG5nLklQcm9taXNlPFRSZXN1bHQ+O1xufVxuXG5leHBvcnQgY2xhc3MgSW52ZW50b3J5U2VydmljZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgJHE6IG5nLklRU2VydmljZSwgcHJpdmF0ZSAkbXd0bkNvbW1vbnM6IENvbW1vblNlcnZpY2UsIHByaXZhdGUgJG13dG5EYXRhYmFzZSwgcHJpdmF0ZSAkbXd0bkxvZykge1xuXG4gIH1cblxuICAvKiogXG4gICAqIEhlbHBlcmZ1bmN0aW9uIHRvIGRldGVjdCBhbmQgY29udmVydCB0aGUgJ3ZhbHVlLW5hbWUtZ3JvdXAnIC5cbiAgICogQHBhcmFtIHByb3BlcnR5TmFtZSBOYW1lIG9mIHRoZSBvYmplY3QgcHJvcGVydHkuXG4gICAqIEBwYXJhbSBwcm9wZXJ0eVZhbHVlIFZhbHVlIG9mIHRoZSBvYmplY3QgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB2YWx1ZU5hbWUgT3B0aW9uYWw6IFRoZSB2YWx1ZS1uYW1lIHRvIGJlIHVzZWQgaW5zdGFlZCBvZiB0aGUgcHJvcGVydHlOYW1lLlxuICAgKiBAcmV0dXJucyBBIHNpbXBsaWZpZWQgcHJvcGVydHkgdmFsdWUgaWYgdGhpcyBpcyBhICd2YWx1ZS1uYW1lLWdyb3VwJyBvdGhlcndoaXNlIHRoZSBwcm9wZXJ0eVZhbHVlLiAqL1xuICBwcml2YXRlIGNvbnZlcnRWYWx1ZSA9IChwcm9wZXJ0eU5hbWU6IHN0cmluZywgcHJvcGVydHlWYWx1ZTogYW55LCB2YWx1ZU5hbWU6IHN0cmluZyA9ICcnKTogYW55ID0+IHtcbiAgICBpZiAocHJvcGVydHlWYWx1ZSAmJiBwcm9wZXJ0eVZhbHVlIGluc3RhbmNlb2YgQXJyYXkgJiYgcHJvcGVydHlWYWx1ZS5sZW5ndGggPT0gMSAmJiAoXG4gICAgICB2YWx1ZU5hbWUgPT0gbnVsbCB8fFxuICAgICAgcHJvcGVydHlWYWx1ZVswXVtcInZhbHVlLW5hbWVcIl0gPT09IHByb3BlcnR5TmFtZSB8fFxuICAgICAgcHJvcGVydHlWYWx1ZVswXVtcInZhbHVlLW5hbWVcIl0gPT09IHZhbHVlTmFtZSlcbiAgICApIHtcbiAgICAgIHJldHVybiBwcm9wZXJ0eVZhbHVlWzBdW1widmFsdWVcIl07XG4gICAgfVxuICAgIHJldHVybiBwcm9wZXJ0eVZhbHVlO1xuICB9XG5cbiAgLyoqIFxuICAgKiAgQ29udmVydHMgYW4gQVBJIG9iamVjdCB0byBhIHNpbXBsaWZpZWQgbG9jYWwgb2JqZWN0LlxuICAgKiAgQHBhcmFtIGFwaVJlc3VsdCBUaGUgQVBJIG9iamVjdCB0byBjb252ZXJ0LlxuICAgKiAgQHBhcmFtIHZhbHVlTmFtZSBPcHRpb25hbDogVGhlIHZhbHVlLW5hbWUgdG8gYmUgdXNlZCBpbnN0YWVkIG9mIHRoZSBwcm9wZXJ0eU5hbWUuXG4gICAqICBAcmV0dXJucyBUaGUgc2ltcGxpZmllZCBsb2NhbCBvYmplY3QuXG4gICovXG4gIHByaXZhdGUgY29udmVydE9iamVjdCA9IChhcGlSZXN1bHQ6IGFueSwgdmFsdWVOYW1lOiBzdHJpbmcgPSAnJyk6IGFueSA9PiB7XG4gICAgaWYgKGFwaVJlc3VsdCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICByZXR1cm4gYXBpUmVzdWx0Lm1hcChlbG0gPT4geyByZXR1cm4gdGhpcy5jb252ZXJ0T2JqZWN0KGVsbSwgdmFsdWVOYW1lKTsgfSk7XG4gICAgfSBlbHNlIGlmIChhcGlSZXN1bHQgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhcGlSZXN1bHQpO1xuICAgICAgbGV0IHJlc3VsdCA9IHt9O1xuICAgICAga2V5cy5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5jb252ZXJ0VmFsdWUoa2V5LCBhcGlSZXN1bHRba2V5XSwgdmFsdWVOYW1lKTtcbiAgICAgICAgcmVzdWx0W2tleV0gPSAodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QgfHwgdmFsdWUgaW5zdGFuY2VvZiBBcnJheSlcbiAgICAgICAgICA/IHRoaXMuY29udmVydE9iamVjdCh2YWx1ZSlcbiAgICAgICAgICA6IHZhbHVlO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gYXBpUmVzdWx0O1xuICB9XG5cbiAgLyoqIFJlcXVlc3RzIGFsbCBhY3RpdmUgbW9pbnQgcG9pbnRzICovXG4gIHB1YmxpYyBnZXRDb25uZWN0ZWRNb3VudHBvaW50cygpOiBuZy5JUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIHJldHVybiB0aGlzLiRtd3RuQ29tbW9ucy5nZXRNb3VudFBvaW50czx7fT4oKS50aGVuKChtb3VudHBvaW50czoge31bXSkgPT4ge1xuICAgICAgLy9jb25zb2xlLmxvZyhtb3VudHBvaW50cyk7XG4gICAgICByZXR1cm4gPHN0cmluZ1tdPm1vdW50cG9pbnRzLnJlZHVjZSgoYWNjOiBzdHJpbmdbXSwgY3VyLCBpbmQsIGFycikgPT4ge1xuICAgICAgICBpZiAoY3VyWyduZXRjb25mLW5vZGUtdG9wb2xvZ3k6Y29ubmVjdGlvbi1zdGF0dXMnXSA9PT0gJ2Nvbm5lY3RlZCcpIGFjYy5wdXNoKGN1cltcIm5vZGUtaWRcIl0pO1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwgW10pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIFxuICAgKiBSZXF1ZXN0cyBhbGwgJ3Jvb3QgaWRlbnRpZmllcnMnIGZvciB0aGUgZ2l2ZW4gJ25vZGUgaWQnLlxuICAgKiBAcGFyYW0gbm9kZUlkIFRoZSBpZCBvZiB0aGUgbm9kZSB0byByZXF1ZXN0IHRoZSByb290IGlkZW50aWZpZXJzIGZvci5cbiAgICogQHJldHVybnMgQSBxLlByb21pc2UgY29udGFpbmluZyBhbiBhcnJheSBvZiBhbGwgcm9vdCBpZGVudGlmaWVycyBmb3IgdGhlIHJlcXVlc3RlZCBub2RlIGlkLlxuICAgKiAqL1xuICBwdWJsaWMgZ2V0Um9vdElkZW50aWZpZXJzKG5vZGVJZDogc3RyaW5nKTogbmcuSVByb21pc2U8c3RyaW5nW10+IHtcblxuICAgIGNvbnN0IHJlcXVlc3Q6IEdlbmVyaWNHZXRSZXF1ZXN0ID0ge1xuICAgICAgdXJsOiBgb3BlcmF0aW9uYWwvbmV0d29yay10b3BvbG9neTpuZXR3b3JrLXRvcG9sb2d5L3RvcG9sb2d5L3RvcG9sb2d5LW5ldGNvbmYvbm9kZS8ke25vZGVJZH0veWFuZy1leHQ6bW91bnQvY29yZS1tb2RlbDpuZXR3b3JrLWVsZW1lbnQvZXh0ZW5zaW9uL3RvcC1sZXZlbC1lcXVpcG1lbnRgLFxuICAgICAgbWV0aG9kOiBcIkdFVFwiXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLiRtd3RuQ29tbW9ucy5nZW5lcmljUmVxdWVzdDxFeHRlbnNpb25SZXN1bHQ+KHJlcXVlc3QpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgaWYgKHJlc3VsdCAmJiByZXN1bHQuc3RhdHVzID09IDIwMCAmJiByZXN1bHQuZGF0YSkge1xuICAgICAgICBjb25zdCB0b3BMZXZlbEVxdWlwbWVudCA9IHRoaXMuY29udmVydE9iamVjdChyZXN1bHQuZGF0YSwgJ3RvcC1sZXZlbC1lcXVpcG1lbnQnKTtcbiAgICAgICAgY29uc3Qgcm9vdElkZW50aWZpZXJzID0gdG9wTGV2ZWxFcXVpcG1lbnQgJiYgdG9wTGV2ZWxFcXVpcG1lbnQuZXh0ZW5zaW9uICYmIHRvcExldmVsRXF1aXBtZW50LmV4dGVuc2lvbi5zcGxpdCgnLCcpO1xuICAgICAgICByZXR1cm4gcm9vdElkZW50aWZpZXJzICYmIHJvb3RJZGVudGlmaWVycy5tYXAoaWRlbnRpZmllciA9PiBpZGVudGlmaWVyICYmIGlkZW50aWZpZXIudHJpbSgpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0sIGVyciA9PiAobnVsbCkpO1xuICB9XG5cbiAgLyoqIFxuICAgKiBSZXF1ZXN0cyB0aGUgZGV0YWlsIGluZm9ybWF0aW9uIGZvciB0aGUgZ2l2ZW4gY29tYmluYXRpb24gb2YgJ25vZGVJZCcgYW5kICdlcXVpcG1lbnRJZGVudGlmaWVyJy5cbiAgICogQHBhcmFtIG5vZGVJZCBUaGUgaWQgb2YgdGhlIHJvb3Qgbm9kZS5cbiAgICogQHBhcmFtIGlkZW50aWZpZXIgVGhlIGlkZW50aWZpZXIgdG8gcmVxdWVzdCB0aGUgZGV0YWlscyBmb3IuXG4gICAqIEByZXR1cm5zIEEgcS5Qcm9taXNlIGNvbnRhaW5pbmcgYW4gb2JqZWN0IHdpdGggYWxsIHRoZSBkZXRhaWxzLlxuICAgKiAqL1xuICBwdWJsaWMgZ2V0RXF1aXBtZW50RGV0YWlscyhub2RlSWQ6IHN0cmluZywgaWRlbnRpZmllcjogc3RyaW5nKTogbmcuSVByb21pc2U8e30+IHtcbiAgICBjb25zdCByZXF1ZXN0OiBHZW5lcmljR2V0UmVxdWVzdCA9IHtcbiAgICAgIHVybDogYG9wZXJhdGlvbmFsL25ldHdvcmstdG9wb2xvZ3k6bmV0d29yay10b3BvbG9neS90b3BvbG9neS90b3BvbG9neS1uZXRjb25mL25vZGUvJHtub2RlSWR9L3lhbmctZXh0Om1vdW50L2NvcmUtbW9kZWw6ZXF1aXBtZW50LyR7aWRlbnRpZmllcn1gLFxuICAgICAgbWV0aG9kOiBcIkdFVFwiXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy4kbXd0bkNvbW1vbnMuZ2VuZXJpY1JlcXVlc3Q8RXh0ZW5zaW9uUmVzdWx0PihyZXF1ZXN0KS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0LnN0YXR1cyA9PSAyMDAgJiYgcmVzdWx0LmRhdGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udmVydE9iamVjdChyZXN1bHQuZGF0YSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9LCBlcnIgPT4gKG51bGwpKTtcbiAgfVxuXG4gIC8qKiBcbiAgICogUmVxdWVzdHMgdGhlIGNvbmRpdGlvbmFsIGluZm9ybWF0aW9uIGZvciB0aGUgZ2l2ZW4gY29tYmluYXRpb24gb2YgJ25vZGVJZCcgYW5kICdlcXVpcG1lbnRJZGVudGlmaWVyJy5cbiAgICogQHBhcmFtIG5vZGVJZCBUaGUgaWQgb2YgdGhlIHJvb3Qgbm9kZS5cbiAgICogQHBhcmFtIGlkZW50aWZpZXIgVGhlIGlkZW50aWZpZXIgdG8gcmVxdWVzdCB0aGUgY29uZGl0aW9uYWxzIGZvci5cbiAgICogQHJldHVybnMgQSBxLlByb21pc2UgY29udGFpbmluZyBhbiBvYmplY3Qgd2l0aCBhbGwgdGhlIGNvbmRpdGlvbmFsIGluZm9ybWF0aW9ucy5cbiAgICogKi9cbiAgcHVibGljIGdldEVxdWlwbWVudENvbmRpdGlvbmFscyhub2RlSWQ6IHN0cmluZywgaWRlbnRpZmllcjogc3RyaW5nKTogbmcuSVByb21pc2U8e30+IHtcbiAgICBjb25zdCByZXF1ZXN0OiBHZW5lcmljR2V0UmVxdWVzdCA9IHtcbiAgICAgIHVybDogYG9wZXJhdGlvbmFsL25ldHdvcmstdG9wb2xvZ3k6bmV0d29yay10b3BvbG9neS90b3BvbG9neS90b3BvbG9neS1uZXRjb25mL25vZGUvJHtub2RlSWR9L3lhbmctZXh0Om1vdW50L29uZi1jb3JlLW1vZGVsLWNvbmRpdGlvbmFsLXBhY2thZ2VzOmVxdWlwbWVudC1wYWMvJHtpZGVudGlmaWVyfWAsXG4gICAgICBtZXRob2Q6IFwiR0VUXCJcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLiRtd3RuQ29tbW9ucy5nZW5lcmljUmVxdWVzdDxFeHRlbnNpb25SZXN1bHQ+KHJlcXVlc3QpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgaWYgKHJlc3VsdCAmJiByZXN1bHQuc3RhdHVzID09IDIwMCAmJiByZXN1bHQuZGF0YSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb252ZXJ0T2JqZWN0KHJlc3VsdC5kYXRhKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0sIGVyciA9PiAobnVsbCkpO1xuICB9XG59XG5td3RuSW52ZW50b3J5LnNlcnZpY2UoJ213dG5JbnZlbnRvcnlTZXJ2aWNlJywgW1wiJHFcIiwgXCIkbXd0bkNvbW1vbnNcIiwgXCIkbXd0bkRhdGFiYXNlXCIsIFwiJG13dG5Mb2dcIiwgSW52ZW50b3J5U2VydmljZV0pO1xuIiwiZXhwb3J0IGNsYXNzIEVxdWlwbWVudCB7XG4gIHV1aWQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xuICBjaGlsZHJlbjogRXF1aXBtZW50W107XG59IiwiZGVjbGFyZSB2YXIgYW5ndWxhcjogYW5ndWxhci5JQW5ndWxhclN0YXRpYzsgIFxuXG5pbXBvcnQgeyBFcXVpcG1lbnQgfSBmcm9tICcuLi9tb2RlbHMvZXF1aXBtZW50JztcblxuY29uc3QgbXd0bkludmVudG9yeSA9IGFuZ3VsYXIubW9kdWxlKCdhcHAubXd0bkludmVudG9yeScpO1xuXG5jb25zdCBFcXVpcG1lbnREaXJlY3RpdmUgPSAoKSA9PiB7XG4gIHJldHVybiB7XG4gICAgdGVtcGxhdGVVcmw6ICdzcmMvYXBwL213dG5JbnZlbnRvcnkvY29tcG9uZW50cy9lcXVpcG1lbnQuaHRtbCcsXG4gICAgY29udHJvbGxlcjogJ213dG5FcXVpcG1lbnRDdHJsJyxcbiAgICBjb250cm9sbGVyQXM6ICd2bScsXG4gICAgc2NvcGU6IHtcbiAgICAgIGVxdWlwbWVudDogXCI9XCJcbiAgICB9XG4gIH1cbn07XG5cbm13dG5JbnZlbnRvcnkuZGlyZWN0aXZlKCdtd3RuRXF1aXBtZW50JywgRXF1aXBtZW50RGlyZWN0aXZlKTtcblxuZXhwb3J0IGNsYXNzIEVxdWlwbWVudENvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlICRzY29wZTogbmcuSVNjb3BlICYgeyBlcXVpcG1lbnQ6IEVxdWlwbWVudCB9KSB7XG4gICBcbiAgfVxuXG4gXG59XG5cbm13dG5JbnZlbnRvcnkuY29udHJvbGxlcignbXd0bkVxdWlwbWVudEN0cmwnLCBbJyRzY29wZScsIEVxdWlwbWVudENvbnRyb2xsZXJdKTtcbiIsImRlY2xhcmUgdmFyIGFuZ3VsYXI6IGFuZ3VsYXIuSUFuZ3VsYXJTdGF0aWM7IFxuXG5pbXBvcnQgeyBFcXVpcG1lbnQgfSBmcm9tICcuLi9tb2RlbHMvZXF1aXBtZW50JztcblxuY29uc3QgbXd0bkludmVudG9yeSA9IGFuZ3VsYXIubW9kdWxlKCdhcHAubXd0bkludmVudG9yeScpO1xuXG5jb25zdCBFcXVpcG1lbnRHcm91cERpcmVjdGl2ZSA9ICgkY29tcGlsZSkgPT4ge1xuICByZXR1cm4ge1xuICAgIHRlbXBsYXRlVXJsOiAnc3JjL2FwcC9td3RuSW52ZW50b3J5L2NvbXBvbmVudHMvZXF1aXBtZW50R3JvdXAuaHRtbCcsXG4gICAgY29udHJvbGxlcjogJ213dG5FcXVpcG1lbnRHcm91cEN0cmwnLFxuICAgIGNvbnRyb2xsZXJBczogJ3ZtJyxcbiAgICBzY29wZToge1xuICAgICAgZXF1aXBtZW50czogXCI9XCJcbiAgICB9LFxuICAgIC8vIEhBQ0s6IGZvciBhbmd1bGFyIDEuNC4gY29tcGF0aWJpbGl0eVxuICAgIGNvbXBpbGU6IGZ1bmN0aW9uICh0RWxlbWVudCwgdEF0dHIsIHRyYW5zY2x1ZGUpIHtcbiAgICAgIHZhciBjb250ZW50cyA9IHRFbGVtZW50LmNvbnRlbnRzKCkucmVtb3ZlKCk7XG4gICAgICB2YXIgY29tcGlsZWRDb250ZW50cztcbiAgICAgIHJldHVybiBmdW5jdGlvbiAoc2NvcGUsIGlFbGVtZW50LCBpQXR0cikge1xuICAgICAgICBpZiAoIWNvbXBpbGVkQ29udGVudHMpIHtcbiAgICAgICAgICBjb21waWxlZENvbnRlbnRzID0gJGNvbXBpbGUoY29udGVudHMsIHRyYW5zY2x1ZGUpO1xuICAgICAgICB9XG4gICAgICAgIGNvbXBpbGVkQ29udGVudHMoc2NvcGUsIGZ1bmN0aW9uIChjbG9uZSwgc2NvcGUpIHtcbiAgICAgICAgICBpRWxlbWVudC5hcHBlbmQoY2xvbmUpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9XG59O1xuXG5td3RuSW52ZW50b3J5LmRpcmVjdGl2ZSgnbXd0bkVxdWlwbWVudEdyb3VwJywgWyckY29tcGlsZScsIEVxdWlwbWVudEdyb3VwRGlyZWN0aXZlXSk7XG5cbmV4cG9ydCBjbGFzcyBFcXVpcG1lbnRHcm91cENvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlICRzY29wZTogbmcuSVNjb3BlICYgeyBlcXVpcG1lbnRzOiBFcXVpcG1lbnRbXSB9KSB7XG4gICAgLy9jb25zb2xlLmxvZyhcIkVxdWlwbWVudEdyb3VwQ29udHJvbGxlclwiLCAkc2NvcGUuZXF1aXBtZW50cyk7XG4gICAgXG4gIH1cblxufVxuXG5td3RuSW52ZW50b3J5LmNvbnRyb2xsZXIoJ213dG5FcXVpcG1lbnRHcm91cEN0cmwnLCBbJyRzY29wZScsIEVxdWlwbWVudEdyb3VwQ29udHJvbGxlcl0pOyIsImRlY2xhcmUgdmFyIGFuZ3VsYXI6IGFuZ3VsYXIuSUFuZ3VsYXJTdGF0aWM7IFxuXG5pbXBvcnQgeyBJbnZlbnRvcnlTZXJ2aWNlIH0gZnJvbSBcIi4vbXd0bkludmVudG9yeS5zZXJ2aWNlXCI7IFxuaW1wb3J0IFwiLi9td3RuSW52ZW50b3J5LnNlcnZpY2VcIjtcbmltcG9ydCBcIi4vY29tcG9uZW50cy9lcXVpcG1lbnRcIjtcbmltcG9ydCBcIi4vY29tcG9uZW50cy9lcXVpcG1lbnRHcm91cFwiO1xuXG5jb25zdCBtd3RuSW52ZW50b3J5ID0gYW5ndWxhci5tb2R1bGUoJ2FwcC5td3RuSW52ZW50b3J5Jyk7XG5cbmludGVyZmFjZSBJTXd0bkludmVudG9yeVNjb3BlIGV4dGVuZHMgbmcuSVNjb3BlIHtcbiAgbWVzc2FnZTogc3RyaW5nLFxuICBlcXVpcG1lbnRzOiB7fVtdO1xuICBsb2FkaW5nOiBib29sZWFuO1xuICBhY3RpdmVNb3VudFBvaW50czogc3RyaW5nW107XG4gIHNlbGVjdGVkTW91bnRQb2ludDogc3RyaW5nO1xufVxuXG5jbGFzcyBNd3RuSW52ZW50b3J5Q3RybCB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgJHJvb3RTY29wZSwgcHJpdmF0ZSAkc2NvcGU6IElNd3RuSW52ZW50b3J5U2NvcGUsIHByaXZhdGUgJHN0YXRlLCBwcml2YXRlICR0aW1lb3V0LCBwcml2YXRlIG13dG5JbnZlbnRvcnlTZXJ2aWNlOiBJbnZlbnRvcnlTZXJ2aWNlKSB7XG4gICAgLy8gdG9kbzogY2hhbmdlIHRoaXNcbiAgICAkcm9vdFNjb3BlLnNlY3Rpb25fbG9nbyA9ICdzcmMvYXBwL213dG5JbnZlbnRvcnkvaW1hZ2VzL213dG5JbnZlbnRvcnkucG5nJztcblxuICAgICRzY29wZS5sb2FkaW5nID0gZmFsc2U7XG4gICAgJHNjb3BlLm1lc3NhZ2UgPSBcIkVtcHR5XCI7XG4gICAgJHNjb3BlLmVxdWlwbWVudHMgPSBbXTtcbiAgICAkc2NvcGUuc2VsZWN0ZWRNb3VudFBvaW50ID0gbnVsbDtcblxuICAgICRzY29wZS5hY3RpdmVNb3VudFBvaW50cyA9IFtdO1xuXG4gICAgY29uc3QgZ2V0QWxsQ2hpbGRFcXVpcG1lbnRzID0gYXN5bmMgKGVxdWlwbWVudHNSb290SWQ6IHN0cmluZywgZXF1aW1lbnRJZHM6IHN0cmluZ1tdKSA9PiB7XG4gICAgICBpZiAoIWVxdWltZW50SWRzIHx8ICFlcXVpbWVudElkcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgY29uc3QgZXF1aXBtZW50T2JqZWN0cyA9IChhd2FpdCBQcm9taXNlLmFsbChlcXVpbWVudElkcy5tYXAoaWQgPT4ge1xuICAgICAgICByZXR1cm4gbXd0bkludmVudG9yeVNlcnZpY2UuZ2V0RXF1aXBtZW50RGV0YWlscyhlcXVpcG1lbnRzUm9vdElkLCBpZCk7XG4gICAgICB9KSkpLm1hcChlcSA9PiAoZXFbXCJlcXVpcG1lbnRcIl1bMF0pKTtcblxuICAgICAgY29uc3QgZXF1aXBtZW50Q29uZGl0aW9uYWxzID0gKGF3YWl0IFByb21pc2UuYWxsKGVxdWltZW50SWRzLm1hcChpZCA9PiB7XG4gICAgICAgIHJldHVybiBtd3RuSW52ZW50b3J5U2VydmljZS5nZXRFcXVpcG1lbnRDb25kaXRpb25hbHMoZXF1aXBtZW50c1Jvb3RJZCwgaWQpO1xuICAgICAgfSkpKS5tYXAoZXEgPT4gKGVxW1wiZXF1aXBtZW50LXBhY1wiXVswXSkpO1xuICAgICAgXG4gICAgICBsZXQgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGVxdWlwbWVudE9iamVjdHMubWFwKGVxID0+IHtcbiAgICAgICAgbGV0IGZydU5hbWVzOiBzdHJpbmdbXSA9IChlcVtcImNvbnRhaW5lZC1ob2xkZXJcIl0gfHwgW10pLm1hcChjaCA9PiBjaFtcIm9jY3VweWluZy1mcnVcIl0pLmZpbHRlcihmcnUgPT4gISFmcnUpO1xuICAgICAgICByZXR1cm4gZ2V0QWxsQ2hpbGRFcXVpcG1lbnRzKGVxdWlwbWVudHNSb290SWQsIGZydU5hbWVzKTtcbiAgICAgIH0pKTtcblxuICAgICAgcmV0dXJuIGVxdWlwbWVudE9iamVjdHMucmVkdWNlKChhY2MsIGN1ciwgaW5kLCBhcnIpID0+IHtcbiAgICAgICAgbGV0IGNvbmRpdGlvbmFsID0gZXF1aXBtZW50Q29uZGl0aW9uYWxzW2luZF0gfHwgbnVsbDtcbiAgICAgICAgLy8gZW5zdXJlIEVOVkVSWSBwcm9wZXJ0eSBjYW4gYmUgbnVsbCBvciB1bmRlZmluZWRcbiAgICAgICAgbGV0IG1hbnVmYWN0dXJlZFRoaW5nID0gY3VyWydtYW51ZmFjdHVyZWQtdGhpbmcnXTtcbiAgICAgICAgbGV0IGVxdWlwbWVudFR5cGUgPSBtYW51ZmFjdHVyZWRUaGluZyAmJiBtYW51ZmFjdHVyZWRUaGluZ1snZXF1aXBtZW50LXR5cGUnXTtcbiAgICAgICAgbGV0IG1hbnVmYWN0dXJlclByb3BlcnRpZXMgPSBtYW51ZmFjdHVyZWRUaGluZyAmJiBtYW51ZmFjdHVyZWRUaGluZ1snbWFudWZhY3R1cmVyLXByb3BlcnRpZXMnXTtcbiAgICAgICAgbGV0IGVxdWlwbWVudEluc3RhbmNlID0gbWFudWZhY3R1cmVkVGhpbmcgJiYgbWFudWZhY3R1cmVkVGhpbmdbJ2VxdWlwbWVudC1pbnN0YW5jZSddO1xuXG4gICAgICAgIGxldCBjYXJkID0ge1xuICAgICAgICAgIG5hbWU6IGN1ci5uYW1lLFxuICAgICAgICAgIGxhYmVsOiBjdXIubGFiZWwsXG4gICAgICAgICAgdXVpZDogY3VyLnV1aWQsXG4gICAgICAgICAgbWFudWZhY3R1cmVyOiB7XG4gICAgICAgICAgICB2ZXJzaW9uOiBlcXVpcG1lbnRUeXBlICYmIGVxdWlwbWVudFR5cGVbXCJ2ZXJzaW9uXCJdLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGVxdWlwbWVudFR5cGUgJiYgZXF1aXBtZW50VHlwZVtcImRlc2NyaXB0aW9uXCJdLFxuICAgICAgICAgICAgcGFydFR5cGVJZGVudGlmaWVyOiBlcXVpcG1lbnRUeXBlICYmIGVxdWlwbWVudFR5cGVbXCJwYXJ0LXR5cGUtaWRlbnRpZmllclwiXSxcbiAgICAgICAgICAgIG1vZGVsSWRlbnRpZmllcjogZXF1aXBtZW50VHlwZSAmJiBlcXVpcG1lbnRUeXBlW1wibW9kZWwtaWRlbnRpZmllclwiXSxcbiAgICAgICAgICAgIHBhcnRUeXBlSWRldHlwZU5hbWVudGlmaWVyOiBlcXVpcG1lbnRUeXBlICYmIGVxdWlwbWVudFR5cGVbXCJ0eXBlLW5hbWVcIl0sXG4gICAgICAgICAgICBpZDogbWFudWZhY3R1cmVyUHJvcGVydGllcyAmJiBtYW51ZmFjdHVyZXJQcm9wZXJ0aWVzWydtYW51ZmFjdHVyZXItaWRlbnRpZmllciddLFxuICAgICAgICAgICAgZGF0ZTogZXF1aXBtZW50SW5zdGFuY2UgJiYgZXF1aXBtZW50SW5zdGFuY2VbJ21hbnVmYWN0dXJlLWRhdGUnXSAmJiBEYXRlLnBhcnNlKGVxdWlwbWVudEluc3RhbmNlICYmIGVxdWlwbWVudEluc3RhbmNlWydtYW51ZmFjdHVyZS1kYXRlJ10pLFxuICAgICAgICAgICAgc2VyaWFsOiBlcXVpcG1lbnRJbnN0YW5jZSAmJiBlcXVpcG1lbnRJbnN0YW5jZVsnc2VyaWFsLW51bWJlciddXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb25kaXRpb25hbDogY29uZGl0aW9uYWxcbiAgICAgICAgfTtcbiAgICAgICAgKHJlc3VsdHNbaW5kXS5sZW5ndGggPyBjYXJkWydjaGlsZHJlbiddID0gcmVzdWx0c1tpbmRdIDogbnVsbCk7XG4gICAgICAgIGFjYy5wdXNoKGNhcmQpO1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwgW10pO1xuICAgIH1cblxuICAgIGNvbnN0IHBsZWFzZVNlbGVjdCA9IFwiUGxlYXNlIHNlbGVjdCBhIG1vdW50IHBvaW50XCI7XG5cbiAgICBjb25zdCByZWZyZXNoID0gYXN5bmMgKGVxdWlwbWVudHNSb290SWQ6IHN0cmluZykgPT4ge1xuICAgICAgbGV0IHJvb3RJZGVudGlmaWVycyA9IGF3YWl0IG13dG5JbnZlbnRvcnlTZXJ2aWNlLmdldFJvb3RJZGVudGlmaWVycyhlcXVpcG1lbnRzUm9vdElkKTtcbiAgICAgIGxldCBlcXVpcG1lbnRzID0gcm9vdElkZW50aWZpZXJzICYmIGF3YWl0IGdldEFsbENoaWxkRXF1aXBtZW50cyhlcXVpcG1lbnRzUm9vdElkLCByb290SWRlbnRpZmllcnMpO1xuICAgICAgJHRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAkc2NvcGUuZXF1aXBtZW50cyA9IGVxdWlwbWVudHM7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgbXd0bkludmVudG9yeVNlcnZpY2UuZ2V0Q29ubmVjdGVkTW91bnRwb2ludHMoKS50aGVuKHJlcyA9PiB7XG4gICAgICAkc2NvcGUuYWN0aXZlTW91bnRQb2ludHMgPSBbcGxlYXNlU2VsZWN0LCAuLi5yZXNdIDtcbiAgICAgICRzY29wZS5zZWxlY3RlZE1vdW50UG9pbnQgPSAkc2NvcGUuc2VsZWN0ZWRNb3VudFBvaW50IHx8IHBsZWFzZVNlbGVjdDtcbiAgICB9KTtcblxuICAgICRzY29wZS4kd2F0Y2goKCkgPT4gKCRzdGF0ZS5wYXJhbXMubm9kZUlkKSwgKG5ld1ZhbDogc3RyaW5nLCBvbGRWYWw6IHN0cmluZykgPT4ge1xuICAgICAgJHNjb3BlLnNlbGVjdGVkTW91bnRQb2ludCA9IG5ld1ZhbDtcbiAgICB9KTtcblxuICAgICRzY29wZS4kd2F0Y2goXCJzZWxlY3RlZE1vdW50UG9pbnRcIiwgYXN5bmMgKG5ld1ZhbDogc3RyaW5nLCBvbGRWYWw6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCFuZXdWYWwgfHwgbmV3VmFsID09PSBwbGVhc2VTZWxlY3QpIHtcbiAgICAgICAgJHNjb3BlLmVxdWlwbWVudHMgPSBbXTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCRzY29wZS5hY3RpdmVNb3VudFBvaW50c1swXSA9PT0gcGxlYXNlU2VsZWN0KSB7XG4gICAgICAgIFssIC4uLiRzY29wZS5hY3RpdmVNb3VudFBvaW50c10gPSAkc2NvcGUuYWN0aXZlTW91bnRQb2ludHM7XG4gICAgICB9IFxuICAgICAgJHNjb3BlLmxvYWRpbmcgPSB0cnVlO1xuICAgICAgaWYgKCRzdGF0ZS5wYXJhbXMubm9kZUlkICE9PSBuZXdWYWwpIHtcbiAgICAgICAgJHN0YXRlLmdvKCdtYWluLm13dG5JbnZlbnRvcnknLCB7IG5vZGVJZDogbmV3VmFsIH0sIHsgbm90aWZ5OiBmYWxzZSB9KTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHJlZnJlc2gobmV3VmFsKS5jYXRjaChlcnIgPT4ge1xuICAgICAgICAkdGltZW91dCgoKSA9PiB7ICRzY29wZS5lcXVpcG1lbnRzID0gbnVsbDsgfSk7XG4gICAgICB9KTtcbiAgICAgICR0aW1lb3V0KCgpID0+IHsgJHNjb3BlLmxvYWRpbmcgPSBmYWxzZTsgfSk7XG4gICAgfSk7XG4gIH1cbn1cblxubXd0bkludmVudG9yeS5jb250cm9sbGVyKCdtd3RuSW52ZW50b3J5Q3RybCcsIFsnJHJvb3RTY29wZScsICckc2NvcGUnLCAnJHN0YXRlJywgJyR0aW1lb3V0JywgJ213dG5JbnZlbnRvcnlTZXJ2aWNlJywgTXd0bkludmVudG9yeUN0cmxdKTtcbiJdfQ==
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.controller.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.controller.ts new file mode 100644 index 00000000..f4cb3e86 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.controller.ts @@ -0,0 +1,116 @@ +declare var angular: angular.IAngularStatic; + +import { InventoryService } from "./mwtnInventory.service"; +import "./mwtnInventory.service"; +import "./components/equipment"; +import "./components/equipmentGroup"; + +const mwtnInventory = angular.module('app.mwtnInventory'); + +interface IMwtnInventoryScope extends ng.IScope { + message: string, + equipments: {}[]; + loading: boolean; + activeMountPoints: string[]; + selectedMountPoint: string; +} + +class MwtnInventoryCtrl { + constructor(private $rootScope, private $scope: IMwtnInventoryScope, private $state, private $timeout, private mwtnInventoryService: InventoryService) { + // todo: change this + $rootScope.section_logo = 'src/app/mwtnInventory/images/mwtnInventory.png'; + + $scope.loading = false; + $scope.message = "Empty"; + $scope.equipments = []; + $scope.selectedMountPoint = null; + + $scope.activeMountPoints = []; + + const getAllChildEquipments = async (equipmentsRootId: string, equimentIds: string[]) => { + if (!equimentIds || !equimentIds.length) { + return []; + } + const equipmentObjects = (await Promise.all(equimentIds.map(id => { + return mwtnInventoryService.getEquipmentDetails(equipmentsRootId, id); + }))).map(eq => (eq["equipment"][0])); + + const equipmentConditionals = (await Promise.all(equimentIds.map(id => { + return mwtnInventoryService.getEquipmentConditionals(equipmentsRootId, id); + }))).map(eq => (eq["equipment-pac"][0])); + + let results = await Promise.all(equipmentObjects.map(eq => { + let fruNames: string[] = (eq["contained-holder"] || []).map(ch => ch["occupying-fru"]).filter(fru => !!fru); + return getAllChildEquipments(equipmentsRootId, fruNames); + })); + + return equipmentObjects.reduce((acc, cur, ind, arr) => { + let conditional = equipmentConditionals[ind] || null; + // ensure ENVERY property can be null or undefined + let manufacturedThing = cur['manufactured-thing']; + let equipmentType = manufacturedThing && manufacturedThing['equipment-type']; + let manufacturerProperties = manufacturedThing && manufacturedThing['manufacturer-properties']; + let equipmentInstance = manufacturedThing && manufacturedThing['equipment-instance']; + + let card = { + name: cur.name, + label: cur.label, + uuid: cur.uuid, + manufacturer: { + version: equipmentType && equipmentType["version"], + description: equipmentType && equipmentType["description"], + partTypeIdentifier: equipmentType && equipmentType["part-type-identifier"], + modelIdentifier: equipmentType && equipmentType["model-identifier"], + partTypeIdetypeNamentifier: equipmentType && equipmentType["type-name"], + id: manufacturerProperties && manufacturerProperties['manufacturer-identifier'], + date: equipmentInstance && equipmentInstance['manufacture-date'] && Date.parse(equipmentInstance && equipmentInstance['manufacture-date']), + serial: equipmentInstance && equipmentInstance['serial-number'] + }, + conditional: conditional + }; + (results[ind].length ? card['children'] = results[ind] : null); + acc.push(card); + return acc; + }, []); + } + + const pleaseSelect = "Please select a mount point"; + + const refresh = async (equipmentsRootId: string) => { + let rootIdentifiers = await mwtnInventoryService.getRootIdentifiers(equipmentsRootId); + let equipments = rootIdentifiers && await getAllChildEquipments(equipmentsRootId, rootIdentifiers); + $timeout(() => { + $scope.equipments = equipments; + }); + }; + + mwtnInventoryService.getConnectedMountpoints().then(res => { + $scope.activeMountPoints = [pleaseSelect, ...res] ; + $scope.selectedMountPoint = $scope.selectedMountPoint || pleaseSelect; + }); + + $scope.$watch(() => ($state.params.nodeId), (newVal: string, oldVal: string) => { + $scope.selectedMountPoint = newVal; + }); + + $scope.$watch("selectedMountPoint", async (newVal: string, oldVal: string) => { + if (!newVal || newVal === pleaseSelect) { + $scope.equipments = []; + return; + } + if ($scope.activeMountPoints[0] === pleaseSelect) { + [, ...$scope.activeMountPoints] = $scope.activeMountPoints; + } + $scope.loading = true; + if ($state.params.nodeId !== newVal) { + $state.go('main.mwtnInventory', { nodeId: newVal }, { notify: false }); + } + await refresh(newVal).catch(err => { + $timeout(() => { $scope.equipments = null; }); + }); + $timeout(() => { $scope.loading = false; }); + }); + } +} + +mwtnInventory.controller('mwtnInventoryCtrl', ['$rootScope', '$scope', '$state', '$timeout', 'mwtnInventoryService', MwtnInventoryCtrl]); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.module.js new file mode 100644 index 00000000..5e104941 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.module.js @@ -0,0 +1,33 @@ +define( ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.mwtnInventory = angular.module('app.mwtnInventory', ['app.core']); + exports.mwtnInventory.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + //$translatePartialLoaderProvider.addPart('app/mwtnInventory/locale/locale'); + NavHelperProvider.addControllerUrl('app/mwtnInventory/mwtnInventory.controller'); + NavHelperProvider.addToMenu('mwtnInventory', { + "link": "#/pnfInventory/", + "active": "main.mwtnInventory", + "title": "pnf Inventory", + "icon": "fa fa-book", + "page": { + "title": "pnf Inventory", + "description": "mwtnInventory" + } + }); + $stateProvider.state('main.mwtnInventory', { + url: 'pnfInventory/:nodeId?', + access: 2, + views: { + 'content': { + templateUrl: 'src/app/mwtnInventory/mwtnInventory.tpl.html', + controller: 'mwtnInventoryCtrl' + } + } + }); + }); +}); +/* non ES6 export */ +// export = mwtnInventory; +// export default mwtnInventory; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXd0bkludmVudG9yeS5tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzcmMvYXBwL213dG5JbnZlbnRvcnkvbXd0bkludmVudG9yeS5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0lBR2EsUUFBQSxhQUFhLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFFL0UscUJBQWEsQ0FBQyxNQUFNLENBQUMsVUFBVSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLGFBQWEsRUFBRSxrQkFBa0IsRUFBRSwrQkFBK0I7UUFFbkwsNkVBQTZFO1FBRTdFLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLDRDQUE0QyxDQUFDLENBQUM7UUFDakYsaUJBQWlCLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRTtZQUMzQyxNQUFNLEVBQUUsa0JBQWtCO1lBQzFCLFFBQVEsRUFBRSxvQkFBb0I7WUFDOUIsT0FBTyxFQUFFLGdCQUFnQjtZQUN6QixNQUFNLEVBQUUsYUFBYTtZQUNyQixNQUFNLEVBQUU7Z0JBQ04sT0FBTyxFQUFFLFdBQVc7Z0JBQ3BCLGFBQWEsRUFBRSxlQUFlO2FBQy9CO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsY0FBYyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRTtZQUN6QyxHQUFHLEVBQUUsd0JBQXdCO1lBQzdCLE1BQU0sRUFBRSxDQUFDO1lBQ1QsS0FBSyxFQUFFO2dCQUNMLFNBQVMsRUFBRTtvQkFDVCxXQUFXLEVBQUUsOENBQThDO29CQUMzRCxVQUFVLEVBQUUsbUJBQW1CO2lCQUNoQzthQUNGO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7O0FBRUgsb0JBQW9CO0FBQ3BCLDZCQUE2QjtBQUM3QixnQ0FBZ0MiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBpbXBvcnQgKiBhcyBhbmd1bGFyIGZyb20gJ2FuZ3VsYXJBTUQnO1xuZGVjbGFyZSB2YXIgYW5ndWxhcjogYW5ndWxhci5JQW5ndWxhclN0YXRpYzsgXG5cbmV4cG9ydCBjb25zdCBtd3RuSW52ZW50b3J5ID0gYW5ndWxhci5tb2R1bGUoJ2FwcC5td3RuSW52ZW50b3J5JywgWydhcHAuY29yZSddKTtcblxubXd0bkludmVudG9yeS5jb25maWcoZnVuY3Rpb24gKCRzdGF0ZVByb3ZpZGVyLCAkY29tcGlsZVByb3ZpZGVyLCAkY29udHJvbGxlclByb3ZpZGVyLCAkcHJvdmlkZSwgTmF2SGVscGVyUHJvdmlkZXIsICRodHRwUHJvdmlkZXIsICR0cmFuc2xhdGVQcm92aWRlciwgJHRyYW5zbGF0ZVBhcnRpYWxMb2FkZXJQcm92aWRlcikge1xuXG4gIC8vJHRyYW5zbGF0ZVBhcnRpYWxMb2FkZXJQcm92aWRlci5hZGRQYXJ0KCdhcHAvbXd0bkludmVudG9yeS9sb2NhbGUvbG9jYWxlJyk7XG5cbiAgTmF2SGVscGVyUHJvdmlkZXIuYWRkQ29udHJvbGxlclVybCgnYXBwL213dG5JbnZlbnRvcnkvbXd0bkludmVudG9yeS5jb250cm9sbGVyJyk7XG4gIE5hdkhlbHBlclByb3ZpZGVyLmFkZFRvTWVudSgnbXd0bkludmVudG9yeScsIHtcbiAgICBcImxpbmtcIjogXCIjL213dG5JbnZlbnRvcnkvXCIsXG4gICAgXCJhY3RpdmVcIjogXCJtYWluLm13dG5JbnZlbnRvcnlcIixcbiAgICBcInRpdGxlXCI6IFwiTVdUTiBJbnZlbnRvcnlcIixcbiAgICBcImljb25cIjogXCJmYSAgZmEtYm9va1wiLCAgLy8gQWRkIG5hdmlnYXRpb24gaWNvbiBjc3MgY2xhc3MgaGVyZVxuICAgIFwicGFnZVwiOiB7XG4gICAgICBcInRpdGxlXCI6IFwiTVdUTiBEZW1vXCIsXG4gICAgICBcImRlc2NyaXB0aW9uXCI6IFwibXd0bkludmVudG9yeVwiXG4gICAgfVxuICB9KTtcblxuICAkc3RhdGVQcm92aWRlci5zdGF0ZSgnbWFpbi5td3RuSW52ZW50b3J5Jywge1xuICAgIHVybDogJ213dG5JbnZlbnRvcnkvOm5vZGVJZD8nLFxuICAgIGFjY2VzczogMixcbiAgICB2aWV3czoge1xuICAgICAgJ2NvbnRlbnQnOiB7XG4gICAgICAgIHRlbXBsYXRlVXJsOiAnc3JjL2FwcC9td3RuSW52ZW50b3J5L213dG5JbnZlbnRvcnkudHBsLmh0bWwnLFxuICAgICAgICBjb250cm9sbGVyOiAnbXd0bkludmVudG9yeUN0cmwnXG4gICAgICB9XG4gICAgfVxuICB9KTtcbn0pO1xuXG4vKiBub24gRVM2IGV4cG9ydCAqL1xuLy8gZXhwb3J0ID0gbXd0bkludmVudG9yeTsgICBcbi8vIGV4cG9ydCBkZWZhdWx0IG13dG5JbnZlbnRvcnk7Il19
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.module.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.module.ts new file mode 100644 index 00000000..6fee7005 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.module.ts @@ -0,0 +1,36 @@ +// import * as angular from 'angularAMD'; +declare var angular: angular.IAngularStatic; + +export const mwtnInventory = angular.module('app.mwtnInventory', ['app.core']); + +mwtnInventory.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + + //$translatePartialLoaderProvider.addPart('app/mwtnInventory/locale/locale'); + + NavHelperProvider.addControllerUrl('app/mwtnInventory/mwtnInventory.controller'); + NavHelperProvider.addToMenu('mwtnInventory', { + "link": "#/pnfInventory/", + "active": "main.mwtnInventory", + "title": "pnf Inventory", + "icon": "fa fa-book", // Add navigation icon css class here + "page": { + "title": "pnf Inventory", + "description": "mwtnInventory" + } + }); + + $stateProvider.state('main.mwtnInventory', { + url: 'pnfInventory/:nodeId?', + access: 2, + views: { + 'content': { + templateUrl: 'src/app/mwtnInventory/mwtnInventory.tpl.html', + controller: 'mwtnInventoryCtrl' + } + } + }); +}); + +/* non ES6 export */ +// export = mwtnInventory; +// export default mwtnInventory;
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.service.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.service.ts new file mode 100644 index 00000000..be381a4c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.service.ts @@ -0,0 +1,144 @@ +import * as angular from 'angularAMD'; + +const mwtnInventory = angular.module('app.mwtnInventory'); + +class ExtensionResult { + public extension: [ + { "value-name": string, "value": string } + ] +} + +interface GenericGetRequest { + url: string; + method: "GET"; +} + +interface GenericPostRequest<T> { + url: string; + method: "POST"; + data: T +} + +interface CommonService { + genericRequest<TResult>(request: GenericGetRequest): ng.IPromise<ng.IHttpResponse<TResult>>; + genericRequest<TRequest, TResult>(request: GenericPostRequest<TRequest>): ng.IPromise<ng.IHttpResponse<TResult>>; + getMountPoints<TResult>(): ng.IPromise<TResult>; +} + +export class InventoryService { + constructor(private $q: ng.IQService, private $mwtnCommons: CommonService, private $mwtnDatabase, private $mwtnLog) { + + } + + /** + * Helperfunction to detect and convert the 'value-name-group' . + * @param propertyName Name of the object property. + * @param propertyValue Value of the object property. + * @param valueName Optional: The value-name to be used instaed of the propertyName. + * @returns A simplified property value if this is a 'value-name-group' otherwhise the propertyValue. */ + private convertValue = (propertyName: string, propertyValue: any, valueName: string = ''): any => { + if (propertyValue && propertyValue instanceof Array && propertyValue.length == 1 && ( + valueName == null || + propertyValue[0]["value-name"] === propertyName || + propertyValue[0]["value-name"] === valueName) + ) { + return propertyValue[0]["value"]; + } + return propertyValue; + } + + /** + * Converts an API object to a simplified local object. + * @param apiResult The API object to convert. + * @param valueName Optional: The value-name to be used instaed of the propertyName. + * @returns The simplified local object. + */ + private convertObject = (apiResult: any, valueName: string = ''): any => { + if (apiResult instanceof Array) { + return apiResult.map(elm => { return this.convertObject(elm, valueName); }); + } else if (apiResult instanceof Object) { + const keys = Object.keys(apiResult); + let result = {}; + keys.forEach(key => { + const value = this.convertValue(key, apiResult[key], valueName); + result[key] = (value instanceof Object || value instanceof Array) + ? this.convertObject(value) + : value; + }); + return result; + } + return apiResult; + } + + /** Requests all active moint points */ + public getConnectedMountpoints(): ng.IPromise<string[]> { + return this.$mwtnCommons.getMountPoints<{}>().then((mountpoints: {}[]) => { + //console.log(mountpoints); + return <string[]>mountpoints.reduce((acc: string[], cur, ind, arr) => { + if (cur['netconf-node-topology:connection-status'] === 'connected') acc.push(cur["node-id"]); + return acc; + }, []); + }); + } + + /** + * Requests all 'root identifiers' for the given 'node id'. + * @param nodeId The id of the node to request the root identifiers for. + * @returns A q.Promise containing an array of all root identifiers for the requested node id. + * */ + public getRootIdentifiers(nodeId: string): ng.IPromise<string[]> { + + const request: GenericGetRequest = { + url: `operational/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount/core-model:network-element/extension/top-level-equipment`, + method: "GET" + }; + + return this.$mwtnCommons.genericRequest<ExtensionResult>(request).then((result) => { + if (result && result.status == 200 && result.data) { + const topLevelEquipment = this.convertObject(result.data, 'top-level-equipment'); + const rootIdentifiers = topLevelEquipment && topLevelEquipment.extension && topLevelEquipment.extension.split(','); + return rootIdentifiers && rootIdentifiers.map(identifier => identifier && identifier.trim()); + } + return null; + }, err => (null)); + } + + /** + * Requests the detail information for the given combination of 'nodeId' and 'equipmentIdentifier'. + * @param nodeId The id of the root node. + * @param identifier The identifier to request the details for. + * @returns A q.Promise containing an object with all the details. + * */ + public getEquipmentDetails(nodeId: string, identifier: string): ng.IPromise<{}> { + const request: GenericGetRequest = { + url: `operational/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount/core-model:equipment/${identifier}`, + method: "GET" + }; + return this.$mwtnCommons.genericRequest<ExtensionResult>(request).then((result) => { + if (result && result.status == 200 && result.data) { + return this.convertObject(result.data); + } + return null; + }, err => (null)); + } + + /** + * Requests the conditional information for the given combination of 'nodeId' and 'equipmentIdentifier'. + * @param nodeId The id of the root node. + * @param identifier The identifier to request the conditionals for. + * @returns A q.Promise containing an object with all the conditional informations. + * */ + public getEquipmentConditionals(nodeId: string, identifier: string): ng.IPromise<{}> { + const request: GenericGetRequest = { + url: `operational/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount/onf-core-model-conditional-packages:equipment-pac/${identifier}`, + method: "GET" + }; + return this.$mwtnCommons.genericRequest<ExtensionResult>(request).then((result) => { + if (result && result.status == 200 && result.data) { + return this.convertObject(result.data); + } + return null; + }, err => (null)); + } +} +mwtnInventory.service('mwtnInventoryService', ["$q", "$mwtnCommons", "$mwtnDatabase", "$mwtnLog", InventoryService]); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.services.js new file mode 100644 index 00000000..25f1f61c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.services.js @@ -0,0 +1,100 @@ +/* + * 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/mwtnInventory/mwtnInventory.module','app/mwtnCommons/mwtnCommons.services'],function(mwtnInventoryApp) { + + mwtnInventoryApp.register.factory('$mwtnInventory', function($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.checkModules = $mwtnCommons.checkModules; + service.getMwtnWebSocketUrl = $mwtnCommons.getMwtnWebSocketUrl; + service.gridOptions = $mwtnCommons.gridOptions; + service.formatData = $mwtnCommons.formatData; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.deleteDocType = $mwtnDatabase.deleteDocType; + + + service.TimeStampToONFFormat=function(timestamp){ + + timestamp=timestamp.split('-').join(''); + timestamp=timestamp.split(':').join(''); + timestamp=timestamp.split(' ').join(''); + timestamp=timestamp.replace('UTC','Z'); + return timestamp; + }; + + service.getAllLogEntries = function(from, size) { + var sort = [ { + "fault.timeStamp" : { + order : 'desc' + } + }]; + var deferred = $q.defer(); + $mwtnDatabase.getAllData('sdnevents', 'faultlog', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnInventory.getAllLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAllLogEntriesWithSort= function(from, size, sort){ + var deferred = $q.defer(); + $mwtnDatabase.getAllData('sdnevents', 'faultlog', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnInventory.getAllLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getFilteredSortedData=function(from, size, sort,query){ + var deferred = $q.defer(); + $mwtnDatabase.getFilteredSortedData('sdnevents', 'faultlog', from, size,sort, query).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnInventory.getFilteredSortedData', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + + }; + + service.getFilteredData= function(from, size, query){ + var deferred = $q.defer(); + $mwtnDatabase.getFilteredData('sdnevents', 'faultlog', from, size, query).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnInventory.getFilteredData', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + service.getAllCurrentProblemEntries = function(from, size) { + var sort = [ { + "faultCurrent.timeStamp" : { + order : 'desc' + } + }]; + var deferred = $q.defer(); + $mwtnDatabase.getAllData('sdnevents', 'faultcurrent', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnInventory.getAllCurrentLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.tpl.html new file mode 100644 index 00000000..4a7504a8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/mwtnInventory.tpl.html @@ -0,0 +1,16 @@ +<ht-header help-link='sdnr/pnfInventory/0.4.0/README.md'></ht-header> +<div class="app-mwtnInventory"> + <div class="col-md-12 form-group"> + <select class="form-control" ng-model="selectedMountPoint" ng-options="x for x in activeMountPoints | orderBy" ng-disabled="loading"> </select> + </div> + <div ng-if="!loading && equipments != null && equipments.length > 0" > + <mwtn-equipment-group equipments="equipments" /> + </div> + <div class="col-md-12" ng-if="!loading && equipments == null" ><h2>This device does not support inventory</h2></div> + <div class="col-md-12" ng-if="loading" ><h2>Loading ... </h2></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/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/templates/_ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/templates/_ new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/templates/_ diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/templates/accordeonHeader.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/templates/accordeonHeader.tpl.html new file mode 100644 index 00000000..1bf88a9c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/mwtnInventory-module/src/main/resources/mwtnInventory/templates/accordeonHeader.tpl.html @@ -0,0 +1,13 @@ +<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)"> + <h4 class="panel-title"> + <a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" + ng-click="toggleOpen()" uib-accordion-transclude="heading" ng-disabled="isDisabled" uib-tabindex-toggle> + <i class="pull-left fa" ng-class="{'fa-chevron-down': isOpen, 'fa-chevron-right': !isOpen}"></i> + <span uib-accordion-header ng-class="{'text-muted': isDisabled}">{{heading}}</span> + </a> + </h4> +</div> +<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" + uib-collapse="!isOpen"> + <div class="panel-body" ng-transclude></div> + </div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/pom.xml new file mode 100644 index 00000000..bec94c14 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnInventory/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnInventory</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnInventory-module</module> + <module>mwtnInventory-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-bundle/pom.xml new file mode 100644 index 00000000..ab98f462 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>mwtnLog</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnLog-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnLog-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnLog-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..cf298447 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnLog"/> + <property name="url" value="/src/app/mwtnLog"/> + <property name="directory" value="/mwtnLog"/> + <property name="requireJs" value="app/mwtnLog/mwtnLog.module"/> + <property name="angularJs" value="app.mwtnLog"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnLog/mwtnLog-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/pom.xml new file mode 100644 index 00000000..72264b86 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnLog</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnLog-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/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/images/mwtnLog.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/images/mwtnLog.png Binary files differnew file mode 100755 index 00000000..8d0bcad5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/images/mwtnLog.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog-custom.css new file mode 100644 index 00000000..47c5864d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog-custom.css @@ -0,0 +1,58 @@ +/** + * Add your application related css here + */ +.owl .uib-tab a { + border: 1px solid #000; + background-color: white; + color: #3276b1; +} + +.owl .uib-tab.active a { + background-color: #3276b1; + color: white; +} + +.mwtnLogGrid { + height: 600px; + background-color: white; +} + +.mwtnLogGrid span { + color: #393939; +} + +.mwtnLogGrid div.debug { + color: #393939; + background-color: white; +} +.mwtnLogGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.mwtnLogGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.mwtnLogGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.controller.js new file mode 100644 index 00000000..c4135e6b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.controller.js @@ -0,0 +1,151 @@ +/* + * 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/mwtnLog/mwtnLog.module', + 'app/mwtnLog/mwtnLog.services', + 'app/mwtnCommons/mwtnCommons.module'], + function(mwtnLogApp) { + + mwtnLogApp.register.controller('mwtnLogCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$mwtnCommons', '$mwtnLogView', '$mwtnLog' , + function(uiGridConstants, $uibModal, $scope, $rootScope, $mwtnCommons, $mwtnLogView, $mwtnLog) { + + var COMPONENT = 'mwtnLogCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'mwtnLogCtrl started!'}); + // $mwtnLog.error({component: COMPONENT, message: 'Just a test of logging an error.'}); + // $mwtnLog.warning({component: COMPONENT, message: 'Just a test of logging a warning.'}); + // $mwtnLog.debug({component: COMPONENT, message: 'Just a test of logging debug information.'}); + + $rootScope.section_logo = 'src/app/mwtnLog/images/mwtnLog.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.highlightFilteredHeader = $mwtnLogView.highlightFilteredHeader; + + var rowTemplate = '<div ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ng-class="[\'ui-grid-cell\', row.entity.type]" ui-grid-cell></div>'; + var iconCell = '<div class="ui-grid-cell-contents tooltip-uigrid" title="TOOLTIP"><i ng-class="{\'fa\':true, \'{{COL_FIELD}}\':true}" aria-hidden="true"></i></div>'; + + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnLogView.gridOptions)); + $scope.gridOptions.rowTemplate = rowTemplate; + $scope.gridOptions.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + { field: 'icon', type: 'string', displayName: '', headerCellClass: $scope.highlightFilteredHeader, width: 25, enableSorting: false, enableFiltering:false, cellTemplate: iconCell }, + { field: 'timestamp', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 200,sort: { + direction: uiGridConstants.DESC, + priority: 1 + } }, + { field: 'type', type: 'string', displayName: 'Type', headerCellClass: $scope.highlightFilteredHeader, width: 70 }, + { field: 'component', type: 'string', displayName: 'Component', headerCellClass: $scope.highlightFilteredHeader, width : 200 }, + { field: 'message', type: 'string', displayName: 'Message', headerCellClass: $scope.highlightFilteredHeader, width : 500 } + ]; + + $scope.progress = { + show: true, + max: 200, + value: 160 + }; + + $scope.clearLog = function () { + + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnLog/templates/clearLogConfirmation.tpl.html', + controller: 'ClearLogCtrl', + size: 'lg', + resolve: { + now: function () { + return new Date().toISOString(); + } + } + }); + + modalInstance.result.then(function () { + var spec = { + functionId : 'mwtn', + docType : 'log', + query: { + match_all: {} + } + }; + $mwtnLogView.deleteDocType(spec).then(function(deleted){ + $scope.gridOptions.data = []; + $mwtnLog.info({component: COMPONENT, message: 'Log cleared!'}); + }, function(error){ + $mwtnLog.error({component: COMPONENT, message:JSON.stringify(error)}); + }); + }, function () { + $mwtnLog.info({component: COMPONENT, message: 'Mount dismissed!'}); + }); + }; + + var getIconFromType = function(type) { + var mapping = { + debug : '', + info : 'fa-info-circle', + warning : 'fa-exclamation-triangle', + error : 'fa-times-circle' + }; + return mapping[type]; + }; + + var processLogEntries = function(logEntries) { + if (logEntries.data.hits.hits) { + logEntries.data.hits.hits.map(function(entry){ + var log = { + id: entry._id, + icon: getIconFromType(entry._source.type), + timestamp: entry._source.timestamp, + type: entry._source.type, + component: entry._source.component, + message: entry._source.message, + }; + $scope.gridOptions.data.push(log); + }); + $scope.progress.max = logEntries.data.hits.total; + $scope.progress.value = $scope.gridOptions.data.length; + $scope.progress.show = $scope.gridOptions.data.length < logEntries.data.hits.total; + } + }; + + $scope.refreshLog = function() { + $scope.gridOptions.data = []; + var from = 0; + var size = 100; + $scope.processing = true; + $mwtnLogView.getAllLogEntries(from, size).then(function(logEntries){ + $scope.processing = false; + processLogEntries(logEntries); + from = from + size; + while (from < $scope.progress.max) { + $mwtnLogView.getAllLogEntries(from, size).then(function(logEntries){ + processLogEntries(logEntries); + }, function(error){ + console.error(JSON.stringify(error)); + }); + from = from + size; + } + }, function(error){ + console.error(JSON.stringify(error)); + }); + }; + $scope.refreshLog(); + + }]); + + mwtnLogApp.register.controller('ClearLogCtrl', ['$scope', '$uibModalInstance', + function ($scope, $uibModalInstance) { + + $scope.ok = function () { + $uibModalInstance.close('ok'); + }; + + $scope.cancel = function () { + $uibModalInstance.dismiss('cancel'); + }; + }]); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.module.js new file mode 100644 index 00000000..faece4fc --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.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 mwtnLogApp = angular.module('app.mwtnLog', ['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' ]); + + mwtnLogApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnLogApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/mwtnLog/mwtnLog.controller'); + NavHelperProvider.addToMenu('mwtnLog', { + "link" : "#/mwtnLog", + "active" : "main.mwtnLog", + "title" : "Logs", + "icon" : "fa fa-list", // Add navigation icon css class here + "page" : { + "title" : "Logs", + "description" : "mwtnLog" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnLog', { + url: 'mwtnLog', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnLog/mwtnLog.tpl.html', + controller: 'mwtnLogCtrl' + } + } + }); + + }); + + return mwtnLogApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.services.js new file mode 100644 index 00000000..ef900e2a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.services.js @@ -0,0 +1,40 @@ +/* + * 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/mwtnLog/mwtnLog.module','app/mwtnCommons/mwtnCommons.services'],function(mwtnLogApp) { + + mwtnLogApp.register.factory('$mwtnLogView', function($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.checkModules = $mwtnCommons.checkModules; + service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + service.gridOptions = $mwtnCommons.gridOptions; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.deleteDocType = $mwtnDatabase.deleteDocType; + + + service.getAllLogEntries = function(from, size) { + var sort = [ { + timestamp : { + order : 'desc' + } + }]; + var deferred = $q.defer(); + $mwtnDatabase.getAllData('mwtn', 'log', from, size, sort).then(function(success){ + deferred.resolve(success); + }, function(error){ + $mwtnLog.error({component: '$mwtnLogView.getAllLogEntries', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.tpl.html new file mode 100644 index 00000000..f20f154b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/mwtnLog.tpl.html @@ -0,0 +1,26 @@ +<ht-header help-link='sdnr/mwtnLog/0.4.0/README.md'></ht-header> +<div id="mwtnLogGrid" ui-grid="gridOptions" ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns ui-grid-move-columns + class="mwtnLogGrid"></div> + <uib-progressbar ng-show="progress.show" class="progress-striped" type="warning" max="progress.max" value="progress.value" ><i>{{progress.value}} / {{progress.max}}</i></uib-progressbar> + +<div class="text-right"> + <br/> + <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-primary" 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()"> + <i class="fa fa-refresh" ng-class="{'fa-pulse':processing}" aria-hidden="true"></i> + <span>{{'MWTN_REFRESH' | translate}}</span> + </button> +</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/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/templates/clearLogConfirmation.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/templates/clearLogConfirmation.tpl.html new file mode 100644 index 00000000..cdd87c6a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/mwtnLog-module/src/main/resources/mwtnLog/templates/clearLogConfirmation.tpl.html @@ -0,0 +1,12 @@ + +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{'Clear Log Confirmation' | translate}}</h3> +</div> +<div class="modal-body" id="modal-body"> + <p>All log entries stored in the database will be deleted.</p> + <p>Please make, sure you have exported the log entries, otherwise they will get lost.</p> +</div> +<div class="modal-footer"> + <button class="btn btn-primary" type="button" ng-click="ok()">{{'Clear log' | translate}}</button> + <button class="btn btn-warning" type="button" ng-click="cancel()">{{'Cancel' | translate}}</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/pom.xml new file mode 100644 index 00000000..ebae8300 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnLog/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnLog</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnLog-module</module> + <module>mwtnLog-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-bundle/pom.xml new file mode 100644 index 00000000..0d668ac1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnMediator</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnMediator-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnMediator-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnMediator-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..100f6e7c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnMediator"/> + <property name="url" value="/src/app/mwtnMediator"/> + <property name="directory" value="/mwtnMediator"/> + <property name="requireJs" value="app/mwtnMediator/mwtnMediator.module"/> + <property name="angularJs" value="app.mwtnMediator"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnMediator/mwtnMediator-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/pom.xml new file mode 100644 index 00000000..9269bf11 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnMediator</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnMediator-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/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/class.mediator.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/class.mediator.js new file mode 100644 index 00000000..b87a465b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/class.mediator.js @@ -0,0 +1,569 @@ +function MediatorConfig(obj) {
+ if (obj !== undefined) {
+ this.Name = obj.Name;
+ this.DeviceType = obj.DeviceType;
+ this.DeviceIp = obj.DeviceIp;
+ this.DevicePort = 'DevicePort' in obj?obj.DevicePort:161;
+ this.TrapsPort = obj.TrapPort;
+ this.IsNetConfConnected = obj.IsNCConnected;
+ this.IsNetworkElementConnected = obj.IsNeConnected;
+ this.NeModel = obj.NeXMLFile;
+ this.NetconfPort = obj.NcPort;
+ this.PID = obj.pid;
+ this.IsLocked = obj.islocked;
+ this.Autorun = obj.autorun;
+ this.FirewallRuleActive = obj.fwactive;
+ this.OpenDaylightConfigs = obj.ODLConfig;
+ } else {
+ this.Name ="";
+ this.DeviceType = -1;
+ this.DeviceIp = "";
+ this.DevicePort = 161;
+ this.TrapsPort = 0;
+ this.IsNetConfConnected = false;
+ this.IsNetworkElementConnected = false;
+ this.NeModel = "";
+ this.NetconfPort = 0;
+ this.PID =0;
+ this.IsLocked = false;
+ this.Autorun = false;
+ this.FirewallRuleActive = false;
+ this.OpenDaylightConfigs=[];
+ }
+ this.DeviceTypeString = this.getDeviceTypeString();
+ this.ConnectionStatus = {Netconf:this.IsNetConfConnected,NetworkElement:this.IsNetworkElementConnected}
+
+}
+MediatorConfig.prototype.refreshData = function(obj)
+{
+ if(obj!==undefined)
+ {
+ //this.Name = obj.Name;
+ this.DeviceType = obj.DeviceType;
+ this.DeviceIp = obj.DeviceIp;
+ this.DevicePort = 'DevicePort' in obj?obj.DevicePort:161;
+ this.TrapsPort = obj.TrapPort;
+ this.IsNetConfConnected = obj.IsNCConnected;
+ this.IsNetworkElementConnected = obj.IsNeConnected;
+ this.NeModel = obj.NeXMLFile;
+ this.NetconfPort = obj.NcPort;
+ this.PID = obj.pid;
+ this.IsLocked = obj.islocked;
+ this.Autorun = false;
+ this.FirewallRuleActive = obj.fwactive;
+ this.OpenDaylightConfigs = obj.ODLConfig;
+ }
+ this.DeviceTypeString = this.getDeviceTypeString();
+ this.ConnectionStatus = {Netconf:this.IsNetConfConnected,NetworkElement:this.IsNetworkElementConnected}
+
+}
+MediatorConfig.prototype.getDeviceTypeString = function()
+{
+ var i;
+ for(i=0;i<MediatorConfig.DeviceTypes.length;i++)
+ {
+ if(MediatorConfig.DeviceTypes[i].Value==this.DeviceType)
+ return MediatorConfig.DeviceTypes[i].Name;
+ }
+ return "unknown";
+}
+/* enum for devicetypes */
+MediatorConfig.DEVICETYPE_SIMULATOR =0;
+
+
+function MediatorConfigStatus(obj){
+ this.Status=obj.Status;
+ this.Name=obj.Name;
+};
+MediatorConfigStatus.STATUS_OKAY = 1;
+MediatorConfigStatus.STATUS_CORRUPTED = 2;
+MediatorConfigStatus.STATUS_LOCKED = 3;
+MediatorConfigStatus.STATUS_REPAIRED = 4;
+MediatorConfigStatus.StatusTypes=[
+ {Value:MediatorConfigStatus.STATUS_OKAY,Name:"Okay"},
+ {Value:MediatorConfigStatus.STATUS_CORRUPTED,Name:"Corrupted"},
+ {Value:MediatorConfigStatus.STATUS_LOCKED,Name:"Locked"},
+ {Value:MediatorConfigStatus.STATUS_REPAIRED,Name:"Repaired"}
+];
+
+/* Names for enum for devicetypes */
+MediatorConfig.DeviceTypes=[
+{Value:MediatorConfig.DEVICETYPE_SIMULATOR,Name:"Simulator"}];
+
+MediatorConfig.prototype.IsRunning = function() {
+ return this.PID > 0;
+}
+MediatorConfig.prototype.TestParams = function() {
+ if(this.Name===undefined || this.Name.length<=0)
+ throw "Name is not given";
+ // Name without spaces
+ var inValidName = /\s/;
+ if(inValidName.test(this.Name))
+ throw "Name cannot have whitespaces";
+ // DeviceType: int from 0 to ...
+ if(this.DeviceType<0 || this.DeviceType>MediatorConfig.DeviceTypes[MediatorConfig.DeviceTypes.length-1].Value)
+ throw "DeviceType is not set";
+ // DeviceIp: valid IP-Address
+ var validIpTest =/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
+ if(!validIpTest.test(this.DeviceIp))
+ throw "IP-Address is not valid";
+ // TrapsPort: valid Port
+ if(this.TrapsPort<=0 || this.TrapsPort>65535)
+ throw "TrapsPort is not valid";
+ // NeModel: valid XMLFilename
+ if(this.NeModel===undefined || this.NeModel.length<=0)
+ throw "NE XML Filename is not valid";
+ // NetconfPort: valid Port
+ if(this.NetconfPort<=0 || this.NetconfPort>65535)
+ throw "Netconf Port is not valid";
+
+ return true;
+}
+function PortRange(a)
+{
+ if(a!==undefined)
+ {
+ this.Min=a[0];
+ this.Max=a[1];
+ }
+ else
+ {
+ this.Min=0;
+ this.Max=0;
+ }
+}
+function JavaMemParam(str)
+{
+ if(str!==undefined)
+ {
+
+
+ }
+}
+function ServerConfig(obj){
+ if (obj !== undefined) {
+ this.HomeDir = obj.home;
+ this.Host = obj.host;
+ this.Port = obj.port;
+ this.NetconfRange=new PortRange(obj.ncrange);
+ this.SnmpRange = new PortRange(obj.snmprange);
+ this.JmxRange = new PortRange(obj.jmxrange);
+ this.LogLevel = obj.loglevel;
+ this.LogFile = obj.logfile;
+ this.MediatorLogLevel = obj.mediator-loglevel;
+ this.MediatorDevicePingTimeout=obj.mediator-devicepingtimeout;
+ this.MediatorSnmpLatency = obj.mediator-snmplatency;
+ this.MediatorMemory = new JavaMemParam(obj.mediator-memory);
+ }
+ else
+ {
+ this.HomeDir = "";
+ this.Host = "";
+ this.Port = 0;
+ this.NetconfRange=new PortRange();
+ this.SnmpRange = new PortRange();
+ this.JmxRange = new PortRange();
+ this.LogLevel = "";
+ this.LogFile = "";
+ this.MediatorLogLevel = "";
+ this.MediatorDevicePingTimeout=0;
+ this.MediatorSnmpLatency = 0;
+ this.MediatorMemory = new JavaMemParam();
+ }
+}
+function MediatorServer(url) {
+ this._root = url;
+ // if(this._root.endsWith("/"))
+ this._root = this._root + "/";
+ this._mediatorConfigs = [];
+ this._neXMLFilenames = undefined;
+ this.defaultODLConfig = {Server:"sendateodl5.fritz.box",Port:8181,User:"admin",Password:"admin"};
+
+}
+MediatorServer.prototype.getConfigs = function(){return this._mediatorConfigs;}
+
+MediatorServer.prototype.SetDefaultODLConfig = function(cfg)
+{
+ this.defaultODLConfig = cfg;
+}
+MediatorServer.prototype.GetDefaultODLConfig = function()
+{
+ return this.defaultODLConfig;
+}
+MediatorServer.prototype.refreshConfig = function(configs,cb)
+{
+ var changed = [];
+ if(this._mediatorConfigs===undefined)
+ {
+ if(cb!==undefined)
+ cb(changed);
+ return;
+ }
+ if(configs!==undefined && configs.length>0)
+ {
+ var i,j;
+ for(i=0;i<configs.length;i++)
+ {
+ //find config in array by name
+ for(j=0;j<this._mediatorConfigs.length;j++)
+ {
+ if(this._mediatorConfigs[j].Name==configs[i].Name)
+ {
+ //refresh data
+ this._mediatorConfigs[j].refreshData(configs[i]);
+ changed.push(configs[i]);
+ break;
+ }
+ }
+ }
+ }
+ if(cb!==undefined)
+ cb(changed);
+}
+MediatorServer.prototype.onConfigsReceived = function(configJSONArray) {
+ this._mediatorConfigs = [];
+ for (var i = 0; i < configJSONArray.length; i++) {
+ var c = new MediatorConfig(configJSONArray[i]);
+ this._mediatorConfigs.push(c);
+ }
+}
+MediatorServer.prototype.onNeXMLReceived = function(neXMLFilenamesArray) {
+ this._neXMLFilenames = neXMLFilenamesArray;
+}
+
+MediatorServer.prototype.LoadNetworkElementXMLFiles = function(cb,cbError) {
+ var _self = this;
+ this.post("getnemodels", function(response) {
+ if (response.code == 1) {
+ _self.onNeXMLReceived(response.data);
+ if (cb !== undefined)
+ cb(_self._neXMLFilenames);
+ } else
+ {
+ _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.LoadLogs = function(name,cb,cbError)
+{
+ var _self = this;
+ this.post("getlog&name="+name,function(response){
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ } else
+ { _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.LoadAvailableNCPorts = function(cb,cbError)
+{
+ var _self = this;
+ this.post("getncports",function(response){
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ } else
+ { _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.LoadAvailableSnmpPorts = function(cb,cbError)
+{
+ var _self = this;
+ this.post("getsnmpports",function(response){
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ }
+ else
+ {
+ _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.StartMediator = function(name, cb, cbError) {
+ var _self = this;
+ this.post("start",{name:name}, function(response) {
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ } else {
+ _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.StopMediator = function(name, cb, cbError) {
+ var _self = this;
+ this.post("stop",{name:name}, function(response) {
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ } else {
+ _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.ReloadConfig = function(name,cb,cbError)
+{
+ var _self = this;
+ this.post("getconfig",{name:name},function(response){
+ if (response.code == 1) {
+ _self.refreshConfig(response.data,function(changes){
+ if (cb !== undefined)
+ cb(changes);
+ });
+ } else {
+ _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+
+}
+MediatorServer.prototype.LoadConfigs = function(cb,cbError) {
+ var _self = this;
+ this.post("getconfig", function(response) {
+ if (response.code == 1) {
+ _self.onConfigsReceived(response.data);
+ if (cb !== undefined)
+ cb(_self._mediatorConfigs);
+ } else {
+ _self.log(response.data);
+ }
+
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.Repair = function(cb,cbError)
+{
+ var _self = this;
+ this.post("repair", function(response) {
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ } else {
+ _self.log(response.data);
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.LoadVersion = function(cb,cbError)
+{
+ var _self = this;
+ this.post("version", function(response) {
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(response.data);
+ } else {
+ _self.log(response.data);
+ }
+
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+/*
+ * name: <String> deviceType: <int> deviceip: <Ipv4-String> trapsPort:<int>
+ * nexml:<String> ncport:<int> cb: callback-function
+ */
+MediatorServer.prototype.CreateMediator = function(name,devicetype,deviceip,deviceport,trapsPort,nexml,ncport, cb, cbError) {
+
+ var obj;
+ try
+ {
+ obj=new MediatorConfig({
+ Name:name,
+ DeviceType:devicetype,
+ DeviceIp:deviceip,
+ DevicePort:deviceport,
+ TrapPort:trapsPort,
+ NeXMLFile:nexml,
+ NcPort:ncport
+ });
+ obj.TestParams();
+ }
+ catch(e)
+ {
+ if(cbError!==undefined)
+ cbError(e);
+ }
+ this.post("create", {
+ config : JSON.stringify({
+ Name : obj.Name,
+ DeviceType : obj.DeviceType,
+ DeviceIp : obj.DeviceIp,
+ DevicePort : obj.DevicePort,
+ TrapPort : obj.TrapsPort,
+ NeXMLFile : obj.NeModel,
+ NcPort : obj.NetconfPort,
+ ODLConfig:[this.defaultODLConfig]
+ })
+ }, function(response) {
+ if(response.code==1)
+ {
+ if(cb!==undefined)
+ cb(true)
+ }
+ else
+ {
+ if(cbError!==undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.DeleteMediator = function(name, cb, cbError)
+{
+ var _self = this;
+ this.post('delete', {name:name}, function(response){
+ if(response.code==1)
+ {
+ if(cb!==undefined)
+ cb(true);
+ }
+ else
+ {
+ if(cb!==undefined)
+ cb(response.data);
+ }
+
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+MediatorServer.prototype.ClearLock = function(name, cb, cbError) {
+ var _self = this;
+ this.post("clearlock", {
+ name : name
+ }, function(response) {
+ if (response.code == 1) {
+ if (cb !== undefined)
+ cb(true);
+ } else {
+ _self.log(response.data);
+ if (cbError !== undefined)
+ cbError(response.data);
+ }
+ },function(err){
+ if(cbError!==undefined)
+ cbError(err);
+ });
+}
+/*
+ * do post request
+ *
+ * @params task
+ */
+MediatorServer.prototype.post = function(task, data, callback,callbackError) {
+ var _self = this;
+ if (typeof (data) === "function")
+ {
+ callbackError = callback;
+ callback = data;
+ }
+ var cb=function(r) {
+ if (callback !== undefined) {
+ try {
+ if (typeof (r) === "string")
+ r = JSON.parse(r);
+ callback(r);
+ } catch (e) {
+ _self.log(e);
+ if(callbackError!==undefined)
+ callbackError(e);
+ }
+ }
+ };
+
+ if(this.usejQueryv3)
+ {
+ $.post({
+ url : this._root + "api/?task=" + task,
+ data : data,
+ success : cb
+ });
+ }
+ else //jquery 1.x
+ {
+ if(typeof(data)=== "function")
+ {
+ $.post(this._root + "api/?task=" + task,cb).done(function() {
+ _self.log( "second success" );
+ })
+ .fail(function(e) {
+ _self.log( "error" +e);
+ if(callbackError!==undefined)
+ callbackError(e);
+ })
+ .always(function() {
+ _self.log( "finished" );
+ });
+ }
+ else
+ {
+ $.post(this._root + "api/?task=" + task,data,cb).done(function() {
+ _self.log( "second success" );
+ })
+ .fail(function(e) {
+ _self.log( "error" +e);
+ if(callbackError!==undefined)
+ callbackError(e);
+ })
+ .always(function() {
+ _self.log( "finished" );
+ });
+ }
+ }
+}
+
+MediatorServer.prototype._error = function(message) {
+ console.log(message);
+}
+MediatorServer.prototype.log = function(message) {
+// console.log(message);
+}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/images/mwtnMediator.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/images/mwtnMediator.png Binary files differnew file mode 100755 index 00000000..f7c2a6c0 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/images/mwtnMediator.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator-custom.css new file mode 100644 index 00000000..15a684f1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator-custom.css @@ -0,0 +1,69 @@ +/** + * Add your application related css here + */ +.mwtnMediatorGrid { + height: 600px; + background-color: white; +} + +.mwtnMediatorGrid span { + color: #393939; +} +span.mwtnMediatorStatusRunning{ + color: darkgreen; +} +span.mwtnMediatorStatusNotRunning{ + color: darkred; +} +span.mwtnMediatorCStatusIcon{ + font-size:2rem; + vertical-align:middle; +} +span.mwtnMediatorOStatusIcon{ + font-size:2.5rem; + vertical-align:middle; +} + +#mediatorserver-list{ + list-style-type:none; + padding:0; + margin:0; + display:block; + +} +#mediatorserver-list > li +{ + padding:0.3rem; + display:block; + position:relative; +} +#mediatorserver-list > li:nth-child(even) +{ + background:#FFF; +} +#mediatorserver-list > li:nth-child(odd) +{ + background:#EEE; +} +#mediatorserver-list > li.selected +{ + background:#EBFF7F; +} +#mediatorserver-list > li > span.desc +{ + display:block; +} +#mediatorserver-list > li > div.icons +{ + position:absolute; + right:0;top:0;bottom:0;width:auto; +} +#mediatorserver-list > li > div.icons > span.fa +{ + position:relative;margin-right:.6rem;margin-top:.3rem;font-size:2rem;cursor:pointer; +} +#mediatorserver-list > li > div.icons > span.fa:hover +{ + font-weight:bold; +} +.acc-mediatorlog > .panel-group .panel-body{padding:0;}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.controller.js new file mode 100644 index 00000000..5f35ba66 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.controller.js @@ -0,0 +1,613 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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/mwtnMediator/mwtnMediator.module', + 'app/mwtnMediator/mwtnMediator.services'], + function(mwtnMediatorApp) { + + var mediatorServer; + var autoRefresh; + mwtnMediatorApp.register.controller('mwtnMediatorCtrl', ['$scope', '$rootScope','$uibModal', '$mwtnLog', '$mwtnMediator', + function($scope, $rootScope, $uibModal, $mwtnLog, $mwtnMediator) { + autoRefresh=false; + var COMPONENT = 'mwtnMediatorCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'mwtnMediatorCtrl started!'}); + $rootScope.section_logo = 'src/app/mwtnMediator/images/mwtnMediator.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + $scope.highlightFilteredHeader = $mwtnMediator.highlightFilteredHeader; + + + + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnMediator.gridOptions)); + $scope.gridOptions.rowHeight = 44; + + var statusCellTemplate = [ + '<div class="ui-grid-cell-contents">', + '<span class="mwtnMediatorStatusRunning" ng-show="grid.getCellValue(row, col)>0">running ({{grid.getCellValue(row, col)}})</span>', + '<span class="mwtnMediatorStatusNotRunning" ng-show="grid.getCellValue(row, col)==0">stopped</span>', + '</div>' + ].join(''); + var connectionStatusCellTemplate = [ + '<div class="ui-grid-cell-contents">', + '<span class="fa fa-server mwtnMediatorOStatusIcon" style="margin-right:-0.5rem;"></span>', + '<span class="fa fa-check-circle-o mwtnMediatorCStatusIcon" style="color:green;" ng-show="grid.getCellValue(row, col).Netconf"></span>', + '<span class="fa fa-times-circle-o mwtnMediatorCStatusIcon" style="color:red;" ng-show="!grid.getCellValue(row, col).Netconf"></span>', + '<span class="fa fa-minus mwtnMediatorCStatusIcon" style="color:green;font-weight:bold;" ng-show="grid.getCellValue(row, col).Netconf"></span>', + '<span class="fa fa-ellipsis-h mwtnMediatorCStatusIcon" style="color:red;font-weight:bold;" ng-show="!grid.getCellValue(row, col).Netconf"></span>', + '<span class="fa fa-dot-circle-o mwtnMediatorCStatusIcon" style="font-size:3rem;color:#666;"></span>', + '<span class="fa fa-minus mwtnMediatorCStatusIcon" style="color:green;font-weight:bold;" ng-show="grid.getCellValue(row, col).NetworkElement"></span>', + '<span class="fa fa-ellipsis-h mwtnMediatorCStatusIcon" style="color:red;font-weight:bold;" ng-show="!grid.getCellValue(row, col).NetworkElement"></span>', + '<span class="fa fa-check-circle-o mwtnMediatorCStatusIcon" style="color:green;" ng-show="grid.getCellValue(row, col).NetworkElement"></span>', + '<span class="fa fa-times-circle-o mwtnMediatorCStatusIcon" style="color:red;" ng-show="!grid.getCellValue(row, col).NetworkElement"></span>', + '<span class="fa fa-wifi mwtnMediatorOStatusIcon" style="margin-left:-0.5rem;"></span>', + '</div>'].join(''); + + var requiredNesActionCellTemplate = [ + '<a class="vCenter" ng-class="{attention: grid.appScope.hover}" >', + '<button class="btn btn-primary" ng-click="grid.appScope.startMediator(row.entity)">Start</button>', + '<button class="btn btn-default" ng-click="grid.appScope.stopMediator(row.entity)">Stop</button>', + '<button class="btn btn-default" ng-click="grid.appScope.showDetails(row.entity)"><i class="fa fa-info-circle" aria-hidden="true"></i></button>', + '</a>' ].join('<span> </span>'); + + $scope.gridOptions.columnDefs = [ + { field: 'Name', type: 'string', displayName: 'Mediator', headerCellClass: $scope.highlightFilteredHeader, width : 200 }, + { field: 'PID', type: 'int', name: 'Status', cellTemplate:statusCellTemplate, headerCellClass: $scope.highlightFilteredHeader, width : 120 }, + { field: 'DeviceIp', type: 'string', displayName: 'IP address', headerCellClass: $scope.highlightFilteredHeader, width : 120 }, + { + field: 'ConnectionStatus', + type: 'object', + name: 'Connection', + enableSorting : false, + enableFiltering: false, + cellTemplate:connectionStatusCellTemplate, + width : 150 + }, + { name : 'actions', + enableSorting : false, + enableFiltering: false, + cellTemplate: requiredNesActionCellTemplate, + width : 280, + pinnedRight : true + } + ]; + + + + var refreshMediators = function() + { + var i=$('#btn_refreshMediators > i'); + i.addClass("fa-spin"); + console.log("refresh mediators list"); + if(mediatorServer!==undefined) + { + mediatorServer.LoadConfigs(function(configs){ + $scope.data = configs; + $scope.$apply(); + i.removeClass("fa-spin"); + }, + function(err){ + $scope.data = []; + $scope.$apply(); + i.removeClass("fa-spin"); + console.log("cannot reach mediatorserver:"+err); + }); + } + } + var refreshMediator = function(name) + { + console.log("refresh mediators list"); + if(mediatorServer!==undefined) + { + mediatorServer.ReloadConfig(name,function(changes){ + $scope.$apply(); + }, + function(err){ + console.log("cannot reach mediatorserver:"+err); + }); + } + } + var onServerSelectedChanged = function(item){ + var serverURL; + if(item!==undefined) + { + if(typeof(item)==='object') + serverURL=item.url; + else if(typeof(item)==='string') + { + try + { + $mwtnMediator.getServerData(parseInt(item)).then(function(data){ + if(data!==undefined) + { + serverURL=data.url; + mediatorServer = new MediatorServer(serverURL); + $mwtnLog.info({component: COMPONENT, message: 'loading server configs for '+serverURL}); + refreshMediators(); + } + else + console.log("search for server data failed. should never happened") + }); + } + catch(e) + {"error loading server:n"+console.log(e);} + } + } + } + + /* GUI Events =======================================*/ + $scope.onAutoRefreshChanged = function() + { + autoRefresh = $('#ckbx_mediatorAutorefresh').prop('checked'); + console.log("set autorefresh to "+autoRefresh); + } + $scope.editMediatorServers = function() + { + var modalInstance = $uibModal.open({ + animation:true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnMediator/templates/mediatorServerConfigCtrl.tpl.html', + controller: 'MediatorServerConfigCtrl', + size: 'lg', + resolve: { + currentElement: function () { + return $scope.currentElement; + } + } + + }); + } + $scope.createNewMediator = function() + { + if(mediatorServer!==undefined) + { + console.log("create new mediator"); + var modalInstance = $uibModal.open({ + animation:true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnMediator/templates/mediatorCreateNew.tpl.html', + controller: 'MediatorNewCtrl', + size: 'lg', + resolve: { + currentElement: function () { + return $scope.currentElement; + } + } + + }); + } + else + { + console.log("no mediatorserver selected"); + } + } + $scope.refreshMediators = refreshMediators; + + $scope.startMediator = function(el) + { + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled',true); + console.log("starting mediator "+el.Name+" ..."); + if(mediatorServer!==undefined) + { + mediatorServer.StartMediator(el.Name,function(res){ + refreshMediator(el.Name); + //console.log(res); + },function(err){ + if(btn!==undefined) + btn.prop('disabled',false); + // console.log("error starting mediator"); + }); + } + } + $scope.stopMediator = function(el) + { + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled',true); + console.log("stopping mediator "+el.Name+" ..."); + if(mediatorServer!==undefined) + { + mediatorServer.StopMediator(el.Name,function(res){ + refreshMediator(el.Name); + //console.log(res); + },function(err){ + if(btn!==undefined) + btn.prop('disabled',false); + // console.log("error stopping mediator"); + }); + } + } + $scope.showDetails = function(el) + { + $scope.currentElement = el; + var modalInstance = $uibModal.open({ + animation:true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/mwtnMediator/templates/mediatorDetails.tpl.html', + controller: 'MediatorDetailsCtrl', + size: 'lg', + resolve: { + currentElement: function () { + return $scope.currentElement; + } + } + + }); + } + $scope.onchangeserver = function(){ + autoRefresh=false; + $('#ckbx_mediatorAutorefresh').prop('checked',autoRefresh); + onServerSelectedChanged($scope.medserver); + } + /* End of GUI Events===========================*/ + + + $scope.gridOptions.data = 'data'; + $scope.options={ + + } + + //load mediator servers from database + $mwtnMediator.getServerData().then(function(data){ + //set as option source for GUI selector + $scope.options.medservers=data; + //autoselect first item + if(data!==undefined && data.length>0) + { + onServerSelectedChanged(data[0]); + //$scope.medserver= + } + }); + var timer = setInterval(function(){ + if(autoRefresh && mediatorServer!==undefined) + { + refreshMediators(); + } + + },30000); + + }]); + + + /************************************************************************************ + * medaitorDetails Controller definition + ************************************************************************************/ + mwtnMediatorApp.register.controller('MediatorDetailsCtrl', ['$scope', '$uibModalInstance', '$uibModal', '$mwtnConnect', '$mwtnLog', '$mwtnMediator','currentElement', + function ($scope, $uibModalInstance, $uibModal, $mwtnConnect, $mwtnLog, $mwtnMediator, currentElement) { + + var COMPONENT = 'MediatorDetailsCtrl'; + var element = currentElement; + var error = function(msg) + { + $scope.statusmessage=''; + $scope.errormessage=msg; + $scope.$apply(); + } + var status = function(msg) + { + $scope.statusmessage=msg; + $scope.errormessage=''; + $scope.$apply(); + } + var reloadDelayed = function() + { + setTimeout(function(){ + mediatorServer.ReloadConfig(element.Name,function(res){ + $scope.$apply(); + },function(err){error(err);}); + },1000); + } + var refreshLogs = function() + { + mediatorServer.LoadLogs(currentElement.Name,function(res){ + $scope.logdata=res; + $scope.$apply(); + + },function(err){ + $scope.logdata=[]; + $scope.$apply(); + }); + } + $scope.statusmessage=''; + $scope.errormessage=''; + $scope.logGridOptions = JSON.parse(JSON.stringify($mwtnMediator.logGridOptions)); + //$scope.logGridOptions.rowHeight = 44; + $scope.logGridOptions.columnDefs = [ + { field: 'ts', type: 'string', displayName: 'Timestamp', headerCellClass: $scope.highlightFilteredHeader, width : 180 }, + { field: 'lvl', type: 'String', displayName: 'LogLevel', headerCellClass: $scope.highlightFilteredHeader, width : 90 }, + { field: 'src', type: 'string', displayName: 'Source', headerCellClass: $scope.highlightFilteredHeader, width : 120 }, + { field: 'msg', type: 'string', displayName: 'Message', headerCellClass: $scope.highlightFilteredHeader, width : 300 }, + + ]; + $scope.logGridOptions.data = 'logdata'; + // $mwtnLog.info({component: COMPONENT, message: 'MediatorDetailsCtrl started!'}); + $scope.data = { + el:currentElement + }; + $scope.ok = function () { + $uibModalInstance.close({el: currentElement}); + }; + $scope.start = function(){ + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled', true); + mediatorServer.StartMediator(element.Name,function(res){ + if(btn!==undefined) + btn.prop('disabled', true); + status(res); + reloadDelayed(); + },function(err){ + if(btn!==undefined) + btn.prop('disabled', false); + error(err); + + }); + }; + $scope.stop = function(){ + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled', true); + mediatorServer.StopMediator(element.Name,function(res){ + if(btn!==undefined) + btn.prop('disabled', true); + status(res); + reloadDelayed(); + },function(err){ + if(btn!==undefined) + btn.prop('disabled', false); + error(err); + + }); + }; + $scope.delete = function(){ + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled', true); + if(confirm("Do you really want to delete this mediator?")) + { + mediatorServer.DeleteMediator(element.Name,function(res){ + status(res); + },function(err){ + if(btn!==undefined) + btn.prop('disabled', false); + error(err); + }); + } + else + { + if(btn!==undefined) + btn.prop('disabled', false); + } + }; + $scope.unlock = function(){ + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled', true); + mediatorServer.ClearLock(element.Name,function(res){ + status(res); + reloadDelayed(); + },function(err){ + if(btn!==undefined) + btn.prop('disabled', false); + error(err); + }); + } + refreshLogs(); + } + ]); + /************************************************************************************ + * medaitorCreateNew Controller definition + ************************************************************************************/ + mwtnMediatorApp.register.controller('MediatorNewCtrl', ['$scope', '$uibModalInstance', '$uibModal', '$mwtnConnect', '$mwtnLog', + function ($scope, $uibModalInstance, $uibModal, $mwtnConnect, $mwtnLog) { + + var COMPONENT = 'MediatorNewCtrl'; + // $mwtnLog.info({component: COMPONENT, message: COMPONENT + ' started!'}); + var status = function(msg) + { + $scope.statusmessage=msg; + $scope.errormessage=""; + $scope.$apply(); + } + var error = function(msg) + { + $scope.statusmessage=""; + $scope.errormessage=msg; + $scope.$apply(); + } + $scope.options={ + nexmlmodel:[], + nedevicetype:MediatorConfig.DeviceTypes + }; + $scope.mediator={name:'',devicetype:0,remoteip:'',remoteport:161,trapsport:0,ncport:0,nexml:''}; + $scope.odlconfig=mediatorServer.GetDefaultODLConfig(); + $scope.odlsavebtn={enabled:false}; + + //=======load data + mediatorServer.LoadNetworkElementXMLFiles(function(xmlNames){ + $scope.options.nexmlmodel=xmlNames; + $scope.$apply(); + },function(err){ + error(err); + }); + mediatorServer.LoadAvailableNCPorts(function(portValues){ + if(portValues!==undefined && portValues.length>0) + { + $scope.mediator.ncport = portValues[0]; + } + },function(err){error(err);}); + mediatorServer.LoadAvailableSnmpPorts(function(portValues){ + if(portValues!==undefined && portValues.length>0) + { + $scope.mediator.trapsport = portValues[0]; + } + },function(err){error(err);}); + + + $scope.errormessage=''; + $scope.statusmessage=''; + + //====handle events======== + $scope.odledit = function(){ + $scope.odlsavebtn.enabled=true; + console.log("enable odl configs") + $scope.$apply(); + } + $scope.odlsave = function(){ + mediatorServer.SetDefaultODLConfig($scope.odlconfig); + } + $scope.ok = function () { + var btn=$(this); + if(btn!==undefined) + btn.prop('disabled', true); + mediatorServer.CreateMediator($scope.mediator.name, + $scope.mediator.devicetype, + $scope.mediator.remoteip, + $scope.mediator.remoteport, + $scope.mediator.trapsport, + $scope.mediator.nexml, + $scope.mediator.ncport, + function(e){ + if(e==true) + { + status("mediator created"); + setTimeout(function(){$uibModalInstance.close();},2000); + } + else + { + if(btn!==undefined) + btn.prop('disabled', false); + error(e); + + } + },function(err){ + if(btn!==undefined) + btn.prop('disabled', false); + error(err); + + }); + + }; + $scope.cancel = function(){ + $uibModalInstance.close(); + }; + + } + ]); + /************************************************************************************ + * medaitorServerConfig Controller definition + ************************************************************************************/ + mwtnMediatorApp.register.controller('MediatorServerConfigCtrl', ['$scope', '$uibModalInstance', '$uibModal', '$mwtnConnect', '$mwtnLog', '$mwtnMediator', + function ($scope, $uibModalInstance, $uibModal, $mwtnConnect, $mwtnLog, $mwtnMediator) { + + var COMPONENT = 'MediatorServerConfigCtrl'; + // $mwtnLog.info({component: COMPONENT, message: COMPONENT + ' started!'}); + var onServerRowSelect = function(obj,id) + { + if(obj!=undefined) + $(obj).addClass("selected"); + var tbxId=$('#tbx_mediatorserver-id'); + var tbxName=$('#tbx_mediatorserver-name'); + var tbxHost = $('#tbx_mediatorserver-host'); + var tbxVersion = $('#tbx_mediatorserver-version'); + var tbxVersionMed = $('#tbx_mediatorserver-medversion'); + tbxId.prop('disabled',true); + tbxName.prop('disabled',true); + tbxHost.prop('disabled',true); + tbxVersion.prop('disabled',true); + tbxVersionMed.prop('disabled',true); + + $mwtnMediator.getServerData(id).then(function(data){ + if(data!==undefined) + { + tbxId.val(data.id); + tbxName.val(data.name); + tbxHost.val(data.url); + tbxVersion.val(""); + tbxVersionMed.val(""); + var s=new MediatorServer(data.url); + s.LoadVersion(function(d){ + tbxVersion.val(d.server); + tbxVersionMed.val(d.mediator); + + },function(err){ + + }); + } + }); + } + var create = function(host,name,port) + { + var url=host+":"+port; + $mwtnMediator.addServer(name,url).then(function(data){ + reload(); + }); + } + var onEdit = function(id) + { + var tbxName=$('#tbx_mediatorserver-name'); + var tbxHost = $('#tbx_mediatorserver-host'); + tbxName.prop('disabled',false); + tbxHost.prop('disabled',false); + + } + var onDelete = function(id) + { + if(confirm("Do you really want to delete?")) + { + // console.log("delete server with id="+id); + $mwtnMediator.removeServer(id).then(function(){reload();}); + } + } + var reload = function(){ + $mwtnMediator.getServerData().then(function(data){ + + //fill table + var list=$('#mediatorserver-list'); + list.html(''); + if(data!==undefined && data.length>0) + { + for(var i=0;i<data.length;i++) + { + var desc=$('<span class="desc" id="item_'+data[i].id+'">'+data[i].name+'</span>'); + var li=$('<li></li>'); + var iconsbox=$('<div class="icons"></div>'); + var edit=$('<span class="fa fa-edit" id="item_edit_'+data[i].id+'"></span>'); + var del=$('<span class="fa fa-trash-o" id="item_del_'+data[i].id+'"></span>'); + iconsbox.html([edit,del]); + li.html([desc,iconsbox]); + if(i==0) + li.addClass("selected"); + //register click handlers + desc.click(function(){ + $('#mediatorserver-list > li').removeClass('selected'); + onServerRowSelect(this.parentNode,$(this).prop('id').substr(5)); + }); + edit.click(function(){ + onEdit($(this).prop('id').substr(10)); + }); + del.click(function(){ + onDelete($(this).prop('id').substr(9)); + }); + list.append(li); + } + onServerRowSelect(undefined,data[0].id); + } + }); + } + reload(); + $scope.close = function(){ + $uibModalInstance.close(); + }; + }]); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.module.js new file mode 100644 index 00000000..19c9142d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.module.js @@ -0,0 +1,54 @@ +/* + * 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', + 'app/mwtnCommons/bower_components/angular-clipboard/angular-clipboard', + 'src/app/mwtnMediator/class.mediator.js'], function(ng) { + var mwtnMediatorApp = angular.module('app.mwtnMediator', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'angular-clipboard']); + + mwtnMediatorApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnMediatorApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + NavHelperProvider.addControllerUrl('app/mwtnMediator/mwtnMediator.controller'); + NavHelperProvider.addToMenu('mwtnMediator', { + "link" : "#/pnfMediator", + "active" : "main.mwtnMediator", + "title" : "pnf Mediator", + "icon" : "fa fa-globe", // Add navigation icon css class here + "page" : { + "title" : "pnf Mediator", + "description" : "mwtnMediator" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnMediator', { + url: 'pnfMediator', + access: access.admin, + views : { + content : { + templateUrl: 'src/app/mwtnMediator/templates/frame.tpl.html', + controller: 'mwtnMediatorCtrl' + } + } + }); + + }); + + return mwtnMediatorApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.services.js new file mode 100644 index 00000000..363b79a8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/mwtnMediator.services.js @@ -0,0 +1,113 @@ +/* + * @copyright 2017 highstreet technologies 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/mwtnCommons/mwtnCommons.module', 'app/mwtnMediator/mwtnMediator.module'],function(mwtnMediatorApp) { + + mwtnMediatorApp.register.factory('$mwtnMediator', function($http, $q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var COMPONENT = '$mwtnMediator'; + $mwtnLog.info({component: COMPONENT, message: '$mwtnMediator started!'}); + + var service = {}; + + // import of mwtnCommons + service.gridOptions = $mwtnCommons.gridOptions; + service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + + service.getAllData = $mwtnDatabase.getAllData; + service.getFilteredSortedData = $mwtnDatabase.getFilteredSortedData; + service.logGridOptions = $mwtnCommons.gridOptions; + + // service specific functions + service.getServerData = function(id){ + var deferred = $q.defer(); + var functionid="mwtn"; + var type="mediator-server"; + var sort = [ { 'id' : {order : 'asc'}}]; + + if(id===undefined)//get all + $mwtnDatabase.getAllData(functionid,type,0,99,sort,null).then(function(success){ + var list=[]; + success.data.hits.hits.map(function(entry){ + var row = { + id: entry._source.id, + url: entry._source.url, + name: entry._source.name + }; + list.push(row); + }); + deferred.resolve(list); + }, function(error){ + $mwtnLog.error({component: 'private getAlldata', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + else //get by id + $mwtnDatabase.getFilteredSortedData(functionid,type,0,99,sort,{'match':{'id':id}}).then(function(success){ + var list=[]; + success.data.hits.hits.map(function(entry){ + var row = { + id: entry._source.id, + url: entry._source.url, + name: entry._source.name + }; + list.push(row); + }); + deferred.resolve(list.length>0?list[0]:undefined); + }, function(error){ + $mwtnLog.error({component: 'private getFilteredSortedData', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + + return deferred.promise; + + + }; + /* + service.getMaxId = function(){ + var deferred = $q.defer(); + $mwtnDatabase.getAllData(functionid,type,0,99,sort,{'match'}).then(function(success){ + + return deferred.promise; + }; + */ + service.addServer = function(name,url){ + var deferred = $q.defer(); + var functionId="mwtn"; + var docType="mediator-server"; + //check params + var data={name:name,url:url}; + //check if contains + //insert into db + $mwtnDatabase.createSingleDocument(functionId, docType, id, data).then(function(success){ + + + deferred.resolve(data); + },function(error){ + $mwtnLog.error({component: 'private addServer', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + service.removeServer = function(id){ + var deferred = $q.defer(); + var functionId="mwtn"; + var docType="mediator-server"; + + $mwtnDatabase.deleteSingleDocument(functionId, docType, id).then(function(success){ + deferred.resolve(data); + },function(error){ + $mwtnLog.error({component: 'private removeServer', message: JSON.stringify(error.data)}); + deferred.reject(error); + }); + return deferred.promise; + }; + + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/frame.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/frame.tpl.html new file mode 100644 index 00000000..debf0c21 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/frame.tpl.html @@ -0,0 +1,49 @@ +<ht-header help-link='sdnr/pnfMediator/0.4.0/README.md'></ht-header> +<div class=""></div> +<div class="owl container" style="width: 100%;"> + <div class="row"> + <div class="col-md-4"> + <div id="mvtnMediatorServerSelector"> + <select class="form-control" ng-model="medserver" ng-change="onchangeserver()" > + <option ng-repeat="option in options.medservers" value="{{option.id}}">{{option.name}}({{option.url}})</option> + </select> + </div> + </div> + <div class="col-md-8"> + <div style="float:left;display:inline-block;"> + <button class="btn btn-default" ng-click="editMediatorServers()"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></button> + </div> + <div style="float:right;display:inline-block;"> + <div class="checkbox" style="display:inline-block;"> + <label style="color:white;"><input type="checkbox" id="ckbx_mediatorAutorefresh" ng-click="onAutoRefreshChanged()" value="">AutoRefresh</label> + </div> + <button class="btn btn-default" ng-click="createNewMediator()"><i class="fa fa-plus-circle" aria-hidden="true"></i></button> + <button class="btn btn-default" id="btn_refreshMediators" ng-click="refreshMediators()"><i class="fa fa-refresh" aria-hidden="true"></i></button> + + </div> + + </div> + </div> + <div class="row"> + <div class="col-md-12"> + <hr class="ng-scope" /> + </div> + </div> + <div class="row"> + <div class="col-md-12"> + <div id="mwtnMediatorGrid" + ui-grid="gridOptions" + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + class="mwtnMediatorGrid"></div> + </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/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorCreateNew.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorCreateNew.tpl.html new file mode 100644 index 00000000..5934eb8b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorCreateNew.tpl.html @@ -0,0 +1,99 @@ +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{ data.el.Name }}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="row"> + <div class="col-md-3"><span>Name:</span></div> + <div class="col-md-9"> + <input type="text" class="form-control" ng-model="mediator.name" /> + </div> + </div> + <div class="row"> + <div class="col-md-3"><span>DeviceType:</div> + <div class="col-md-9"> + <select class="form-control" ng-model="mediator.devicetype" > + <option ng-repeat="option in options.nedevicetype" value="{{option.Value}}">{{option.Name}}</option> + </select> + </div> + </div> + <div class="row"> + <div class="col-md-3"><span>IP address:</div> + <div class="col-md-9"> + <input type="text" ng-model="mediator.remoteip" class="form-control" style="display:inline-block;width:70%;"/> + <span> : </span> + <input type="text" ng-model="mediator.remoteport" class="form-control" style="display:inline-block;width:25%;float:right;"/> + + </div> + </div> + <div class="row"> + <div class="col-md-3"><span>TrapsPort:</div> + <div class="col-md-9"> + <input type="number" class="form-control" ng-model="mediator.trapsport" /> + </div> + </div> + <div class="row"> + <div class="col-md-3"><span>NetconfPort:</div> + <div class="col-md-9"> + <input type="number" class="form-control" ng-model="mediator.ncport" /> + </div> + </div> + <div class="row"> + <div class="col-md-3"><span>NeModel:</div> + <div class="col-md-9"> + <select class="form-control" ng-model="mediator.nexml"> + <option ng-repeat="option in options.nexmlmodel" value="{{option}}">{{option}}</option> + </select> + </div> + </div> + <hr class="row" /> + <div class="row"> + <uib-accordion close-others="oneAtATime"> + <div uib-accordion-group class="panel-default" is-open="false"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': false, 'fa-chevron-right': true}"></i> + <span>{{'ODL Connection Config' | translate}}</span> + </uib-accordion-heading> + <div class="" style="position:relative;"> + <button class="btn btn-default" ng-click="odledit()" style="position:absolute;top:1rem;right:1rem;"><i class="fa fa-edit"></i></button> + <div class="row"> + <div class="col-md-3"><span >Hostname:</span></div> + <div class="col-md-6"><input ng-disabled="!odlsavebtn.enabled" class="form-control" type="text" ng-model="odlconfig.Server" /></div> + </div> + <div class="row"> + <div class="col-md-3"><span >Port:</span></div> + <div class="col-md-6"><input ng-disabled="!odlsavebtn.enabled" class="form-control" type="text" ng-model="odlconfig.Port" /></div> + </div> + <div class="row"> + <div class="col-md-3"><span >Username:</span></div> + <div class="col-md-6"><input ng-disabled="!odlsavebtn.enabled" class="form-control" type="text" ng-model="odlconfig.User" /></div> + </div> + <div class="row"> + <div class="col-md-3"><span >Password:</span></div> + <div class="col-md-6"><input ng-disabled="!odlsavebtn.enabled" class="form-control" type="text" ng-model="odlconfig.Password" /></div> + </div> + <div class="row"> + <div class="col-md-3"></div> + <div class="col-md-6"><button class="btn btn-default" ng-click="odlsave()" ng-disabled="!odlsavebtn.enabled">Save</button></div> + </div> + + </div> +</div> + </uib-accordion> + </div> + <div class="row"> + <div class="col-md-12"> + <span style="display:block;text-align:right;color:#0F0;">{{statusmessage}}</span> + <span style="display:block;text-align:right;color:#F00;">{{errormessage}}</span> + </div> + </div> + +</div> +<div class="modal-footer"> + <button class="btn btn-primary" type="button" ng-click="ok()"> + <span>{{'MWTN_MED_ADD' | translate}}</span> + </button> + <button class="btn btn-danger" type="button" ng-show="true" ng-click="cancel()"> + <i class="fa fa-trash" aria-hidden="true"></i> + <span>{{'MWTN_CANCEL' | translate}}...</span> + </button> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorDetails.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorDetails.tpl.html new file mode 100644 index 00000000..5223df03 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorDetails.tpl.html @@ -0,0 +1,96 @@ +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{ data.el.Name }}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="row"> + <div class="col-xs-3"><span>DeviceType:</span></div> + <div class="col-xs-9"><span>{{data.el.DeviceTypeString}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>DeviceIP:</span></div> + <div class="col-xs-9"><span>{{data.el.DeviceIp}}:{{data.el.DevicePort}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>TrapsPort:</span></div> + <div class="col-xs-9"><span>{{data.el.TrapsPort}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>NetconfPort:</span></div> + <div class="col-xs-9"><span>{{data.el.NetconfPort}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>NeXMLModel:</span></div> + <div class="col-xs-9"><span>{{data.el.NeModel}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>Status:</span></div> + <div class="col-xs-9"> + <span class="mwtnMediatorStatusRunning" ng-show="{{data.el.PID}}>0">running ({{data.el.PID}})</span> + <span class="mwtnMediatorStatusNotRunning" ng-show="{{data.el.PID}}==0">stopped</span> + </div> + </div> + <div class="row"> + <div class="col-xs-3"><span>Locked:</span></div> + <div class="col-xs-9"><span>{{data.el.IsLocked}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>NetconfConnected:</span></div> + <div class="col-xs-9"><span>{{data.el.IsNetConfConnected}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>NEConnected:</span></div> + <div class="col-xs-9"><span>{{data.el.IsNetworkElementConnected}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>Firewall Configured:</span></div> + <div class="col-xs-9"><span>{{data.el.FirewallRuleActive}}</span></div> + </div> + <div class="row"> + <div class="col-xs-3"><span>Autorun:</span></div> + <div class="col-xs-9"><span>{{data.el.Autorun}}</span></div> + </div> + <div class="row"> + <uib-accordion close-others="oneAtATime" class="acc-mediatorlog"> + <div uib-accordion-group class="panel-default" is-open="false"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': false, 'fa-chevron-right': true}"></i> + <span>{{'Logs' | translate}}</span> + </uib-accordion-heading> + <div id="mwtnLogGrid" + ui-grid="logGridOptions" + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + class="mwtnLogGrid"></div> + +</div> + </uib-accordion> + </div> + <div class="row"> + <div class="col-md-12"> + <span style="display:block;text-align:right;color:#0F0;">{{statusmessage}}</span> + <span style="display:block;text-align:right;color:#F00;">{{errormessage}}</span> + </div> + </div> +</div> +<div class="modal-footer"> + <button class="btn btn-default" type="button" ng-show="{{data.el.IsLocked}}" ng-click="unlock()"> + <i class="fa fa-lock" aria-hidden="true"></i> + <span>{{'Unlock' | translate}}</span> + </button> + <button class="btn btn-danger" type="button" ng-show="true" ng-click="delete()"> + <i class="fa fa-trash" aria-hidden="true"></i> + <span>{{'MWTN_MED_DELETE' | translate}}...</span> + </button> + <button class="btn btn-primary" type="button" ng-show="true" ng-click="start()"> + <span>{{'MWTN_MED_START' | translate}}...</span> + </button> + <button class="btn btn-primary" type="button" ng-show="true" ng-click="stop()"> + <span>{{'MWTN_MED_STOP' | translate}}...</span> + </button> + <button class="btn btn-primary" type="button" ng-click="ok()"> + <span>{{'MWTN_MED_CLOSE' | translate}}</span> + </button> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorServerConfigCtrl.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorServerConfigCtrl.tpl.html new file mode 100644 index 00000000..c3e96585 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/mwtnMediator-module/src/main/resources/mwtnMediator/templates/mediatorServerConfigCtrl.tpl.html @@ -0,0 +1,41 @@ +<div class="modal-header"> + <h3 class="modal-title" id="modal-title">{{ data.el.Name }}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div class="row"> + <div class="col-xs-12 col-lg-6"> + <h3>MediatorServers:</h3> + <ul id="mediatorserver-list" > + </ul> + </div> + <div class="col-xs-6 col-lg-6"> + <h3>Configuration:</h3> + <div id="mediatorserver-details"> + <div class="row"> + <div class="col-xs-5"><span style="float:right;">Id:</span></div> + <div class="col-xs-7"><input type="text" id="tbx_mediatorserver-id" name="mediatorserver-id" value="" /></div> + </div> + <div class="row"> + <div class="col-xs-5"><span style="float:right;">Name:</span></div> + <div class="col-xs-7"><input type="text" id="tbx_mediatorserver-name" name="mediatorserver-name" value="" /></div> + </div> + <div class="row"> + <div class="col-xs-5"><span style="float:right;">Host:</span></div> + <div class="col-xs-7"><input type="text" id="tbx_mediatorserver-host" name="mediatorserver-host" value="" /></div> + </div> + <div class="row"> + <div class="col-xs-5"><span style="float:right;">Version:</span></div> + <div class="col-xs-7"><input type="text" id="tbx_mediatorserver-version" name="mediatorserver-version" value="" /></div> + </div> + <div class="row"> + <div class="col-xs-5"><span style="float:right;">MediatorVersion:</span></div> + <div class="col-xs-7"><input type="text" id="tbx_mediatorserver-medversion" name="mediatorserver-medversion" value="" /></div> + </div> + </div> + </div> + </div> + <hr class="row" /> + <div class="row"> + <button class="btn btn-primary" ng-click="close()">Close</button> + </div> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/pom.xml new file mode 100644 index 00000000..d19f85ed --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnMediator/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnMediator</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnMediator-module</module> + <module>mwtnMediator-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-bundle/pom.xml new file mode 100644 index 00000000..0b03bf59 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnPerformanceCurrent</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnPerformanceCurrent-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnPerformanceCurrent-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnPerformanceCurrent-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..4f73e930 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnPerformanceCurrent"/> + <property name="url" value="/src/app/mwtnPerformanceCurrent"/> + <property name="directory" value="/mwtnPerformanceCurrent"/> + <property name="requireJs" value="app/mwtnPerformanceCurrent/mwtnPerformanceCurrent.module"/> + <property name="angularJs" value="app.mwtnPerformanceCurrent"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnPerformanceCurrent/mwtnPerformanceCurrent-custom.css</value> + </list> + </property> + </bean> +</blueprint> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/pom.xml new file mode 100644 index 00000000..2573f41a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnPerformanceCurrent</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnPerformanceCurrent-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/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/images/mwtnPerformance.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/images/mwtnPerformance.png Binary files differnew file mode 100755 index 00000000..5517f5b1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/images/mwtnPerformance.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent-custom.css new file mode 100644 index 00000000..5e3cf838 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent-custom.css @@ -0,0 +1,13 @@ +/** + * Add your application related css here + */ + +.mwtnCurrentGrid{ + height: 600px; + background-color: white; + color:black; +} + +.mwtnCurrentGrid span{ + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.controller.js new file mode 100644 index 00000000..bffc77be --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.controller.js @@ -0,0 +1,741 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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/mwtnPerformanceCurrent/mwtnPerformanceCurrent.module', + 'app/mwtnPerformanceCurrent/mwtnPerformanceCurrent.services'], + function (mwtnPerformanceCurrentApp) { + + mwtnPerformanceCurrentApp.register.controller('mwtnPerformanceCurrentCtrl', ['$scope', '$rootScope', '$window', '$translate', '$mwtnLog', '$mwtnPerformanceCurrent', 'uiGridConstants', 'OnfNetworkElement', + function ($scope, $rootScope, $window, $translate, $mwtnLog, $mwtnPerformanceCurrent, uiGridConstants, OnfNetworkElement) { + + var COMPONENT = 'mwtnPerformanceCurrent'; + $mwtnLog.info({ component: COMPONENT, message: 'mwtnPerformanceCurrent started!' }); + + $rootScope.section_logo = 'src/app/mwtnPerformanceCurrent/images/mwtnPerformance.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + var radioSignalMap = new Map(); //holds uuid/singalid + + var initPac = { + layerProtocol: 'unknown' + }; + + $scope.layerProtocol = 'MWPS'; + $scope.layerProtocols = ['MWPS', 'ETC']; + + var updateNe = function (data) { + if (!data) return; + + // update onfNetworkElement + switch (data.revision) { + case '2016-03-23': + $mwtnLog.info({ component: COMPONENT, message: 'Revision ' + data.revision + 'not supported!' }); + break; + default: //4. PoC + $scope.onfNetworkElement = JSON.parse(JSON.stringify(data['network-element'])); + $scope.onfLtps = data['network-element'].ltp; + $scope.onfNetworkElement.ltpRefList = undefined; + } + + // update onfLTPs + var order = $mwtnPerformanceCurrent.layerProtocolNameOrder; + $scope.onfLtps.sort(function (a, b) { + if (order[a.lp[0]['layer-protocol-name']] < order[b.lp[0]['layer-protocol-name']]) return -1; + if (order[a.lp[0]['layer-protocol-name']] > order[b.lp[0]['layer-protocol-name']]) return 1; + if (a.lp[0].uuid < b.lp[0].uuid) return -1; + if (a.lp[0].uuid > b.lp[0].uuid) return 1; + return 0; + }); + + // calculate conditional packages + $scope.airinterfaces = []; + $scope.ethernets = []; + $scope.tdms = []; + $scope.onfLtps.map(function (ltp) { + var lpId = ltp.lp[0].uuid; + + + + switch (ltp.lp[0]['layer-protocol-name']) { + case "MWPS": + var init = JSON.parse(JSON.stringify(initPac)); + init.layerProtocol = lpId; + $scope.airinterfaces.push(init); + + break; + case "ETH-CTP": + case "ETC": + var init = JSON.parse(JSON.stringify(initPac)); + init.layerProtocol = lpId; + $scope.ethernets.push(init); + break; + + default: + $mwtnLog.info({ component: COMPONENT, message: 'The layerProtocol ' + ltp.lp[0]['layer-protocol-name'] + ' is not supported (yet)!' }); + } + }); + + data.revision = undefined; + }; + + var updateAirInterface = function (data, key) { + // console.log(JSON.stringify(data), lpId); + + if (Object.keys(data)[0].startsWith('air-interface-current-performance')) { + + $scope.jsonvalue.push(data); + var label = new OnfNetworkElement($scope.onfNetworkElement).getLpById(data['layer-protocol']).getLabel() || data['layer-protocol']; + var radioSignal = radioSignalMap.get(data['layer-protocol']) + var list = data['air-interface-current-performance']['current-performance-data-list'] || data['air-interface-current-performance']['current-performance-data']; + list.map(function(item) { + + + var timestamp = $mwtnPerformanceCurrent.formatTimeStamp(item.timestamp); + + switch (key) { + + case 'performance826': + $scope.performance826.push({ + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + es: item['performance-data'].es, + ses: item['performance-data'].ses, + uas: item['performance-data'].unavailability, + radioSignal: radioSignal + }); + break; + + case 'receiveLevel': + $scope.receiveLevel.push({ + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + rxmin: checkData(item['performance-data']['rx-level-min']), + rxmax: checkData(item['performance-data']['rx-level-max']), + rxavg: checkData(item['performance-data']['rx-level-avg']), + radioSignal: radioSignal + }); + break; + + case 'transmissionLevel': + + $scope.transmissionLevel.push({ + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + txmin: checkData(item['performance-data']['tx-level-min']), + txmax: checkData(item['performance-data']['tx-level-max']), + txavg: checkData(item['performance-data']['tx-level-avg']), + radioSignal: radioSignal + }); + + break; + + case 'modulation': + + $scope.modulation.push( + { + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + time2S: checkData(item['performance-data']['time2-states-s']), + time2: checkData(item['performance-data']['time2-states']), + time2L: checkData(item['performance-data']['time2-states-l']), + time4S: checkData(item['performance-data']['time4-states-s']), + time4: checkData(item['performance-data']['time4-states']), + time4L: checkData(item['performance-data']['time4-states-l']), + time16S: checkData(item['performance-data']['time16-states-s']), + time16: checkData(item['performance-data']['time16-states']), + time16L: checkData(item['performance-data']['time16-states-l']), + time32S: checkData(item['performance-data']['time32-states-s']), + time32: checkData(item['performance-data']['time32-states']), + time32L: checkData(item['performance-data']['time32-states-l']), + time64S: checkData(item['performance-data']['time64-states-s']), + time64: checkData(item['performance-data']['time64-states']), + time64L: checkData(item['performance-data']['time64-states-l']), + time128S: checkData(item['performance-data']['time128-states-s']), + time128: checkData(item['performance-data']['time128-states']), + time128L: checkData(item['performance-data']['time128-states-l']), + time256S: checkData(item['performance-data']['time256-states-s']), + time256: checkData(item['performance-data']['time256-states']), + time256L: checkData(item['performance-data']['time256-states-l']), + time512S: checkData(item['performance-data']['time512-states-s']), + time512: checkData(item['performance-data']['time512-states']), + time512L: checkData(item['performance-data']['time512-states-l']), + time1024S: checkData(item['performance-data']['time1024-states-s']), + time1024: checkData(item['performance-data']['time1024-states']), + time1024L: checkData(item['performance-data']['time1024-states-l']), + time2048S: checkData(item['performance-data']['time2048-states-s']), + time2048: checkData(item['performance-data']['time2048-states']), + time2048L: checkData(item['performance-data']['time2048-states-l']), + time4096S: checkData(item['performance-data']['time4096-states-s']), + time4096: checkData(item['performance-data']['time4096-states']), + time4096L: checkData(item['performance-data']['time4096-states-l']), + time8192S: checkData(item['performance-data']['time8192-states-s']), + time8192: checkData(item['performance-data']['time8192-states']), + time8192L: checkData(item['performance-data']['time8192-states-l']), + radioSignal: radioSignal + }); + + break; + + case 'temperature': + + $scope.temperature.push({ + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + rfTempMin: item['performance-data']['rf-temp-min'], + rfTempAvg: item['performance-data']['rf-temp-avg'], + rfTempMax: item['performance-data']['rf-temp-max'], + radioSignal: radioSignal + }); + break; + + case 'snir': + + $scope.snir.push({ + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + snirMin: item['performance-data']['snir-min'], + snirAvg: item['performance-data']['snir-avg'], + snirMax: item['performance-data']['snir-max'], + radioSignal: radioSignal + } + ); + + break; + + case 'crossPolarDiscrimination': + + $scope.cpdData.push({ + + timestamp: timestamp, + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + id: label, + period: item['granularity-period'], + xpdMin: item['performance-data']['xpd-min'], + xpdAvg: item['performance-data']['xpd-avg'], + xpdMax: item['performance-data']['xpd-max'], + radioSignal: radioSignal + }); + + break; + } + + }); + + } + }; + + var updateContainer = function (lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + var label = new OnfNetworkElement($scope.onfNetworkElement).getLpById(data['layer-protocol']).getLabel() || data['layer-protocol']; + + if (Object.keys(data)[0].contains('ethernet-container')) { + $scope.ethernetJsonValue.push(data); + + var list = data['ethernet-container-current-performance']['current-performance-data-list'] || data['ethernet-container-current-performance']['current-performance-data'] + list.map(function (item) { + + $scope.performanceEthernetContainer.push({ + timestamp: $mwtnPerformanceCurrent.formatTimeStamp(item['timestamp']), + elapsedTime: checkData(item['elapsed-time']), + suspectInterval: item['suspect-interval-flag'], + scannerId: item['scanner-id'], + period: item['granularity-period'], + txEthernetBytesMaxS: checkData(item['performance-data']['tx-ethernet-bytes-max-s']), + txEthernetBytesMaxM: checkData(item['performance-data']['tx-ethernet-bytes-max-m']), + txEthernetBytesSum: checkData(item['performance-data']['tx-ethernet-bytes-sum']), + id: label + }); + }); + } + }; + + //replace -1 with undefined in json data + var checkData = function (value) { + if (value === -1 || value === undefined) return undefined; + else return value; + }; + + //perf log configuration + $scope.gridOptionsPerformance826 = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'es', type: 'string', displayName: 'ES', width: 70 }, + { field: 'ses', type: 'string', displayName: 'SES', width: 70 }, + { field: 'uas', type: 'string', displayName: 'UAS', width: 70 } + ], + data: 'performance826' + }; + + //receive lvl configuration + $scope.gridOptionsReceiveLevel = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'rxmin', type: 'string', displayName: 'Rx min [dBm]', width: 90 }, + { field: 'rxavg', type: 'string', displayName: 'Rx avg [dBm]', width: 90 }, + { field: 'rxmax', type: 'string', displayName: 'Rx max [dBm]', width: 90 } + + ], + data: 'receiveLevel' + }; + + //transmission lvl configuration + $scope.gridOptionsTransmissionLevel = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'txmin', type: 'string', displayName: 'Tx min [dBm]', width: 90 }, + { field: 'txavg', type: 'string', displayName: 'Tx avg [dBm]', width: 90 }, + { field: 'txmax', type: 'string', displayName: 'Tx max [dBm]', width: 90 } + + ], + data: 'transmissionLevel' + }; + + //modulation configuration + $scope.gridOptionsModulation = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'time2S', type: 'string', displayName: 'QAM2S', width: 90 }, + { field: 'time2', type: 'string', displayName: 'QAM2', width: 90 }, + { field: 'time2L', type: 'string', displayName: 'QAM2L', width: 90 }, + { field: 'time4S', type: 'string', displayName: 'QAM4S', width: 90 }, + { field: 'time4', type: 'string', displayName: 'QAM4', width: 90 }, + { field: 'time4L', type: 'string', displayName: 'QAM4L', width: 90 }, + { field: 'time16S', type: 'string', displayName: 'QAM16S', width: 90 }, + { field: 'time16', type: 'string', displayName: 'QAM16', width: 90 }, + { field: 'time16L', type: 'string', displayName: 'QAM16L', width: 90 }, + { field: 'time32S', type: 'string', displayName: 'QAM32S', width: 90 }, + { field: 'time32', type: 'string', displayName: 'QAM32', width: 90 }, + { field: 'time32L', type: 'string', displayName: 'QAM32L', width: 90 }, + { field: 'time64S', type: 'string', displayName: 'QAM64S', width: 90 }, + { field: 'time64', type: 'string', displayName: 'QAM64', width: 90 }, + { field: 'time64L', type: 'string', displayName: 'QAM64L', width: 90 }, + { field: 'time128S', type: 'string', displayName: 'QAM128S', width: 90 }, + { field: 'time128', type: 'string', displayName: 'QAM128', width: 90 }, + { field: 'time128L', type: 'string', displayName: 'QAM128L', width: 90 }, + { field: 'time256S', type: 'string', displayName: 'QAM256S', width: 90 }, + { field: 'time256', type: 'string', displayName: 'QAM256', width: 90 }, + { field: 'time256L', type: 'string', displayName: 'QAM256L', width: 90 }, + { field: 'time512S', type: 'string', displayName: 'QAM512S', width: 90 }, + { field: 'time512', type: 'string', displayName: 'QAM512', width: 90 }, + { field: 'time512L', type: 'string', displayName: 'QAM512L', width: 90 }, + { field: 'time1024S', type: 'string', displayName: 'QAM1024S', width: 90 }, + { field: 'time1024', type: 'string', displayName: 'QAM1024', width: 90 }, + { field: 'time1024L', type: 'string', displayName: 'QAM1024L', width: 90 }, + { field: 'time2048S', type: 'string', displayName: 'QAM2048S', width: 90 }, + { field: 'time2048', type: 'string', displayName: 'QAM2048', width: 90 }, + { field: 'time2048L', type: 'string', displayName: 'QAM2048L', width: 90 }, + { field: 'time4096S', type: 'string', displayName: 'QAM4096S', width: 90 }, + { field: 'time4096', type: 'string', displayName: 'QAM4096', width: 90 }, + { field: 'time4096L', type: 'string', displayName: 'QAM4096L', width: 90 }, + { field: 'time8192S', type: 'string', displayName: 'QAM8192S', width: 90 }, + { field: 'time8192', type: 'string', displayName: 'QAM8192', width: 90 }, + { field: 'time8192L', type: 'string', displayName: 'QAM8192L', width: 90 } + + ], + data: 'modulation', onRegisterApi: function (gridApi) { + $scope.gridApi = gridApi; + } + }; + + //temperature configuration + $scope.gridOptionsTemperature = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'rfTempMin', type: 'string', displayName: 'Rf Temp Min [°C]', width: 90 }, + { field: 'rfTempAvg', type: 'string', displayName: 'Rf Temp Avg [°C]', width: 90 }, + { field: 'rfTempMax', type: 'string', displayName: 'Rf Temp Max [°C]', width: 90 } + + ], + data: 'temperature' + } + + //SNIR configuration + $scope.gridOptionsSnir = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false}, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'snirMin', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MIN'),'[dB]'].join(' '), width: 90 }, + { field: 'snirAvg', type: 'string', displayName: [$translate.instant('MWTN_SNIR_AVG'),'[dB]'].join(' '), width: 90 }, + { field: 'snirMax', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MAX'),'[dB]'].join(' '), width: 90 } + ], + data: 'snir' + } + + //CPD Configuration + $scope.gridOptionsCrossPolarDiscrimination = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'radioSignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'xpdMin', type: 'string', displayName: 'CPD min [dB]', width: 90 }, + { field: 'xpdAvg', type: 'string', displayName: 'CPD avg [dB]', width: 90 }, + { field: 'xpdMax', type: 'string', displayName: 'CPD max [dB]', width: 90 } + + ], + data: 'cpdData' + } + + //ethernet perf configuration + $scope.gridOptionsPerformanceEthernetContainer = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + enablePaginationControls: true, + enableFiltering: true, + enableGridMenu: true, + columnDefs: [ + + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LP'), width: 300 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'Request time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'elapsedTime', type: 'string', displayName: 'Elapsed Time', width: 100 }, + { field: 'period', type: 'string', displayName: 'Period', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'txEthernetBytesMaxS', type: 'number', displayName: 'Tx BytesMaxS', width: 90 }, + { field: 'txEthernetBytesMaxM', type: 'number', displayName: 'Tx BytesMaxM', width: 90 }, + { field: 'txEthernetBytesSum', type: 'number', displayName: 'Tx BytesSum', width: 90 } + + ], + data: 'performanceEthernetContainer' + }; + + var updatePart = function (spec, data, key) { + switch (spec.pacId) { + case 'ne': + updateNe(data); + break; + + case 'airinterface': + console.log(JSON.stringify(spec, JSON.stringify(data))); + updateAirInterface(data, key); + break; + + case 'container': + updateContainer(spec.layerProtocolId, spec.partId, data); + break; + + } + }; + + var refreshAirInterface = function (key) { + //get performance data from interfaces + for (var interf of $scope.airinterfaces) { + var airIterfaceSpec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: 'airinterface', + partId: 'CurrentPerformance', + layerProtocolId: interf.layerProtocol + }; + $mwtnPerformanceCurrent.getPacParts(airIterfaceSpec).then(function (data) { + var yangfiedObj = $mwtnPerformanceCurrent.yangifyObject(data); + updatePart(airIterfaceSpec, yangfiedObj, key); + }); + } + }; + + $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.status = { performanceEthernetContainer: true }; + $scope.spinner = {}; + $scope.separator = $mwtnPerformanceCurrent.separator; //' ' + + //get data on ne selection + $scope.$watch('networkElement', function (neId, oldValue) { + if (neId && neId !== '' && neId !== oldValue) { + $scope.collapseAll(); + + // clear lists visible on screen + $scope.performance826 = []; + $scope.receiveLevel = []; + $scope.transmissionLevel = []; + $scope.modulation = []; + $scope.temperature = []; + $scope.snir = []; + $scope.cpdData = []; + $scope.jsonvalue = []; + $scope.performanceEthernetContainer = []; + $scope.ethernetJsonValue = []; + + var revision; + $scope.networkElements.map(function (ne) { + if (ne.id === neId) revision = ne.revision; + }); + $scope.networkElementId = neId; + $scope.revision = revision; + + var spec = { + nodeId: neId, + revision: revision, + pacId: 'ne' + }; + + //get ne data + $mwtnPerformanceCurrent.getPacParts(spec).then(function (success) { + var yangfiedObj = $mwtnPerformanceCurrent.yangifyObject(success); + + updatePart(spec, yangfiedObj); + + //get performance data from interfaces + $scope.airinterfaces.map(function(airInterface) { + + //get configuration for airinterfaces + var airIterfaceSpec = { + nodeId: neId, + revision: revision, + pacId: 'airinterface', + partId: 'Configuration', + layerProtocolId: airInterface.layerProtocol + }; + + //get radioSignalID and add it to map + $mwtnPerformanceCurrent.getPacParts(airIterfaceSpec).then(function (data) { + var yangfiedObj = $mwtnPerformanceCurrent.yangifyObject(data); + radioSignalMap.set(yangfiedObj['layer-protocol'], yangfiedObj['air-interface-configuration']['radio-signal-id']); + }); + }); + + }, function (error) { + updatePart(spec, error); + }); + } + }); + + $scope.$watch('layerProtocol', function (newValue, oldValue) { + + if (newValue && oldValue !== "" && newValue !== oldValue) { + $scope.collapseAll(); + } + + }, true); + + //update data within tables on accordion - open + $scope.$watch('status', function (status, oldValue) { + Object.keys(status).map(function (key) { + if ($scope.networkElementId && status[key] && status[key] !== oldValue[key]) { + switch (key) { + + case 'performance826': + $scope.performance826 = []; + refreshAirInterface(key); + break; + + case 'receiveLevel': + $scope.receiveLevel = []; + refreshAirInterface(key); + break; + + case 'transmissionLevel': + $scope.transmissionLevel = []; + refreshAirInterface(key); + break; + + case 'modulation': + $scope.modulation = []; + refreshAirInterface(key); + break; + + case 'temperature': + $scope.temperature = []; + refreshAirInterface(key); + break; + + case 'snir': + $scope.snir = []; + refreshAirInterface(key); + break; + + case 'crossPolarDiscrimination': + $scope.cpdData = []; + refreshAirInterface(key); + break; + + case 'performanceEthernetContainer': + $scope.performanceEthernetContainer = []; + $scope.ethernetJsonValue = []; + + //get performance data for ethernet + $scope.ethernets.map(function (item) { + var ethernetSpec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: 'container', + partId: 'CurrentPerformance', + layerProtocolId: item.layerProtocol + }; + + $mwtnPerformanceCurrent.getPacParts(ethernetSpec).then(function (data) { + var yangfiedObj = $mwtnPerformanceCurrent.yangifyObject(data); + updatePart(ethernetSpec, yangfiedObj); + }); + }); + break; + + } + $window.dispatchEvent(new Event("resize")); + } + }); + }, true); + + }]); + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.module.js new file mode 100644 index 00000000..e0e4e2fb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.module.js @@ -0,0 +1,55 @@ +/* + * 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 mwtnPerformanceCurrentApp = angular.module('app.mwtnPerformanceCurrent', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'ui.router.state','ui.grid.exporter', + 'ui.grid.moveColumns', 'ui.grid.pinning', 'ui.grid.selection', + 'ui.grid.resizeColumns', 'ui.grid.pagination','ui.grid.autoResize']); + + mwtnPerformanceCurrentApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnPerformanceCurrentApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + NavHelperProvider.addControllerUrl('app/mwtnPerformanceCurrent/mwtnPerformanceCurrent.controller'); + NavHelperProvider.addToMenu('mwtnPerformanceCurrent', { + "link" : "#/pnfPerformanceCurrent", + "active" : "main.mwtnPerformanceCurrent", + "title" : "pnf PM Current", + "icon" : "fa fa-bar-chart", // Add navigation icon css class here + "page" : { + "title" : "pnf PM Current", + "description" : "mwtnPerformanceCurrent" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnPerformanceCurrent', { + url: 'pnfPerformanceCurrent', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnPerformanceCurrent/mwtnPerformanceCurrent.tpl.html', + controller: 'mwtnPerformanceCurrentCtrl' + } + } + }); + + }); + + return mwtnPerformanceCurrentApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.services.js new file mode 100644 index 00000000..d7adb5a6 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.services.js @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 HCL Inc. 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/mwtnCommons/mwtnCommons.module', 'app/mwtnPerformanceCurrent/mwtnPerformanceCurrent.module'],function(mwtnPerformanceCurrentApp) { + + mwtnPerformanceCurrentApp.register.factory('$mwtnPerformanceCurrent', function($mwtnCommons, $mwtnLog) { + + var COMPONENT = '$mwtnPerformanceCurrent'; + $mwtnLog.info({component: COMPONENT, message: '$mwtnPerformanceCurrent started!'}); + + var service = {}; + + service.separator = $mwtnCommons.separator; + service.parts = $mwtnCommons.parts; + service.getMountPoints = $mwtnCommons.getMountPoints; + service.getPacParts = $mwtnCommons.getPacParts; + service.layerProtocolNameOrder = $mwtnCommons.layerProtocolNameOrder; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + + service.yangifyObject=$mwtnCommons.yangifyObject; + + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.tpl.html new file mode 100644 index 00000000..a212971e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/mwtnPerformanceCurrent-module/src/main/resources/mwtnPerformanceCurrent/mwtnPerformanceCurrent.tpl.html @@ -0,0 +1,119 @@ +<ht-header help-link='sdnr/pnfPerformance/0.4.0/README.md'></ht-header> +<mwtn-select-network-element></mwtn-select-network-element> + +<div class="owl container" ng-if="networkElements.lenght !== 0 && networkElement" style="width: 100%"> + <div class="row"> + <div class="col-md-3"> + <div class="form-group"> + <select class="form-control" ng-model="layerProtocol"> + <option ng-repeat="protocol in layerProtocols">{{protocol}}</option> + </select> + </div> + </div> + <div class="col-md-2"> + <span class="white">{{'Select Layer Protocol' }}</span> + </div> + </div> + <div class="row" ng-if="layerProtocol === 'MWPS' "> + <div class="col"> + <uib-accordion close-others="oneATime"> + <div uib-accordion-group class="panel-primary" is-open="status.performance826"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.performance826, 'fa-chevron-right': !status.performance826}"></i> + <span>Performance Data G.826</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.performance826"></i> + </uib-accordion-heading> + + <div id="mwtnFaultGridAlarmLog" ui-grid="gridOptionsPerformance826" ui-grid-pagination ui-grid-exporter ui-grid-selection + ui-grid-pinning ui-grid-resize-columns ui-grid-auto-resize ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + </div> + <div uib-accordion-group class="panel-primary" is-open="status.receiveLevel"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.receiveLevel, 'fa-chevron-right': !status.receiveLevel}"></i> + <span>Receive Level</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.receiveLevel"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsReceiveLevel" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-auto-resize ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.transmissionLevel"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.transmissionLevel, 'fa-chevron-right': !status.transmissionLevel}"></i> + <span>Transmission Power</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.transmissionLevel"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsTransmissionLevel" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-auto-resize ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.modulation"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.modulation, 'fa-chevron-right': !status.modulation}"></i> + <span>Adaptive Modulation</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.modulation"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsModulation" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.temperature"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.temperature, 'fa-chevron-right': !status.temperature}"></i> + <span>Temperature</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.temperature"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsTemperature" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnFaultGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.snir"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.snir, 'fa-chevron-right': !status.snir}"></i> + <span>{{'MWTN_SINR' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.snir"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsSnir" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.crossPolarDiscrimination"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.crossPolarDiscrimination, 'fa-chevron-right': !status.crossPolarDiscrimination}"></i> + <span>Cross Polar Discrimination</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.crossPolarDiscrimination"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsCrossPolarDiscrimination" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + + </div> + </uib-accordion> + </div> + </div> + <div class="row" ng-if="layerProtocol === 'ETC' "> + <div class="col"> + <uib-accordion close-others="oneATime"> + <div uib-accordion-group class="panel-primary" is-open="status.performanceEthernetContainer"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.performanceEthernetContainer, 'fa-chevron-right': !status.performanceEthernetContainer}"></i> + <span>Performance Data</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.performanceEthernetContainer"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsPerformanceEthernetContainer" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-auto-resize ui-grid-move-columns class="mwtnCurrentGrid"> + </div> + </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/mwtnPerformanceCurrent/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/pom.xml new file mode 100644 index 00000000..7f2c1e52 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceCurrent/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnPerformanceCurrent</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnPerformanceCurrent-module</module> + <module>mwtnPerformanceCurrent-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-bundle/pom.xml new file mode 100644 index 00000000..feb32631 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnPerformanceHistory</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnPerformanceHistory-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnPerformanceHistory-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnPerformanceHistory-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..3288e4f1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnPerformanceHistory"/> + <property name="url" value="/src/app/mwtnPerformanceHistory"/> + <property name="directory" value="/mwtnPerformanceHistory"/> + <property name="requireJs" value="app/mwtnPerformanceHistory/mwtnPerformanceHistory.module"/> + <property name="angularJs" value="app.mwtnPerformanceHistory"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnPerformanceHistory/mwtnPerformanceHistory-custom.css</value> + </list> + </property> + </bean> +</blueprint> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/pom.xml new file mode 100644 index 00000000..9665ca86 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnPerformanceHistory</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnPerformanceHistory-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/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/images/mwtnPerformance.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/images/mwtnPerformance.png Binary files differnew file mode 100755 index 00000000..5517f5b1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/images/mwtnPerformance.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory-custom.css new file mode 100644 index 00000000..43663034 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory-custom.css @@ -0,0 +1,13 @@ +/** + * Add your application related css here + */ + + .mwtnHistoryGrid { + height: 600px; + background-color: white; + color:black; +} + +.mwtnHistoryGrid span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.controller.js new file mode 100644 index 00000000..6a5a2e9a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.controller.js @@ -0,0 +1,1196 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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/mwtnPerformanceHistory/mwtnPerformanceHistory.module', + 'app/mwtnPerformanceHistory/mwtnPerformanceHistory.services'], + function (mwtnPerformanceHistoryoryApp) { + + mwtnPerformanceHistoryoryApp.register.controller('mwtnPerformanceHistoryCtrl', ['$scope', '$rootScope', '$window', '$translate', '$mwtnLog', '$mwtnPerformanceHistory', 'uiGridConstants', 'OnfNetworkElement', + function ($scope, $rootScope, $window, $translate, $mwtnLog, $mwtnPerformanceHistory, uiGridConstants, OnfNetworkElement) { + + var COMPONENT = 'mwtnPerformanceHistory'; + $mwtnLog.info({ component: COMPONENT, message: 'mwtn historical Performance started!' }); + + $rootScope.section_logo = 'src/app/mwtnPerformanceHistory/images/mwtnPerformance.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + var globalFilter; + + $scope.selecteditem = {}; + + //time selector + $scope.selecteditem.timePeriod = "15 minutes"; + $scope.timePeriods = ["15 minutes", "24 hours"]; + + //interface selector + $scope.selecteditem.selectedLtpId = undefined; + $scope.availableLtpIds = []; + + //stateobject + $scope.state = {}; + $scope.state.filter = false; + $scope.state.sort = false; + $scope.state.lastfilter = null; + $scope.state.lastSort = null; + $scope.state.grid = null; + + //perf log configuration + $scope.gridOptionsPerformance826 = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + + { field: 'es', type: 'string', displayName: 'ES', width: 70 }, + { field: 'ses', type: 'string', displayName: 'SES', width: 70 }, + { field: 'uas', type: 'string', displayName: 'UAS', width: 70 } + + ], + data: 'performance826', + onRegisterApi: function (gridApi) { + $scope.performancegridApi = gridApi; + $scope.performancegridApi.core.on.filterChanged($scope, $scope.filter); + $scope.performancegridApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.performancegridApi.grid, [$scope.gridOptionsPerformance826.columnDefs[1]]); + + $scope.performancegridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsPerformance826); + }); + } + }; + + //receive lvl configuration + $scope.gridOptionsReceiveLevel = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'rxmin', type: 'string', displayName: 'Rx min', width: 90 }, + { field: 'rxavg', type: 'string', displayName: 'Rx avg', width: 90 }, + { field: 'rxmax', type: 'string', displayName: 'Rx max', width: 90 } + ], + data: 'receiveLevel', + onRegisterApi: function (gridApi) { + $scope.recvGridApi = gridApi; + $scope.recvGridApi.core.on.filterChanged($scope, $scope.filter); + $scope.recvGridApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.recvGridApi.grid, [$scope.gridOptionsReceiveLevel.columnDefs[1]]); + + $scope.recvGridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsReceiveLevel); + }); + } + }; + + //transmission lvl configuration + $scope.gridOptionsTransmissionLevel = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'txmin', type: 'string', displayName: 'Tx min', width: 90 }, + { field: 'txavg', type: 'string', displayName: 'Tx avg', width: 90 }, + { field: 'txmax', type: 'string', displayName: 'Tx max', width: 90 } + ], + data: 'transmissionLevel', + onRegisterApi: function (gridApi) { + $scope.transmissionGridApi = gridApi; + $scope.transmissionGridApi.core.on.filterChanged($scope, $scope.filter); + $scope.transmissionGridApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.transmissionGridApi.grid, [$scope.gridOptionsTransmissionLevel.columnDefs[1]]); + + $scope.transmissionGridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsTransmissionLevel); + }); + } + }; + + //modulation configuration + $scope.gridOptionsModulation = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'time2S', type: 'string', displayName: 'QAM2S', width: 90 }, + { field: 'time2', type: 'string', displayName: 'QAM2', width: 90 }, + { field: 'time2L', type: 'string', displayName: 'QAM2L', width: 90 }, + { field: 'time4S', type: 'string', displayName: 'QAM4S', width: 90 }, + { field: 'time4', type: 'string', displayName: 'QAM4', width: 90 }, + { field: 'time4L', type: 'string', displayName: 'QAM4L', width: 90 }, + { field: 'time16S', type: 'string', displayName: 'QAM16S', width: 90 }, + { field: 'time16', type: 'string', displayName: 'QAM16', width: 90 }, + { field: 'time16L', type: 'string', displayName: 'QAM16L', width: 90 }, + { field: 'time32S', type: 'string', displayName: 'QAM32S', width: 90 }, + { field: 'time32', type: 'string', displayName: 'QAM32', width: 90 }, + { field: 'time32L', type: 'string', displayName: 'QAM32L', width: 90 }, + { field: 'time64S', type: 'string', displayName: 'QAM64S', width: 90 }, + { field: 'time64', type: 'string', displayName: 'QAM64', width: 90 }, + { field: 'time64L', type: 'string', displayName: 'QAM64L', width: 90 }, + { field: 'time128S', type: 'string', displayName: 'QAM128S', width: 90 }, + { field: 'time128', type: 'string', displayName: 'QAM128', width: 90 }, + { field: 'time128L', type: 'string', displayName: 'QAM128L', width: 90 }, + { field: 'time256S', type: 'string', displayName: 'QAM256S', width: 90 }, + { field: 'time256', type: 'string', displayName: 'QAM256', width: 90 }, + { field: 'time256L', type: 'string', displayName: 'QAM256L', width: 90 }, + { field: 'time512S', type: 'string', displayName: 'QAM512S', width: 90 }, + { field: 'time512', type: 'string', displayName: 'QAM512', width: 90 }, + { field: 'time512L', type: 'string', displayName: 'QAM512L', width: 90 }, + { field: 'time1024S', type: 'string', displayName: 'QAM1024S', width: 90 }, + { field: 'time1024', type: 'string', displayName: 'QAM1024', width: 90 }, + { field: 'time1024L', type: 'string', displayName: 'QAM1024L', width: 90 }, + { field: 'time2048S', type: 'string', displayName: 'QAM2048S', width: 90 }, + { field: 'time2048', type: 'string', displayName: 'QAM2048', width: 90 }, + { field: 'time2048L', type: 'string', displayName: 'QAM2048L', width: 90 }, + { field: 'time4096S', type: 'string', displayName: 'QAM4096S', width: 90 }, + { field: 'time4096', type: 'string', displayName: 'QAM4096', width: 90 }, + { field: 'time4096L', type: 'string', displayName: 'QAM4096L', width: 90 }, + { field: 'time8192S', type: 'string', displayName: 'QAM8192S', width: 90 }, + { field: 'time8192', type: 'string', displayName: 'QAM8192', width: 90 }, + { field: 'time8192L', type: 'string', displayName: 'QAM8192L', width: 90 } + + + ], + data: 'modulation', + 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.gridOptionsModulation.columnDefs[1]]); + + $scope.gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsModulation); + }); + } + }; + + //temperature configuration + $scope.gridOptionsTemperature = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'rfTempMin', type: 'string', displayName: 'Rf Temp Min [°C]', width: 90 }, + { field: 'rfTempAvg', type: 'string', displayName: 'Rf Temp Avg [°C]', width: 90 }, + { field: 'rfTempMax', type: 'string', displayName: 'Rf Temp Max [°C]', width: 90 } + + ], + data: 'temperature', + onRegisterApi: function (gridApi) { + $scope.gridTemperatureApi = gridApi; + $scope.gridTemperatureApi.core.on.filterChanged($scope, $scope.filter); + $scope.gridTemperatureApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.gridTemperatureApi.grid, [$scope.gridOptionsTemperature.columnDefs[1]]); + + $scope.gridTemperatureApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsTemperature); + }); + } + } + + //SNIR configuration + $scope.gridOptionsSnir = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'snirMin', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MIN'),'[dB]'].join(' '), width: 90 }, + { field: 'snirAvg', type: 'string', displayName: [$translate.instant('MWTN_SNIR_AVG'),'[dB]'].join(' '), width: 90 }, + { field: 'snirMax', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MAX'),'[dB]'].join(' '), width: 90 } + ], + data: 'snir', + onRegisterApi: function (gridApi) { + $scope.gridSNIRApi = gridApi; + $scope.gridSNIRApi.core.on.filterChanged($scope, $scope.filter); + $scope.gridSNIRApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.gridSNIRApi.grid, [$scope.gridOptionsSnir.columnDefs[1]]); + + $scope.gridSNIRApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsSnir); + }); + } + } + + //CPD Configuration + $scope.gridOptionsCrossPolarDiscrimination = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'xpdMin', type: 'string', displayName: 'CPD min [dB]', width: 90 }, + { field: 'xpdAvg', type: 'string', displayName: 'CPD avg [dB]', width: 90 }, + { field: 'xpdMax', type: 'string', displayName: 'CPD max [dB]', width: 90 } + + ], + data: 'crossPolarDiscrimination', + onRegisterApi: function (gridApi) { + $scope.gridXpdApi = gridApi; + $scope.gridXpdApi.core.on.filterChanged($scope, $scope.filter); + $scope.gridXpdApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.gridOptionsCrossPolarDiscrimination, [$scope.gridOptionsCrossPolarDiscrimination.columnDefs[1]]); + + $scope.gridXpdApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsCrossPolarDiscrimination); + }); + } + } + + //ethernet perf configuration + $scope.gridOptionsPerformanceEthernetContainer = { + paginationPageSizes: [25, 100, 1000, 10000], + paginationPageSize: 25, + useExternalPagination: true, + useExternalSorting: true, + enablePaginationControls: true, + enableFiltering: true, + useExternalFiltering: true, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90, visible: false }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { + field: 'timestamp', type: 'string', displayName: 'End time', width: 200, sort: { + direction: uiGridConstants.ASC, + priority: 1 + } + }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'txEthernetBytesMaxS', type: 'number', displayName: 'Tx BytesMaxS', width: 90 }, + { field: 'txEthernetBytesMaxM', type: 'number', displayName: 'Tx BytesMaxM', width: 90 }, + { field: 'txEthernetBytesSum', type: 'number', displayName: 'Tx BytesSum', width: 90 } + + ], + data: 'performanceEthernetContainer', + onRegisterApi: function (gridApi) { + $scope.gridPerfEthernetApi = gridApi; + $scope.gridPerfEthernetApi.core.on.filterChanged($scope, $scope.filter); + $scope.gridPerfEthernetApi.core.on.sortChanged($scope, $scope.sortChanged); + $scope.sortChanged($scope.gridPerfEthernetApi.grid, [$scope.gridOptionsPerformanceEthernetContainer.columnDefs[1]]); + + $scope.gridPerfEthernetApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + getPage($scope.gridOptionsPerformanceEthernetContainer); + }); + } + }; + + //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.field); + if (col === "time-stamp") { + //convert timestamp to db format + var timestamp = $mwtnPerformanceHistory.TimeStampToONFFormat(value.filters[0].term); + columns.push({ column: col, value: timestamp }); + } + else + columns.push({ column: col, value: value.filters[0].term }); //create column object + } + }); + + if (columns.length == 0) { //all filter data cleared away + $scope.state.filter = false; + $scope.state.lastfilter = null; + + //get unfiltered data + getData($scope.state.lastSort, $scope.state.lastfilter, grid.options, null, null).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, grid.options); + + } + }); + + } else { + //base filter string + var filter = { "query": { "bool": { "must": [] } } }; + + //create filter objects + var prefixs = []; + prefixs.push({ prefix: globalFilter }); + + columns.map(function (obj) { + var prefixObj = {}; + prefixObj[obj.column] = obj.value;//add like: {column: "fault.counter", value: "1"} => {"fault.counter":1} + prefixs.push({ prefix: prefixObj }); // => {"prefix":{...}} + }); + + //add objects to must property + filter.query.bool.must = prefixs; + + //save filter + $scope.state.lastfilter = filter; + $scope.state.filter = true; + + getData($scope.state.lastSort, $scope.state.lastfilter, grid.options, filter, null).then(function (response) { + if (response.data.hits.total > 0) { //only, when hits exist + processRequestInGrid(response, grid.options); + //$scope.gridOptionsAlarmLog.totalItems = response.data.hits.total; + } else { + //clear data from list + $scope[grid.options.data] = []; + grid.options.totalItems = 0; + + } + }); + } + }; + + $scope.sortChanged = function (grid, sortColumns) { // sortColumns is an array containing just the column sorted in the grid + + + if (sortColumns && sortColumns.length > 0) { + if (sortColumns[0].sort) { + var name = sortColumns[0].field; // the field (name) of the column sorted + var direction = sortColumns[0].sort.direction // the direction of the column sorted: "desc" or "asc" + sort(direction, findColumn(name), grid); + } + } else if (sortColumns) { + $scope.state.sort = false; + $scope.state.lastSort = null; + + //get unsorted data + getData($scope.state.lastSort, $scope.state.lastfilter, grid.options, null, null).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, grid.options); + } + }); + } + }; + + var sort = function (direction, columnName, grid) { + switch (direction) { + case uiGridConstants.ASC: + + //create sort object + var sortObj = {}; + sortObj[columnName] = { order: 'asc' }; + var sort = [sortObj]; + //save last sort + $scope.state.lastSort = sort; + + getData($scope.state.lastSort, $scope.state.lastfilter, grid.options, null, sort).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, grid.options); + $scope.state.sort = true; + + } + }); + + break; + + case uiGridConstants.DESC: + + var sortObj = {}; + sortObj[columnName] = { order: 'desc' }; + var sort = [sortObj]; + $scope.state.lastSort = sort; + + getData($scope.state.lastSort, $scope.state.lastfilter, grid.options, null, sort).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, grid.options); + $scope.state.sort = true; + } + }); + break; + + case undefined: + + $scope.state.sort = false; + $scope.state.lastSort = null; + + getData($scope.state.lastSort, $scope.state.lastfilter, grid.options, null, null) + .then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, grid.options); + } + }); + + break; + } + } + + function findColumn(name) { + + if (name === "timestamp") { return "time-stamp"; } + else if (name === "layerprotocol") { return "layer-protocol-name"; } + else if (name === "id") { return "uuid-interface"; } + else if (name === "suspectInterval") { return "suspect-interval-flag"; } + else if (name === "scannerId") { return "scanner-id"; } + else if (name === "radiosignal") { return "radio-signal-id"; } + else if (name === "es") { return "performance-data.es"; } + else if (name === "ses") { return "performance-data.ses"; } + else if (name === "uas") { return "performance-data.unavailability"; } + else if (name === "rxmin") { return "performance-data.rx-level-min"; } + else if (name === "rxmax") { return "performance-data.rx-level-max"; } + else if (name === "rxavg") { return "performance-data.rx-level-avg"; } + else if (name === "txmin") { return "performance-data.tx-level-min"; } + else if (name === "txmax") { return "performance-data.tx-level-max"; } + else if (name === "txavg") { return "performance-data.tx-level-avg"; } + else if (name === "Tx BytesMaxS") { return "performance-data.tx-ethernet-bytes-max-s"; } + else if (name === "Tx BytesMaxM") { return "performance-data.tx-ethernet-bytes-max-m"; } + else if (name === "Tx BytesSum") { return "performance-data.tx-ethernet-bytes-sum"; } + else if (name === "xpdMin") { return "performance-data.xpd-min"; } + else if (name === "xpdAvg") { return "performance-data.xpd-avg"; } + else if (name === "xpdMax") { return "performance-data.xpd-max"; } + else if (name === "snirMin") { return "performance-data.snir-min"; } + else if (name === "snirAvg") { return "performance-data.snir-avg"; } + else if (name === "snirMax") { return "performance-data.snir-max"; } + else if (name === "rfTempMin") { return "performance-data.rf-temp-min"; } + else if (name === "rfTempAvg") { return "performance-data.rf-temp-avg"; } + else if (name === "rfTempMax") { return "performance-data.rf-temp-max"; } + else if (name === "time2S") { return "performance-data.time2-states-s"; } + else if (name === "time2") { return "performance-data.time2-states"; } + else if (name === "time2L") { return "performance-data.time2-states-l"; } + else if (name === "time4S") { return "performance-data.time4-states-s"; } + else if (name === "time4") { return "performance-data.time4-states"; } + else if (name === "time4L") { return "performance-data.time4-states-l"; } + else if (name === "time16S") { return "performance-data.time16-states-s"; } + else if (name === "time16") { return "performance-data.time16-states"; } + else if (name === "time16L") { return "performance-data.time16-states-l"; } + else if (name === "time32S") { return "performance-data.time32-states-s"; } + else if (name === "time32") { return "performance-data.time32-states"; } + else if (name === "time32L") { return "performance-data.time32-states-l"; } + else if (name === "time64S") { return "performance-data.time64-states-s"; } + else if (name === "time64") { return "performance-data.time64-states"; } + else if (name === "time64L") { return "performance-data.time64-states-l"; } + else if (name === "time128S") { return "performance-data.time128-states-s"; } + else if (name === "time128") { return "performance-data.time128-states"; } + else if (name === "time128L") { return "performance-data.time128-states-l"; } + else if (name === "time256S") { return "performance-data.time256-states-s"; } + else if (name === "time256") { return "performance-data.time256-states"; } + else if (name === "time256L") { return "performance-data.time256-states-l"; } + else if (name === "time512S") { return "performance-data.time512-states-s"; } + else if (name === "time512") { return "performance-data.time512-states"; } + else if (name === "time512L") { return "performance-data.time512-states-l"; } + else if (name === "time1024S") { return "performance-data.time1024-states-s"; } + else if (name === "time1024") { return "performance-data.time1024-states"; } + else if (name === "time1024L") { return "performance-data.time1024-states-l"; } + else if (name === "time2048S") { return "performance-data.time2048-states-s"; } + else if (name === "time2048") { return "performance-data.time2048-states"; } + else if (name === "time2048L") { return "performance-data.time2048-states-l"; } + else if (name === "time4096S") { return "performance-data.time4096-states-s"; } + else if (name === "time4096") { return "performance-data.time4096-states"; } + else if (name === "time4096L") { return "performance-data.time4096-states-l"; } + else if (name === "time8192S") { return "performance-data.time8192-states-s"; } + else if (name === "time8192") { return "performance-data.time8192-states"; } + else if (name === "time8192L") { return "performance-data.time8192-states-l"; } + + + }; + + var checkData = function (value) { + if (value === -1 || value === undefined) return undefined; + else return value; + }; + + var getPage = function (grid) { + + //from, how many, sort, filter + getData($scope.state.lastSort, $scope.state.lastfilter, grid, null, null) + .then(function (data) { + + processRequestInGrid(data, grid); + }); + }; + + var processRequestInGrid = function (response, grid) { + // console.log(grid.data); + switch (grid.data) { + case "performance826": + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + es: checkData(entry._source['performance-data'].es), + ses: checkData(entry._source['performance-data'].ses), + uas: checkData(entry._source['performance-data'].unavailability), + radiosignal: entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + $scope.performance826 = list; + $scope.gridOptionsPerformance826.totalItems = response.data.hits.total; + break; + case "transmissionLevel": + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + txmin: checkData(entry._source['performance-data']['tx-level-min']), + txavg: checkData(entry._source['performance-data']['tx-level-avg']), + txmax: checkData(entry._source['performance-data']['tx-level-max']), + radiosignal: entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + $scope.transmissionLevel = list; + $scope.gridOptionsTransmissionLevel.totalItems = response.data.hits.total; + + break; + case "receiveLevel": + + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + rxmin: checkData(entry._source['performance-data']['rx-level-min']), + rxavg: checkData(entry._source['performance-data']['rx-level-avg']), + rxmax: checkData(entry._source['performance-data']['rx-level-max']), + radiosignal: entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + $scope.receiveLevel = list; + $scope.gridOptionsReceiveLevel.totalItems = response.data.hits.total; + + break; + case "modulation": + + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + time2S: checkData(entry._source['performance-data']['time2-states-s']), + time2: checkData(entry._source['performance-data']['time2-states']), + time2L: checkData(entry._source['performance-data']['time2-states-l']), + time4S: checkData(entry._source['performance-data']['time4-states-s']), + time4: checkData(entry._source['performance-data']['time4-states']), + time4L: checkData(entry._source['performance-data']['time4-states-l']), + time16S: checkData(entry._source['performance-data']['time16-states-s']), + time16: checkData(entry._source['performance-data']['time16-states']), + time16L: checkData(entry._source['performance-data']['time16-states-l']), + time32S: checkData(entry._source['performance-data']['time32-states-s']), + time32: checkData(entry._source['performance-data']['time32-states']), + time32L: checkData(entry._source['performance-data']['time32-states-l']), + time64S: checkData(entry._source['performance-data']['time64-states-s']), + time64: checkData(entry._source['performance-data']['time64-states']), + time64L: checkData(entry._source['performance-data']['time64-states-l']), + time128S: checkData(entry._source['performance-data']['time128-states-s']), + time128: checkData(entry._source['performance-data']['time128-states']), + time128L: checkData(entry._source['performance-data']['time128-states-l']), + time256S: checkData(entry._source['performance-data']['time256-states-s']), + time256: checkData(entry._source['performance-data']['time256-states']), + time256L: checkData(entry._source['performance-data']['time256-states-l']), + time512S: checkData(entry._source['performance-data']['time512-states-s']), + time512: checkData(entry._source['performance-data']['time512-states']), + time512L: checkData(entry._source['performance-data']['time512-states-l']), + time1024S: checkData(entry._source['performance-data']['time1024-states-s']), + time1024: checkData(entry._source['performance-data']['time1024-states']), + time1024L: checkData(entry._source['performance-data']['time1024-states-l']), + time2048S: checkData(entry._source['performance-data']['time2048-states-s']), + time2048: checkData(entry._source['performance-data']['time2048-states']), + time2048L: checkData(entry._source['performance-data']['time2048-states-l']), + time4096S: checkData(entry._source['performance-data']['time4096-states-s']), + time4096: checkData(entry._source['performance-data']['time4096-states']), + time4096L: checkData(entry._source['performance-data']['time4096-states-l']), + time8192S: checkData(entry._source['performance-data']['time8192-states-s']), + time8192: checkData(entry._source['performance-data']['time8192-states']), + time8192L: checkData(entry._source['performance-data']['time8192-states-l']), + radiosignal: entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + $scope.modulation = list; + $scope.gridOptionsModulation.totalItems = response.data.hits.total; + + break; + + case "temperature": + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + rfTempMin: entry._source['performance-data']['rf-temp-min'], + rfTempAvg: entry._source['performance-data']['rf-temp-avg'], + rfTempMax: entry._source['performance-data']['rf-temp-max'], + radiosignal: entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + $scope.temperature = list; + $scope.gridOptionsTemperature.totalItems = response.data.hits.total; + + break; + + case "snir": + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + snirMin: entry._source['performance-data']['snir-min'], + snirAvg: entry._source['performance-data']['snir-avg'], + snirMax: entry._source['performance-data']['snir-max'], + radiosignal: entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + $scope.snir = list; + $scope.gridOptionsSnir.totalItems = response.data.hits.total; + + break; + + case "crossPolarDiscrimination": + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + xpdMin: entry._source['performance-data']['xpd-min'], + xpdAvg: entry._source['performance-data']['xpd-avg'], + xpdMax: entry._source['performance-data']['xpd-max'], + radiosignal: entry._source['radio-signal-id'] + + }; + + list.push(item); + + }); + $scope.crossPolarDiscrimination = list; + $scope.gridOptionsCrossPolarDiscrimination.totalItems = response.data.hits.total; + + break; + + + case "performanceEthernetContainer": + + var list = []; + + response.data.hits.hits.map(function (entry) { + var item = { + timestamp: $mwtnPerformanceHistory.formatTimeStamp(entry._source['time-stamp']), + id: $scope.onfNetworkElement.getLpById(entry._source['uuid-interface']).getLabel() || entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + period: entry._source['granularity-period'], + txEthernetBytesMaxS: checkData(entry._source['performance-data']['tx-ethernet-bytes-max-s']), + txEthernetBytesMaxM: checkData(entry._source['performance-data']['tx-ethernet-bytes-max-m']), + txEthernetBytesSum: checkData(entry._source['performance-data']['tx-ethernet-bytes-sum']) + + }; + + list.push(item); + + }); + $scope.performanceEthernetContainer = list; + $scope.gridOptionsPerformanceEthernetContainer.totalItems = response.data.hits.total; + + break; + } + }; + + var getData = function (sort, query, grid, currFilter, currSort) { + + // console.log(grid); + var pagesize; + var pagenr; + + switch (grid.data) { //get pagesize / nr according to current grid (else everything gets messy => wana get next page in grid a, get next page for grid b too) + case 'performance826': + pagesize = $scope.gridOptionsPerformance826.paginationPageSize; + pagenr = $scope.gridOptionsPerformance826.paginationCurrentPage; + break; + + case 'receiveLevel': + pagesize = $scope.gridOptionsReceiveLevel.paginationPageSize; + pagenr = $scope.gridOptionsReceiveLevel.paginationCurrentPage; + break; + + case 'transmissionLevel': + pagesize = $scope.gridOptionsTransmissionLevel.paginationPageSize; + pagenr = $scope.gridOptionsTransmissionLevel.paginationCurrentPage; + break; + + case 'modulation': + pagesize = $scope.gridOptionsModulation.paginationPageSize; + pagenr = $scope.gridOptionsModulation.paginationCurrentPage; + break; + + case 'temperature': + pagesize = $scope.gridOptionsTemperature.paginationPageSize; + pagenr = $scope.gridOptionsTemperature.paginationCurrentPage; + break; + + case 'snir': + pagesize = $scope.gridOptionsSnir.paginationPageSize; + pagenr = $scope.gridOptionsSnir.paginationCurrentPage; + break; + + case 'crossPolarDiscrimination': + pagesize = $scope.gridOptionsCrossPolarDiscrimination.paginationPageSize; + pagenr = $scope.gridOptionsCrossPolarDiscrimination.paginationCurrentPage; + break; + + case 'performanceEthernetContainer': + pagesize = $scope.gridOptionsPerformanceEthernetContainer.paginationPageSize; + pagenr = $scope.gridOptionsPerformanceEthernetContainer.paginationCurrentPage; + break; + + default: + $mwtnLog.warning({component: COMPONENT, message: ['Unexpected grid.data', grid.data, '!'].join(' ')}); + } + + if (grid !== undefined) { + + if ($scope.state.grid === null || $scope.state.grid === undefined) { + $scope.state.grid = grid.data; + } + + //check, if sort/filter params are for current grid + if ($scope.state.grid !== grid.data) { + $scope.state.sort = false; + $scope.state.lastSort = null; + $scope.state.filter = false; + $scope.state.lastfilter = null; + if (currSort !== null) { + sort = currSort; + } else { + sort = null; + } + + if (currFilter !== null) { + query = currFilter; + } else { + query = null; + } + + //update current grid + $scope.state.grid = grid.data; + } + } + + if (!sort) { //default sort value + sort = [{ 'time-stamp': { order: 'desc' } }]; + //sort=[]; + } + if (!query) { //default filter value + query = { query: { bool: { must: [{ prefix: globalFilter }] } } }; + } + + //add layer protocol selector to filter query + var localQuery = angular.copy(query); //copy the object for adding layerprotocol locally + var lpn = $scope.layerProtocol; + if (lpn === 'ETC' && $scope.revision.contains('2016')) lpn = 'ETH-CTP'; + localQuery.query.bool.must.push({ prefix: { "layer-protocol-name": lpn } }); + + //add interface selector to filter query + if ($scope.selecteditem.selectedLtpId) { + localQuery.query.bool.must.push({ prefix: { "uuid-interface": $scope.selecteditem.selectedLtpId } }); + } + + var selected15minPeriod = true; + if ($scope.selecteditem.timePeriod !== $scope.timePeriods[0]) selected15minPeriod = false; + console.warn('selected15minPeriod', selected15minPeriod); + return $mwtnPerformanceHistory.getFilteredSortedData((pagenr - 1) * pagesize, pagesize, sort, localQuery, selected15minPeriod); + }; + + /** + * function to calculate the current open tab + * @param status - Object of current tab opening information + * @param previousStatus - optional Object of previous tab opening information + * @return latest opened tab key or undefined, in case none is currently open + */ + var getKey = function(status, previousStatus) { + var result = Object.keys(status).filter(function(key){ + return status[key] === true && !(previousStatus && previousStatus[key]) + }); + if (result.length > 0) { + return result[0]; + } + } + + // events + $scope.status = { performance826: true, performanceEthernetContainer: false }; + $scope.spinner = {}; + + $scope.$watch(function() { + return $scope.selecteditem; + }, function (newValue, oldValue) { + console.warn('selecteditem###', newValue, oldValue, $scope.networkElementId ); + + if (newValue.selectedLtpId && newValue.selectedLtpId !== oldValue.selectedLtpId && $scope.onfNetworkElement) { + $scope.layerProtocol = $scope.onfNetworkElement.getLpById(newValue.selectedLtpId).getLayer(); + + $scope.performance826 = []; + $scope.receiveLevel = []; + $scope.transmissionLevel = []; + $scope.modulation = []; + $scope.temperature = []; + $scope.performanceEthernetContainer = []; + $scope.snir = []; + $scope.crossPolarDiscrimination = []; + $scope.jsonvalue = []; + + // if all tabs are closed - open first. + var isOneTabOpen = Object.keys($scope.status).filter(function(key){ + return $scope.status[key] === true; + }).length > 0; + if (!isOneTabOpen) { + $scope.status = { performance826: $scope.layerProtocol === 'MWPS', performanceEthernetContainer: $scope.layerProtocol === 'ETC' }; + } + } + + chooseGrid(getKey($scope.status)); + + }, true); + + + $scope.$watch('status', function (status, oldValue) { + console.warn('status', status, oldValue,$scope.networkElementId ); + if ($scope.networkElementId && status && status !== oldValue) { + chooseGrid(getKey(status, oldValue)); + } + }, true); + + + // $scope.$watch(function(){ + // $scope.selecteditem.timePeriod; + // }, function (newValue, oldValue) { + // console.warn('timePeriod', status, oldValue,$scope.networkElementId ); + // if (newValue && oldValue !== "" && newValue !== oldValue) { + // chooseGrid(getKey($scope.status)); + // } + // }, true); + + $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; + }); + }; + + var order = $mwtnPerformanceHistory.layerProtocolNameOrder; + + /** + * @function updateNe + * A function, which updates onfNetworkElement by new data. + * @param {*} data New data recieved from OpenDaylight via RestConf + */ + var updateNe = function(data) { + if (!data) return; + // update onfNetworkElement + switch ($scope.revision) { + case '2016-08-09': + case '2016-08-11': + case '2016-09-01': + case '2017-02-17': + case '2017-03-20': + case '2017-03-24': + // console.log(JSON.stringify(data)); + $scope.onfNetworkElement = new OnfNetworkElement(data['network-element']); + $scope.onfLtps = $scope.onfNetworkElement.getLogicalTerminationPoints().filter(function(ltp){ + return ltp.getLayer() === 'MWPS' || ltp.getLayer() === 'ETC'; + }).sort(function(a, b){ + if(order[a.getLayer()] < order[b.getLayer()]) return 1; + if(order[a.getLayer()] > order[b.getLayer()]) return -1; + if(a.getId() < b.getId()) return -1; + if(a.getId() > b.getId()) return 1; + return 0; + }); + $scope.availableLtpIds = $scope.onfLtps.map(function(ltp){ + return {key: ltp.getLayerProtocols()[0].getId(), label:ltp.getLabel()}; + }); + if ($scope.availableLtpIds.length > 0) { + $scope.selecteditem.selectedLtpId = $scope.availableLtpIds[0].key; + } + break; + default: + $mwtnLog.info({component: COMPONENT, message: ['The ONF Microwave Model revision', $scope.revision, ' is not supported (yet)!'].join(' ')}); + $scope.onfNetworkElement = {}; + $scope.onfLtps = {}; + } + }; + + var updatePart = function(spec, data) { + switch (spec.pacId) { + case 'ne': + updateNe(data); + break; + } + }; + + //get data on ne selection + $scope.$watch('networkElement', function (neId, oldValue) { + console.warn('networkElement', neId, oldValue,$scope.networkElementId ); + + if (neId && neId !== '' && neId !== oldValue) { + $scope.selecteditem.selectedLtpId = undefined; + var revision; + $scope.networkElements.map(function (ne) { + if (ne.id === neId) revision = ne.revision; + }); + $scope.networkElementId = neId; + $scope.revision = revision; + + //get data + var filter = { "query": { "bool": { "must": [{ "prefix": { "node-name": $scope.networkElementId } }] } } }; + // var filter={"query":{"bool":{"must":[{"prefix":{"node-name": "new"}}]}}}; //first part of my local simulator name + globalFilter = filter.query.bool.must[0].prefix; + $scope.state.filter = true; + $scope.state.lastfilter = filter; + $scope.state.sort = false; + $scope.state.lastSort = null; + + // get onf network element data + var spec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: 'ne' + }; + console.warn('PM HIstory getPacPMHistory', JSON.stringify(spec)); + $mwtnPerformanceHistory.getPacParts(spec).then(function(success){ + $scope.collapseAll(); + // console.warn('PM HIstory getPacPMHistory', JSON.stringify(success)); + updatePart(spec, $mwtnPerformanceHistory.yangifyObject(success)); + }, function(error){ + console.error(JSON.stringify(error)); + $scope.collapseAll(); + updatePart(spec, error); + }); + } + }); + + var chooseGrid = function (key) { + if (!$scope.networkElementId || !key) return; + + switch (key) { + + case 'performance826': + getData(null, null, $scope.gridOptionsPerformance826).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsPerformance826); + } + }); + break; + + case 'receiveLevel': + getData(null, null, $scope.gridOptionsReceiveLevel).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsReceiveLevel); + } + }); + break; + + case 'transmissionLevel': + getData(null, null, $scope.gridOptionsTransmissionLevel).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsTransmissionLevel); + } + }); + break; + + case 'modulation': + getData(null, null, $scope.gridOptionsModulation).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsModulation); + } + }); + break; + + case 'temperature': + getData(null, null, $scope.gridOptionsTemperature).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsTemperature); + } + }); + break; + + case 'snir': + getData(null, null, $scope.gridOptionsSnir).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsSnir); + } + }); + break; + + case 'crossPolarDiscrimination': + getData(null, null, $scope.gridOptionsCrossPolarDiscrimination).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsCrossPolarDiscrimination); + } + }); + break; + + case 'performanceEthernetContainer': + getData(null, null, $scope.gridOptionsPerformanceEthernetContainer).then(function (response) { + if (response.data.hits.hits) { + processRequestInGrid(response, $scope.gridOptionsPerformanceEthernetContainer); + } + }); + break; + } + $window.dispatchEvent(new Event("resize")); + }; + }]); + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.module.js new file mode 100644 index 00000000..4199ae62 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.module.js @@ -0,0 +1,55 @@ +/* + * 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 mwtnPerformanceHistoryApp = angular.module('app.mwtnPerformanceHistory', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'ui.router.state','ui.grid.exporter', + 'ui.grid.moveColumns', 'ui.grid.pinning', 'ui.grid.selection', + 'ui.grid.resizeColumns', 'ui.grid.pagination']); + + mwtnPerformanceHistoryApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnPerformanceHistoryApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + NavHelperProvider.addControllerUrl('app/mwtnPerformanceHistory/mwtnPerformanceHistory.controller'); + NavHelperProvider.addToMenu('mwtnPerformanceHistory', { + "link" : "#/pnfPerformanceHistory/", + "active" : "main.mwtnPerformanceHistory", + "title" : "pnf PM History", + "icon" : "fa fa-bar-chart", // Add navigation icon css class here + "page" : { + "title" : "pnf PM History", + "description" : "mwtnHistoricalPerformance" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnPerformanceHistory', { + url: 'pnfPerformanceHistory/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnPerformanceHistory/mwtnPerformanceHistory.tpl.html', + controller: 'mwtnPerformanceHistoryCtrl' + } + } + }); + + }); + + return mwtnPerformanceHistoryApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.services.js new file mode 100644 index 00000000..94aeb935 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.services.js @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 HCL Inc. 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/mwtnCommons/mwtnCommons.module', 'app/mwtnPerformanceHistory/mwtnPerformanceHistory.module'], function (mwtnPerformanceHistoryoryApp) { + + mwtnPerformanceHistoryoryApp.register.factory('$mwtnPerformanceHistory', function ($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var COMPONENT = '$mwtnPerformanceHistory'; + $mwtnLog.info({ component: COMPONENT, message: '$mwtnPerformanceHistory started!' }); + + var service = {}; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.getMountPoints = $mwtnCommons.getMountPoints; + service.getPacParts = $mwtnCommons.getPacParts; + service.layerProtocolNameOrder = $mwtnCommons.layerProtocolNameOrder; + + service.yangifyObject = $mwtnCommons.yangifyObject; + + service.TimeStampToONFFormat = function (timestamp) { + timestamp = timestamp.split('-').join(''); + timestamp = timestamp.split(':').join(''); + timestamp = timestamp.split(' ').join(''); + timestamp = timestamp.replace('UTC', 'Z'); + return timestamp; + }; + + service.getFilteredSortedData = function (from, size, sort, query, selected15minPeriod) { + var func = function () { + if (selected15minPeriod) { + return $mwtnDatabase.getFilteredSortedData('sdnperformance', 'historicalperformance15min', from, size, sort, query); + } else { + return $mwtnDatabase.getFilteredSortedData('sdnperformance', 'historicalperformance24h', from, size, sort, query); + } + }; + var deferred = $q.defer(); + func().then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: '$mwtnHistPerformance.getFilteredSortedData', message: JSON.stringify(error.data) }); + deferred.reject(error) + }); + return deferred.promise; + + }; + + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.tpl.html new file mode 100644 index 00000000..bb5f6e46 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/mwtnPerformanceHistory-module/src/main/resources/mwtnPerformanceHistory/mwtnPerformanceHistory.tpl.html @@ -0,0 +1,127 @@ +<ht-header help-link='sdnr/pnfPerformance/0.4.0/README.md'></ht-header> +<mwtn-select-network-element></mwtn-select-network-element> + +<div class="owl container" ng-if="networkElements.lenght !== 0 && networkElement" style="width: 100%"> + + <div class="row" ng-show="networkElements.lenght !== 0"> + <div class="col-md-3"> + <div class="form-group"> + <select class="form-control" ng-model="selecteditem.selectedLtpId"> + <option ng-repeat="ltp in availableLtpIds" value="{{ltp.key}}">{{ltp.label}}</option> + </select> + </div> + </div> + <div class="col-md-3"> + <span class="white">{{'MWTN_SELECT_LTP' | translate }}</span> + </div> + <div class="col-md-2"> + <div class="form-group"> + <select class="form-control" ng-model="selecteditem.timePeriod"> + <option ng-repeat="time in timePeriods">{{time}}</option> + </select> + </div> + </div> + <div class="col-md-2"> + <span class="white">{{'MWTN_TIME_PERIOD' | translate}}</span> + </div> + </div> + + <div class="row" ng-show="selecteditem.selectedLtpId"> + <div class="col-md-12"> + <uib-accordion close-others="true"> + <div uib-accordion-group class="panel-primary" is-open="status.performance826" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.performance826, 'fa-chevron-right': !status.performance826}"></i> + <span>Performance Data G.826</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.performance826"></i> + </uib-accordion-heading> + + <div id="mwtnFaultGridAlarmLog" ui-grid="gridOptionsPerformance826" ui-grid-pagination ui-grid-exporter ui-grid-selection + ui-grid-pinning ui-grid-resize-columns ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + </div> + <div uib-accordion-group class="panel-primary" is-open="status.receiveLevel" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.receiveLevel, 'fa-chevron-right': !status.receiveLevel}"></i> + <span>Receive Level</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.receiveLevel"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsReceiveLevel" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.transmissionLevel" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.transmissionLevel, 'fa-chevron-right': !status.transmissionLevel}"></i> + <span>Transmission Power</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.transmissionLevel"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsTransmissionLevel" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.modulation" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.modulation, 'fa-chevron-right': !status.modulation}"></i> + <span>Adaptive Modulation</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.modulation"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsModulation" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.temperature" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.temperature, 'fa-chevron-right': !status.temperature}"></i> + <span>Temperature</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.temperature"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsTemperature" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.snir" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.snir, 'fa-chevron-right': !status.snir}"></i> + <span>{{'MWTN_SINR' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.snir"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsSnir" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + + </div> + <div uib-accordion-group class="panel-primary" is-open="status.crossPolarDiscrimination" ng-show="layerProtocol==='MWPS'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.crossPolarDiscrimination, 'fa-chevron-right': !status.crossPolarDiscrimination}"></i> + <span>Cross Polar Discrimination</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.crossPolarDiscrimination"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsCrossPolarDiscrimination" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + + </div> + + <div uib-accordion-group class="panel-primary" is-open="status.performanceEthernetContainer" ng-show="layerProtocol==='ETC'"> + <uib-accordion-heading> <i class="pull-left fa" ng-class="{'fa-chevron-down': status.performanceEthernetContainer, 'fa-chevron-right': !status.performanceEthernetContainer}"></i> + <span>Performance Data</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.performanceEthernetContainer"></i> + </uib-accordion-heading> + + <div ui-grid="gridOptionsPerformanceEthernetContainer" ui-grid-pagination ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns + ui-grid-auto-resize ui-grid-move-columns class="mwtnHistoryGrid"> + </div> + </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/mwtnPerformanceHistory/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/pom.xml new file mode 100644 index 00000000..2d6ced8c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceHistory/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnPerformanceHistory</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnPerformanceHistory-module</module> + <module>mwtnPerformanceHistory-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-bundle/pom.xml new file mode 100644 index 00000000..ebc28975 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnPerformanceLink</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnPerformanceLink-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnPerformanceLink-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnPerformanceLink-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..0f87a770 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnPerformanceLink"/> + <property name="url" value="/src/app/mwtnPerformanceLink"/> + <property name="directory" value="/mwtnPerformanceLink"/> + <property name="requireJs" value="app/mwtnPerformanceLink/mwtnPerformanceLink.module"/> + <property name="angularJs" value="app.mwtnPerformanceLink"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnPerformanceLink/mwtnPerformanceLink-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/pom.xml new file mode 100644 index 00000000..7be5f5f2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnPerformanceLink</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnPerformanceLink-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/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/images/mwtnPerformance.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/images/mwtnPerformance.png Binary files differnew file mode 100755 index 00000000..5517f5b1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/images/mwtnPerformance.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink-custom.css new file mode 100644 index 00000000..eafc20b5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink-custom.css @@ -0,0 +1,17 @@ +/** + * Add your application related css here + */ + +.mwtnLinkGrid { + height: 600px; + background-color: white; + color:black; +} + +.mwtnLinkGrid span { + color: #393939; +} + +.ht-pagination span{ + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.controller.js new file mode 100644 index 00000000..bb3ac9c2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.controller.js @@ -0,0 +1,3346 @@ +/* + * 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/mwtnPerformanceLink/mwtnPerformanceLink.module', + 'app/mwtnPerformanceLink/mwtnPerformanceLink.services'], + function (mwtnPerformanceLinkApp) { + + mwtnPerformanceLinkApp.register.controller('mwtnPerformanceLinkCtrl', ['$scope', '$rootScope', '$window', '$translate', '$mwtnLog', '$mwtnPerformanceLink', 'uiGridConstants', + function ($scope, $rootScope, $window, $translate, $mwtnLog, $mwtnPerformanceLink, uiGridConstants) { + + var COMPONENT = 'mwtnPerformanceLink'; + $mwtnLog.info({ component: COMPONENT, message: 'mwtn Link Performance started!' }); + + $rootScope.section_logo = 'src/app/mwtnPerformanceLink/images/mwtnPerformance.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + var globalFilter; + + //time selector + $scope.timePeriod = "15 minutes"; + $scope.timePeriods = ["15 minutes", "24 hours"]; + + //interface selector + $scope.selectedLtpIdA = 'Select LTP'; + $scope.selectedLtpIdB = 'Select LTP'; + $scope.availableLtpIdsA = ['Select LTP']; + $scope.availableLtpIdsB = ['Select LTP']; + + var formatTimeStamp = function(timeStamp) { + var result = $mwtnPerformanceLink.formatTimeStamp(timeStamp); + // 2017-06-22 14:52:21.0 UTC -> 2017-06-22 14:52 UTC + var array = result.split(' '); + if (array && array.length === 3) { + result = [array[0], array[1].slice(0,-5), array[2]].join(' '); + } + return result; + }; + + var initNodeList = function (nodes) { + $scope.networkElements = []; + nodes.map(function (ne) { + // revision detection should go to commons + if (ne['netconf-node-topology:connection-status'] === 'connected' && ne['netconf-node-topology:available-capabilities'] && ne['netconf-node-topology:available-capabilities']['available-capability']) { + ne['netconf-node-topology:available-capabilities']['available-capability'].map(function (cap) { + if (cap.contains('CoreModel-CoreNetworkModule-ObjectClasses')) { + ne.onfCoreModelRevision = cap.split('?revision=')[1].substring(0, 10); + } else if (cap.contains('MicrowaveModel-ObjectClasses-AirInterface')) { + ne.onfAirInterfaceRevision = cap.split('?revision=')[1].substring(0, 10); + } else if (!ne.onfAirInterfaceRevision && cap.contains('MicrowaveModel-ObjectClasses')) { + ne.onfAirInterfaceRevision = cap.split('?revision=')[1].substring(0, 10); + } + }); + if (ne.onfAirInterfaceRevision) { + $scope.networkElements.push({ id: ne['node-id'], revision: ne.onfAirInterfaceRevision }); + } + } + }); + $scope.networkElements.sort(function (a, b) { + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; + return 0; + }); + + // select one of the nodes + // var select = parseInt(Math.random() * $scope.networkElements.length); + // $scope.networkElementA = $scope.networkElements[select].id; + // $scope.networkElementB = $scope.networkElements[select].id; + }; + + var initLinkIds = function () { + var functionId = 'sdnperformance'; + var docType = 'historicalperformance15min'; + if ($scope.timePeriod !== $scope.timePeriods[0]) { + docType = 'historicalperformance24h'; + } + var aggregations = { + "size":0, + "aggregations": { + "radio-signal-id": { + "terms": { + "field": "radio-signal-id" + } + } + } + }; + $mwtnPerformanceLink.getAggregations(functionId, docType, aggregations).then(function (success) { + $scope.linkIds = success.data.aggregations['radio-signal-id'].buckets.map(function(bucket){ + return bucket.key; + }); + }, function (error) { + console.log(error); + $scope.linkIds = []; + }); + }; + + $mwtnPerformanceLink.getMountPoints().then(function (mountpoints) { + initNodeList(mountpoints); + initLinkIds(); + }, function (error) { + $scope.networkElements = []; + }); + + //table stuff + + //data visible on screen + $scope.performance826 = []; + $scope.receiveLevel = []; + $scope.transmissionLevel = []; + $scope.modulation = []; + $scope.temperature = []; + $scope.snir = []; + $scope.crossPolarDiscrimination = []; + + $scope.paginationOptions = { + pageNumber: 1, + pageSize: 2, + sort: null + }; + + //page sizes, based on time period + $scope.pageSizes = function () { + var arr; + if ($scope.timePeriod && $scope.timePeriod === "15 minutes") { + + arr = [96, (96 * 2), (96 * 7)]; + + } else { + arr = [7, 30, (30 * 3), (30 * 6), (30 * 12)]; + } + return arr; + }; + + //init page sizes + $scope.selectPageSize = function () { + + if ($scope.timePeriod && $scope.timePeriod === "15 minutes") { + + return 96; + + } else { + return 7; + } + + }; + + $scope.itemsMessage = function () { + if ($scope.timePeriod && $scope.timePeriod === "15 minutes") { + return "15 minutes items per page"; + } else { + return "24 hours items per page"; + } + }; + + + $scope.paginationStatusMessage = function (grid) { + if (grid === 'receiveLevel') { + let start = ($scope.gridOptionsReceiveLevel.paginationCurrentPage - 1) * $scope.gridOptionsReceiveLevel.paginationPageSize + 1; + let end = ($scope.gridOptionsReceiveLevel.paginationCurrentPage - 1) * $scope.gridOptionsReceiveLevel.paginationPageSize + 1 + $scope.receiveLevel.length - 1; + let total = $scope.gridOptionsReceiveLevel.totalItems; + let message = "Showing {0} to {1} of {2} items"; + return message.format(start, end, total); + } + else if (grid === 'transmissionLevel') { + let start = ($scope.gridOptionsTransmissionLevel.paginationCurrentPage - 1) * $scope.gridOptionsTransmissionLevel.paginationPageSize + 1; + let end = ($scope.gridOptionsTransmissionLevel.paginationCurrentPage - 1) * $scope.gridOptionsTransmissionLevel.paginationPageSize + 1 + $scope.transmissionLevel.length - 1; + let total = $scope.gridOptionsTransmissionLevel.totalItems; + let message = "Showing {0} to {1} of {2} items"; + return message.format(start, end, total); + } + else if (grid === 'modulation') { + let start = ($scope.gridOptionsModulation.paginationCurrentPage - 1) * $scope.gridOptionsModulation.paginationPageSize + 1; + let end = ($scope.gridOptionsModulation.paginationCurrentPage - 1) * $scope.gridOptionsModulation.paginationPageSize + 1 + $scope.modulation.length - 1; + let total = $scope.gridOptionsModulation.totalItems; + let message = "Showing {0} to {1} of {2} items"; + return message.format(start, end, total); + + } else if (grid === 'temperature') { + let start = ($scope.gridOptionsTemperature.paginationCurrentPage - 1) * $scope.gridOptionsTemperature.paginationPageSize + 1; + let end = ($scope.gridOptionsTemperature.paginationCurrentPage - 1) * $scope.gridOptionsTemperature.paginationPageSize + 1 + $scope.temperature.length - 1; + let total = $scope.gridOptionsTemperature.totalItems; + let message = "Showing {0} to {1} of {2} items"; + return message.format(start, end, total); + + } else if (grid === 'snir') { + let start = ($scope.gridOptionsSnir.paginationCurrentPage - 1) * $scope.gridOptionsSnir.paginationPageSize + 1; + let end = ($scope.gridOptionsSnir.paginationCurrentPage - 1) * $scope.gridOptionsSnir.paginationPageSize + 1 + $scope.snir.length - 1; + let total = $scope.gridOptionsSnir.totalItems; + let message = "Showing {0} to {1} of {2} items"; + return message.format(start, end, total); + + } else if (grid === 'crossPolarDiscrimination') { + let start = ($scope.gridOptionsCrossPolarDiscrimination.paginationCurrentPage - 1) * $scope.gridOptionsCrossPolarDiscrimination.paginationPageSize + 1; + let end = ($scope.gridOptionsCrossPolarDiscrimination.paginationCurrentPage - 1) * $scope.gridOptionsCrossPolarDiscrimination.paginationPageSize + 1 + $scope.crossPolarDiscrimination.length - 1; + let total = $scope.gridOptionsCrossPolarDiscrimination.totalItems; + let message = "Showing {0} to {1} of {2} items"; + return message.format(start, end, total); + } + }; + + //seek page based on grid + $scope.seekPage = function (page, grid) { + if (!page) { + page = 1; + return; + } + switch (grid) { + case 'receiveLevel': $scope.recvGridApi.pagination.seek(parseInt(page)); + break; + + case 'transmissionLevel': $scope.transmissionGridApi.pagination.seek(parseInt(page)); + break; + + case 'modulation': $scope.gridApi.pagination.seek(parseInt(page)); + break; + + case 'temperature': $scope.gridTemperatureApi.pagination.seek(parseInt(page)); + break; + + case 'snir': $scope.gridSNIRApi.pagination.seek(parseInt(page)); + break; + + case 'crossPolarDiscrimination': $scope.gridXpdApi.pagination.seek(parseInt(page)); + break; + } + + }; + //table configuration + + //receive lvl configuration + $scope.gridOptionsReceiveLevel = { + paginationPageSizes: $scope.pageSizes(), + paginationPageSize: $scope.selectPageSize(), + useExternalPagination: true, + enablePaginationControls: false, + enableFiltering: false, + enableSorting: false, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { field: 'timestamp', type: 'string', displayName: 'End time', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'rxmina', type: 'string', displayName: 'Rx min A', width: 90 }, + { field: 'rxavga', type: 'string', displayName: 'Rx avg A', width: 90 }, + { field: 'rxmaxa', type: 'string', displayName: 'Rx max A', width: 90 }, + { field: 'rxminb', type: 'string', displayName: 'Rx min B', width: 90 }, + { field: 'rxavgb', type: 'string', displayName: 'Rx avg B', width: 90 }, + { field: 'rxmaxb', type: 'string', displayName: 'Rx max B', width: 90 } + ], + data: 'receiveLevel', + onRegisterApi: function (gridApi) { + $scope.recvGridApi = gridApi; + $scope.recvGridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, "receiveLevel"); + }); + } + }; + + $scope.gridOptionsTransmissionLevel = { + paginationPageSizes: $scope.pageSizes(), + paginationPageSize: $scope.selectPageSize(), + useExternalPagination: true, + enablePaginationControls: false, + enableFiltering: false, + enableSorting: false, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { field: 'timestamp', type: 'string', displayName: 'End time', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'txmina', type: 'string', displayName: 'Tx min A', width: 90 }, + { field: 'txavga', type: 'string', displayName: 'Tx avg A', width: 90 }, + { field: 'txmaxa', type: 'string', displayName: 'Tx max A', width: 90 }, + { field: 'txminb', type: 'string', displayName: 'Tx min B', width: 90 }, + { field: 'txavgb', type: 'string', displayName: 'Tx avg B', width: 90 }, + { field: 'txmaxb', type: 'string', displayName: 'Tx max B', width: 90 } + ], + data: 'transmissionLevel', + onRegisterApi: function (gridApi) { + $scope.transmissionGridApi = gridApi; + $scope.transmissionGridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, "transmissionLevel"); + }); + } + }; + + $scope.gridOptionsModulation = { + paginationPageSizes: $scope.pageSizes(), + paginationPageSize: $scope.selectPageSize(), + useExternalPagination: true, + enablePaginationControls: false, + enableFiltering: false, + enableSorting: false, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { field: 'timestamp', type: 'string', displayName: 'End time', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'time2Sa', type: 'string', displayName: 'QAM2S A', width: 90 }, + { field: 'time2a', type: 'string', displayName: 'QAM2 A', width: 90 }, + { field: 'time2La', type: 'string', displayName: 'QAM2L A', width: 90 }, + { field: 'time4Sa', type: 'string', displayName: 'QAM4S A', width: 90 }, + { field: 'time4a', type: 'string', displayName: 'QAM4 A', width: 90 }, + { field: 'time4La', type: 'string', displayName: 'QAM4L A', width: 90 }, + { field: 'time16Sa', type: 'string', displayName: 'QAM16S A', width: 90 }, + { field: 'time16a', type: 'string', displayName: 'QAM16 A', width: 90 }, + { field: 'time16La', type: 'string', displayName: 'QAM16L A', width: 90 }, + { field: 'time32Sa', type: 'string', displayName: 'QAM32S A', width: 90 }, + { field: 'time32a', type: 'string', displayName: 'QAM32 A', width: 90 }, + { field: 'time32La', type: 'string', displayName: 'QAM32L A', width: 90 }, + { field: 'time64Sa', type: 'string', displayName: 'QAM64S A', width: 90 }, + { field: 'time64a', type: 'string', displayName: 'QAM64 A', width: 90 }, + { field: 'time64La', type: 'string', displayName: 'QAM64L A', width: 90 }, + { field: 'time128Sa', type: 'string', displayName: 'QAM128S A', width: 90 }, + { field: 'time128a', type: 'string', displayName: 'QAM128 A', width: 90 }, + { field: 'time128La', type: 'string', displayName: 'QAM128L A', width: 90 }, + { field: 'time256Sa', type: 'string', displayName: 'QAM256S A', width: 90 }, + { field: 'time256a', type: 'string', displayName: 'QAM256 A', width: 90 }, + { field: 'time256La', type: 'string', displayName: 'QAM256L A', width: 90 }, + { field: 'time512Sa', type: 'string', displayName: 'QAM512S A', width: 90 }, + { field: 'time512a', type: 'string', displayName: 'QAM512 A', width: 90 }, + { field: 'time512La', type: 'string', displayName: 'QAM512L A', width: 90 }, + { field: 'time1024Sa', type: 'string', displayName: 'QAM1024S A', width: 90 }, + { field: 'time1024a', type: 'string', displayName: 'QAM1024 A', width: 90 }, + { field: 'time1024La', type: 'string', displayName: 'QAM1024L A', width: 90 }, + { field: 'time2048Sa', type: 'string', displayName: 'QAM2048S A', width: 90 }, + { field: 'time2048a', type: 'string', displayName: 'QAM2048 A', width: 90 }, + { field: 'time2048La', type: 'string', displayName: 'QAM2048L A', width: 90 }, + { field: 'time4096Sa', type: 'string', displayName: 'QAM4096S A', width: 90 }, + { field: 'time4096a', type: 'string', displayName: 'QAM4096 A', width: 90 }, + { field: 'time4096La', type: 'string', displayName: 'QAM4096L A', width: 90 }, + { field: 'time8192Sa', type: 'string', displayName: 'QAM8192S A', width: 90 }, + { field: 'time8192a', type: 'string', displayName: 'QAM8192 A', width: 90 }, + { field: 'time8192La', type: 'string', displayName: 'QAM8192L A', width: 90 }, + + { field: 'time2Sb', type: 'string', displayName: 'QAM2S B', width: 90 }, + { field: 'time2b', type: 'string', displayName: 'QAM2 B', width: 90 }, + { field: 'time2Lb', type: 'string', displayName: 'QAM2L B', width: 90 }, + { field: 'time4Sb', type: 'string', displayName: 'QAM4S B', width: 90 }, + { field: 'time4b', type: 'string', displayName: 'QAM4 B', width: 90 }, + { field: 'time4Lb', type: 'string', displayName: 'QAM4L B', width: 90 }, + { field: 'time16Sb', type: 'string', displayName: 'QAM16S B', width: 90 }, + { field: 'time16b', type: 'string', displayName: 'QAM16 B', width: 90 }, + { field: 'time16Lb', type: 'string', displayName: 'QAM16L B', width: 90 }, + { field: 'time32Sb', type: 'string', displayName: 'QAM32S B', width: 90 }, + { field: 'time32b', type: 'string', displayName: 'QAM32 B', width: 90 }, + { field: 'time32Lb', type: 'string', displayName: 'QAM32L B', width: 90 }, + { field: 'time64Sb', type: 'string', displayName: 'QAM64S B', width: 90 }, + { field: 'time64b', type: 'string', displayName: 'QAM64 B', width: 90 }, + { field: 'time64Lb', type: 'string', displayName: 'QAM64L B', width: 90 }, + { field: 'time128Sb', type: 'string', displayName: 'QAM128S B', width: 90 }, + { field: 'time128b', type: 'string', displayName: 'QAM128 B', width: 90 }, + { field: 'time128Lb', type: 'string', displayName: 'QAM128L B', width: 90 }, + { field: 'time256Sb', type: 'string', displayName: 'QAM256S B', width: 90 }, + { field: 'time256b', type: 'string', displayName: 'QAM256 B', width: 90 }, + { field: 'time256Lb', type: 'string', displayName: 'QAM256L B', width: 90 }, + { field: 'time512Sb', type: 'string', displayName: 'QAM512S B', width: 90 }, + { field: 'time512b', type: 'string', displayName: 'QAM512 B', width: 90 }, + { field: 'time512Lb', type: 'string', displayName: 'QAM512L B', width: 90 }, + { field: 'time1024Sb', type: 'string', displayName: 'QAM1024S B', width: 90 }, + { field: 'time1024b', type: 'string', displayName: 'QAM1024 B', width: 90 }, + { field: 'time1024Lb', type: 'string', displayName: 'QAM1024L B', width: 90 }, + { field: 'time2048Sb', type: 'string', displayName: 'QAM2048S B', width: 90 }, + { field: 'time2048b', type: 'string', displayName: 'QAM2048 B', width: 90 }, + { field: 'time2048Lb', type: 'string', displayName: 'QAM2048L B', width: 90 }, + { field: 'time4096Sb', type: 'string', displayName: 'QAM4096S B', width: 90 }, + { field: 'time4096b', type: 'string', displayName: 'QAM4096 B', width: 90 }, + { field: 'time4096Lb', type: 'string', displayName: 'QAM4096L B', width: 90 }, + { field: 'time8192Sb', type: 'string', displayName: 'QAM8192S B', width: 90 }, + { field: 'time8192b', type: 'string', displayName: 'QAM8192 B', width: 90 }, + { field: 'time8192Lb', type: 'string', displayName: 'QAM8192L B', width: 90 } + ], + data: 'modulation', + onRegisterApi: function (gridApi) { + $scope.gridApi = gridApi; + $scope.gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, "modulation"); + }); + } + }; + + $scope.gridOptionsTemperature = { + paginationPageSizes: $scope.pageSizes(), + paginationPageSize: $scope.selectPageSize(), + useExternalPagination: true, + enablePaginationControls: false, + enableFiltering: false, + enableSorting: false, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { field: 'timestamp', type: 'string', displayName: 'End time', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'rfTempMina', type: 'string', displayName: 'Rf Temp Min A [°C]', width: 90 }, + { field: 'rfTempAvga', type: 'string', displayName: 'Rf Temp Avg A[°C]', width: 90 }, + { field: 'rfTempMaxa', type: 'string', displayName: 'Rf Temp Max A [°C]', width: 90 }, + { field: 'rfTempMinb', type: 'string', displayName: 'Rf Temp Min B [°C]', width: 90 }, + { field: 'rfTempAvgb', type: 'string', displayName: 'Rf Temp Avg B [°C]', width: 90 }, + { field: 'rfTempMaxb', type: 'string', displayName: 'Rf Temp Max B [°C]', width: 90 } + + ], + data: 'temperature', + onRegisterApi: function (gridApi) { + $scope.gridTemperatureApi = gridApi; + $scope.gridTemperatureApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, "temperature"); + }); + } + }; + + $scope.gridOptionsSnir = { + paginationPageSizes: $scope.pageSizes(), + paginationPageSize: $scope.selectPageSize(), + useExternalPagination: true, + enablePaginationControls: false, + enableFiltering: false, + enableSorting: false, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: 'Termination point', width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { field: 'timestamp', type: 'string', displayName: 'End time', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'snirMin', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MIN'), 'A', '[dB]'].join(' '), width: 90 }, + { field: 'snirAvg', type: 'string', displayName: [$translate.instant('MWTN_SNIR_AVG'), 'A', '[dB]'].join(' '), width: 90 }, + { field: 'snirMax', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MAX'), 'A', '[dB]'].join(' '), width: 90 }, + { field: 'snirMin', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MIN'), 'B', '[dB]'].join(' '), width: 90 }, + { field: 'snirAvg', type: 'string', displayName: [$translate.instant('MWTN_SNIR_AVG'), 'B', '[dB]'].join(' '), width: 90 }, + { field: 'snirMax', type: 'string', displayName: [$translate.instant('MWTN_SNIR_MAX'), 'B', '[dB]'].join(' '), width: 90 } + ], + data: 'snir', + onRegisterApi: function (gridApi) { + $scope.gridSNIRApi = gridApi; + $scope.gridSNIRApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, "snir"); + }); + } + }; + + + $scope.gridOptionsCrossPolarDiscrimination = { + paginationPageSizes: $scope.pageSizes(), + paginationPageSize: $scope.selectPageSize(), + useExternalPagination: true, + enablePaginationControls: false, + enableFiltering: false, + enableSorting: false, + enableGridMenu: true, + columnDefs: [ + { field: 'layerProtocol', type: 'string', displayName: 'Layer Protocol Name', width: 90, visible: false }, + { field: 'id', type: 'string', displayName: $translate.instant('MWTN_LTP'), width: 200, visible: false }, + { field: 'radiosignal', type: 'string', displayName: 'Radio Signal Id', width: 90 }, + { field: 'scannerId', type: 'string', displayName: 'Scanner Id', width: 90 }, + { field: 'timestamp', type: 'string', displayName: 'End time', width: 200 }, + { field: 'suspectInterval', type: 'string', displayName: 'Suspect Interval Flag', width: 100 }, + { field: 'xpdMina', type: 'string', displayName: 'CPD min A [dB]', width: 90 }, + { field: 'xpdAvga', type: 'string', displayName: 'CPD avg A [dB]', width: 90 }, + { field: 'xpdMaxa', type: 'string', displayName: 'CPD max A [dB]', width: 90 }, + { field: 'xpdMinb', type: 'string', displayName: 'CPD min B [dB]', width: 90 }, + { field: 'xpdAvgb', type: 'string', displayName: 'CPD avg B [dB]', width: 90 }, + { field: 'xpdMaxb', type: 'string', displayName: 'CPD max B [dB]', width: 90 } + ], + data: 'crossPolarDiscrimination', + onRegisterApi: function (gridApi) { + $scope.gridXpdApi = gridApi; + $scope.gridXpdApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + $scope.paginationOptions.pageNumber = newPage; + $scope.paginationOptions.pageSize = pageSize; + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, "crossPolarDiscrimination"); + }); + } + }; + + //sanitize -1 to no value + var checkData = function (value) { + if (value === -1 || value === undefined) return undefined; + else return value; + }; + + var calculateMissingTimestamp = function (lastTimestamp, missingNr) { + var dateInMS = Date.parse(lastTimestamp); + return new Date(dateInMS + ((missingNr * 15) * 60000)) + .toISOString() + .toHumanReadableTimeFormat() + .replace('.000', '.0'); + }; + + var processResponseForGrid = function (dataA, dataB, grid) { + // console.log(grid); + switch (grid) { + case "transmissionLevel": + var list = []; + var lookupMap = new Map(); //add data based on timestamp + + dataA.data.hits.hits.map(function (entry, index) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + lookupMap.set(timeStamp, index); //add timestamp and index to map + var item = { + timestamp: timeStamp, + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + txmina: checkData(entry._source['performance-data']['tx-level-min']), + txavga: checkData(entry._source['performance-data']['tx-level-avg']), + txmaxa: checkData(entry._source['performance-data']['tx-level-max']), + 'radiosignal': entry._source['radio-signal-id'] + }; + list.push(item); + }); + + dataB.data.hits.hits.map(function (entry) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + var index = lookupMap.get(timeStamp); //look for timestamp in map + if (index !== undefined) { //if a timestamp was found + list[index].txminb = checkData(entry._source['performance-data']['tx-level-min']); //add data to b side of element + list[index].txavgb = checkData(entry._source['performance-data']['tx-level-avg']); + list[index].txmaxb = checkData(entry._source['performance-data']['tx-level-max']); + } else { + if (list[0].timestamp === $mwtnPerformanceLink.formatTimeStamp(timeStamp)) { //look, if first element in list is same (first element in map is never found against an equals) + list[0].txminb = checkData(entry._source['performance-data']['tx-level-min']); //add data to b side of element + list[0].txavgb = checkData(entry._source['performance-data']['tx-level-avg']); + list[0].txmaxb = checkData(entry._source['performance-data']['tx-level-max']); + } + else { //add new element for b side to list + list.push({ + timestamp: timeStamp, + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + txminb: checkData(entry._source['performance-data']['tx-level-min']), + txavgb: checkData(entry._source['performance-data']['tx-level-avg']), + txmaxb: checkData(entry._source['performance-data']['tx-level-max']), + 'radiosignal': entry._source['radio-signal-id'] + }); + } + } + }); + + $scope.transmissionLevel = list; //add list to databound table list + $scope.gridOptionsTransmissionLevel.totalItems = getMaxItems(dataA.data.hits.total, dataB.data.hits.total); + break; + + case "receiveLevel": + + var list = []; + var lookupMap = new Map(); + + dataA.data.hits.hits.map(function (entry, index) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + lookupMap.set(timeStamp, index); + var item = { + timestamp: timeStamp, + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + rxmina: checkData(entry._source['performance-data']['rx-level-min']), + rxavga: checkData(entry._source['performance-data']['rx-level-avg']), + rxmaxa: checkData(entry._source['performance-data']['rx-level-max']), + 'radiosignal': entry._source['radio-signal-id'] + }; + + list.push(item); + }); + + dataB.data.hits.hits.map(function (entry) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + var index = lookupMap.get(timeStamp); + if (index !== undefined) { + list[index].rxminb = checkData(entry._source['performance-data']['rx-level-min']); + list[index].rxavgb = checkData(entry._source['performance-data']['rx-level-avg']); + list[index].rxmaxb = checkData(entry._source['performance-data']['rx-level-max']); + } else { + if (list[0].timestamp === $mwtnPerformanceLink.formatTimeStamp(timeStamp)) { + list[0].rxminb = checkData(entry._source['performance-data']['rx-level-min']); + list[0].rxavgb = checkData(entry._source['performance-data']['rx-level-avg']); + list[0].rxmaxb = checkData(entry._source['performance-data']['rx-level-max']); + } else { + list.push({ + timestamp: timeStamp, + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + rxminb: checkData(entry._source['performance-data']['rx-level-min']), + rxavgb: checkData(entry._source['performance-data']['rx-level-avg']), + rxmaxb: checkData(entry._source['performance-data']['rx-level-max']), + 'radiosignal': entry._source['radio-signal-id'] + }); + } + } + + }); + + + $scope.receiveLevel = list; + $scope.gridOptionsReceiveLevel.totalItems = getMaxItems(dataA.data.hits.total, dataB.data.hits.total); + + break; + + case "modulation": + + var list = []; + + var lookupMap = new Map(); + + dataA.data.hits.hits.map(function (entry, index) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + lookupMap.set(timeStamp, index); + var item = { + timestamp: timeStamp, + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + 'time2Sa': checkData(entry._source['performance-data']['time2-states-s']), + 'time2a': checkData(entry._source['performance-data']['time2-states']), + 'time2La': checkData(entry._source['performance-data']['time2-states-l']), + 'time4Sa': checkData(entry._source['performance-data']['time4-states-s']), + 'time4a': checkData(entry._source['performance-data']['time4-states']), + 'time4La': checkData(entry._source['performance-data']['time4-states-l']), + 'time16Sa': checkData(entry._source['performance-data']['time16-states-s']), + 'time16a': checkData(entry._source['performance-data']['time16-states']), + 'time16La': checkData(entry._source['performance-data']['time16-states-l']), + 'time32Sa': checkData(entry._source['performance-data']['time32-states-s']), + 'time32a': checkData(entry._source['performance-data']['time32-states']), + 'time32La': checkData(entry._source['performance-data']['time32-states-l']), + 'time64Sa': checkData(entry._source['performance-data']['time64-states-s']), + 'time64a': checkData(entry._source['performance-data']['time64-states']), + 'time64La': checkData(entry._source['performance-data']['time64-states-l']), + 'time128Sa': checkData(entry._source['performance-data']['time128-states-s']), + 'time128a': checkData(entry._source['performance-data']['time128-states']), + 'time128La': checkData(entry._source['performance-data']['time128-states-l']), + 'time256Sa': checkData(entry._source['performance-data']['time256-states-s']), + 'time256a': checkData(entry._source['performance-data']['time256-states']), + 'time256La': checkData(entry._source['performance-data']['time256-states-l']), + 'time512Sa': checkData(entry._source['performance-data']['time512-states-s']), + 'time512a': checkData(entry._source['performance-data']['time512-states']), + 'time512La': checkData(entry._source['performance-data']['time512-states-l']), + 'time1024Sa': checkData(entry._source['performance-data']['time1024-states-s']), + 'time1024a': checkData(entry._source['performance-data']['time1024-states']), + 'time1024La': checkData(entry._source['performance-data']['time1024-states-l']), + 'time2048Sa': checkData(entry._source['performance-data']['time2048-states-s']), + 'time2048a': checkData(entry._source['performance-data']['time2048-states']), + 'time2048La': checkData(entry._source['performance-data']['time2048-states-l']), + 'time4096Sa': checkData(entry._source['performance-data']['time4096-states-s']), + 'time4096a': checkData(entry._source['performance-data']['time4096-states']), + 'time4096La': checkData(entry._source['performance-data']['time4096-states-l']), + 'time8192Sa': checkData(entry._source['performance-data']['time8192-states-s']), + 'time8192a': checkData(entry._source['performance-data']['time8192-states']), + 'time8192La': checkData(entry._source['performance-data']['time8192-states-l']), + 'radiosignal': entry._source['radio-signal-id'] + }; + + list.push(item); + + }); + + dataB.data.hits.hits.map(function (entry) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + var index = lookupMap.get(timeStamp); + if (index !== undefined) { + + list[index].time2Sb = checkData(entry._source['performance-data']['time2-states-s']); + list[index].time2b = checkData(entry._source['performance-data']['time2-states']); + list[index].time2Lb = checkData(entry._source['performance-data']['time2-states-l']); + list[index].time4Sb = checkData(entry._source['performance-data']['time4-states-s']); + list[index].time4b = checkData(entry._source['performance-data']['time4-states']); + list[index].time4Lb = checkData(entry._source['performance-data']['time4-states-l']); + list[index].time16Sb = checkData(entry._source['performance-data']['time16-states-s']); + list[index].time16b = checkData(entry._source['performance-data']['time16-states']); + list[index].time16Lb = checkData(entry._source['performance-data']['time16-states-l']); + list[index].time32Sb = checkData(entry._source['performance-data']['time32-states-s']); + list[index].time32b = checkData(entry._source['performance-data']['time32-states']); + list[index].time32Lb = checkData(entry._source['performance-data']['time32-states-l']); + list[index].time64Sb = checkData(entry._source['performance-data']['time64-states-s']); + list[index].time64b = checkData(entry._source['performance-data']['time64-states']); + list[index].time64Lb = checkData(entry._source['performance-data']['time64-states-l']); + list[index].time128Sb = checkData(entry._source['performance-data']['time128-states-s']); + list[index].time128b = checkData(entry._source['performance-data']['time128-states']); + list[index].time128Lb = checkData(entry._source['performance-data']['time128-states-l']); + list[index].time256Sb = checkData(entry._source['performance-data']['time256-states-s']); + list[index].time256b = checkData(entry._source['performance-data']['time256-states']); + list[index].time256Lb = checkData(entry._source['performance-data']['time256-states-l']); + list[index].time512Sb = checkData(entry._source['performance-data']['time512-states-s']); + list[index].time512b = checkData(entry._source['performance-data']['time512-states']); + list[index].time512Lb = checkData(entry._source['performance-data']['time512-states-l']); + list[index].time1024Sb = checkData(entry._source['performance-data']['time1024-states-s']); + list[index].time1024b = checkData(entry._source['performance-data']['time1024-states']); + list[index].time1024Lb = checkData(entry._source['performance-data']['time1024-states-l']); + list[index].time2048Sb = checkData(entry._source['performance-data']['time2048-states-s']); + list[index].time2048b = checkData(entry._source['performance-data']['time2048-states']); + list[index].time2048Lb = checkData(entry._source['performance-data']['time2048-states-l']); + list[index].time4096Sb = checkData(entry._source['performance-data']['time4096-states-s']); + list[index].time4096b = checkData(entry._source['performance-data']['time4096-states']); + list[index].time4096Lb = checkData(entry._source['performance-data']['time4096-states-l']); + list[index].time8192Sb = checkData(entry._source['performance-data']['time8192-states-s']); + list[index].time8192b = checkData(entry._source['performance-data']['time8192-states']); + list[index].time8192Lb = checkData(entry._source['performance-data']['time8192-states-l']); + } else { + if (list[0].timestamp === $mwtnPerformanceLink.formatTimeStamp(timeStamp)) { + list[index].time2Sb = checkData(entry._source['performance-data']['time2-states-s']); + list[0].time2b = checkData(entry._source['performance-data']['time2-states']); + list[0].time2Lb = checkData(entry._source['performance-data']['time2-states-l']); + list[0].time4Sb = checkData(entry._source['performance-data']['time4-states-s']); + list[0].time4b = checkData(entry._source['performance-data']['time4-states']); + list[0].time4Lb = checkData(entry._source['performance-data']['time4-states-l']); + list[0].time16Sb = checkData(entry._source['performance-data']['time16-states-s']); + list[0].time16b = checkData(entry._source['performance-data']['time16-states']); + list[0].time16Lb = checkData(entry._source['performance-data']['time16-states-l']); + list[0].time32Sb = checkData(entry._source['performance-data']['time32-states-s']); + list[0].time32b = checkData(entry._source['performance-data']['time32-states']); + list[0].time32Lb = checkData(entry._source['performance-data']['time32-states-l']); + list[0].time64Sb = checkData(entry._source['performance-data']['time64-states-s']); + list[0].time64b = checkData(entry._source['performance-data']['time64-states']); + list[0].time64Lb = checkData(entry._source['performance-data']['time64-states-l']); + list[0].time128Sb = checkData(entry._source['performance-data']['time128-states-s']); + list[0].time128b = checkData(entry._source['performance-data']['time128-states']); + list[0].time128Lb = checkData(entry._source['performance-data']['time128-states-l']); + list[0].time256Sb = checkData(entry._source['performance-data']['time256-states-s']); + list[0].time256b = checkData(entry._source['performance-data']['time256-states']); + list[0].time256Lb = checkData(entry._source['performance-data']['time256-states-l']); + list[0].time512Sb = checkData(entry._source['performance-data']['time512-states-s']); + list[0].time512b = checkData(entry._source['performance-data']['time512-states']); + list[0].time512Lb = checkData(entry._source['performance-data']['time512-states-l']); + list[0].time1024Sb = checkData(entry._source['performance-data']['time1024-states-s']); + list[0].time1024b = checkData(entry._source['performance-data']['time1024-states']); + list[0].time1024Lb = checkData(entry._source['performance-data']['time1024-states-l']); + list[0].time2048Sb = checkData(entry._source['performance-data']['time2048-states-s']); + list[0].time2048b = checkData(entry._source['performance-data']['time2048-states']); + list[0].time2048Lb = checkData(entry._source['performance-data']['time2048-states-l']); + list[0].time4096Sb = checkData(entry._source['performance-data']['time4096-states-s']); + list[0].time4096b = checkData(entry._source['performance-data']['time4096-states']); + list[0].time4096Lb = checkData(entry._source['performance-data']['time4096-states-l']); + list[0].time8192Sb = checkData(entry._source['performance-data']['time8192-states-s']); + list[0].time8192b = checkData(entry._source['performance-data']['time8192-states']); + list[0].time8192Lb = checkData(entry._source['performance-data']['time8192-states-l']); + } + else { + var item = { + timestamp: timeStamp, + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + 'time2Sb': checkData(entry._source['performance-data']['time2-states-s']), + 'time2b': checkData(entry._source['performance-data']['time2-states']), + 'time2Lb': checkData(entry._source['performance-data']['time2-states-l']), + 'time4Sb': checkData(entry._source['performance-data']['time4-states-s']), + 'time4b': checkData(entry._source['performance-data']['time4-states']), + 'time4Lb': checkData(entry._source['performance-data']['time4-states-l']), + 'time16Sb': checkData(entry._source['performance-data']['time16-states-s']), + 'time16b': checkData(entry._source['performance-data']['time16-states']), + 'time16Lb': checkData(entry._source['performance-data']['time16-states-l']), + 'time32Sb': checkData(entry._source['performance-data']['time32-states-s']), + 'time32b': checkData(entry._source['performance-data']['time32-states']), + 'time32Lb': checkData(entry._source['performance-data']['time32-states-l']), + 'time64Sb': checkData(entry._source['performance-data']['time64-states-s']), + 'time64b': checkData(entry._source['performance-data']['time64-states']), + 'time64Lb': checkData(entry._source['performance-data']['time64-states-l']), + 'time128Sb': checkData(entry._source['performance-data']['time128-states-s']), + 'time128b': checkData(entry._source['performance-data']['time128-states']), + 'time128Lb': checkData(entry._source['performance-data']['time128-states-l']), + 'time256Sb': checkData(entry._source['performance-data']['time256-states-s']), + 'time256b': checkData(entry._source['performance-data']['time256-states']), + 'time256Lb': checkData(entry._source['performance-data']['time256-states-l']), + 'time512Sb': checkData(entry._source['performance-data']['time512-states-s']), + 'time512b': checkData(entry._source['performance-data']['time512-states']), + 'time512Lb': checkData(entry._source['performance-data']['time512-states-l']), + 'time1024Sb': checkData(entry._source['performance-data']['time1024-states-s']), + 'time1024b': checkData(entry._source['performance-data']['time1024-states']), + 'time1024Lb': checkData(entry._source['performance-data']['time1024-states-l']), + 'time2048Sb': checkData(entry._source['performance-data']['time2048-states-s']), + 'time2048b': checkData(entry._source['performance-data']['time2048-states']), + 'time2048Lb': checkData(entry._source['performance-data']['time2048-states-l']), + 'time4096Sb': checkData(entry._source['performance-data']['time4096-states-s']), + 'time4096b': checkData(entry._source['performance-data']['time4096-states']), + 'time4096Lb': checkData(entry._source['performance-data']['time4096-states-l']), + 'time8192Sb': checkData(entry._source['performance-data']['time8192-states-s']), + 'time8192b': checkData(entry._source['performance-data']['time8192-states']), + 'time8192Lb': checkData(entry._source['performance-data']['time8192-states-l']), + 'radiosignal': entry._source['radio-signal-id'] + }; + + list.push(item); + } + } + }); + $scope.modulation = list; + $scope.gridOptionsModulation.totalItems = getMaxItems(dataA.data.hits.total, dataB.data.hits.total); + + break; + + case "temperature": + + var list = []; + var lookupMap = new Map(); + + dataA.data.hits.hits.map(function (entry, index) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + lookupMap.set(timeStamp, index); + var item = { + 'timestamp': $mwtnPerformanceLink.formatTimeStamp(timeStamp), + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + rfTempMina: entry._source['performance-data']['rf-temp-min'], + rfTempAvga: entry._source['performance-data']['rf-temp-avg'], + rfTempMaxa: entry._source['performance-data']['rf-temp-max'], + 'radiosignal': entry._source['radio-signal-id'] + }; + + list.push(item); + }); + + dataB.data.hits.hits.map(function (entry) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + var index = lookupMap.get(timeStamp); + if (index !== undefined) { + list[index].rfTempMinb = entry._source['performance-data']['rf-temp-min']; + list[index].rfTempMaxb = entry._source['performance-data']['rf-temp-max']; + list[index].rfTempAvgb = entry._source['performance-data']['rf-temp-avg']; + } else { + if (list[0].timestamp === $mwtnPerformanceLink.formatTimeStamp(timeStamp)) { + list[0].rfTempMinb = entry._source['performance-data']['rf-temp-min']; + list[0].rfTempMaxb = entry._source['performance-data']['rf-temp-max']; + list[0].rfTempAvgb = entry._source['performance-data']['rf-temp-avg']; + } else { + list.push({ + 'timestamp': $mwtnPerformanceLink.formatTimeStamp(timeStamp), + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + rfTempMinb: entry._source['performance-data']['rf-temp-min'], + rfTempAvgb: entry._source['performance-data']['rf-temp-avg'], + rfTempMaxb: entry._source['performance-data']['rf-temp-max'], + 'radiosignal': entry._source['radio-signal-id'] + }); + } + } + }); + + $scope.temperature = list; + $scope.gridOptionsTemperature.totalItems = getMaxItems(dataA.data.hits.total, dataB.data.hits.total); + + break; + + case "snir": + + var list = []; + var lookupMap = new Map(); + + dataA.data.hits.hits.map(function (entry, index) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + lookupMap.set(timeStamp, index); + var item = { + 'timestamp': $mwtnPerformanceLink.formatTimeStamp(timeStamp), + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + snirMina: entry._source['performance-data']['snir-min'], + snirAvga: entry._source['performance-data']['snir-avg'], + snirMaxa: entry._source['performance-data']['snir-max'], + 'radiosignal': entry._source['radio-signal-id'] + }; + + list.push(item); + }); + + dataB.data.hits.hits.map(function (entry) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + var index = lookupMap.get(timeStamp); + if (index !== undefined) { + list[index].snirMinb = entry._source['performance-data']['snir-min']; + list[index].snirMaxb = entry._source['performance-data']['snir-max']; + list[index].snirAvgb = entry._source['performance-data']['snir-max']; + } + else { + if (list[0].timestamp === $mwtnPerformanceLink.formatTimeStamp(timeStamp)) { + list[0].snirMinb = entry._source['performance-data']['snir-min']; + list[0].snirMaxb = entry._source['performance-data']['snir-max']; + list[0].snirAvgb = entry._source['performance-data']['snir-max']; + } else { + list.push({ + 'timestamp': $mwtnPerformanceLink.formatTimeStamp(timeStamp), + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + snirMinb: entry._source['performance-data']['snir-min'], + snirAvgb: entry._source['performance-data']['snir-avg'], + snirMaxb: entry._source['performance-data']['snir-max'], + 'radiosignal': entry._source['radio-signal-id'] + }); + } + } + }); + $scope.snir = list; + $scope.gridOptionsSnir.totalItems = getMaxItems(dataA.data.hits.total, dataB.data.hits.total); + + break; + + case "crossPolarDiscrimination": + var list = []; + + var lookupMap = new Map(); + + dataA.data.hits.hits.map(function (entry, index) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + lookupMap.set(timeStamp, index); + var item = { + 'timestamp': $mwtnPerformanceLink.formatTimeStamp(timeStamp), + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + xpdMina: entry._source['performance-data']['xpd-min'], + xpdAvga: entry._source['performance-data']['xpd-avg'], + xpdMaxa: entry._source['performance-data']['xpd-max'], + 'radiosignal': entry._source['radio-signal-id'] + + }; + + list.push(item); + + }); + + dataB.data.hits.hits.map(function (entry) { + var timeStamp = formatTimeStamp(entry._source['time-stamp']); + var index = lookupMap.get(timeStamp); + if (index !== undefined) { + list[index].xpdMinb = entry._source['performance-data']['xpd-min']; + list[index].xpdMaxb = entry._source['performance-data']['xpd-max']; + list[index].xpdAvgb = entry._source['performance-data']['xpd-avg']; + } + else { + if (list[0].timestamp === $mwtnPerformanceLink.formatTimeStamp(timeStamp)) { + + list[0].xpdMinb = entry._source['performance-data']['xpd-min']; + list[0].xpdMaxb = entry._source['performance-data']['xpd-max']; + list[0].xpdAvgb = entry._source['performance-data']['xpd-avg']; + + } else { + list.push({ + 'timestamp': $mwtnPerformanceLink.formatTimeStamp(timeStamp), + id: entry._source['uuid-interface'], + layerProtocol: entry._source['layer-protocol-name'], + suspectInterval: entry._source['suspect-interval-flag'], + scannerId: entry._source['scanner-id'], + xpdMinb: entry._source['performance-data']['xpd-min'], + xpdAvgb: entry._source['performance-data']['xpd-avg'], + xpdMaxb: entry._source['performance-data']['xpd-max'], + 'radiosignal': entry._source['radio-signal-id'] + + }); + } + + } + }); + + $scope.crossPolarDiscrimination = list; + $scope.gridOptionsCrossPolarDiscrimination.totalItems = getMaxItems(dataA.data.hits.total, dataB.data.hits.total); + + break; + } + }; + + + var getMaxItems = function (a, b) { + if ($scope.networkElementA === $scope.networkElementB && $scope.selectedLtpIdA === $scope.selectedLtpIdB) { + //assume same network element and intefaces selected, return only 1 length + return a; + } else { + return a + b; + } + } + + //get data for pm link interafces / ne's from db + var getDataFromNEs = function (networkElementA, selectedLtpIdA, networkElementB, selectedLtpIdB, grid) { + var pagesize; + var pagenr; + + switch (grid) { //get pagesize / nr according to current grid (else everything gets messy => wana get next page in grid a, get next page for grid b too) + case 'receiveLevel': + pagesize = $scope.gridOptionsReceiveLevel.paginationPageSize; + pagenr = $scope.gridOptionsReceiveLevel.paginationCurrentPage; + break; + + case 'transmissionLevel': + pagesize = $scope.gridOptionsTransmissionLevel.paginationPageSize; + pagenr = $scope.gridOptionsTransmissionLevel.paginationCurrentPage; + break; + + case 'modulation': + pagesize = $scope.gridOptionsModulation.paginationPageSize; + pagenr = $scope.gridOptionsModulation.paginationCurrentPage; + break; + + case 'temperature': + pagesize = $scope.gridOptionsTemperature.paginationPageSize; + pagenr = $scope.gridOptionsTemperature.paginationCurrentPage; + break; + + case 'snir': + pagesize = $scope.gridOptionsSnir.paginationPageSize; + pagenr = $scope.gridOptionsSnir.paginationCurrentPage; + break; + + case 'crossPolarDiscrimination': + pagesize = $scope.gridOptionsCrossPolarDiscrimination.paginationPageSize; + pagenr = $scope.gridOptionsCrossPolarDiscrimination.paginationCurrentPage; + + break; + } + + var dataA; + var dataB; + getData((pagenr - 1) * pagesize, pagesize, networkElementA, selectedLtpIdA).then(function (response) { + dataA = response; + getData((pagenr - 1) * pagesize, pagesize, networkElementB, selectedLtpIdB).then(function (response) { + dataB = response; + drawLineChart(dataA, dataB, grid); + processResponseForGrid(dataA, dataB, grid); + }); + }); + }; + + //override points on graphs + var overridePoints = function (series, overrideArray) { + + + let patternArray = ['rect', 'triangle', 'point', 'rectRot']; + let patternCounter = 0; + + + for (let i = 0; i < series.length; i++) { + + overrideArray[i].pointStyle = patternArray[patternCounter]; + patternCounter++; + + if (patternCounter === 4) patternCounter = 0; + overrideArray[i].pointRadius = 10; + } + + }; + + var drawLineChart = function (dataA, dataB, grid) { + + //create a sorted lookup array + + var tempSet = new Set(); //remove duplicate timestamps + + dataA.data.hits.hits.map(function (item) { + tempSet.add($mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp'])); + }); + + dataB.data.hits.hits.map(function (item) { + tempSet.add($mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp'])); + }); + + // console.log(tempSet); + var tempArr = Array.from(tempSet); //create an array from unique timestamps + + tempArr.sort(function (a, b) { //sort it + if (a > b) { return 1; } + else if (a < b) { return -1; } + else { + return 0; + } + }); + + //process data according to grid + switch (grid) { + case 'receiveLevel': { + + //chart specific data + $scope.receiveData = []; + $scope.receiveSeries = []; + $scope.receiveLabels = []; + $scope.receiveDatasetOverride = []; + + $scope.receiveOptions = { + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom', + afterTickToLabelConversion: function (data) { //adds our custom timestamp labels + + var xLabels = data.ticks; + xLabels.forEach(function (labels, i) { + var timestamp = $scope.toolTipMap.get(parseInt(labels)); + if (parseInt(labels) == labels) + xLabels[i] = timestamp; + else + xLabels[i] = ''; + }); + + //calculate last timestamp if label is missing + if (xLabels[xLabels.length - 1] === undefined) { + var timestamp = $scope.toolTipMap.get($scope.toolTipMap.size - 1); + let stopper = true; + let counter = 0; + let labelLength = xLabels.length - 1; + while (stopper) { + if (labelLength % 10 == 0) { + stopper = false; + } else { + labelLength++; + counter++; + } + } + + xLabels[xLabels.length - 1] = calculateMissingTimestamp(timestamp, counter); + } + + + + } + }], + yAxes: [ + { + id: 'y-axis-1', + type: 'linear', + display: true, + position: 'left' + } + ] + }, + tooltips: { + enabled: true, + mode: 'point', + callbacks: { + title: function (tooltipItem, data) { //picks right tool tip + var vaue = $scope.toolTipMap.get(tooltipItem[0].xLabel); //changes int label to timestamp + return vaue; + } + } + }, + legend: { + display: true, + position: "bottom" + } + }; + + $scope.testMap = new Map(); + $scope.toolTipMap = new Map(); + + tempArr.map(function (item, index) { + $scope.testMap.set(item, index); + $scope.toolTipMap.set(index, item); + }); + + //process a side + + var maxListA = []; + var minListA = []; + var avgListA = []; + + //add data to array + dataA.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.testMap.get(timestamp); + if (test) { + maxListA.push({ x: test, y: item._source['performance-data']['rx-level-max'] }); + minListA.push({ x: test, y: item._source['performance-data']['rx-level-min'] }); + avgListA.push({ x: test, y: item._source['performance-data']['rx-level-avg'] }); + } else { + maxListA.push({ x: 0, y: item._source['performance-data']['rx-level-max'] }); //for some odd reason first is not found, although available within map + minListA.push({ x: 0, y: item._source['performance-data']['rx-level-min'] }); + avgListA.push({ x: 0, y: item._source['performance-data']['rx-level-avg'] }); + } + }); + + //add series names and data + $scope.receiveSeries.push('Rx max A', 'Rx min A', 'Rx avg A'); + + + $scope.receiveData.push(maxListA); + $scope.receiveData.push(minListA); + $scope.receiveData.push(avgListA); + + //add y axis override + $scope.receiveDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.receiveDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.receiveDatasetOverride.push({ yAxisID: 'y-axis-1' }); + + + //process b side + + var maxListB = []; + var minListB = []; + var avgListB = []; + + dataB.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.testMap.get(timestamp); + if (test) { + maxListB.push({ x: test, y: item._source['performance-data']['rx-level-max'] }); + minListB.push({ x: test, y: item._source['performance-data']['rx-level-min'] }); + avgListB.push({ x: test, y: item._source['performance-data']['rx-level-avg'] }); + } else { + maxListB.push({ x: 0, y: item._source['performance-data']['rx-level-max'] }); + minListB.push({ x: 0, y: item._source['performance-data']['rx-level-min'] }); + avgListB.push({ x: 0, y: item._source['performance-data']['rx-level-avg'] }); + console.log("timestamp" + timestamp + "at first position in map" + $scope.testMap.get(timestamp) + "wasnt found."); + } + }); + + //add series names and data + $scope.receiveSeries.push('Rx max B', 'Rx min B', 'Rx avg B'); + + $scope.receiveData.push(maxListB); + $scope.receiveData.push(minListB); + $scope.receiveData.push(avgListB); + + //add y axis override id + $scope.receiveDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.receiveDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.receiveDatasetOverride.push({ yAxisID: 'y-axis-1' }); + + overridePoints($scope.receiveSeries, $scope.receiveDatasetOverride); + + + } + + break; + + case 'transmissionLevel': { + + $scope.transmissionData = []; + $scope.transmissionSeries = []; + $scope.transmissionDatasetOverride = []; + + $scope.transmissionOptions = { + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom', + afterTickToLabelConversion: function (data) { //adds our custom timestamp labels + + var xLabels = data.ticks; + xLabels.forEach(function (labels, i) { + var timestamp = $scope.transmissiontoolTipMap.get(parseInt(labels)); + if (parseInt(labels) == labels) + xLabels[i] = timestamp; + else + xLabels[i] = ''; + + }); + + //calculate last timestamp if label is missing + if (xLabels[xLabels.length - 1] === undefined) { + let timestamp = $scope.transmissiontoolTipMap.get($scope.transmissiontoolTipMap.size - 1); + let stopper = true; + let counter = 0; + let labelLength = xLabels.length - 1; + while (stopper) { + if (labelLength % 10 == 0) { + stopper = false; + } else { + labelLength++; + counter++; + } + } + + xLabels[xLabels.length - 1] = calculateMissingTimestamp(timestamp, counter); + } + } + }], + yAxes: [ + { + id: 'y-axis-1', + type: 'linear', + display: true, + position: 'left' + } + ] + }, + tooltips: { + enabled: true, + mode: 'point', + callbacks: { + title: function (tooltipItem, data) { //picks right tool tip + var vaue = $scope.transmissiontoolTipMap.get(tooltipItem[0].xLabel); + return vaue; + } + } + }, + legend: { + display: true, + position: "bottom" + } + }; + + + $scope.transmissiontestMap = new Map(); + $scope.transmissiontoolTipMap = new Map(); + + tempArr.map(function (item, index) { + $scope.transmissiontestMap.set(item, index); + $scope.transmissiontoolTipMap.set(index, item); + }); + + var maxListA = []; + var minListA = []; + var avgListA = []; + + dataA.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.transmissiontestMap.get(timestamp); + if (test) { + maxListA.push({ x: test, y: item._source['performance-data']['tx-level-max'] }); + minListA.push({ x: test, y: item._source['performance-data']['tx-level-min'] }); + avgListA.push({ x: test, y: item._source['performance-data']['tx-level-avg'] }); + } else { + + maxListA.push({ x: 0, y: item._source['performance-data']['tx-level-max'] }); + minListA.push({ x: 0, y: item._source['performance-data']['tx-level-min'] }); + avgListA.push({ x: 0, y: item._source['performance-data']['tx-level-avg'] }); + } + }); + + $scope.transmissionSeries.push('Tx max A', 'Tx min A', 'Tx avg A'); + + + $scope.transmissionData.push(maxListA); + $scope.transmissionData.push(minListA); + $scope.transmissionData.push(avgListA); + + $scope.transmissionDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.transmissionDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.transmissionDatasetOverride.push({ yAxisID: 'y-axis-1' }); + + var maxListB = []; + var minListB = []; + var avgListB = []; + + dataB.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + var test = $scope.transmissiontestMap.get(timestamp); + if (test) { + maxListB.push({ x: test, y: item._source['performance-data']['tx-level-max'] }); + minListB.push({ x: test, y: item._source['performance-data']['tx-level-min'] }); + avgListB.push({ x: test, y: item._source['performance-data']['tx-level-avg'] }); + } else { + + maxListB.push({ x: 0, y: item._source['performance-data']['tx-level-max'] }); + minListB.push({ x: 0, y: item._source['performance-data']['tx-level-min'] }); + avgListB.push({ x: 0, y: item._source['performance-data']['tx-level-avg'] }); + } + }); + + $scope.transmissionSeries.push('Tx max B', 'Tx min B', 'Tx avg B'); + + $scope.transmissionData.push(maxListB); + $scope.transmissionData.push(minListB); + $scope.transmissionData.push(avgListB); + + $scope.transmissionDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.transmissionDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.transmissionDatasetOverride.push({ yAxisID: 'y-axis-1' }); + + overridePoints($scope.transmissionSeries, $scope.transmissionDatasetOverride); + } + + break; + + case 'modulation': { + + $scope.modulationData = []; + $scope.modultaionSeries = []; + $scope.modulationDatasetOverride = []; + + $scope.modulationOptions = { + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom', + afterTickToLabelConversion: function (data) { //adds our custom timestamp labels + + var xLabels = data.ticks; + xLabels.forEach(function (labels, i) { + var timestamp = $scope.modLabelMap.get(parseInt(labels)); + if (parseInt(labels) == labels) + xLabels[i] = timestamp; + else + xLabels[i] = ''; + + }); + + //calculate last timestamp if label is missing + if (xLabels[xLabels.length - 1] === undefined) { + var timestamp = $scope.modLabelMap.get($scope.modLabelMap.size - 1); + let stopper = true; + let counter = 0; + let labelLength = xLabels.length - 1; + while (stopper) { + if (labelLength % 10 == 0) { + stopper = false; + } else { + labelLength++; + counter++; + } + + } + + xLabels[xLabels.length - 1] = calculateMissingTimestamp(timestamp, counter); + } + } + }], + yAxes: [ + { + id: 'y-axis-1', + type: 'linear', + display: true, + position: 'left' + } + ] + }, + tooltips: { + enabled: true, + mode: 'point', + callbacks: { + title: function (tooltipItem, data) { //picks right tool tip + + var vaue = $scope.modtestMap.get(tooltipItem[0].xLabel); + return vaue; + } + } + }, + legend: { + display: true, + position: "bottom" + } + + }; + + $scope.modtestMap = new Map(); + $scope.modLabelMap = new Map(); + + tempArr.map(function (item, index) { + $scope.modtestMap.set(item, index); + $scope.modLabelMap.set(index, item); + }); + + var time2S = []; + var time2 = []; + var time2L = []; + var time4S = []; + var time4 = []; + var time4L = []; + var time16S = []; + var time16 = []; + var time16L = []; + var time32S = []; + var time32 = []; + var time32L = []; + var time64S = []; + var time64 = []; + var time64L = []; + var time128S = []; + var time128 = []; + var time128L = []; + var time256S = []; + var time256 = []; + var time256L = []; + var time512S = []; + var time512 = []; + var time512L = []; + var time1024S = []; + var time1024 = []; + var time1024L = []; + var time2048S = []; + var time2048 = []; + var time2048L = []; + var time4096S = []; + var time4096 = []; + var time4096L = []; + var time8192S = []; + var time8192 = []; + var time8192L = []; + + dataA.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.modtestMap.get(timestamp); + if (test) { + + //check if data is not undefined, if yes: add + let t2s = checkData(item._source['performance-data']['time2-states-s']); + if (t2s != undefined) + time2S.push({ x: test, y: t2s }); + + let t2 = checkData(item._source['performance-data']['time2-states']); + if (t2 != undefined) + time2.push({ x: test, y: t2 }); + + let t2L = checkData(item._source['performance-data']['time2-states-l']); + if (t2L != undefined) + time2L.push({ x: test, y: t2L }); + + let t4s = checkData(item._source['performance-data']['time4-states-s']); + if (t4s != undefined) + time4S.push({ x: test, y: t4s }); + + let t4 = checkData(item._source['performance-data']['time4-states']); + if (t4 != undefined) + time4.push({ x: test, y: t4 }); + + let t4L = checkData(item._source['performance-data']['time4-states-l']); + if (t4L != undefined) + time4L.push({ x: test, y: t4L }); + + let t16s = checkData(item._source['performance-data']['time16-states-s']); + if (t16s != undefined) + time16S.push({ x: test, y: t16s }); + + + let t16 = checkData(item._source['performance-data']['time16-states']); + if (t16 != undefined) + time16.push({ x: test, y: t16 }); + + + let t16L = checkData(item._source['performance-data']['time16-states-l']); + if (t16L != undefined) + time16L.push({ x: test, y: t16L }); + + let t32s = checkData(item._source['performance-data']['time32-states-s']); + if (t32s != undefined) + time32S.push({ x: test, y: t32s }); + + let t32 = checkData(item._source['performance-data']['time32-states']); + if (t32 != undefined) + time32.push({ x: test, y: t32 }); + + + let t32L = checkData(item._source['performance-data']['time32-states-l']); + if (t32L != undefined) + time32L.push({ x: test, y: t32L }); + + + + let t64s = checkData(item._source['performance-data']['time64-states-s']); + if (t64s != undefined) + time64S.push({ x: test, y: t64s }); + + let t64 = checkData(item._source['performance-data']['time64-states']); + if (t64 != undefined) + time64.push({ x: test, y: t64 }); + + let t64L = checkData(item._source['performance-data']['time64-states-l']); + if (t64L != undefined) + time64L.push({ x: test, y: t64L }); + + + let t128s = checkData(item._source['performance-data']['time128-states-s']); + if (t128s != undefined) + time128S.push({ x: test, y: t128s }); + + let t128 = checkData(item._source['performance-data']['time128-states']); + if (t128 != undefined) + time128.push({ x: test, y: t128 }); + + let t128L = checkData(item._source['performance-data']['time128-states-l']); + if (t128L != undefined) + time128L.push({ x: test, y: t128L }); + + + let t256s = checkData(item._source['performance-data']['time256-states-s']); + if (t256s != undefined) + time256S.push({ x: test, y: t256s }); + + let t256 = checkData(item._source['performance-data']['time256-states']); + if (t256 != undefined) + time256.push({ x: test, y: t256 }); + + let t256L = checkData(item._source['performance-data']['time256-states-l']); + if (t256L != undefined) + time256L.push({ x: test, y: t256L }); + + let t512s = checkData(item._source['performance-data']['time512-states-s']); + if (t512s != undefined) + time512S.push({ x: test, y: t512s }); + + let t512 = checkData(item._source['performance-data']['time512-states']); + if (t512 != undefined) + time512.push({ x: test, y: t512 }); + + let t512L = checkData(item._source['performance-data']['time512-states-l']); + if (t512L != undefined) + time512L.push({ x: test, y: t512L }); + + let t1024s = checkData(item._source['performance-data']['time1024-states-s']); + if (t1024s != undefined) + time1024S.push({ x: test, y: t1024s }); + + let t1024 = checkData(item._source['performance-data']['time1024-states']); + if (t1024 != undefined) + time1024.push({ x: test, y: t1024 }); + + let t1024L = checkData(item._source['performance-data']['time1024-states-l']); + if (t1024L != undefined) + time1024L.push({ x: test, y: t1024L }); + + let t2048s = checkData(item._source['performance-data']['time2048-states-s']); + if (t2048s != undefined) + time2048S.push({ x: test, y: t2048s }); + + let t2048 = checkData(item._source['performance-data']['time2048-states']); + if (t2048 != undefined) + time2048.push({ x: test, y: t2048 }); + + let t2048L = checkData(item._source['performance-data']['time2048-states-l']); + if (t2048L != undefined) + time2048L.push({ x: test, y: t2048L }); + + let t4096s = checkData(item._source['performance-data']['time4096-states-s']); + if (t4096s != undefined) + time4096S.push({ x: test, y: t4096s }); + + let t4096 = checkData(item._source['performance-data']['time4096-states']); + if (t4096 != undefined) + time4096.push({ x: test, y: t4096 }); + + let t4096L = checkData(item._source['performance-data']['time4096-states-l']); + if (t4096L != undefined) + time4096L.push({ x: test, y: t4096L }); + + let t8192s = checkData(item._source['performance-data']['time8192-states-s']); + if (t8192s != undefined) + time8192S.push({ x: test, y: t8192s }); + + let t8192 = checkData(item._source['performance-data']['time8192-states']); + if (t8192 != undefined) + time8192.push({ x: test, y: t8192 }); + + let t8192L = checkData(item._source['performance-data']['time8192-states-l']); + if (t8192L != undefined) + time8192L.push({ x: test, y: t8192L }); + + } else { + + let t2s = checkData(item._source['performance-data']['time2-states-s']); + if (t2s != undefined) + time2S.push({ x: 0, y: t2s }); + + let t2 = checkData(item._source['performance-data']['time2-states']); + if (t2 != undefined) + time2.push({ x: 0, y: t2 }); + + let t2L = checkData(item._source['performance-data']['time2-states-l']); + if (t2L != undefined) + time2L.push({ x: 0, y: t2L }); + + let t4s = checkData(item._source['performance-data']['time4-states-s']); + if (t4s != undefined) + time4S.push({ x: 0, y: t4s }); + + let t4 = checkData(item._source['performance-data']['time4-states']); + if (t4 != undefined) + time4.push({ x: 0, y: t4 }); + + let t4L = checkData(item._source['performance-data']['time4-states-l']); + if (t4L != undefined) + time4L.push({ x: 0, y: t4L }); + + let t16s = checkData(item._source['performance-data']['time16-states-s']); + if (t16s != undefined) + time16S.push({ x: 0, y: t16s }); + + + let t16 = checkData(item._source['performance-data']['time16-states']); + if (t16 != undefined) + time16.push({ x: 0, y: t16 }); + + + let t16L = checkData(item._source['performance-data']['time16-states-l']); + if (t16L != undefined) + time16L.push({ x: 0, y: t16L }); + + let t32s = checkData(item._source['performance-data']['time32-states-s']); + if (t32s != undefined) + time32S.push({ x: 0, y: t32s }); + + let t32 = checkData(item._source['performance-data']['time32-states']); + if (t32 != undefined) + time32.push({ x: 0, y: t32 }); + + + let t32L = checkData(item._source['performance-data']['time32-states-l']); + if (t32L != undefined) + time32L.push({ x: 0, y: t32L }); + + let t64s = checkData(item._source['performance-data']['time64-states-s']); + if (t64s != undefined) + time64S.push({ x: 0, y: t64s }); + + let t64 = checkData(item._source['performance-data']['time64-states']); + if (t64 != undefined) + time64.push({ x: 0, y: t64 }); + + let t64L = checkData(item._source['performance-data']['time64-states-l']); + if (t64L != undefined) + time64L.push({ x: 0, y: t64L }); + + + let t128s = checkData(item._source['performance-data']['time128-states-s']); + if (t128s != undefined) + time128S.push({ x: 0, y: t128s }); + + let t128 = checkData(item._source['performance-data']['time128-states']); + if (t128 != undefined) + time128.push({ x: 0, y: t128 }); + + let t128L = checkData(item._source['performance-data']['time128-states-l']); + if (t128L != undefined) + time128L.push({ x: 0, y: t128L }); + + + let t256s = checkData(item._source['performance-data']['time256-states-s']); + if (t256s != undefined) + time256S.push({ x: 0, y: t256s }); + + let t256 = checkData(item._source['performance-data']['time256-states']); + if (t256 != undefined) + time256.push({ x: 0, y: t256 }); + + let t256L = checkData(item._source['performance-data']['time256-states-l']); + if (t256L != undefined) + time256L.push({ x: 0, y: t256L }); + + let t512s = checkData(item._source['performance-data']['time512-states-s']); + if (t512s != undefined) + time512S.push({ x: 0, y: t512s }); + + let t512 = checkData(item._source['performance-data']['time512-states']); + if (t512 != undefined) + time512.push({ x: 0, y: t512 }); + + let t512L = checkData(item._source['performance-data']['time512-states-l']); + if (t512L != undefined) + time512L.push({ x: 0, y: t512L }); + + let t1024s = checkData(item._source['performance-data']['time1024-states-s']); + if (t1024s != undefined) + time1024S.push({ x: 0, y: t1024s }); + + let t1024 = checkData(item._source['performance-data']['time1024-states']); + if (t1024 != undefined) + time1024.push({ x: 0, y: t1024 }); + + let t1024L = checkData(item._source['performance-data']['time1024-states-l']); + if (t1024L != undefined) + time1024L.push({ x: 0, y: t1024L }); + + let t2048s = checkData(item._source['performance-data']['time2048-states-s']); + if (t2048s != undefined) + time2048S.push({ x: 0, y: t2048s }); + + let t2048 = checkData(item._source['performance-data']['time2048-states']); + if (t2048 != undefined) + time2048.push({ x: 0, y: t2048 }); + + let t2048L = checkData(item._source['performance-data']['time2048-states-l']); + if (t2048L != undefined) + time2048L.push({ x: 0, y: t2048L }); + + let t4096s = checkData(item._source['performance-data']['time4096-states-s']); + if (t4096s != undefined) + time4096S.push({ x: 0, y: t4096s }); + + let t4096 = checkData(item._source['performance-data']['time4096-states']); + if (t4096 != undefined) + time4096.push({ x: 0, y: t4096 }); + + let t4096L = checkData(item._source['performance-data']['time4096-states-l']); + if (t4096L != undefined) + time4096L.push({ x: 0, y: t4096L }); + + let t8192s = checkData(item._source['performance-data']['time8192-states-s']); + if (t8192s != undefined) + time8192S.push({ x: 0, y: t8192s }); + + let t8192 = checkData(item._source['performance-data']['time8192-states']); + if (t8192 != undefined) + time8192.push({ x: 0, y: t8192 }); + + let t8192L = checkData(item._source['performance-data']['time8192-states-l']); + if (t8192L != undefined) + time8192L.push({ x: 0, y: t8192L }); + + } + }); + + //check, if array has items, if yes: add series and data to chart + //reduces amount of labels shown in chart => shows only series' with data + if (time2S.length > 0) { + $scope.modultaionSeries.push('QAM2S A'); + $scope.modulationData.push(time2S); + } + + if (time2.length > 0) { + $scope.modultaionSeries.push('QAM2 A'); + $scope.modulationData.push(time2); + } + + if (time2L.length > 0) { + $scope.modultaionSeries.push('QAM2L A'); + $scope.modulationData.push(time2L); + } + + if (time4S.length > 0) { + $scope.modultaionSeries.push('QAM4S A'); + $scope.modulationData.push(time4S); + } + + if (time4.length > 0) { + $scope.modultaionSeries.push('QAM4 A'); + $scope.modulationData.push(time4); + } + + if (time4L.length > 0) { + $scope.modultaionSeries.push('QAM4L A'); + $scope.modulationData.push(time4L); + } + + if (time16S.length > 0) { + $scope.modultaionSeries.push('QAM16S A'); + $scope.modulationData.push(time16S); + } + + + if (time16.length > 0) { + $scope.modultaionSeries.push('QAM16 A'); + $scope.modulationData.push(time16); + } + + if (time16L.length > 0) { + $scope.modultaionSeries.push('QAM16L A'); + $scope.modulationData.push(time16L); + } + + if (time32S.length > 0) { + $scope.modulationData.push(time32S); + $scope.modultaionSeries.push('QAM32S A'); + } + + if (time32.length > 0) { + $scope.modulationData.push(time32); + $scope.modultaionSeries.push('QAM32 A'); + } + + if (time32L.length > 0) { + $scope.modulationData.push(time32L); + $scope.modultaionSeries.push('QAM32L A'); + } + + + if (time64S.length > 0) { + $scope.modulationData.push(time64S); + $scope.modultaionSeries.push('QAM64S A'); + } + + + if (time64.length > 0) { + $scope.modulationData.push(time64); + $scope.modultaionSeries.push('QAM64 A'); + } + + if (time64L.length > 0) { + $scope.modulationData.push(time64L); + $scope.modultaionSeries.push('QAM64L A'); + } + + + if (time128S.length > 0) { + $scope.modultaionSeries.push('QAM128S A'); + $scope.modulationData.push(time128S); + } + + if (time128.length > 0) { + $scope.modultaionSeries.push('QAM128 A'); + $scope.modulationData.push(time128); + } + + if (time128L.length > 0) { + $scope.modultaionSeries.push('QAM128L A'); + $scope.modulationData.push(time128L); + } + + if (time256S.length > 0) { + $scope.modulationData.push(time256S); + $scope.modultaionSeries.push('QAM256S A'); + } + + if (time256.length > 0) { + $scope.modulationData.push(time256); + $scope.modultaionSeries.push('QAM256 A'); + } + + if (time256L.length > 0) { + $scope.modulationData.push(time256L); + $scope.modultaionSeries.push('QAM256L A'); + } + + if (time512S.length > 0) { + $scope.modultaionSeries.push('QAM512S A'); + $scope.modulationData.push(time512S); + } + + if (time512.length > 0) { + $scope.modultaionSeries.push('QAM512 A'); + $scope.modulationData.push(time512); + } + + if (time512S.length > 0) { + $scope.modultaionSeries.push('QAM512S A'); + $scope.modulationData.push(time512S); + } + + if (time512.length > 0) { + $scope.modultaionSeries.push('QAM512 A'); + $scope.modulationData.push(time512); + } + + if (time512L.length > 0) { + $scope.modultaionSeries.push('QAM512L A'); + $scope.modulationData.push(time512L); + + } + + if (time1024S.length > 0) { + $scope.modultaionSeries.push('QAM1024S A'); + $scope.modulationData.push(time1024S); + } + + if (time1024.length > 0) { + $scope.modultaionSeries.push('QAM1024 A'); + $scope.modulationData.push(time1024); + } + + + if (time1024L.length > 0) { + $scope.modultaionSeries.push('QAM1024L A'); + $scope.modulationData.push(time1024L); + } + + + if (time2048S.length > 0) { + $scope.modultaionSeries.push('QAM2048S A'); + $scope.modulationData.push(time2048S); + } + + if (time2048.length > 0) { + $scope.modultaionSeries.push('QAM2048 A'); + $scope.modulationData.push(time2048); + } + + if (time2048L.length > 0) { + $scope.modultaionSeries.push('QAM2048L A'); + $scope.modulationData.push(time2048L); + + } + + if (time4096S.length > 0) { + $scope.modultaionSeries.push('QAM4096S A'); + $scope.modulationData.push(time4096S); + } + + if (time4096.length > 0) { + $scope.modultaionSeries.push('QAM4096 A'); + $scope.modulationData.push(time4096); + } + + + if (time4096L.length > 0) { + $scope.modultaionSeries.push('QAM4096L A'); + $scope.modulationData.push(time4096L); + } + + if (time8192S.length > 0) { + $scope.modultaionSeries.push('QAM8192S A'); + $scope.modulationData.push(time8192S); + } + + + if (time8192.length > 0) { + $scope.modultaionSeries.push('QAM8192 A'); + $scope.modulationData.push(time8192); + } + + if (time8192L.length > 0) { + $scope.modultaionSeries.push('QAM8192L A'); + $scope.modulationData.push(time8192L); + } + + //process data for b side + + time2S = []; + time2 = []; + time2L = []; + time4S = []; + time4 = []; + time4L = []; + time16S = []; + time16 = []; + time16L = []; + time32S = []; + time32 = []; + time32L = []; + time64S = []; + time64 = []; + time64L = []; + time128S = []; + time128 = []; + time128L = []; + time256S = []; + time256 = []; + time256L = []; + time512S = []; + time512 = []; + time512L = []; + time1024S = []; + time1024 = []; + time1024L = []; + time2048S = []; + time2048 = []; + time2048L = []; + time4096S = []; + time4096 = []; + time4096L = []; + time8192S = []; + time8192 = []; + time8192L = []; + + dataB.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + var test = $scope.modtestMap.get(timestamp); + if (test) { + let t2s = checkData(item._source['performance-data']['time2-states-s']); + if (t2s != undefined) + time2S.push({ x: test, y: t2s }); + + let t2 = checkData(item._source['performance-data']['time2-states']); + if (t2 != undefined) + time2.push({ x: test, y: t2 }); + + let t2L = checkData(item._source['performance-data']['time2-states-l']); + if (t2L != undefined) + time2L.push({ x: test, y: t2L }); + + let t4s = checkData(item._source['performance-data']['time4-states-s']); + if (t4s != undefined) + time4S.push({ x: test, y: t4s }); + + let t4 = checkData(item._source['performance-data']['time4-states']); + if (t4 != undefined) + time4.push({ x: test, y: t4 }); + + let t4L = checkData(item._source['performance-data']['time4-states-l']); + if (t4L != undefined) + time4L.push({ x: test, y: t4L }); + + let t16s = checkData(item._source['performance-data']['time16-states-s']); + if (t16s != undefined) + time16S.push({ x: test, y: t16s }); + + + let t16 = checkData(item._source['performance-data']['time16-states']); + if (t16 != undefined) + time16.push({ x: test, y: t16 }); + + + let t16L = checkData(item._source['performance-data']['time16-states-l']); + if (t16L != undefined) + time16L.push({ x: test, y: t16L }); + + let t32s = checkData(item._source['performance-data']['time32-states-s']); + if (t32s != undefined) + time32S.push({ x: test, y: t32s }); + + let t32 = checkData(item._source['performance-data']['time32-states']); + if (t32 != undefined) + time32.push({ x: test, y: t32 }); + + + let t32L = checkData(item._source['performance-data']['time32-states-l']); + if (t32L != undefined) + time32L.push({ x: test, y: t32L }); + + + + let t64s = checkData(item._source['performance-data']['time64-states-s']); + if (t64s != undefined) + time64S.push({ x: test, y: t64s }); + + let t64 = checkData(item._source['performance-data']['time64-states']); + if (t64 != undefined) + time64.push({ x: test, y: t64 }); + + let t64L = checkData(item._source['performance-data']['time64-states-l']); + if (t64L != undefined) + time64L.push({ x: test, y: t64L }); + + + let t128s = checkData(item._source['performance-data']['time128-states-s']); + if (t128s != undefined) + time128S.push({ x: test, y: t128s }); + + let t128 = checkData(item._source['performance-data']['time128-states']); + if (t128 != undefined) + time128.push({ x: test, y: t128 }); + + let t128L = checkData(item._source['performance-data']['time128-states-l']); + if (t128L != undefined) + time128L.push({ x: test, y: t128L }); + + + let t256s = checkData(item._source['performance-data']['time256-states-s']); + if (t256s != undefined) + time256S.push({ x: test, y: t256s }); + + let t256 = checkData(item._source['performance-data']['time256-states']); + if (t256 != undefined) + time256.push({ x: test, y: t256 }); + + let t256L = checkData(item._source['performance-data']['time256-states-l']); + if (t256L != undefined) + time256L.push({ x: test, y: t256L }); + + let t512s = checkData(item._source['performance-data']['time512-states-s']); + if (t512s != undefined) + time512S.push({ x: test, y: t512s }); + + let t512 = checkData(item._source['performance-data']['time512-states']); + if (t512 != undefined) + time512.push({ x: test, y: t512 }); + + let t512L = checkData(item._source['performance-data']['time512-states-l']); + if (t512L != undefined) + time512L.push({ x: test, y: t512L }); + + let t1024s = checkData(item._source['performance-data']['time1024-states-s']); + if (t1024s != undefined) + time1024S.push({ x: test, y: t1024s }); + + let t1024 = checkData(item._source['performance-data']['time1024-states']); + if (t1024 != undefined) + time1024.push({ x: test, y: t1024 }); + + let t1024L = checkData(item._source['performance-data']['time1024-states-l']); + if (t1024L != undefined) + time1024L.push({ x: test, y: t1024L }); + + let t2048s = checkData(item._source['performance-data']['time2048-states-s']); + if (t2048s != undefined) + time2048S.push({ x: test, y: t2048s }); + + let t2048 = checkData(item._source['performance-data']['time2048-states']); + if (t2048 != undefined) + time2048.push({ x: test, y: t2048 }); + + let t2048L = checkData(item._source['performance-data']['time2048-states-l']); + if (t2048L != undefined) + time2048L.push({ x: test, y: t2048L }); + + let t4096s = checkData(item._source['performance-data']['time4096-states-s']); + if (t4096s != undefined) + time4096S.push({ x: test, y: t4096s }); + + let t4096 = checkData(item._source['performance-data']['time4096-states']); + if (t4096 != undefined) + time4096.push({ x: test, y: t4096 }); + + let t4096L = checkData(item._source['performance-data']['time4096-states-l']); + if (t4096L != undefined) + time4096L.push({ x: test, y: t4096L }); + + let t8192s = checkData(item._source['performance-data']['time8192-states-s']); + if (t8192s != undefined) + time8192S.push({ x: test, y: t8192s }); + + let t8192 = checkData(item._source['performance-data']['time8192-states']); + if (t8192 != undefined) + time8192.push({ x: test, y: t8192 }); + + let t8192L = checkData(item._source['performance-data']['time8192-states-l']); + if (t8192L != undefined) + time8192L.push({ x: test, y: t8192L }); + + } else { + + let t2s = checkData(item._source['performance-data']['time2-states-s']); + if (t2s != undefined) + time2S.push({ x: 0, y: t2s }); + + let t2 = checkData(item._source['performance-data']['time2-states']); + if (t2 != undefined) + time2.push({ x: 0, y: t2 }); + + let t2L = checkData(item._source['performance-data']['time2-states-l']); + if (t2L != undefined) + time2L.push({ x: 0, y: t2L }); + + let t4s = checkData(item._source['performance-data']['time4-states-s']); + if (t4s != undefined) + time4S.push({ x: 0, y: t4s }); + + let t4 = checkData(item._source['performance-data']['time4-states']); + if (t4 != undefined) + time4.push({ x: 0, y: t4 }); + + let t4L = checkData(item._source['performance-data']['time4-states-l']); + if (t4L != undefined) + time4L.push({ x: 0, y: t4L }); + + let t16s = checkData(item._source['performance-data']['time16-states-s']); + if (t16s != undefined) + time16S.push({ x: 0, y: t16s }); + + + let t16 = checkData(item._source['performance-data']['time16-states']); + if (t16 != undefined) + time16.push({ x: 0, y: t16 }); + + + let t16L = checkData(item._source['performance-data']['time16-states-l']); + if (t16L != undefined) + time16L.push({ x: 0, y: t16L }); + + let t32s = checkData(item._source['performance-data']['time32-states-s']); + if (t32s != undefined) + time32S.push({ x: 0, y: t32s }); + + let t32 = checkData(item._source['performance-data']['time32-states']); + if (t32 != undefined) + time32.push({ x: 0, y: t32 }); + + + let t32L = checkData(item._source['performance-data']['time32-states-l']); + if (t32L != undefined) + time32L.push({ x: 0, y: t32L }); + + let t64s = checkData(item._source['performance-data']['time64-states-s']); + if (t64s != undefined) + time64S.push({ x: 0, y: t64s }); + + let t64 = checkData(item._source['performance-data']['time64-states']); + if (t64 != undefined) + time64.push({ x: 0, y: t64 }); + + let t64L = checkData(item._source['performance-data']['time64-states-l']); + if (t64L != undefined) + time64L.push({ x: 0, y: t64L }); + + + let t128s = checkData(item._source['performance-data']['time128-states-s']); + if (t128s != undefined) + time128S.push({ x: 0, y: t128s }); + + let t128 = checkData(item._source['performance-data']['time128-states']); + if (t128 != undefined) + time128.push({ x: 0, y: t128 }); + + let t128L = checkData(item._source['performance-data']['time128-states-l']); + if (t128L != undefined) + time128L.push({ x: 0, y: t128L }); + + + let t256s = checkData(item._source['performance-data']['time256-states-s']); + if (t256s != undefined) + time256S.push({ x: 0, y: t256s }); + + let t256 = checkData(item._source['performance-data']['time256-states']); + if (t256 != undefined) + time256.push({ x: 0, y: t256 }); + + let t256L = checkData(item._source['performance-data']['time256-states-l']); + if (t256L != undefined) + time256L.push({ x: 0, y: t256L }); + + let t512s = checkData(item._source['performance-data']['time512-states-s']); + if (t512s != undefined) + time512S.push({ x: 0, y: t512s }); + + let t512 = checkData(item._source['performance-data']['time512-states']); + if (t512 != undefined) + time512.push({ x: 0, y: t512 }); + + let t512L = checkData(item._source['performance-data']['time512-states-l']); + if (t512L != undefined) + time512L.push({ x: 0, y: t512L }); + + let t1024s = checkData(item._source['performance-data']['time1024-states-s']); + if (t1024s != undefined) + time1024S.push({ x: 0, y: t1024s }); + + let t1024 = checkData(item._source['performance-data']['time1024-states']); + if (t1024 != undefined) + time1024.push({ x: 0, y: t1024 }); + + let t1024L = checkData(item._source['performance-data']['time1024-states-l']); + if (t1024L != undefined) + time1024L.push({ x: 0, y: t1024L }); + + let t2048s = checkData(item._source['performance-data']['time2048-states-s']); + if (t2048s != undefined) + time2048S.push({ x: 0, y: t2048s }); + + let t2048 = checkData(item._source['performance-data']['time2048-states']); + if (t2048 != undefined) + time2048.push({ x: 0, y: t2048 }); + + let t2048L = checkData(item._source['performance-data']['time2048-states-l']); + if (t2048L != undefined) + time2048L.push({ x: 0, y: t2048L }); + + let t4096s = checkData(item._source['performance-data']['time4096-states-s']); + if (t4096s != undefined) + time4096S.push({ x: 0, y: t4096s }); + + let t4096 = checkData(item._source['performance-data']['time4096-states']); + if (t4096 != undefined) + time4096.push({ x: 0, y: t4096 }); + + let t4096L = checkData(item._source['performance-data']['time4096-states-l']); + if (t4096L != undefined) + time4096L.push({ x: 0, y: t4096L }); + + let t8192s = checkData(item._source['performance-data']['time8192-states-s']); + if (t8192s != undefined) + time8192S.push({ x: 0, y: t8192s }); + + let t8192 = checkData(item._source['performance-data']['time8192-states']); + if (t8192 != undefined) + time8192.push({ x: 0, y: t8192 }); + + let t8192L = checkData(item._source['performance-data']['time8192-states-l']); + if (t8192L != undefined) + time8192L.push({ x: 0, y: t8192L }); + + } + }); + + if (time2S.length > 0) { + $scope.modultaionSeries.push('QAM2S B'); + $scope.modulationData.push(time2S); + } + + if (time2.length > 0) { + $scope.modultaionSeries.push('QAM2 B'); + $scope.modulationData.push(time2); + } + + if (time2L.length > 0) { + $scope.modultaionSeries.push('QAM2L B'); + $scope.modulationData.push(time2L); + } + + if (time4S.length > 0) { + $scope.modultaionSeries.push('QAM4S B'); + $scope.modulationData.push(time4S); + } + + if (time4.length > 0) { + $scope.modultaionSeries.push('QAM4 B'); + $scope.modulationData.push(time4); + } + + if (time4L.length > 0) { + $scope.modultaionSeries.push('QAM4L B'); + $scope.modulationData.push(time4L); + } + + if (time16S.length > 0) { + $scope.modultaionSeries.push('QAM16S B'); + $scope.modulationData.push(time16S); + } + + + if (time16.length > 0) { + $scope.modultaionSeries.push('QAM16 B'); + $scope.modulationData.push(time16); + } + + + if (time16L.length > 0) { + $scope.modultaionSeries.push('QAM16L B'); + $scope.modulationData.push(time16L); + } + + if (time32S.length > 0) { + $scope.modulationData.push(time32S); + $scope.modultaionSeries.push('QAM32S B'); + } + + if (time32.length > 0) { + $scope.modulationData.push(time32); + $scope.modultaionSeries.push('QAM32 B'); + } + + if (time32L.length > 0) { + $scope.modulationData.push(time32L); + $scope.modultaionSeries.push('QAM32L B'); + } + + + if (time64S.length > 0) { + $scope.modulationData.push(time64S); + $scope.modultaionSeries.push('QAM64S B'); + } + + + if (time64.length > 0) { + $scope.modulationData.push(time64); + $scope.modultaionSeries.push('QAM64 B'); + } + + if (time64L.length > 0) { + $scope.modulationData.push(time64L); + $scope.modultaionSeries.push('QAM64L B'); + } + + + if (time128S.length > 0) { + $scope.modultaionSeries.push('QAM128S B'); + $scope.modulationData.push(time128S); + } + + if (time128.length > 0) { + $scope.modultaionSeries.push('QAM128 B'); + $scope.modulationData.push(time128); + } + + if (time128L.length > 0) { + $scope.modultaionSeries.push('QAM128L B'); + $scope.modulationData.push(time128L); + } + + if (time256S.length > 0) { + $scope.modulationData.push(time256S); + $scope.modultaionSeries.push('QAM256S B'); + } + + if (time256.length > 0) { + $scope.modulationData.push(time256); + $scope.modultaionSeries.push('QAM256 B'); + } + + if (time256L.length > 0) { + $scope.modulationData.push(time256L); + $scope.modultaionSeries.push('QAM256L B'); + } + + if (time512S.length > 0) { + $scope.modultaionSeries.push('QAM512S B'); + $scope.modulationData.push(time512S); + + } + + if (time512.length > 0) { + $scope.modultaionSeries.push('QAM512 B'); + $scope.modulationData.push(time512); + + } + + if (time512S.length > 0) { + $scope.modultaionSeries.push('QAM512S B'); + $scope.modulationData.push(time512S); + } + + if (time512.length > 0) { + $scope.modultaionSeries.push('QAM512 B'); + $scope.modulationData.push(time512); + } + + if (time512L.length > 0) { + $scope.modultaionSeries.push('QAM512L B'); + $scope.modulationData.push(time512L); + } + + if (time1024S.length > 0) { + $scope.modultaionSeries.push('QAM1024S B'); + $scope.modulationData.push(time1024S); + + } + + if (time1024.length > 0) { + $scope.modultaionSeries.push('QAM1024 B'); + $scope.modulationData.push(time1024); + } + + + if (time1024L.length > 0) { + $scope.modultaionSeries.push('QAM1024L B'); + $scope.modulationData.push(time1024L); + + } + + + if (time2048S.length > 0) { + $scope.modultaionSeries.push('QAM2048S B'); + $scope.modulationData.push(time2048S); + + } + + if (time2048.length > 0) { + $scope.modultaionSeries.push('QAM2048 B'); + $scope.modulationData.push(time2048); + } + + if (time2048L.length > 0) { + $scope.modultaionSeries.push('QAM2048L B'); + $scope.modulationData.push(time2048L); + } + + if (time4096S.length > 0) { + $scope.modultaionSeries.push('QAM4096S B'); + $scope.modulationData.push(time4096S); + } + + if (time4096.length > 0) { + $scope.modultaionSeries.push('QAM4096 B'); + $scope.modulationData.push(time4096); + } + + + if (time4096L.length > 0) { + $scope.modultaionSeries.push('QAM4096L B'); + $scope.modulationData.push(time4096L); + + } + + if (time8192S.length > 0) { + $scope.modultaionSeries.push('QAM8192S B'); + $scope.modulationData.push(time8192S); + + } + + + if (time8192.length > 0) { + $scope.modultaionSeries.push('QAM8192 B'); + $scope.modulationData.push(time8192); + + } + + if (time8192L.length > 0) { + $scope.modultaionSeries.push('QAM8192L B'); + $scope.modulationData.push(time8192L); + + } + + let patternArray = ['rect', 'triangle', 'point', 'cross']; + let patternCounter = 0; + + //add y axis override and remove color below graph for all items in chart series + for (let i = 0; i < $scope.modultaionSeries.length; i++) { + $scope.modulationDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.modulationDatasetOverride[i].fill = false; + + //override points in graph + $scope.modulationDatasetOverride[i].pointStyle = patternArray[patternCounter]; + patternCounter++; + if (patternCounter === 4) patternCounter = 0; + $scope.modulationDatasetOverride[i].pointRadius = 10; + + } + } + + break; + + case 'temperature': { + + $scope.tempData = []; + $scope.tempSeries = []; + $scope.tempDatasetOverride = []; + + $scope.tempOptions = { + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom', + afterTickToLabelConversion: function (data) { //adds our custom timestamp labels + + var xLabels = data.ticks; + xLabels.forEach(function (labels, i) { + var timestamp = $scope.tempLabelMap.get(parseInt(labels)); + if (parseInt(labels) == labels) + xLabels[i] = timestamp; + else + xLabels[i] = ''; + }); + + //calculate last timestamp if label is missing + if (xLabels[xLabels.length - 1] === undefined) { + var timestamp = $scope.tempLabelMap.get($scope.tempLabelMap.size - 1); + let stopper = true; + let counter = 0; + let labelLength = xLabels.length - 1; + while (stopper) { + if (labelLength % 10 == 0) { + stopper = false; + } else { + labelLength++; + counter++; + } + } + + xLabels[xLabels.length - 1] = calculateMissingTimestamp(timestamp, counter); + } + } + }], + yAxes: [ + { + id: 'y-axis-1', + type: 'linear', + display: true, + position: 'left' + } + ] + }, + tooltips: { + enabled: true, + mode: 'point', + callbacks: { + title: function (tooltipItem, data) { //picks right tool tip + + var vaue = $scope.tempLabelMap.get(tooltipItem[0].xLabel); + return vaue; + } + } + }, + legend: { + display: true, + position: "bottom" + } + }; + + $scope.temptestMap = new Map(); + $scope.tempLabelMap = new Map(); + + + tempArr.map(function (item, index) { + $scope.temptestMap.set(item, index); + $scope.tempLabelMap.set(index, item); + }); + + //process data for a side + var maxListA = []; + var minListA = []; + var avgListA = []; + + dataA.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.temptestMap.get(timestamp); + if (test) { + maxListA.push({ x: test, y: item._source['performance-data']['rf-temp-max'] }); + minListA.push({ x: test, y: item._source['performance-data']['rf-temp-min'] }); + avgListA.push({ x: test, y: item._source['performance-data']['rf-temp-avg'] }); + } else { + + maxListA.push({ x: 0, y: item._source['performance-data']['rf-temp-max'] }); + minListA.push({ x: 0, y: item._source['performance-data']['rf-temp-min'] }); + avgListA.push({ x: 0, y: item._source['performance-data']['rf-temp-avg'] }); + } + }); + + $scope.tempSeries.push('Rf temp max A', 'Rf temp min A', 'Rf temp avg A'); + + + $scope.tempData.push(maxListA); + $scope.tempData.push(minListA); + $scope.tempData.push(avgListA); + + $scope.tempDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.tempDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.tempDatasetOverride.push({ yAxisID: 'y-axis-1' }); + + //process data fro side b + + var maxListB = []; + var minListB = []; + var avgListB = []; + + dataB.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + var test = $scope.temptestMap.get(timestamp); + if (test) { + maxListB.push({ x: test, y: item._source['performance-data']['rf-temp-max'] }); + minListB.push({ x: test, y: item._source['performance-data']['rf-temp-min'] }); + avgListB.push({ x: test, y: item._source['performance-data']['rf-temp-avg'] }); + } else { + + maxListB.push({ x: 0, y: item._source['performance-data']['rf-temp-max'] }); + minListB.push({ x: 0, y: item._source['performance-data']['rf-temp-min'] }); + avgListB.push({ x: 0, y: item._source['performance-data']['rf-temp-avg'] }); + } + }); + + $scope.tempSeries.push('Rf temp max B', 'Rf temp min B', 'Rf temp avg B'); + + + + $scope.tempData.push(maxListB); + $scope.tempData.push(minListB); + $scope.tempData.push(avgListB); + + $scope.tempDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.tempDatasetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.tempDatasetOverride.push({ yAxisID: 'y-axis-1' }); + + overridePoints($scope.tempSeries, $scope.tempDatasetOverride); + } + break; + + case 'snir': { + + $scope.snirChartData = []; + $scope.snirSeries = []; + $scope.snirsetOverride = []; + + $scope.snirOptions = { + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom', + afterTickToLabelConversion: function (data) { //adds our custom timestamp labels + + var xLabels = data.ticks; + xLabels.forEach(function (labels, i) { + var timestamp = $scope.snirLabelMap.get(parseInt(labels)); + if (parseInt(labels) == labels) + xLabels[i] = timestamp; + else + xLabels[i] = ''; + }); + + //calculate last timestamp if label is missing + if (xLabels[xLabels.length - 1] === undefined) { + var timestamp = $scope.snirLabelMap.get($scope.snirLabelMap.size - 1); + let stopper = true; + let counter = 0; + let labelLength = xLabels.length - 1; + while (stopper) { + if (labelLength % 10 == 0) { + stopper = false; + } else { + labelLength++; + counter++; + } + } + + xLabels[xLabels.length - 1] = calculateMissingTimestamp(timestamp, counter); + } + } + }], + yAxes: [ + { + id: 'y-axis-1', + type: 'linear', + display: true, + position: 'left' + } + ] + }, + tooltips: { + enabled: true, + mode: 'point', + callbacks: { + title: function (tooltipItem, data) { //picks right tool tip + + var vaue = $scope.snirLabelMap.get(tooltipItem[0].xLabel); + return vaue; + } + } + }, + legend: { + display: true, + position: "bottom" + } + }; + + $scope.snirtestMap = new Map(); + $scope.snirLabelMap = new Map(); + + tempArr.map(function (item, index) { + $scope.snirtestMap.set(item, index); + $scope.snirLabelMap.set(index, item); + }); + + var maxListA = []; + var minListA = []; + var avgListA = []; + + dataA.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.snirtestMap.get(timestamp); + if (test) { + maxListA.push({ x: test, y: item._source['performance-data']['rf-temp-max'] }); + minListA.push({ x: test, y: item._source['performance-data']['rf-temp-min'] }); + avgListA.push({ x: test, y: item._source['performance-data']['rf-temp-avg'] }); + } else { + maxListA.push({ x: 0, y: item._source['performance-data']['rf-temp-max'] }); + minListA.push({ x: 0, y: item._source['performance-data']['rf-temp-min'] }); + avgListA.push({ x: 0, y: item._source['performance-data']['rf-temp-avg'] }); + } + }); + + $scope.snirSeries.push('Snir max A', 'Snir min A', 'Snir avg A'); + + + $scope.snirChartData.push(maxListA); + $scope.snirChartData.push(minListA); + $scope.snirChartData.push(avgListA); + + $scope.snirsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.snirsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.snirsetOverride.push({ yAxisID: 'y-axis-1' }); + + var maxListB = []; + var minListB = []; + var avgListB = []; + + dataB.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + var test = $scope.snirtestMap.get(timestamp); + if (test) { + maxListB.push({ x: test, y: item._source['performance-data']['rf-temp-max'] }); + minListB.push({ x: test, y: item._source['performance-data']['rf-temp-min'] }); + avgListB.push({ x: test, y: item._source['performance-data']['rf-temp-avg'] }); + } else { + maxListB.push({ x: 0, y: item._source['performance-data']['rf-temp-max'] }); + minListB.push({ x: 0, y: item._source['performance-data']['rf-temp-min'] }); + avgListB.push({ x: 0, y: item._source['performance-data']['rf-temp-avg'] }); + } + }); + + $scope.snirSeries.push('Snir max B', 'Snir min B', 'Snir avg B'); + + + + $scope.snirChartData.push(maxListB); + $scope.snirChartData.push(minListB); + $scope.snirChartData.push(avgListB); + + $scope.snirsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.snirsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.snirsetOverride.push({ yAxisID: 'y-axis-1' }); + + overridePoints($scope.snirSeries, $scope.snirsetOverride); + } + break; + + case 'crossPolarDiscrimination': { + + $scope.xpdChartData = []; + $scope.xpdSeries = []; + $scope.crossPolarDiscriminationsetOverride = []; + + $scope.xpdOptions = { + scales: { + xAxes: [{ + + type: 'linear', + position: 'bottom', + afterTickToLabelConversion: function (data) { //adds our custom timestamp labels + + var xLabels = data.ticks; + xLabels.forEach(function (labels, i) { + var timestamp = $scope.xpdLabelMap.get(parseInt(labels)); + if (parseInt(labels) == labels) + xLabels[i] = timestamp; + else + xLabels[i] = ''; + + }); + + //calculate last timestamp if label is missing + if (xLabels[xLabels.length - 1] === undefined) { + var timestamp = $scope.xpdLabelMap.get($scope.xpdLabelMap.size - 1); + let stopper = true; + let counter = 0; + let labelLength = xLabels.length - 1; + while (stopper) { + if (labelLength % 10 == 0) { + stopper = false; + } else { + labelLength++; + counter++; + } + } + + xLabels[xLabels.length - 1] = calculateMissingTimestamp(timestamp, counter); + } + } + }], + yAxes: [ + { + id: 'y-axis-1', + type: 'linear', + display: true, + position: 'left' + } + ] + }, + tooltips: { + enabled: true, + mode: 'point', + callbacks: { + title: function (tooltipItem, data) { //picks right tool tip + + var vaue = $scope.xpdLabelMap.get(tooltipItem[0].xLabel); + return vaue; + } + } + }, + legend: { + display: true, + position: "bottom" + } + }; + + $scope.xpdtestMap = new Map(); + $scope.xpdLabelMap = new Map(); + + tempArr.map(function (item, index) { + $scope.xpdtestMap.set(item, index); + $scope.xpdLabelMap.set(index, item); + }); + + var maxListA = []; + var minListA = []; + var avgListA = []; + + dataA.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + + var test = $scope.xpdtestMap.get(timestamp); + if (test) { + maxListA.push({ x: test, y: item._source['performance-data']['xpd-max'] }); + minListA.push({ x: test, y: item._source['performance-data']['xpd-min'] }); + avgListA.push({ x: test, y: item._source['performance-data']['xpd-avg'] }); + } else { + maxListA.push({ x: 0, y: item._source['performance-data']['xpd-max'] }); + minListA.push({ x: 0, y: item._source['performance-data']['xpd-min'] }); + avgListA.push({ x: 0, y: item._source['performance-data']['xpd-avg'] }); + } + }); + + $scope.xpdSeries.push('CPD max A', 'CPD min A', 'CPD avg A'); + + + $scope.xpdChartData.push(maxListA); + $scope.xpdChartData.push(minListA); + $scope.xpdChartData.push(avgListA); + + $scope.crossPolarDiscriminationsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.crossPolarDiscriminationsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.crossPolarDiscriminationsetOverride.push({ yAxisID: 'y-axis-1' }); + + var maxListB = []; + var minListB = []; + var avgListB = []; + + dataB.data.hits.hits.map(function (item, index) { + var timestamp = $mwtnPerformanceLink.formatTimeStamp(item._source['time-stamp']); + var test = $scope.xpdtestMap.get(timestamp); + if (test) { + maxListB.push({ x: test, y: item._source['performance-data']['xpd-max'] }); + minListB.push({ x: test, y: item._source['performance-data']['xpd-min'] }); + avgListB.push({ x: test, y: item._source['performance-data']['xpd-avg'] }); + } else { + maxListB.push({ x: 0, y: item._source['performance-data']['xpd-max'] }); + minListB.push({ x: 0, y: item._source['performance-data']['xpd-min'] }); + avgListB.push({ x: 0, y: item._source['performance-data']['xpd-avg'] }); + } + }); + + $scope.xpdSeries.push('CPD max B', 'CPD min B', 'CPD avg B'); + + $scope.xpdChartData.push(maxListB); + $scope.xpdChartData.push(minListB); + $scope.xpdChartData.push(avgListB); + + $scope.crossPolarDiscriminationsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.crossPolarDiscriminationsetOverride.push({ yAxisID: 'y-axis-1' }); + $scope.crossPolarDiscriminationsetOverride.push({ yAxisID: 'y-axis-1' }); + + overridePoints($scope.xpdSeries, $scope.crossPolarDiscriminationsetOverride); + + } + break; + + } + }; + + var getColor = function (hexcolorCode) { + var color = { + backgroundColor: hexcolorCode, pointBackgroundColor: hexcolorCode, + pointHoverBackgroundColor: hexcolorCode, + borderColor: hexcolorCode, + pointBorderColor: hexcolorCode, + pointHoverBorderColor: hexcolorCode, + fill: false + }; + return color; + }; + + var getData = function (from, size, networkElement, selectedLtpId) { + + var sort = [{ "time-stamp": { order: 'desc' } }]; + + var query = { "query": { "bool": { "must": [{ prefix: { "node-name": networkElement } }] } } }; + + + //add layer protocol selector to filter query + query.query.bool.must.push({ prefix: { "layer-protocol-name": "MWPS" } }); + + //add interface selector to filter query + if (selectedLtpId && selectedLtpId !== 'Select LTP') { + query.query.bool.must.push({ prefix: { "uuid-interface": selectedLtpId } }); + } + + var selected15minPeriod = true; + if ($scope.timePeriod !== $scope.timePeriods[0]) selected15minPeriod = false; + + return $mwtnPerformanceLink.getFilteredSortedData(from, size, sort, query, selected15minPeriod); + }; + + $scope.status = { ne: false }; + $scope.spinner = { ne: false }; + + // events + $scope.$watch('linkId', function (newValue, oldValue) { + if (newValue && oldValue !== "" && newValue !== oldValue) { + + var functionId = 'sdnperformance'; + var docType = 'historicalperformance15min'; + if ($scope.timePeriod !== $scope.timePeriods[0]) { + docType = 'historicalperformance24h'; + } + var aggregations = { + "size":0, + "query": { + "match": { + "radio-signal-id": newValue + } + }, + "aggregations": { + "node-name": { + "terms": { + "field": "node-name" + } + }, + "ltp": { + "terms": { + "field": "uuid-interface" + } + } + } + }; + $mwtnPerformanceLink.getAggregations(functionId, docType, aggregations).then(function (success) { + console.log(JSON.stringify(success)); + var nodes = success.data.aggregations['node-name'].buckets.map(function(bucket){ + return bucket.key; + }); + console.warn(nodes); + if (nodes.length = 0) { + $scope.networkElementA = ''; + $scope.networkElementB = ''; + } else if (nodes.length = 1) { + $scope.networkElementA = nodes[0]; + $scope.networkElementB = ''; + } else if (nodes.length = 2) { + $scope.networkElementA = nodes[0]; + $scope.networkElementB = nodes[1] + } else { + $scope.networkElementA = nodes[0]; + $scope.networkElementB = nodes[1] + console.warn('Check nodes for radio signal id: ' + newValue + ' ' + JSON.stringify(nodes)); + } + var ltps = success.data.aggregations['ltp'].buckets.map(function(bucket){ + return bucket.key; + }); + if (ltps.length = 0) { + $scope.selectedLtpIdA = ''; + $scope.selectedLtpIdB = ''; + } else if (ltps.length = 1) { + $scope.selectedLtpIdA = ltps[0]; + $scope.selectedLtpIdB = ltps[0]; + } else if (ltps.length = 2) { + // TODO Who belongs to whom - just guessing ;/ + $scope.selectedLtpIdA = ltps[0]; + $scope.selectedLtpIdB = ltps[1] + } else { + $scope.selectedLtpIdA = ltps[0]; + $scope.selectedLtpIdB = ltps[1] + console.warn('Check ltps for radio signal id: ' + newValue + ' ' + JSON.stringify(nodes)); + } + }, function (error) { + console.log(error); + $scope.networkElementA = ''; + $scope.networkElementB = ''; + $scope.selectedLtpIdA = ''; + $scope.selectedLtpIdB = ''; + }); + } + }); + + $scope.$watch('selectedLtpIdA', function (newValue, oldValue) { + if (newValue && oldValue !== "" && newValue !== oldValue) { + //TODO: get data based on open grids + Object.keys($scope.status).map(function (key) { + if ($scope.status[key]) { + $scope.defaultColors = []; + $scope.defaultColors.push(getColor('#0062ff')); + $scope.defaultColors.push(getColor('#b9341b')); + $scope.defaultColors.push(getColor('#f0141f')); + $scope.defaultColors.push(getColor('#4c7759')); + $scope.defaultColors.push(getColor('#55b64e')); + $scope.defaultColors.push(getColor("#6c8995")); + + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, key) + $window.dispatchEvent(new Event("resize")); + } + }); + } + + }, true); + + $scope.$watch('selectedLtpIdB', function (newValue, oldValue) { + if (newValue && oldValue !== "" && newValue !== oldValue && newValue != 'Select LTP') { + Object.keys($scope.status).map(function (key) { + if ($scope.status[key]) { + $scope.defaultColors = []; + $scope.defaultColors.push(getColor('#0062ff')); + $scope.defaultColors.push(getColor('#b9341b')); + $scope.defaultColors.push(getColor('#f0141f')); + $scope.defaultColors.push(getColor('#4c7759')); + $scope.defaultColors.push(getColor('#55b64e')); + $scope.defaultColors.push(getColor("#6c8995")); + + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, key) + $window.dispatchEvent(new Event("resize")); + } + }); + } + + }, true); + + $scope.$watch('status', function (status, oldValue) { + Object.keys(status).map(function (key) { + if ($scope.networkElementIdA && $scope.networkElementIdB && status[key] && status[key] !== oldValue[key]) { + + + //add a set of default colors for line graphs with 6 values + $scope.defaultColors = []; + $scope.defaultColors.push(getColor('#0062ff')); + $scope.defaultColors.push(getColor('#b9341b')); + $scope.defaultColors.push(getColor('#f0141f')); + $scope.defaultColors.push(getColor('#4c7759')); + $scope.defaultColors.push(getColor('#55b64e')); + $scope.defaultColors.push(getColor("#6c8995")); + + getDataFromNEs($scope.networkElementIdA, $scope.selectedLtpIdA, $scope.networkElementIdB, $scope.selectedLtpIdB, key) + $window.dispatchEvent(new Event("resize")); + + } + + }); + }, true); + + $scope.$watch('timePeriod', function (newValue, oldValue) { + + if (newValue && oldValue !== "" && newValue !== oldValue) { + + //change page sizes and tell gridapi to update + + $scope.gridOptionsReceiveLevel.paginationPageSizes = $scope.pageSizes(); + $scope.gridOptionsReceiveLevel.paginationPageSize = $scope.gridOptionsReceiveLevel.paginationPageSizes[0]; + $scope.recvGridApi.core.notifyDataChange(uiGridConstants.dataChange.OPTIONS); + + $scope.gridOptionsTransmissionLevel.paginationPageSizes = $scope.pageSizes(); + $scope.gridOptionsTransmissionLevel.paginationPageSize = $scope.gridOptionsTransmissionLevel.paginationPageSizes[0]; + $scope.transmissionGridApi.core.notifyDataChange(uiGridConstants.dataChange.OPTIONS); + + + $scope.gridOptionsModulation.paginationPageSizes = $scope.pageSizes(); + $scope.gridOptionsModulation.paginationPageSize = $scope.gridOptionsModulation.paginationPageSizes[0]; + $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.OPTIONS); + + $scope.gridOptionsTemperature.paginationPageSizes = $scope.pageSizes(); + $scope.gridOptionsTemperature.paginationPageSize = $scope.gridOptionsTemperature.paginationPageSizes[0]; + $scope.gridTemperatureApi.core.notifyDataChange(uiGridConstants.dataChange.OPTIONS); + + $scope.gridOptionsSnir.paginationPageSizes = $scope.pageSizes(); + $scope.gridOptionsSnir.paginationPageSize = $scope.gridOptionsSnir.paginationPageSizes[0]; + $scope.gridSNIRApi.core.notifyDataChange(uiGridConstants.dataChange.OPTIONS); + + $scope.gridOptionsCrossPolarDiscrimination.paginationPageSizes = $scope.pageSizes(); + $scope.gridOptionsCrossPolarDiscrimination.paginationPageSize = $scope.gridOptionsCrossPolarDiscrimination.paginationPageSizes[0]; + $scope.gridXpdApi.core.notifyDataChange(uiGridConstants.dataChange.OPTIONS); + + //get new interface data + getInterfaces($scope.networkElementIdA, $scope.availableLtpIdsA); + getInterfaces($scope.networkElementIdB, $scope.availableLtpIdsB); + } + + }, true); + + $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; + }); + }; + + //get data on ne selection + + $scope.$watch('networkElementA', function (neId, oldValue) { + if (neId && neId !== '' && neId !== oldValue) { + var revision; + $scope.networkElements.map(function (ne) { + if (ne.id === neId) revision = ne.revision; + }); + $scope.networkElementIdA = neId; + $scope.revisionA = revision; + + getInterfaces(neId, $scope.availableLtpIdsA); + $scope.collapseAll(); + + } + }); + + $scope.$watch('networkElementB', function (neId, oldValue) { + if (neId && neId !== '' && neId !== oldValue) { + var revision; + $scope.networkElements.map(function (ne) { + if (ne.id === neId) revision = ne.revision; + }); + $scope.networkElementIdB = neId; + $scope.revisionB = revision; + + getInterfaces(neId, $scope.availableLtpIdsB); + $scope.collapseAll(); + + } + }); + + var getInterfaces = function (networkElement, networkList) { + + //clear interface array + var length = networkList.length; + networkList.splice(1, length); + + //request to get interfaces + var aggr = { + "size": 0, + "aggregations": { + "neinterfaces": { + "filter": { + "bool": { + "must": [ + { + "term": { + "node-name": networkElement + } + }, + { + "term": { + "layer-protocol-name": "MWPS" + } + } + ] + } + }, + "aggregations": { + "interfaces": { + "terms": { + "field": "uuid-interface" + } + } + } + } + } + }; + + + var selected15minPeriod = true; + if ($scope.timePeriod !== $scope.timePeriods[0]) selected15minPeriod = false; + + $mwtnPerformanceLink.getInterfaces(aggr, selected15minPeriod).then(function (response) { + + if (response.data.aggregations.neinterfaces.interfaces.buckets.length >= 0) { + response.data.aggregations.neinterfaces.interfaces.buckets.map(function (item) { + networkList.push(item.key); + }); + } + + + }); + }; + + + }]); + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.module.js new file mode 100644 index 00000000..34a0d583 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.module.js @@ -0,0 +1,55 @@ +/* + * 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 mwtnPerformanceLinkApp = angular.module('app.mwtnPerformanceLink', ['ui.grid','chart.js', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'ui.router.state','ui.grid.exporter', + 'ui.grid.moveColumns', 'ui.grid.pinning', 'ui.grid.selection', + 'ui.grid.resizeColumns', 'ui.grid.pagination']); + + mwtnPerformanceLinkApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnPerformanceLinkApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + NavHelperProvider.addControllerUrl('app/mwtnPerformanceLink/mwtnPerformanceLink.controller'); + NavHelperProvider.addToMenu('mwtnPerformanceLink', { + "link" : "#/pnfPerformanceLink", + "active" : "main.mwtnPerformanceLink", + "title" : "pnf PM Link", + "icon" : "fa fa-bar-chart", // Add navigation icon css class here + "page" : { + "title" : "pnf PM Link", + "description" : "mwtnLinkPerformance" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnPerformanceLink', { + url: 'pnfPerformanceLink', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnPerformanceLink/mwtnPerformanceLink.tpl.html', + controller: 'mwtnPerformanceLinkCtrl' + } + } + }); + + }); + + return mwtnPerformanceLinkApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.services.js new file mode 100644 index 00000000..eb18b629 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.services.js @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 HCL Inc. 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/mwtnCommons/mwtnCommons.module', 'app/mwtnPerformanceLink/mwtnPerformanceLink.module'], function (mwtnPerformanceLinkApp) { + + mwtnPerformanceLinkApp.register.factory('$mwtnPerformanceLink', function ($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var COMPONENT = '$mwtnPerformanceLink'; + $mwtnLog.info({ component: COMPONENT, message: '$mwtnPerformanceLink started!' }); + + var service = {}; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.getMountPoints = $mwtnCommons.getMountPoints; + service.getAggregations = $mwtnDatabase.getAggregations; + + + service.TimeStampToONFFormat = function (timestamp) { + timestamp = timestamp.split('-').join(''); + timestamp = timestamp.split(':').join(''); + timestamp = timestamp.split(' ').join(''); + timestamp = timestamp.replace('UTC', 'Z'); + return timestamp; + }; + + service.getFilteredSortedData = function (from, size, sort, query, selected15minPeriod) { + + var functionId = 'sdnperformance'; + var docType = 'historicalperformance15min'; + if (selected15minPeriod === false) { + docType = 'historicalperformance24h'; + } + + var deferred = $q.defer(); + $mwtnDatabase.getFilteredSortedData(functionId, docType, from, size, sort, query).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: '$mwtnPerformanceLink.getFilteredSortedData', message: JSON.stringify(error.data) }); + deferred.reject(error) + }); + return deferred.promise; + }; + + service.getInterfaces = function (aggregation, selected15minPeriod) { + + var functionId = 'sdnperformance'; + var docType = 'historicalperformance15min'; + if (selected15minPeriod === false) { + docType = 'historicalperformance24h'; + } + + var deferred = $q.defer(); + $mwtnDatabase.getAggregatedData(functionId, docType, aggregation).then(function (success) { + deferred.resolve(success); + }, function (error) { + $mwtnLog.error({ component: '$mwtnPerformanceLink.getFilteredSortedData', message: JSON.stringify(error.data) }); + deferred.reject(error) + }); + return deferred.promise; + }; + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.tpl.html new file mode 100644 index 00000000..a65d5cf2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/mwtnPerformanceLink-module/src/main/resources/mwtnPerformanceLink/mwtnPerformanceLink.tpl.html @@ -0,0 +1,487 @@ +<ht-header help-link='sdnr/pnfPerformance/0.4.0/README.md'></ht-header> +<div class="owl container"> + +<!-- input for link id + <div class="row"> + <div class="col-md-2 text-right radio"> + <span>{{'MWTN_LINK_IDENTIFIER' | translate }}</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <input list="linkIds" class="form-control" ng-model="linkId"> + <datalist id="linkIds"> + <option ng-repeat="linkId in linkIds" value="{{linkId}}" >{{linkId}}</option> + </datalist> + </div> + </div> + </div> --> + + <div class="row"> + <div class="col-md-2 text-right radio"> + <span class="white">{{'MWTN_NETWORKELEMENT' | translate}} A</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <input list="networkElementsA" class="form-control" ng-model="networkElementA" placeholder="Select network element"> + <datalist id="networkElementsA"> + <option ng-repeat="ne in networkElements" value="{{ne.id}}">{{ne.id}}</option> + </datalist> + </div> + </div> + + <div class="col-md-2 text-right radio"> + <span class="white">{{'MWTN_NETWORKELEMENT' | translate}} B</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <input list="networkElementsB" class="form-control" ng-model="networkElementB" placeholder="Select network element"> + <datalist id="networkElementsB"> + <option ng-repeat="ne in networkElements" value="{{ne.id}}">{{ne.id}}</option> + </datalist> + </div> + </div> + + </div> + <div class="row"> + <div class="col-md-2 text-right radio"> + <span class="white">{{'MWTN_AIR_INTERFACE' | translate }} A</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <select class="form-control" ng-model="selectedLtpIdA"> + <option ng-repeat="protocol in availableLtpIdsA">{{protocol}}</option> + </select> + </div> + </div> + + + <div class="col-md-2 text-right radio"> + <span class="white">{{'MWTN_AIR_INTERFACE' | translate }} B</span> + </div> + <div class="col-md-4"> + <div class="form-group"> + <select class="form-control" ng-model="selectedLtpIdB"> + <option ng-repeat="protocol in availableLtpIdsB">{{protocol}}</option> + </select> + </div> + </div> + </div> + + <div class="row"> + <div class="col-md-2 text-right radio"> + <span class="white">{{'MWTN_TIME_PERIOD' | translate}}</span> + </div> + <div class="col-md-2"> + <div class="form-group"> + <select class="form-control" ng-model="timePeriod"> + <option ng-repeat="time in timePeriods">{{time}}</option> + </select> + </div> + </div> + </div> + + <div class="row" ng-if="networkElementA && networkElementB && selectedLtpIdA !== 'Select LTP' && selectedLtpIdB !== 'Select LTP' "> + <uib-accordion close-others="true"> + <div uib-accordion-group class="panel-primary" is-open="status.receiveLevel"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.receiveLevel, 'fa-chevron-right': !status.receiveLevel}"></i> + <span>Receive Level</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.receiveLevel"></i> + </uib-accordion-heading> + <canvas id="line" + class="chart chart-line" + chart-data="receiveData" + chart-series="receiveSeries" + chart-options="receiveOptions" + chart-dataset-override="receiveDatasetOverride" + chart-colors="defaultColors"> + </canvas + </div> <!-- canvas bugs with div, please keep in!--> + + <div + ui-grid="gridOptionsReceiveLevel" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns class="mwtnLinkGrid"> + </div> + + <!-- pagniation controll for grid--> + <div class="ht-pagination"> + <button class="btn btn-default" + ng-disabled="gridOptionsReceiveLevel.paginationCurrentPage === 1" + ng-click="recvGridApi.pagination.seek(1)" + ng-class="{'cancelCursor':gridOptionsReceiveLevel.paginationCurrentPage === 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="gridOptionsReceiveLevel.paginationCurrentPage === 1" + ng-class="{'cancelCursor':gridOptionsReceiveLevel.paginationCurrentPage === 1}" + ng-click="recvGridApi.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="gridOptionsReceiveLevel.paginationCurrentPage" + ng-change="seekPage(gridOptionsReceiveLevel.paginationCurrentPage,'receiveLevel')" + type="number" style="width:20px;"/> + <span class="dark"> / {{ recvGridApi.pagination.getTotalPages() }}</span> + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsReceiveLevel.paginationCurrentPage === recvGridApi.pagination.getTotalPages()" + ng-click="recvGridApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsReceiveLevel.paginationCurrentPage === recvGridApi.pagination.getTotalPages()" + ng-click="recvGridApi.pagination.seek(recvGridApi.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="gridOptionsReceiveLevel.paginationPageSize = gridOptionsReceiveLevel.paginationPageSizes[0]" + ng-model="gridOptionsReceiveLevel.paginationPageSize" + ng-options="option for option in gridOptionsReceiveLevel.paginationPageSizes"></select> + <span class="dark"> {{ itemsMessage() }}</span> + <span class="pull-right dark">{{ paginationStatusMessage('receiveLevel') }}</span> + </div> + </div> + + <div uib-accordion-group class="panel-primary" is-open="status.transmissionLevel"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.transmissionLevel, 'fa-chevron-right': !status.transmissionLevel}"></i> + <span>Transmission Power</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.transmissionLevel"></i> + </uib-accordion-heading> + <canvas id="line" + class="chart chart-line" + chart-data="transmissionData" + chart-series="transmissionSeries" + chart-options="transmissionOptions" + chart-dataset-override="transmissionDatasetOverride" + chart-colors="defaultColors"> + </canvas + </div> <!-- canvas bugs with div, please keep in!--> + <div + ui-grid="gridOptionsTransmissionLevel" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns class="mwtnLinkGrid"> + </div> + <!-- pagniation controll for grid--> + <div class="ht-pagination"> + <button class="btn btn-default" + ng-disabled="gridOptionsTransmissionLevel.paginationCurrentPage === 1" + ng-click="transmissionGridApi.pagination.seek(1)" + ng-class="{'cancelCursor':gridOptionsTransmissionLevel.paginationCurrentPage === 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="gridOptionsTransmissionLevel.paginationCurrentPage === 1" + ng-class="{'cancelCursor':gridOptionsTransmissionLevel.paginationCurrentPage === 1}" + ng-click="transmissionGridApi.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="gridOptionsTransmissionLevel.paginationCurrentPage" + ng-change="seekPage(gridOptionsTransmissionLevel.paginationCurrentPage,'transmissionLevel')" + type="number" style="width:20px;"/> + <span class="dark"> / {{ transmissionGridApi.pagination.getTotalPages() }}</span> + + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsTransmissionLevel.paginationCurrentPage === transmissionGridApi.pagination.getTotalPages()" + ng-click="transmissionGridApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsTransmissionLevel.paginationCurrentPage === transmissionGridApi.pagination.getTotalPages()" + ng-click="transmissionGridApi.pagination.seek(transmissionGridApi.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" + ng-init="gridOptionsTransmissionLevel.paginationPageSize = gridOptionsTransmissionLevel.paginationPageSizes[0]" + ng-model="gridOptionsTransmissionLevel.paginationPageSize" + ng-options="option for option in gridOptionsTransmissionLevel.paginationPageSizes"></select> + + <span class="dark"> {{ itemsMessage() }}</span> + <span class="pull-right dark">{{ paginationStatusMessage('transmissionLevel') }}</span> + </div> + </div> + + <div uib-accordion-group class="panel-primary" is-open="status.modulation"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.modulation, 'fa-chevron-right': !status.modulation}"></i> + <span>Adaptive Modulation</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.modulation"></i> + </uib-accordion-heading> + <canvas id="line" + class="chart chart-line" + chart-data="modulationData" + chart-series="modultaionSeries" + chart-options="modulationOptions" + chart-dataset-override="modulationDatasetOverride"> + </canvas + </div> <!-- canvas bugs with div, please keep in!--> + <div + ui-grid="gridOptionsModulation" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns class="mwtnLinkGrid"> + </div> + <!-- pagniation controll for grid--> + <div class="ht-pagination"> + <button class="btn btn-default" + ng-disabled="gridOptionsModulation.paginationCurrentPage === 1" + ng-click="gridApi.pagination.seek(1)" + ng-class="{'cancelCursor':gridOptionsModulation.paginationCurrentPage === 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="gridOptionsModulation.paginationCurrentPage === 1" + ng-class="{'cancelCursor':gridOptionsModulation.paginationCurrentPage === 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="gridOptionsModulation.paginationCurrentPage" + ng-change="seekPage(gridOptionsModulation.paginationCurrentPage,'modulation')" + type="number" style="width:20px;"/> + <span class="dark"> / {{ gridApi.pagination.getTotalPages() }}</span> + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsModulation.paginationCurrentPage === gridApi.pagination.getTotalPages()" + ng-click="gridApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsModulation.paginationCurrentPage === 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" + ng-init="gridOptionsModulation.paginationPageSize = gridOptionsModulation.paginationPageSizes[0]" + ng-model="gridOptionsModulation.paginationPageSize" + ng-options="option for option in gridOptionsModulation.paginationPageSizes"></select> + <span class="dark"> {{ itemsMessage() }}</span> + <span class="pull-right dark">{{ paginationStatusMessage('modulation') }}</span> + </div> + </div> + + <div uib-accordion-group class="panel-primary" is-open="status.temperature"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.temperature, 'fa-chevron-right': !status.temperature}"></i> + <span>Temperature</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.temperature"></i> + </uib-accordion-heading> + <canvas id="line" + class="chart chart-line" + chart-data="tempData" + chart-series="tempSeries" + chart-options="tempOptions" + chart-dataset-override="tempDatasetOverride" + chart-colors="defaultColors"> + </canvas + </div> <!-- canvas bugs with div, please keep in!--> + <div + ui-grid="gridOptionsTemperature" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + class="mwtnLinkGrid"> + </div> + <!-- pagniation controll for grid--> + <div class="ht-pagination"> + <button class="btn btn-default" + ng-disabled="gridOptionsTemperature.paginationCurrentPage === 1" + ng-click="gridTemperatureApi.pagination.seek(1)" + ng-class="{'cancelCursor':gridOptionsTemperature.paginationCurrentPage === 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="gridOptionsTemperature.paginationCurrentPage === 1" + ng-class="{'cancelCursor':gridOptionsTemperature.paginationCurrentPage === 1}" + ng-click="gridTemperatureApi.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="gridOptionsTemperature.paginationCurrentPage" + ng-change="seekPage(gridOptionsTemperature.paginationCurrentPage,'temperature')" + type="number" style="width:20px;"/> + <span class="dark"> / {{ gridTemperatureApi.pagination.getTotalPages() }}</span> + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsTemperature.paginationCurrentPage === gridTemperatureApi.pagination.getTotalPages()" + ng-click="gridTemperatureApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsTemperature.paginationCurrentPage === gridTemperatureApi.pagination.getTotalPages()" + ng-click="gridTemperatureApi.pagination.seek(gridTemperatureApi.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" + ng-init="gridOptionsTemperature.paginationPageSize = gridOptionsTemperature.paginationPageSizes[0]" + ng-model="gridOptionsTemperature.paginationPageSize" + ng-options="option for option in gridOptionsTemperature.paginationPageSizes"></select> + <span class="dark"> {{ itemsMessage() }}</span> + <span class="pull-right dark">{{ paginationStatusMessage('temperature') }}</span> + </div> + </div> + + <div uib-accordion-group class="panel-primary" is-open="status.snir"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.snir, 'fa-chevron-right': !status.snir}"></i> + <span>{{'MWTN_SINR' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.snir"></i> + </uib-accordion-heading> + <canvas id="line" + class="chart chart-line" + chart-data="snirChartData" + chart-series="snirSeries" + chart-options="snirOptions" + chart-dataset-override="snirsetOverride" + chart-colors="defaultColors"> + </canvas + </div> <!-- canvas bugs with div, please keep in!--> + <div + ui-grid="gridOptionsSnir" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + class="mwtnLinkGrid"> + </div> + <!-- pagniation controll for grid--> + <div class="ht-pagination"> + <button class="btn btn-default" + ng-disabled="gridOptionsSnir.paginationCurrentPage === 1" + ng-click="gridSNIRApi.pagination.seek(1)" + ng-class="{'cancelCursor':gridOptionsSnir.paginationCurrentPage === 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="gridOptionsSnir.paginationCurrentPage === 1" + ng-class="{'cancelCursor':gridOptionsSnir.paginationCurrentPage === 1}" + ng-click="gridSNIRApi.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="gridOptionsSnir.paginationCurrentPage" + ng-change="seekPage(gridOptionsSnir.paginationCurrentPage,'snir')" + type="number" style="width:20px;"/> + <span class="dark"> / {{ gridSNIRApi.pagination.getTotalPages() }}</span> + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsSnir.paginationCurrentPage === gridSNIRApi.pagination.getTotalPages()" + ng-click="gridSNIRApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsSnir.paginationCurrentPage === gridSNIRApi.pagination.getTotalPages()" + ng-click="gridSNIRApi.pagination.seek(gridSNIRApi.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" + ng-init="gridOptionsSnir.paginationPageSize = gridOptionsSnir.paginationPageSizes[0]" + ng-model="gridOptionsSnir.paginationPageSize" + ng-options="option for option in gridOptionsSnir.paginationPageSizes"></select> + <span class="dark"> {{ itemsMessage() }}</span> + <span class="pull-right dark">{{ paginationStatusMessage('snir') }}</span> + </div> + </div> + + <div uib-accordion-group class="panel-primary" is-open="status.crossPolarDiscrimination"> + <uib-accordion-heading> <i class="pull-left fa" + ng-class="{'fa-chevron-down': status.crossPolarDiscrimination, 'fa-chevron-right': !status.crossPolarDiscrimination}"></i> + <span>Cross Polar Discrimination</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.crossPolarDiscrimination"></i> + </uib-accordion-heading> + <canvas id="line" + class="chart chart-line" + chart-data="xpdChartData" + chart-series="xpdSeries" + chart-options="xpdOptions" + chart-dataset-override="crossPolarDiscriminationsetOverride" + chart-colors="defaultColors"> + </canvas + </div> <!-- canvas bugs with div, please keep in!--> + <div + ui-grid="gridOptionsCrossPolarDiscrimination" + ui-grid-pagination + ui-grid-exporter + ui-grid-selection + ui-grid-pinning + ui-grid-resize-columns + ui-grid-move-columns + class="mwtnLinkGrid"> + </div> + <!-- pagniation controll for grid--> + <div class="ht-pagination"> + <button class="btn btn-default" + ng-disabled="gridOptionsCrossPolarDiscrimination.paginationCurrentPage === 1" + ng-click="gridXpdApi.pagination.seek(1)" + ng-class="{'cancelCursor':gridOptionsCrossPolarDiscrimination.paginationCurrentPage === 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="gridOptionsCrossPolarDiscrimination.paginationCurrentPage === 1" + ng-class="{'cancelCursor':gridOptionsCrossPolarDiscrimination.paginationCurrentPage === 1}" + ng-click="gridXpdApi.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="gridOptionsCrossPolarDiscrimination.paginationCurrentPage" + ng-change="seekPage(gridOptionsCrossPolarDiscrimination.paginationCurrentPage,'crossPolarDiscrimination')" + type="number" style="width:20px;"/> + <span class="dark"> / {{ gridXpdApi.pagination.getTotalPages() }}</span> + <button class="btn btn-default" role="menuitem" type="button" title="Next Page" aria-label="Next Page" + ng-disabled="gridOptionsCrossPolarDiscrimination.paginationCurrentPage === gridXpdApi.pagination.getTotalPages()" + ng-click="gridXpdApi.pagination.nextPage()"> + <i class="fa fa-play "></i> + </button> + <button class="btn btn-default" ng-disabled="gridOptionsCrossPolarDiscrimination.paginationCurrentPage === gridXpdApi.pagination.getTotalPages()" + ng-click="gridXpdApi.pagination.seek(gridXpdApi.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" + ng-init="gridOptionsCrossPolarDiscrimination.paginationPageSize = gridOptionsCrossPolarDiscrimination.paginationPageSizes[0]" + ng-model="gridOptionsCrossPolarDiscrimination.paginationPageSize" + ng-options="option for option in gridOptionsCrossPolarDiscrimination.paginationPageSizes"></select> + <span class="dark"> {{ itemsMessage() }}</span> + <span class="pull-right dark">{{ paginationStatusMessage('crossPolarDiscrimination') }}</span> + </div> + </div> + </uib-accordion> + </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/mwtnPerformanceLink/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/pom.xml new file mode 100644 index 00000000..840b923f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnPerformanceLink/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnPerformanceLink</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnPerformanceLink-module</module> + <module>mwtnPerformanceLink-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-bundle/pom.xml new file mode 100644 index 00000000..7a50612c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-bundle/pom.xml @@ -0,0 +1,119 @@ +<?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>mwtnSpectrum</artifactId> + <groupId>cn.com.zte.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>mwtnSpectrum-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>cn.com.zte.odl.dlux</groupId> + <artifactId>mwtnSpectrum-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>cn.com.zte.odl.dlux</groupId> + <includeArtifactIds>mwtnSpectrum-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..51ddc024 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnSpectrum"/> + <property name="url" value="/src/app/mwtnSpectrum"/> + <property name="directory" value="/mwtnSpectrum"/> + <property name="requireJs" value="app/mwtnSpectrum/mwtnSpectrum.module"/> + <property name="angularJs" value="app.mwtnSpectrum"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnSpectrum/mwtnSpectrum-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/pom.xml new file mode 100644 index 00000000..ca8ef939 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-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>mwtnSpectrum</artifactId> + <groupId>cn.com.zte.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>mwtnSpectrum-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/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/images/bluelight.gif b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/images/bluelight.gif Binary files differnew file mode 100644 index 00000000..33de2178 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/images/bluelight.gif diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/images/mwtnSpectrum.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/images/mwtnSpectrum.png Binary files differnew file mode 100755 index 00000000..23956335 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/images/mwtnSpectrum.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum-custom.css new file mode 100644 index 00000000..df461795 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum-custom.css @@ -0,0 +1,45 @@ +/** + * Add your application related css here + */ + +.alarm div { + height: 160px; + vertical-align: middle; +} + +.cleared { + color: lightgreen; +} +.cleared span { + color: lightgreen; +} + +.raised { + color: red; +} +.raised span { + color: red; +} + +.mwtnSpectrumGrid { + height: 600px; + background-color: white; +} + +.mwtnSpectrumGrid span { + color: #393939; +} + +.mwtnSpectrumGrid span.mismatch { + font-weight: bold; + color: #428bca; +} + +.mwtnSpectrumGrid .green { + color: darkgreen; +} +.mwtnSpectrumGrid .green span { + color: darkgreen; +} + +
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.controller.js new file mode 100644 index 00000000..f2433853 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.controller.js @@ -0,0 +1,135 @@ +/* + * 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/mwtnSpectrum/mwtnSpectrum.module', + 'app/mwtnSpectrum/mwtnSpectrum.services', + 'app/mwtnCommons/mwtnCommons.services'], function(mwtnSpectrumApp) { + + mwtnSpectrumApp.register.controller('mwtnSpectrumCtrl', ['$scope', '$rootScope', 'uiGridConstants','$mwtnSpectrum', '$mwtnLog', 'OnfNetworkElement', 'MicrowavePhysicalSection', + function($scope, $rootScope, uiGridConstants, $mwtnSpectrum, $mwtnLog, OnfNetworkElement, MicrowavePhysicalSection) { + + var COMPONENT = 'mwtnSpectrumCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'mwtnSpectrumCtrl started!'}); + + $rootScope.section_logo = 'src/app/mwtnSpectrum/images/mwtnSpectrum.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.interference = { + alarmStatus: 'cleared' + }; + + $scope.execute = function() { + $scope.interference.alarmStatus = 'raised'; + $mwtnSpectrum.execute().then(function(success) { + $scope.interference.alarmStatus = 'cleared'; + }, function(error) { + $scope.interference.alarmStatus = 'cleared'; + }); + }; + $scope.clear = function() { + console.log("Cleared"); + $scope.interference.alarmStatus = 'cleared'; + }; + + var updateAirInterface = function(spec, data) { + if (data) { + var radioSignalID = data.airInterfaceConfiguration.radioSignalID; + $scope.gridOptions.data.map(function(row){ + if (row.name === spec.nodeId && row.radioSignalID === radioSignalID) { + row.actualTxFrequency = data.airInterfaceConfiguration.txFrequency; + row.actualRxFrequency = data.airInterfaceConfiguration.rxFrequency; + } + }); + } else { + $scope.gridOptions.data.map(function(row){ + if (row.nodeId === spec.nodeId) { + row.actualTxFrequency = '?'; + row.actualRxFrequency = '?'; + } + }); + } + }; + + $scope.processing = false; + $scope.refresh = function() { + $scope.processing = true; + $scope.interference.alarmStatus = 'cleared'; + $mwtnSpectrum.refresh().then(function(success){ + $scope.processing = false; + $scope.gridOptions.data = success.airInterfaces; + success.actualNodes.map(function(actualNode){ + if (actualNode.connectionStatus !== 'connected') { + return; + } + var revision = '2016-09-01'; + $mwtnSpectrum.getActualNetworkElement(actualNode.id, revision).then(function(onfNe){ + var aOnfNe = new OnfNetworkElement(onfNe.NetworkElement); + aOnfNe.getLTPMwpsList().map(function(ltp){ + var spec = { + nodeId: actualNode.id, + revision: revision, + pacId: 'airinterface', + layerProtocolId: ltp._lpList[0].uuid, + partId: 'Configuration' + }; + $mwtnSpectrum.getPacParts(spec).then(function(success){ + updateAirInterface(spec, success); + }, function(error){ + updateAirInterface(spec, error); + }); + }); + }, function(error){ + // do nothing + }); + }); + }, function(error){ + $scope.processing = false; + $scope.gridOptions.data = []; + }); + }; + + $scope.highlightFilteredHeader = $mwtnSpectrum.highlightFilteredHeader; + + var requiredNesConnectionStatusCellTemplate = [ + '<div class="ui-grid-cell-contents" ng-class="{ \'green\': grid.getCellValue(row, col) === \'connected\'}"}>', + ' <i ng-show="grid.getCellValue(row, col) === \'connected\'" class="fa fa-link" aria-hidden="true"></i>', + ' <span>{{grid.getCellValue(row, col)}}</span>', + '</div>'].join(''); + + var actualTxFrequencyCellTemplate = [ + '<div class="ui-grid-cell-contents" ng-class="{ \'green\': grid.getCellValue(row, col) === \'connected\'}"}>', + ' <span ng-class="{\'mismatch\': {{row.entity.plannedTxFrequency}} !== grid.getCellValue(row, col) }">{{grid.getCellValue(row, col)}}</span>', + '</div>'].join(''); + + var actualRxFrequencyCellTemplate = [ + '<div class="ui-grid-cell-contents" ng-class="{ \'green\': grid.getCellValue(row, col) === \'connected\'}"}>', + ' <span ng-class="{\'mismatch\': {{row.entity.plannedRxFrequency}} !== grid.getCellValue(row, col) }">{{grid.getCellValue(row, col)}}</span>', + '</div>'].join(''); + + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnSpectrum.gridOptions)); + $scope.gridOptions.columnDefs = [ + { 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 : 140 }, + { field: 'connectionStatus', type: 'string', displayName: 'Connection status', headerCellClass: $scope.highlightFilteredHeader, width : 150, cellTemplate: requiredNesConnectionStatusCellTemplate }, + { field: 'airInterfaceName', type: 'string', displayName: 'Airinterface name', headerCellClass: $scope.highlightFilteredHeader, width : 140 }, + { field: 'radioSignalID', type: 'string', displayName: 'Radio signal id', headerCellClass: $scope.highlightFilteredHeader, width : 130 }, + { field: 'plannedTxFrequency', type: 'number', displayName: 'TX (plan)', headerCellClass: $scope.highlightFilteredHeader, width : 110, cellClass: 'number' }, + { field: 'actualTxFrequency', type: 'number', displayName: 'TX (actual)', headerCellClass: $scope.highlightFilteredHeader, width : 110, cellClass: 'number', cellTemplate: actualTxFrequencyCellTemplate}, + { field: 'plannedRxFrequency', type: 'number', displayName: 'RX (plan)', headerCellClass: $scope.highlightFilteredHeader, width : 110, cellClass: 'number' }, + { field: 'actualRxFrequency', type: 'number', displayName: 'RX (actual)', headerCellClass: $scope.highlightFilteredHeader, width : 110, cellClass: 'number', cellTemplate: actualRxFrequencyCellTemplate} + ]; + + $scope.refresh(); + + }]); + + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.module.js new file mode 100644 index 00000000..238f3ad3 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.module.js @@ -0,0 +1,54 @@ +/* + * 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 mwtnSpectrumApp = angular.module('app.mwtnSpectrum', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state','config']); + + mwtnSpectrumApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnSpectrumApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + + NavHelperProvider.addControllerUrl('app/mwtnSpectrum/mwtnSpectrum.controller'); + NavHelperProvider.addToMenu('mwtnSpectrum', { + "link" : "#/mwtnSpectrum", + "active" : "main.mwtnSpectrum", + "title" : "MWTN Spectrum", + "icon" : "fa fa-bar-chart", // Add navigation icon css class here + "page" : { + "title" : "MWTN Spectrum", + "description" : "mwtnSpectrum" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnSpectrum', { + url: 'mwtnSpectrum', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/mwtnSpectrum/mwtnSpectrum.tpl.html', + controller: 'mwtnSpectrumCtrl' + } + } + }); + + }); + + return mwtnSpectrumApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.services.js new file mode 100644 index 00000000..df822a9b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.services.js @@ -0,0 +1,90 @@ +/* + * 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/mwtnSpectrum/mwtnSpectrum.module'],function(mwtnSpectrumApp) { + + + mwtnSpectrumApp.register.factory('$mwtnSpectrum', function($q, $mwtnCommons, $mwtnLog) { + var service = {}; + + service.gridOptions = $mwtnCommons.gridOptions; + service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + service.getActualNetworkElement = $mwtnCommons.getActualNetworkElement; + service.getPacParts = $mwtnCommons.getPacParts; + + + service.execute = function() { + var request = { + method: 'POST', + url: 'operations/scheduler:next' + }; + var deferred = $q.defer(); + $mwtnCommons.genericRequest(request).then(function(success) { + deferred.resolve(success); + }, function(error) { + deferred.reject(error); + }); + return deferred.promise; + }; + + service.refresh = function() { + var deferred = $q.defer(); + $mwtnCommons.getRequiredNetworkElements(true).then(function(pNes){ + var neIds = pNes.map(function(pNe){ + pNe._source.connectionStatus = 'disconnected'; + return pNe._id; + }); + $mwtnCommons.getMountPoints(). then(function(mountpoints){ + var actualNodes = mountpoints.map(function(mountpoint){ + var pIndex = neIds.indexOf(mountpoint['node-id']); + if (pIndex > -1) { + pNes[pIndex]._source.connectionStatus = mountpoint['netconf-node-topology:connection-status']; + } + return { + id: mountpoint['node-id'], + connectionStatus: mountpoint['netconf-node-topology:connection-status'] + }; + }); + var airInterfaces = []; + pNes.map(function(hit){ + hit._source.MW_AirInterface_Pac.filter(function(airinterface){ + return airinterface.airInterfaceConfiguration; + }).map(function(airinterface){ + airInterfaces.push({ + id: $mwtnCommons.getNodeIntIdFromNodeId(hit._source.nodeId), + name: hit._source.nodeId, + connectionStatus: hit._source.connectionStatus, + airInterfaceName: airinterface.airInterfaceConfiguration.airInterfaceName, + radioSignalID: airinterface.airInterfaceConfiguration.radioSignalID, + plannedTxFrequency: airinterface.airInterfaceConfiguration.txFrequency, + actualTxFrequency: '?', + plannedRxFrequency: airinterface.airInterfaceConfiguration.rxFrequency, + actualRxFrequency: '?' + }); + }); + }); + + airInterfaces.sort(function(a, b){ + if(a.radioSignalID < b.radioSignalID) return -1; + if(a.radioSignalID > b.radioSignalID) return 1; + return 0; + }); + deferred.resolve({airInterfaces: airInterfaces, actualNodes: actualNodes}); + }, function(error){ + deferred.reject([]); + }); + + }, function(error){ + deferred.reject([]); + }); + return deferred.promise; + }; + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.tpl.html new file mode 100644 index 00000000..ae9543dd --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/mwtnSpectrum-module/src/main/resources/mwtnSpectrum/mwtnSpectrum.tpl.html @@ -0,0 +1,64 @@ +<ht-header help-link='sdnr/mwtnSpectrum/0.4.0/README.md'></ht-header> +<div class="owl container"> + <div class="row"> + <div clase="col-md-12 text-left radio" + ng-class="{'raised':interference.alarmStatus !== 'cleared', 'cleared':interference.alarmStatus === 'cleared' }"> + <span>{{'MWTN_INTERFERENCE_ALARM_STATUS' | translate}}: </span> + <i class="fa fa-bell" aria-hidden="true" ng-show="interference.alarmStatus !== 'cleared'"></i> + <span>{{interference.alarmStatus}}</span> + </div> + </div> + <div class="row"> + <div clase="col-md-12"> + <hr/> + <button class="btn btn-lg btn-block" ng-click="execute()" ng-class="{'btn-danger':interference.alarmStatus !== 'cleared', 'btn-success':interference.alarmStatus === 'cleared' }"> + <div class="container" > + <div class="row alarm"> + <div class="col-md-2 text-left"> + <img ng-show="interference.alarmStatus !== 'cleared'" src="src/app/mwtnSpectrum/images/bluelight.gif" ></img> + </div> + <div class="col-md-8"> + </br></br> + <i class="fa" ng-class="{'fa-exclamation-triangle':interference.alarmStatus !== 'cleared', 'fa-question-circle-o':interference.alarmStatus === 'cleared' }" aria-hidden="true"></i> + <span ng-show="interference.alarmStatus !== 'cleared'">{{'MWTN_INTERFERENCE_ALARM!' | translate}}</span> + <span ng-show="interference.alarmStatus === 'cleared'">{{'MWTN_INTERFERENCE_ALARM?' | translate}}</span> + </div> + <div class="col-md-2"> + <img ng-show="interference.alarmStatus !== 'cleared'" src="src/app/mwtnSpectrum/images/bluelight.gif" ></img> + </div> + </div> + </div> + </button> + <hr/> + </div> + </div> +<!-- <div class="row"> + <div clase="col-md-12"> + <button class="btn btn-success" ng-click="clear()"> + <i class="fa fa-magic" aria-hidden="true"></i> + <span>{{'MWTN_CLEAR' | translate}}</span> + </button> + </div> + </div> --> + <div class="row"> + <div clase="col-md-12 text-right"> + <button class="btn btn-primary pull-right" ng-click="refresh()"> + <i class="fa fa-refresh" ng-class="{'fa-spin':processing == true}" aria-hidden="true"></i> + <span>{{'MWTN_REFRESH' | translate}}</span> + </button> + </div> + </div> + <div class="row"> + <div clase="col-md-12"> + <div><span class="white">All frequencies in kHz</span></div> + <div id="mwtnSpectrumGrid" ui-grid="gridOptions" ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns ui-grid-move-columns + class="mwtnSpectrumGrid"> + </div> + </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/mwtnSpectrum/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/pom.xml new file mode 100644 index 00000000..06cc878a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnSpectrum/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>cn.com.zte.odl.dlux</groupId> + <artifactId>mwtnSpectrum</artifactId> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnSpectrum-module</module> + <module>mwtnSpectrum-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-bundle/pom.xml new file mode 100644 index 00000000..11d9cec3 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnTdm</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnTdm-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTdm-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnTdm-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..02eb833c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnTdm"/> + <property name="url" value="/src/app/mwtnTdm"/> + <property name="directory" value="/mwtnTdm"/> + <property name="requireJs" value="app/mwtnTdm/mwtnTdm.module"/> + <property name="angularJs" value="app.mwtnTdm"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnTdm/mwtnTdm-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/pom.xml new file mode 100644 index 00000000..9c8c8716 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnTdm</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnTdm-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/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/images/mwtnTdm.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/images/mwtnTdm.png Binary files differnew file mode 100755 index 00000000..2da5f584 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/images/mwtnTdm.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm-custom.css new file mode 100644 index 00000000..d396932f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm-custom.css @@ -0,0 +1,11 @@ +/** + * Add your application related css here + */ + +.owl .bbg b { + color: white; +} + +.owl .bbg i { + color: white; +} diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.controller.js new file mode 100644 index 00000000..e4e488bc --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.controller.js @@ -0,0 +1,159 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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/mwtnTdm/mwtnTdm.module', + 'app/mwtnTdm/mwtnTdm.services'], + function (mwtnTdmApp) { + + mwtnTdmApp.register.controller('mwtnTdmCtrl', ['$scope', '$rootScope', '$timeout', '$mwtnLog', '$mwtnTdm', '$translate', 'OnfNetworkElement', 'uiGridConstants', + function ($scope, $rootScope, $timeout, $mwtnLog, $mwtnTdm, $translate, OnfNetworkElement, uiGridConstants) { + + var COMPONENT = 'mwtnTdmCtrl'; + $rootScope.section_logo = 'src/app/mwtnTdm/images/mwtnTdm.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.highlightFilteredHeader = $mwtnTdm.highlightFilteredHeader; + $scope.gridOptions = JSON.parse(JSON.stringify($mwtnTdm.gridOptions)); + $scope.gridOptions.onRegisterApi = function (gridApi) { + $scope.gridApi = gridApi; + }; + $scope.gridOptions.columnDefs = [ + // { field: 'id', type: 'number', displayName: 'No.', headerCellClass: $scope.highlightFilteredHeader, width : 50, cellClass: 'number', pinnedLeft : true }, + { field: 'nodeId', type: 'string', displayName: 'Node', headerCellClass: $scope.highlightFilteredHeader, width: 200 }, + { field: 'layer', type: 'string', displayName: 'Layer', headerCellClass: $scope.highlightFilteredHeader, width: 100 }, + { field: 'ltpRef', type: 'string', displayName: 'Logical termiantion point', headerCellClass: $scope.highlightFilteredHeader, width: 300 }, + { field: 'reserved', type: 'number', displayName: 'Reserved E1', headerCellClass: $scope.highlightFilteredHeader, width: 150, cellClass: 'number' }, + { field: 'configured', type: 'number', displayName: 'Configured E1', headerCellClass: $scope.highlightFilteredHeader, width: 150, cellClass: 'number' }, + { field: 'utilization', type: 'number', displayName: 'Utilization [%]', headerCellClass: $scope.highlightFilteredHeader, width: 150, cellClass: 'number', sort: { + direction: uiGridConstants.ASC, + priority: 1 + } } + ]; + + $scope.gridOptions.data = []; + + var getUtilization = function(row) { + if (row.reserved === '?' || row.configured === '?' || row.reserved < 1) { + return '?'; + } + return (( row.configured / row.reserved ) * 100).toFixed(2); + }; + + var cleanProgess = function() { + $scope.progress = { + show: false, + max: 0, + value: 0 + }; + }; + cleanProgess(); + + var cleanMessage = function() { + $scope.message = { + error: undefined, + show: true, + startTime: undefined, + endTime: undefined, + duration: undefined + }; + }; + + var finish = function() { + $scope.message.endTime = new Date().toISOString(); + $scope.message.duration = ((new Date($scope.message.endTime) - new Date($scope.message.startTime))/1000).toFixed(1) + 's'; + $scope.gridOptions.columnDefs.filter(function(column){ + return column.field === 'utilization'; + }).map(function(column){ + column.sort.direction = uiGridConstants.ASC; + $scope.gridApi.core.refresh(); + }); + $timeout(cleanProgess, 1000); + }; + $scope.scan = function() { + cleanMessage(); + $scope.progress.show = true; + $scope.message.startTime = new Date().toISOString(); + + $mwtnTdm.getMountPoints().then(function (mountpoints) { + $scope.gridOptions.data = []; + if (mountpoints.length === 0) { + $timeout(cleanProgess, 1000); + } + mountpoints.filter(function (mountpoint) { + return mountpoint['netconf-node-topology:connection-status'] === 'connected'; + }).map(function (mountpoint) { + $mwtnTdm.getActualNetworkElement(mountpoint['node-id'], '2017-03-24').then(function (success) { + var onfNetworkElement = new OnfNetworkElement(success['network-element']); + var tdmLtps = onfNetworkElement.getLTPMwsList().filter(function (ltp) { + return ltp.getConditionalPackages()[0].contains('hybrid'); + }).map(function (ltp) { + $scope.progress.max = $scope.progress.max + 1; + var row = { + ltpId: [ltp.getId(), onfNetworkElement.getId()].join('@'), + nodeId: onfNetworkElement.getName(), + layer: 'MWS', + ltpRef: ltp.getLabel(), + reserved: '?', + configured: '?', + utilization: '?' + }; + + var specConfig = { + nodeId: mountpoint['node-id'], + revision: '2017-03-24', + pacId: 'microwave-model:mw-hybrid-mw-structure-pac', + layerProtocolId: ltp.getLayerProtocols()[0].getId(), + partId: 'hybrid-mw-structure-configuration' + }; + $mwtnTdm.getPacParts(specConfig).then(function(success){ + success = $mwtnTdm.yangifyObject(success); + row.reserved = success['hybrid-mw-structure-configuration']['number-of-tdm-segments-to-be-reserved']; + row.utilization = getUtilization(row); + }, function(error){ + // ignore + }); + + var specStatus = { + nodeId: mountpoint['node-id'], + revision: '2017-03-24', + pacId: 'microwave-model:mw-hybrid-mw-structure-pac', + layerProtocolId: ltp.getLayerProtocols()[0].getId(), + partId: 'hybrid-mw-structure-status' + }; + $mwtnTdm.getPacParts(specStatus).then(function(success){ + success = $mwtnTdm.yangifyObject(success); + row.configured = success['hybrid-mw-structure-status']['segment-status-list'].filter(function(item){ + return item['segment-is-reserved-for-tdm'] === true; + }).length; + row.utilization = getUtilization(row); + $scope.progress.value = $scope.progress.value + 1; + if ($scope.progress.max === $scope.progress.value) { + finish(); + } + }, function(error){ + // ignore + }); + + $scope.gridOptions.data.push(row); + }); + console.warn(JSON.stringify(tdmLtps)); + if (tdmLtps.length === 0 && $scope.progress.max === $scope.progress.value) { + finish(); + } + }); + }, function (error) { + $scope.gridOptions.data = []; + }); + + }); + }; + $scope.scan(); + + }]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.module.js new file mode 100644 index 00000000..b136b535 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.module.js @@ -0,0 +1,53 @@ +/* + * 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', + 'app/mwtnCommons/bower_components/angular-clipboard/angular-clipboard'], function(ng) { + var mwtnTdmApp = angular.module('app.mwtnTdm', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'angular-clipboard']); + + mwtnTdmApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnTdmApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + NavHelperProvider.addControllerUrl('app/mwtnTdm/mwtnTdm.controller'); + NavHelperProvider.addToMenu('mwtnTdm', { + "link" : "#/mwtnTdm", + "active" : "main.mwtnTdm", + "title" : "MWTN TDM", + "icon" : "fa fa-cogs", // Add navigation icon css class here + "page" : { + "title" : "MWTN TDM", + "description" : "mwtnTdm" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnTdm', { + url: 'mwtnTdm', + access: access.admin, + views : { + content : { + templateUrl: 'src/app/mwtnTdm/templates/frame.tpl.html', + controller: 'mwtnTdmCtrl' + } + } + }); + + }); + + return mwtnTdmApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.services.js new file mode 100644 index 00000000..824fd26b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/mwtnTdm.services.js @@ -0,0 +1,31 @@ +/* + * @copyright 2017 highstreet technologies 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/mwtnCommons/mwtnCommons.module', 'app/mwtnTdm/mwtnTdm.module'],function(mwtnTdmApp) { + + mwtnTdmApp.register.factory('$mwtnTdm', function($mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.getPacParts = $mwtnCommons.getPacParts; + service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + service.getMountPoints = $mwtnCommons.getMountPoints; + service.gridOptions = $mwtnCommons.gridOptions; + service.getActualNetworkElement = $mwtnCommons.getActualNetworkElement; + service.getMountPoints = $mwtnCommons.getMountPoints; + service.getPacParts = $mwtnCommons.getPacParts; + + service.parts = $mwtnCommons.parts; + service.separator = $mwtnCommons.separator; + service.yangify = $mwtnCommons.yangify; + service.yangifyObject = $mwtnCommons.yangifyObject; + + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/templates/frame.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/templates/frame.tpl.html new file mode 100644 index 00000000..c253807c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/mwtnTdm-module/src/main/resources/mwtnTdm/templates/frame.tpl.html @@ -0,0 +1,52 @@ +<ht-header help-link='sdnr/mwtnTdm/0.4.0/README.md'></ht-header> + +<div class="owl container" style="width: 100%;"> + + <div class="row bbg"> + <div class="col-md-2"> + <button type="button" id="scan" class="btn btn-primary" ng-click="scan()"> + <i class="fa fa-spinner fa-pulse" aria-hidden="true" ng-if="progress.show"></i> + <span>{{'MWTN_SCAN_NETWORK' | translate}}</span> + </button> + </div> + <div class="col-md-3" ng-if="message.startTime !== undefined"> + <span>{{'MWTN_START_TIME' | translate}}</span> + <b>{{message.startTime.toHumanReadableTimeFormat()}}</b> + </div> + <div class="col-md-3" ng-if="message.endTime !== undefined"> + <span>{{'MWTN_END_TIME' | translate}}</span> + <b>{{message.endTime.toHumanReadableTimeFormat()}}</b> + </div> + <div class="col-md-2" ng-if="message.duration !== undefined"> + <span>{{'MWTN_DURATION' | translate}}</span> + <b>{{message.duration}}</b> + </div> + </div> + + <div class="row"> + <div class=" col-md-12"> + <hr/> + </div> + </div> + + <div class="row"> + <div class=" col-md-12"> + <div id="mwtnTdmGrid" ui-grid="gridOptions" ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns ui-grid-move-columns + class="mwtnLogGrid"></div> + </div> + </div> + + <div class="row"> + <div class=" col-md-12"> + <uib-progressbar ng-if="progress.show" class="progress-striped col-md-12" type="primary" max="progress.max" value="progress.value"> + <i class="owl-dark">{{progress.value}} / {{progress.max}}</i> + </uib-progressbar> + </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/mwtnTdm/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/pom.xml new file mode 100644 index 00000000..8abbeca5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTdm/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTdm</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnTdm-module</module> + <module>mwtnTdm-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-bundle/pom.xml new file mode 100644 index 00000000..984511b7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-bundle/pom.xml @@ -0,0 +1,89 @@ +<?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>mwtnTest</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnTest-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTest-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnTest-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..512631f5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnTest"/> + <property name="url" value="/src/app/mwtnTest"/> + <property name="directory" value="/mwtnTest"/> + <property name="requireJs" value="app/mwtnTest/mwtnTest.module"/> + <property name="angularJs" value="app.mwtnTest"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnTest/mwtnTest-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/pom.xml new file mode 100644 index 00000000..400eada1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnTest</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnTest-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/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/images/mwtnTest.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/images/mwtnTest.png Binary files differnew file mode 100755 index 00000000..bd00ceda --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/images/mwtnTest.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest-custom.css new file mode 100644 index 00000000..15c398c1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest-custom.css @@ -0,0 +1,24 @@ +/** + * Add your application related css here + */ + +.json-formatter-row .constructor-name { + cursor: pointer; + color: #333333; +} + +.json-formatter-row .toggler:after { + color: darkgreen; + font-weight: bold; + display: inline-block; + transition: transform .1s ease-in; + content: ">" +} + +.owl span.key-text { + color: #333333; +} + +.owl span.colon { + color: #333333; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.controller.js new file mode 100644 index 00000000..e873f19c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.controller.js @@ -0,0 +1,477 @@ +/* + * @copyright 2017 highstreet technologies GmbH and others. All rights reserved. + * + * @license + * 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/mwtnTest/mwtnTest.module', + 'app/mwtnTest/mwtnTest.services'], + function(mwtnTestApp) { + + mwtnTestApp.register.controller('mwtnTestCtrl', ['$scope', '$rootScope', '$mwtnLog', '$mwtnTest', '$translate', 'OnfNetworkElement', 'LogicalTerminationPoint', + function($scope, $rootScope, $mwtnLog, $mwtnTest, $translate, OnfNetworkElement, LogicalTerminationPoint) { + + var COMPONENT = 'mwtnTestCtrl'; + $mwtnLog.info({component: COMPONENT, message: 'mwtnTestCtrl started!'}); + $rootScope.section_logo = 'src/app/mwtnTest/images/mwtnTest.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + var pacTemplate = { + 'layer-protocol': 'unknown' + }; + + // get important infromation from yang modules + $mwtnTest.getModules().then(function(success){ + + var pacOrder = { + 'onf-otn-odu-conditional-packages:otn-odu-connection-pac' : 2, + 'onf-otn-odu-conditional-packages:otn-odu-termination-pac' : 1, + 'onf-ethernet-conditional-packages:ethernet-pac' : 1, + 'microwave-model:mw-air-interface-diversity-pac' : 1, + 'microwave-model:mw-air-interface-hsb-end-point-pac' : 1, + 'microwave-model:mw-air-interface-hsb-fc-switch-pac' : 2, + 'onf-core-model-conditional-packages:holder-pac' : 3, + 'onf-core-model-conditional-packages:connector-pac' : 4, + 'onf-core-model-conditional-packages:equipment-pac' : 5, + 'microwave-model:mw-ethernet-container-pac' : 6, + 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac' : 7, + 'microwave-model:mw-ethernet-container-pac' : 8, + 'microwave-model:mw-tdm-container-pac': 9, + 'microwave-model:mw-pure-ethernet-structure-pac': 10, + 'microwave-model:mw-hybrid-mw-structure-pac': 11, + 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac' : 12, + 'microwave-model:mw-air-interface-pac' : 13, + 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac' : 14 + }; + + $scope.modules = success; + $scope.orderedPacs = []; + $scope.parts = []; + Object.keys(success).map(function(module){ + Object.keys(success[module]).filter(function(key){ + return key.endsWith('-pac') || key.endsWith('_Pac'); + }).map(function(pacName){ + $scope.orderedPacs.push([module, pacName].join(':')); + // sort + $scope.orderedPacs.sort(function(a, b) { + if (!pacOrder[a]) console.warn(a); + if (!pacOrder[b]) console.warn(b); + if(pacOrder[a] > pacOrder[b]) return 1; + if(pacOrder[a] < pacOrder[b]) return -1; + return 0; + }) + + if (pacName === 'mw-air-interface-pac') { + $scope.parts = Object.keys(success[module][pacName]).filter(function(conditionalPackage){ + return success[module][pacName][conditionalPackage]['local-name']; + }).map(function(conditionalPackage){ + return success[module][pacName][conditionalPackage]['local-name']; + }); + } + }); + }); + }, function(error){ + $scope.modules = undefined; + $scope.orderedPacs = undefined; + $scope.parts = undefined; + }); + + /** + * @function updateNe + * A function, which updates onfNetworkElement by new data. + * @param {*} data New data recieved from OpenDaylight via RestConf + */ + var updateNe = function(data) { + if (!data) return; + // update onfNetworkElement + switch ($scope.revision) { + case '2016-03-23': + $scope.onfNetworkElement = JSON.parse(JSON.stringify(data['network-element'][0])); + $scope.onfLtps = data['network-element'][0].ltp; + $scope.onfNetworkElement.ltp = undefined; + break; + case '2016-08-09': + case '2016-08-11': + case '2017-02-17': + case '2017-03-20': + // console.log(JSON.stringify(data)); + $scope.onfNetworkElement = new OnfNetworkElement(data['network-element']); + $scope.onfLtps = $scope.onfNetworkElement.getLogicalTerminationPoints(); + // $scope.onfNetworkElement.ltp = undefined; + break; + default: + $mwtnLog.info({component: COMPONENT, message: ['The ONF CoreModel revision', $scope.mountpoint.onfCoreModelRevision, ' is not supported (yet)!'].join(' ')}); + $scope.onfNetworkElement = {}; + $scope.onfLtps = {}; + } + + var order = $mwtnTest.layerProtocolNameOrder; + // update onfLTPs + $scope.onfLtps.sort(function(a, b){ + if(order[a.getLayer()] < order[b.getLayer()]) return -1; + if(order[a.getLayer()] > order[b.getLayer()]) return 1; + if(a.getId() < b.getId()) return -1; + if(a.getId() > b.getId()) return 1; + return 0; + }); + + // calculate conditional packages + $scope.pacs = {}; + $scope.onfLtps.map(function(ltp) { + ltp.getLayerProtocols().map( + /** + * A function processing a layer-protocol object + * @param {LayerProtocol} lp A layer-protocol object + */ + function(lp) { + var template = JSON.parse(JSON.stringify(pacTemplate)); + template['layer-protocol'] = lp.getId(); + var conditionalPackage = lp.getConditionalPackage(true); + // console.log(conditionalPackage); + if (conditionalPackage !== '') { + if ($scope.pacs[conditionalPackage] === undefined) { + // create missing pac array + $scope.pacs[conditionalPackage] = []; + } + $scope.pacs[conditionalPackage].push(template); + } else { + $mwtnLog.info({component: COMPONENT, message: 'No conditional package for ' + ltp.getLabel() }); + } + }); + }); + + // sort the conditional packages + if ($scope.orderedPacs) { + $scope.orderedPacs.filter(function(item){ + return $scope.pacs[item] !== undefined; + }).map(function(item){ + $scope.pacs[item].sort(function(a, b){ + if(a['layer-protocol'] < b['layer-protocol']) return -1; + if(a['layer-protocol'] > b['layer-protocol']) return 1; + return 0; + }); + }); + } + data.revision = undefined; + }; + + var updateNetworkElementCurrentProblems = function(data) { + if (!data) return; + $scope.neCurrentProblems = data; + }; + + var updateLtp = function(data) { + $scope.onfLtps.map(function(ltp){ + if (ltp.getData().uuid === data.data.ltp[0].uuid) { + ltp = new LogicalTerminationPoint(data.data.ltp[0]); + } + }); + }; + + /** + * @deprecated since all conditaional packages are handle the same way even for + * 3rd and 4th PoC model - 2nd PoC model not supported any more. + * @param {*} lpId + * @param {*} part + * @param {*} data + */ + var updateAirInterface = function(lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + $scope.airinterfaces.map(function(airinterface){ + // console.log(JSON.stringify(airinterface)); + if (airinterface['layer-protocol'] === lpId) { + if (Object.keys(data)[0].startsWith('air-interface')) { + airinterface[part] = data; + } else if (part === 'Capability') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + airinterface[part] = data['mw-air-interface-pac'][0]['air-interface-capability-list']; + } else if (part === 'CurrentProblems') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + airinterface[part] = data['mw-air-interface-pac'][0]['air-interface-current-problem-list']; + } + } + }); + data.revision = undefined; + }; + + /** + * @deprecated since all conditaional packages are handle the same way even for + * 3rd and 4th PoC model - 2nd PoC model not supported any more. + * @param {*} lpId + * @param {*} part + * @param {*} data + */ + var updateStructure = function(lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + $scope.structures.map(function(structure){ + // console.log(JSON.stringify(structure)); + if (structure['layer-protocol'] === lpId) { + if (Object.keys(data)[0].contains('tructure')) { + structure[part] = data; + } else if (part === 'Capability') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + structure[part] = data['mw-structure-pac'][0]['structure.capability-list']; + } else if (part === 'CurrentProblems') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + structure[part] = data['mw-structure-pac'][0]['structure-current-problem-list']; + } + } + }); + data.revision = undefined; + }; + + /** + * @deprecated since all conditaional packages are handle the same way even for + * 3rd and 4th PoC model - 2nd PoC model not supported any more. + * @param {*} lpId + * @param {*} part + * @param {*} data + */ + var updateContainer = function(lpId, part, data) { + // console.log(JSON.stringify(data), lpId); + $scope.containers.map(function(container){ + // console.log(JSON.stringify(container)); + if (container['layer-protocol'] === lpId) { + if (Object.keys(data)[0].contains('ontainer') ) { + container[part] = data; + } else if (part === 'Capability') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + container[part] = data['mw-container-pac'][0]['container-capability-list']; + } else if (part === 'CurrentProblems') { + // 2. PoC + // console.log(part, JSON.stringify(data)); + container[part] = data['mw-container-pac'][0]['container-current-problem-list']; + } + } + }); + data.revision = undefined; + }; + + /** + * Creates a template of a conditional packages with its subclasses + * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass + */ + var initPac = function(spec) { + $scope.pacs[spec.pacId].filter(function(conditionalPackage){ + return conditionalPackage['layer-protocol'] === spec.layerProtocolId; + }).map(function(pac){ + $scope.parts.map(function(localName){ + pac[localName] = {id:$mwtnTest.getPartGlobalId(spec, localName),localName: localName, data:'No data available'} + }); + }); + }; + + /** + * Updates an existing template of a conditional packages with its subclasses + * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass + */ + var updateSubClassData = function(spec, data) { + $scope.pacs[spec.pacId].filter(function(conditionalPackage){ + return conditionalPackage['layer-protocol'] === spec.layerProtocolId; + }).map(function(conditionalPackage){ + conditionalPackage[$mwtnTest.getPartLocalId(spec)].data = data[$mwtnTest.yangify(spec.partId)]; + }); + }; + + var updatePart = function(spec, data) { + switch (spec.pacId) { + case 'ne': + updateNe(data); + break; + case 'neCurrentProblems': + updateNetworkElementCurrentProblems(data); + case 'clock': + // console.warn('yea clock', JSON.stringify(data)); + $scope.clock = data; + break; + case 'ltp': + updateLtp(data); + break; + case 'airinterface': + console.log(JSON.stringify(spec, JSON.stringify(data))); + updateAirInterface(spec.layerProtocolId, spec.partId, data); + break; + case 'structure': + console.log(JSON.stringify(data)); + updateStructure(spec.layerProtocolId, spec.partId, data); + break; + case 'container': + console.log(JSON.stringify(data)); + updateContainer(spec.layerProtocolId, spec.partId, data); + break; + // 3rd Poc + case 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac': + case 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac': + case 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac': + // 4th Poc + case 'microwave-model:mw-air-interface-pac': + case 'microwave-model:mw-air-interface-diversity-pac': + case 'microwave-model:mw-pure-ethernet-structure-pac': + case 'microwave-model:mw-hybrid-mw-structure-pac': + case 'microwave-model:mw-tdm-container-pac': + case 'microwave-model:mw-ethernet-container-pac': + case 'onf-ethernet-conditional-packages:ethernet-pac': + // Poc 4.1 + case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac': + case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac': + if (!spec.partId) { + initPac(spec); + } else { + updateSubClassData(spec, data); + } + break; + } + }; + + // events + $scope.status = {ne:false}; + $scope.spinner = {ne:false}; + $scope.separator = $mwtnTest.separator; //' ' + + $scope.myClipboard = { + data : {'key': 'value'}, + supported : true, + getJson : function() { + return JSON.stringify(this.data, null, ' '); + }, + copyToClipboard : function() { + var message = 'Copied to clipboard! ' + this.getJson(); + $mwtnLog.info({component: COMPONENT, message: message}); + }, + error : function(err) { + $mwtnLog.error({component: COMPONENT, message: err}); + } + }; + + $scope.$watch('status', function(status, oldValue) { + Object.keys(status).filter(function(key){ + return $scope.networkElementId && status[key] && status[key] !== oldValue[key]; + }).map(function(key){ + $scope.spinner[key] = true; + var info = key.split($scope.separator); + var spec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: info[0], + layerProtocolId: info[1], + partId: info[2] + }; + $mwtnTest.getPacParts(spec).then(function(success){ + success = $mwtnTest.yangifyObject(success) + $scope.myClipboard.data = success; + updatePart(spec, success); + $scope.spinner[key] = false; + }, function(error){ + $scope.myClipboard.data = 'Opps!'; + updatePart(spec, error); + $scope.spinner[key] = false; + }); + $scope.mountpoint = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === $scope.networkElementId; + })[0]; + if (key === 'mountpoint') { + $scope.spinner['mountpoint'] = false; + $scope.myClipboard.data = $scope.mountpoint; + } + }); + }, true); + + // var spec = { + // nodeId: $scope.networkElementId, + // revision: $scope.revision, + // pacId: 'clock' + // }; + // $mwtnTest.getPacParts(spec).then(function(success){ + // $scope.collapseAll(); + // updatePart(spec, $mwtnTest.yangifyObject(success)); + // }, function(error){ + // $scope.collapseAll(); + // updatePart(spec, error); + // }); + + + $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; + }); + }; + + $scope.$watch('networkElement', function(neId, oldValue) { + if (neId && neId !== '' && neId !== oldValue) { + + // clear old data + $scope.airinterfaces = []; + $scope.structures = []; + $scope.containers = []; + $scope.onfLtps = []; + $scope.clock = undefined; + + $scope.networkElementId = neId; + $scope.revision = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === neId; + }).map(function(mountpoint){ + return mountpoint.onfCoreModelRevision; + })[0]; + + // network element alarms + var neAlarms = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === neId; + }).map(function(mountpoint){ + return mountpoint.onfCapabilities.filter(function(cap){ + return cap.module === 'MicrowaveModel-NetworkElement-CurrentProblemList' || cap.module === 'onf-core-model-conditional-packages'; + }); + }); + if (neAlarms.length === 1 && neAlarms[0].length === 1 ) { + $translate('MWTN_LOADING').then(function (translation) { + $scope.neCurrentProblems = translation; + }); + } else { + $scope.neCurrentProblems = undefined; + } + + var spec = { + nodeId: $scope.networkElementId, + revision: $scope.revision, + pacId: 'ne' + }; + $mwtnTest.getPacParts(spec).then(function(success){ + $scope.collapseAll(); + updatePart(spec, $mwtnTest.yangifyObject(success)); + }, function(error){ + $scope.collapseAll(); + updatePart(spec, error); + }); + + // ptp-clock + var ptpClock = $scope.mountPoints.filter(function(mountpoint){ + return mountpoint['node-id'] === neId; + }).map(function(mountpoint){ + return mountpoint.onfCapabilities.filter(function(cap){ + return cap.module === 'onf-ptp-dataset'; + }); + }); + if (ptpClock.length === 1 && ptpClock[0].length === 1 ) { + $translate('MWTN_LOADING').then(function (translation) { + $scope.clock = translation; + }); + } else { + $scope.clock = undefined; + } + + } + }); + + }]); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.module.js new file mode 100644 index 00000000..b2f0a8fd --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.module.js @@ -0,0 +1,53 @@ +/* + * 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', + 'app/mwtnCommons/bower_components/angular-clipboard/angular-clipboard'], function(ng) { + var mwtnTestApp = angular.module('app.mwtnTest', ['ui.grid', 'ui.bootstrap', 'app.core', 'ui.router.state', 'config', 'angular-clipboard']); + + mwtnTestApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + mwtnTestApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + NavHelperProvider.addControllerUrl('app/mwtnTest/mwtnTest.controller'); + NavHelperProvider.addToMenu('mwtnTest', { + "link" : "#/mwtnTest/", + "active" : "main.mwtnTest", + "title" : "LTE RAN Test", + "icon" : "fa fa-check-square-o", // Add navigation icon css class here + "page" : { + "title" : "LTE RAN Test", + "description" : "mwtnTest" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnTest', { + url: 'mwtnTest/:nodeId', + access: access.admin, + views : { + content : { + templateUrl: 'src/app/mwtnTest/templates/frame.tpl.html', + controller: 'mwtnTestCtrl' + } + } + }); + + }); + + return mwtnTestApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.services.js new file mode 100644 index 00000000..b61ca531 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/mwtnTest.services.js @@ -0,0 +1,32 @@ +/* + * @copyright 2017 highstreet technologies 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/mwtnCommons/mwtnCommons.module', 'app/mwtnTest/mwtnTest.module'],function(mwtnTestApp) { + + mwtnTestApp.register.factory('$mwtnTest', function($mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var COMPONENT = '$mwtnTest'; + $mwtnLog.info({component: COMPONENT, message: '$mwtnTest started!'}); + + var service = {}; + + service.parts = $mwtnCommons.parts; + service.getPacParts = $mwtnCommons.getPacParts; + service.getModules = $mwtnDatabase.getModules; + service.getPartGlobalId = $mwtnCommons.getPartGlobalId; + service.getPartLocalId = $mwtnCommons.getPartLocalId; + service.layerProtocolNameOrder = $mwtnCommons.layerProtocolNameOrder; + + service.separator = $mwtnCommons.separator; + service.yangify = $mwtnCommons.yangify; + service.yangifyObject = $mwtnCommons.yangifyObject; + + return service; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/templates/frame.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/templates/frame.tpl.html new file mode 100644 index 00000000..6a341d20 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/mwtnTest-module/src/main/resources/mwtnTest/templates/frame.tpl.html @@ -0,0 +1,172 @@ +<ht-header help-link='sdnr/mwtnTest/0.4.0/README.md'></ht-header> +<mwtn-select-network-element></mwtn-select-network-element> + + +<div class="owl container" ng-show="networkElements.lenght !== 0"> + <div class="row"> + + <uib-accordion close-others="oneAtATime"> + + <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}} '{{onfNetworkElement.getName()}}'</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.ne"></i> + </uib-accordion-heading> + + <button class="pull-right btn btn-default" type="button" + clipboard + supported="myClipboard.supported" + text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" + on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + + <json-formatter json="onfNetworkElement.data" open="1"></json-formatter> + </div> + + <div uib-accordion-group class="panel-default" + is-open="status.mountpoint"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': status.mountpoint, 'fa-chevron-right': !status.mountpoint}"></i> + <span>{{'MWTN_MOUNTPOINT' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.mountpoint"></i> + </uib-accordion-heading> + + <button class="pull-right btn btn-default" type="button" + clipboard + supported="myClipboard.supported" + text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" + on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + + <json-formatter json="mountpoint" open="1"></json-formatter> + </div> + + <div uib-accordion-group class="panel-default" + is-open="status.clock" ng-show="clock"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': status.clock, 'fa-chevron-right': !status.clock}"></i> + <span>{{'MWTN_CLOCK' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.clock"></i> + </uib-accordion-heading> + + <button class="pull-right btn btn-default" type="button" + clipboard + supported="myClipboard.supported" + text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" + on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + + <json-formatter json="clock" open="1"></json-formatter> + </div> + + <div uib-accordion-group class="panel-default" + is-open="status.neCurrentProblems" ng-show="neCurrentProblems"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': status.neCurrentProblems, 'fa-chevron-right': !status.neCurrentProblems}"></i> + <span>{{'MWTN_CURRENT_PROBLEM_LIST' | translate}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner.neCurrentProblems"></i> + </uib-accordion-heading> + + <button class="pull-right btn btn-default" type="button" + clipboard + supported="myClipboard.supported" + text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" + on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + + <json-formatter json="neCurrentProblems" open="1"></json-formatter> + </div> + + <div ng-repeat="ltp in onfLtps" + uib-accordion-group + class="panel-default" + is-open="status['ltp' + separator + ltp.getData().uuid]"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': status['ltp' + separator + ltp.getData().uuid], 'fa-chevron-right': !status['ltp' + separator + ltp.getData().uuid]}"></i> + <span>{{'MWTN_LTP' | translate}}(</span> + <b>{{ltp.getLayerProtocols()[0].getItuLabel().toUpperCase()}}</b> + <span>): {{ltp.getId()}}</span> + </uib-accordion-heading> + + <button class="pull-right btn btn-default" type="button" + clipboard + supported="myClipboard.supported" + text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" + on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + + <span>{{'MWTN_ID' | translate}}</span> <b>{{ltp.getId()}}</b><br/> + <span>{{'MWTN_DIRECTIONALITY' | translate}}</span> <b>{{ltp.getDirectionality()}}</b><br/> + <span>{{'MWTN_SERVER_LTPS' | translate}}</span> <b>{{ltp.getServerLtps()}}</b><br/> + <span>{{'MWTN_CLIENT_LTPS' | translate}}</span> <b>{{ltp.getClientLtps()}}</b><br/><br/> + + <div ng-repeat="lp in ltp.getLayerProtocols()"> + <b>{{'MWTN_LAYER_PROTOCOL' | translate}}</b><br/> + <span>{{'MWTN_ID' | translate}}</span> <b>{{lp.getId()}}</b><br/> + <span>{{'MWTN_LAYER' | translate}}</span> <b>{{lp.getLayer()}}</b><br/> + <span>{{'MWTN_TERMINATION_STATE' | translate}}</span> <b>{{lp.getTerminationState()}}</b><br/> + <span>{{'MWTN_LABEL' | translate}}</span> <b>{{lp.getItuLabel().toUpperCase()}}</b><br/> + <span>{{'MWTN_CAPABILITY' | translate}}</span> <b>{{lp.getCapability()}}</b><br/> + <span>{{'MWTN_REVISON' | translate}}</span> <b>{{lp.getRevision()}}</b><br/> + <span>{{'MWTN_CONDITIONAL_PACKAGE' | translate}}</span> <b>{{lp.getConditionalPackage()}}</b><br/><br/> + <!-- <pre>{{lp.getData() | json}}</pre> --> + </div> + <json-formatter json="ltp.getData()" open="1"></json-formatter> + </div> + + </uib-accordion> + </div> + + <div ng-repeat="orderedPac in orderedPacs" class="row" style="margin-top: 5px" ng-show="pacs[orderedPac]"> + <uib-accordion close-others="oneAtATime"> + <div ng-repeat="pac in pacs[orderedPac]" + uib-accordion-group + class="panel-primary" + is-open="status[ [orderedPac, pac['layer-protocol']].join(separator) ]"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': status[ [orderedPac, pac['layer-protocol']].join(separator) ], 'fa-chevron-right': !status[ [orderedPac, pac['layer-protocol']].join(separator) ]}"></i> + <span>{{ 'MWTN_' + orderedPac.toUpperCase().replaceAll('-', '_') | translate }} '{{pac['layer-protocol']}}'</span> + </uib-accordion-heading> + + <div ng-repeat="part in parts" + uib-accordion-group + class="panel-default" + is-open="status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"> + <uib-accordion-heading> + <i class="pull-left fa" ng-class="{'fa-chevron-down': status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ], 'fa-chevron-right': !status[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]}"></i> + <span>{{part}}</span> + <i class="pull-right fa fa-spinner fa-pulse" ng-show="spinner[ [orderedPac, pac['layer-protocol'], pac[part].id].join(separator) ]"></i> + </uib-accordion-heading> + + <button class="pull-right btn btn-default" type="button" + clipboard + supported="myClipboard.supported" + text="myClipboard.getJson()" + on-copied="myClipboard.copyToClipboard()" + on-error="myClipboard.error(err)"> + <i class="fa fa-clipboard" aria-hidden="true"></i> + </button> + + <json-formatter json="pac[part].data" open="1"></json-formatter> + </div> + </div> + + </uib-accordion> + </div> +</div> +<hr /> +<div class="owl"> + <span>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/mwtnTest/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/pom.xml new file mode 100644 index 00000000..b0436ffb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTest/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTest</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnTest-module</module> + <module>mwtnTest-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-bundle/pom.xml new file mode 100644 index 00000000..c1639dcb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-bundle/pom.xml @@ -0,0 +1,117 @@ +<?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>mwtnTopology</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnTopology-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTopology-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>mwtnTopology-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..a5cfcfc2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="mwtnTopology"/> + <property name="url" value="/src/app/mwtnTopology"/> + <property name="directory" value="/mwtnTopology"/> + <property name="requireJs" value="app/mwtnTopology/mwtnTopology.module"/> + <property name="angularJs" value="app.mwtnTopology"/> + <property name="cssDependencies"> + <list> + <value>src/app/mwtnTopology/mwtnTopology-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/pom.xml new file mode 100644 index 00000000..1eb8126c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/pom.xml @@ -0,0 +1,14 @@ +<?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>mwtnTopology</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>mwtnTopology-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/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/doc/mwtnTopology.builinfo.md b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/doc/mwtnTopology.builinfo.md new file mode 100755 index 00000000..594b8e26 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/doc/mwtnTopology.builinfo.md @@ -0,0 +1,39 @@ +# Buildinfo
+
+Ausgehend vom Verzeichnis:
+SDN-Projects-Boron/code/ux
+
+ll => pom.xml muss vorhanden sein.
+
+## manuelles Builden
+
+Die Schritte 1, 5 und 6 sind während des Buildens notwendig, die anderen Schritte sind zu Kontrollzwecken und zum starten / Stoppen vom Karaf Server
+
+1. Für den Compilevorgang der eigenen Komponenten:
+ - `cd ~/SDN-Projects-Boron/code`
+ - `mvn clean install -DskipTests`
+ - `cp -R ~/.m2/repository/com/highstreet $ODL_KARAF_HOME/system/com`
+2. Zum beenden von Karaf:
+ - ctrl+d in der Shell, auf der Karaf läuft.
+ - `sudo $ODL_KARAF_HOME/bin/client -u karaf "shutdown --force"`, wenn man nicht in der passenden Shell ist
+3. Starten von Karaf:
+ - `cd $ODL_KARAF_HOME`
+ - `./bin/karaf`
+4. Zum gucken, welche Module installiert sind (von highstreet, grep):
+ - `bundle:list | grep mwtn`
+5. Bundles deinstallieren (Funktioniert nur innerhalb der Karaf Shell)
+ - `bundle:uninstall "ONF :: Wireless :: mwtnCommons-bundle" "ONF :: Wireless :: mwtnTopology-bundle"`
+6. (geänderte) Bundles installieren (Funktioniert nur innerhalb der Karaf Shell)
+ - `bundle:install -s mvn:com.highstreet.technologies.odl.dlux/mwtnCommons-bundle/0.4.0-SNAPSHOT mvn:com.highstreet.technologies.odl.dlux/mwtnTopology-bundle/0.4.0-SNAPSHOT`
+
+## GIT:
+
+Abrufen:
+- `cd ~/SDN-Projects-Boron/code/ux/mwtnTopology/mwtnTopology-module/src/main/resources`
+- `git pull`
+
+Einchecken:
+- `git add doc/*.md`
+- `git status` (Kontrolle der einzucheckenden Dateien)
+- `git commit` (Ist der eincheckvorgang an sich (lokaler GitServer))
+- `git push` (Übertragen aller Commits zum zentralen Server)
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/doc/mwtnTopology.fs.md b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/doc/mwtnTopology.fs.md new file mode 100755 index 00000000..861306c2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/doc/mwtnTopology.fs.md @@ -0,0 +1,78 @@ +# mwtnTopology - Functional Specification
+
+## Beschreibung
+
+Das mwtnTopology Control zeichnet eine Karte mit Hilfe eines austauschbaren Kartendienstes
+Dabei wird die Satellitendarstellung verwendet (wenn möglich), sonst wird die Kartendarstellung gewählt.
+Über dem Kartenlayer soll ein Vectorlayer mit Informationen zu Mobilfunkmasten und zugehörigen Richtfunkstrecken dargestellt werden.
+Die Karte soll mittels Mausbedienung Scroll und Zoombar sein, Klicks auf einen Mast oder eine Richtfunkstrecke stellen weitere Informationen in einem Popup zur Verfügung.
+
+## Anforderungen
+
+* Die Webseite / der Webserver hat *keinen* Zugriff auf das öffentliche Internet. Online-Kartendienste wie Google, Bing oder OpenStreetMap sind damit nicht erreichbar.
+* Der Server stellt eine API bereit, an welcher die Kartenkacheln als Bitmaps (png/jpeg) bereitgestellt werden.
+* Der darzustellende Bereich wird angegeben durch
+ - Ein Latitude/Longitude Koordinatenpaar (Mittelpunkt) und eine Zoomstufe in % wobei 0% der "Weltraumansicht" und 100% der "Sandkrümel auf der Straße" entspricht.
+ Die benötigten Kacheln werden anhand der Zoomstufe und der Größe des Kartenausschnitts in Bildschirmpixel berechnet.
+ - Zwei Latitude/Longitude Koordinatenpaare, welche die obere rechte Ecke und die untere linke Ecke des darzustellenden Kartenausschnitts darstellen.
+ Die benötigte Zoomstufe wird anhand der Koordinatenpaare und der Größe des Kartenausschnitts in Bildschirmpixel berechnet.
+ + 2 Mögliche SubModi: "Fill" und "Cut"
+* Die Zoomstufen als %-Angaben werden auf die vom Kartenprovider verwendeten ganzzahligen Zoomstufen gemappt.
+ - Nicht jeder Kartenprovider kann für alle Zoomstufen Bitmaps liefern. Gibt es eine Möglichkeit die maximale Provider-Zoomstufe für eine Koordinate abzufragen?
+* Der Client cached die Bildkacheln, um die Serverlast zu reduzieren.
+ - Localstorage?
+
+## Offene Fragen
+
+* Soll die Karte immer eingenordet sein oder ist eine Kartenrotation erforderlich?
+* Welche Karten-UI-Steuerelemente müssen angezeigt werden
+ - +/- Button / Zoom-Slider
+ - 2D-Rotations-Gizmo / Kompass
+ - Geokoordinate Zentrieren
+ - Kartenscale (20m|---------------|)
+ - Copyright-Angaben der verwendeten Kartendaten
+ - Ein/Ausblenden des Vector-Overlays
+* Kann ein eigener Tile Render Server (wie z.B. Maperitive) verwendet werden?
+* Transparente, vorberechnete Kacheln des VectorLayers verfügbar? (Kacheln erlauben keine Hover-Informationen einzelner Richtfunktstrecken)
+
+## Berechnungsformeln
+
+- [OSM: Slippy map tilenames](http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
+
+The first part of the URL specifies the tile server, and perhaps other parameters which might influence the style.
+
+Generally several subdomains (server names) are provided to get around browser limitations on the number of simultaneous HTTP connections to each host.
+Browser-based applications can thus request multiple tiles from multiple subdomains faster than from one subdomain.
+For example, OSM, OpenCycleMap and CloudMade servers have three subdomains (a.tile, b.tile, c.tile), MapQuest has four (otile1, otile2, otile3, otile4),
+all pointing to the same CDN. That all comes before the /zoom/x/y.png tail.
+
+Example:
+http://[abc].tile.openstreetmap.org/zoom/x/y.png
+
+```js
+function long2tile(lon,zoom) { return (Math.floor((lon+180)/360*Math.pow(2,zoom))); }
+function lat2tile(lat,zoom) { return (Math.floor((1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,zoom))); }
+
+var zoom = 9;
+var top_tile = lat2tile(north_edge, zoom); // eg.lat2tile(34.422, 9);
+var left_tile = lon2tile(west_edge, zoom);
+var bottom_tile = lat2tile(south_edge, zoom);
+var right_tile = lon2tile(east_edge, zoom);
+var width = Math.abs(left_tile - right_tile) + 1;
+var height = Math.abs(top_tile - bottom_tile) + 1;
+
+// total tiles
+var total_tiles = width * height; // -> eg. 377
+```
+
+## Links
+
+- [OpenStreetMap DE:Tile usage policy](http://wiki.openstreetmap.org/wiki/DE:Tile_usage_policy)
+- [OpenStreetMap DE:Karte in Webseite einbinden](http://wiki.openstreetmap.org/wiki/DE:Karte_in_Webseite_einbinden)
+- [OpenStreetMap DE:Maperitive](http://wiki.openstreetmap.org/wiki/DE:Maperitive)
+- [Maperitive, EN:Hauptwebseite](http://maperitive.net/)
+- [Google Maps Javascript API + Key anfordern](https://developers.google.com/maps/documentation/javascript/?hl=de)
+- [Google Maps Javascript Erste Schritte](https://developers.google.com/maps/documentation/javascript/tutorial?hl=de)
+- [Google Developer Console](https://console.developers.google.com/)
+- [GoogleMap AngularJS Directive](https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/docs/index.html)
+- [Sample asnyc script load into head element](http://just-run.it/#/ByvA_ClTe/0)
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/images/mwtnTopology.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/images/mwtnTopology.png Binary files differnew file mode 100755 index 00000000..7ddbeb2e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/images/mwtnTopology.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology-custom.css new file mode 100755 index 00000000..d04a7645 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology-custom.css @@ -0,0 +1,102 @@ +/** + * Add your application related css here + */ + +.owl p span { + color: #393939; +} + +.angular-google-map-container { + height: 1200px; +} + +.mwtnTopologyGrid { + height: 412px; + background-color: white; +} + +.mwtnTopologyGrid span { + color: #393939; +} + +#mwtnTopology .nav-tabs { + border-bottom: 1px solid #ddd; +} +#mwtnTopology .nav-tabs > li { + float: left; + margin-bottom: -1px; +} +#mwtnTopology .nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; + + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +#mwtnTopology .nav-tabs > li > a:hover { + color: #fff; + cursor: default; + background-color: #428bca; + border: 1px solid #428bca; + border-color: #eee #eee #ddd; + border-bottom-color: transparent; + +} +#mwtnTopology .nav-tabs > li.active > a, +#mwtnTopology .nav-tabs > li.active > a:hover, +#mwtnTopology .nav-tabs > li.active > a:focus { + color: #fff; + cursor: default; + background-color: #428bca; + border: 1px solid #428bca; + border-bottom-color: transparent; +} +#mwtnTopology .nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +#mwtnTopology .nav-tabs.nav-justified > li { + float: none; +} +#mwtnTopology .nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +#mwtnTopology .nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + #mwtnTopology .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + #mwtnTopology .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +#mwtnTopology .nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +#mwtnTopology .nav-tabs.nav-justified > .active > a, +#mwtnTopology .nav-tabs.nav-justified > .active > a:hover, +#mwtnTopology .nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + #mwtnTopology .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + #mwtnTopology .nav-tabs.nav-justified > .active > a, + #mwtnTopology .nav-tabs.nav-justified > .active > a:hover, + #mwtnTopology .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.controller.js new file mode 100755 index 00000000..f8aa303a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.controller.js @@ -0,0 +1,4877 @@ +/* + * 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 + */ +if (typeof (Number.prototype.toRad) === "undefined") { + Number.prototype.toRadians = function () { + return this * Math.PI / 180; + } +} + +if (Number.prototype.toDegrees === undefined) { + Number.prototype.toDegrees = function () { + return this * 180 / Math.PI; + }; +} + +// If array is empty, undefined is returned. If not empty, the first element +// that evaluates to false is returned. If no elements evaluate to false, the +// last element in the array is returned. +Array.prototype.and = function (defaultValue) { + for (var i = 0, len = this.length - 1; i < len && this[i]; i++); + return this.length ? this[i] : defaultValue; +}; + +// If array is empty, undefined is returned. If not empty, the first element +// that evaluates to true is returned. If no elements evaluate to true, the +// last element in the array is returned. +Array.prototype.or = function () { + for (var i = 0, len = this.length - 1; i < len && !this[i]; i++); + return this[i]; +}; + +var eventsFabric = function () { + var topics = {}; + var hOP = topics.hasOwnProperty; + + return { + subscribe: function (topic, listener) { + // Create the topic's object if not yet created + if (!hOP.call(topics, topic)) topics[topic] = []; + + // Add the listener to queue + var index = topics[topic].push(listener) - 1; + + // Provide handle back for removal of topic + return { + remove: function () { + delete topics[topic][index]; + } + }; + }, + publish: function (topic, info) { + // If the topic doesn't exist, or there's no listeners in queue, just leave + if (!hOP.call(topics, topic)) return; + + // Cycle through topics queue, fire! + topics[topic].forEach(function (item) { + item(info != undefined ? info : {}); + }); + } + }; +}; + +var lastOpenedInfoWindow = null; + +/*********************************************************************************************/ + +/** @typedef {{ id: string, siteA: string, siteZ: string, siteNameA: string, siteNameZ: string, airInterfaceLinks: {id: string, siteLink: string, radio: string, polarization: string }[]}} SiteLinkDetails */ + +define(['app/mwtnCommons/bower_components/lodash/dist/lodash', + 'app/mwtnCommons/bower_components/cytoscape/dist/cytoscape', + 'app/mwtnTopology/mwtnTopology.module', + 'app/mwtnTopology/mwtnTopology.services', + 'app/mwtnCommons/mwtnCommons.services' +], function (_, cytoscape, mwtnTopologyApp) { + + // module.exports = function () { + // const mwtnTopologyApp = require('app/mwtnTopology/mwtnTopology.module'); + // const mwtnTopologyService = require('app/mwtnTopology/mwtnTopology.services'); + // const cytoscape = require('cytoscape'); + + // remove '_' from global scope but use it here as '_'. + _.noConflict(); + + /********************************************* Sites *************************/ + + mwtnTopologyApp.directive('mwtnTopologyMap', ["$timeout", "$q", "$mwtnTopology", function ($timeout, $q, $mwtnTopology) { + return { + restrict: 'E', + replace: true, + template: '<div style="position:realtive;width:100%;height:700px" ng-transclude=""></div>', + controller: function () { + + }, + transclude: true, + scope: { + manualMapBounds: "=?", + onBoundsChanged: "&?" + }, + link: function (scope, element, attrs, ctrl) { + + var mapApiReadyDefer = $q.defer(); + var disbaleNotifications = true; + //var includeCenter = false; + + var initialMapOptions = { + center: new google.maps.LatLng(0, 0), + mapTypeId: google.maps.MapTypeId.HYBRID, + panControl: false, + rotateControl: false, + streetViewControl: false, + tilt: 0, + zoom: 2, + minZoom: 2 + }; + + // Wait at least one digest cycle before init the google map. + $timeout(function () { + ctrl.map = new google.maps.Map(element[0], initialMapOptions); + + // Wait until google maps is fully intialized to attach nessessary event handler. + waitUntilGoogleMapsIsReady(); + }); + + element.on("$destroy", function () { + if (scope.waitUntilGoogleMapsIsReadyTimeoutId) { + $timeout.cancel(scope.waitUntilGoogleMapsIsReadyTimeoutId); + } + if (scope.onDragEndListener) { + google.maps.event.removeListener(scope.onDragEndListener); + delete (scope.onDragEndListener); + } + if (scope.onZoomChangedListener) { + google.maps.event.removeListener(scope.onZoomChangedListener); + delete (scope.onZoomChangedListener); + } + + // window.removeEventListener('resize', onBoundsChanged); + + }); + + scope.$watch("manualMapBounds", function (newBounds, oldBounds) { + mapApiReadyDefer.promise.then(function () { + + // if this was an uri change from an not user originated action just return; + if (newBounds.internal) return; + + // values must exist and at least one must be different or initial load (new === old) + if (newBounds.bottom != null && newBounds.left != null && newBounds.top != null && newBounds.right != null) { + fitBounds(ctrl.map, new google.maps.LatLngBounds( + new google.maps.LatLng(newBounds.bottom, newBounds.left), + new google.maps.LatLng(newBounds.top, newBounds.right))); + } else if (newBounds.lat != null && newBounds.lng != null && newBounds.zoom != null && (newBounds.lat != oldBounds.lat || newBounds.lng != oldBounds.lng || newBounds.zoom != oldBounds.zoom || newBounds === oldBounds)) { + disbaleNotifications = true; + google.maps.event.addListenerOnce(ctrl.map, 'bounds_changed', function (event) { + disbaleNotifications = false; + onBoundsChanged(false); + + }); + ctrl.map.setCenter({ lat: newBounds.lat, lng: newBounds.lng }); + ctrl.map.setZoom(newBounds.zoom); + + } + console.log("manualMapBounds", newBounds); + }); + }); + + /** + * An asynchronous function that is called continuously every 100 milliseconds until the google maps control has finished its first complete draw. + * Then it sets up all event handlers and reports its bounds. + */ + function waitUntilGoogleMapsIsReady() { + var getBoundsApi = ctrl.map.getBounds(); + if (getBoundsApi) { + delete (scope.waitUntilGoogleMapsIsReadyTimeoutId); + // Change to dragend https://developers.google.com/maps/documentation/javascript/events?hl=de + scope.onDragEndListener = ctrl.map.addListener('dragend', function () { + onBoundsChanged(true); + }); + scope.onZoomChangedListener = ctrl.map.addListener('zoom_changed', function () { + onBoundsChanged(true); + }); + // window.addEventListener('resize', function () { + // onBoundsChanged(false); + // }); + + disbaleNotifications = false; + mapApiReadyDefer.resolve(); + } else { + scope.waitUntilGoogleMapsIsReadyTimeoutId = $timeout(waitUntilGoogleMapsIsReady, 100); + } + } + + /** + * Gets the current bound and zoom level of the map control and reports it to its parent component. + * Hint: do not call directly use fitBounds helper function since there is a google bug in the fit bounds function. + */ + function onBoundsChanged(userOriginated) { + if (!disbaleNotifications && scope.onBoundsChanged && angular.isFunction(scope.onBoundsChanged)) { + + var getBoundsApi = ctrl.map.getBounds(); + var northEastApi = getBoundsApi.getNorthEast(); + var southWestApi = getBoundsApi.getSouthWest(); + var center = ctrl.map.getCenter(); + + var data = { + top: northEastApi.lat(), + right: northEastApi.lng(), + bottom: southWestApi.lat(), + left: southWestApi.lng(), + lat: center.lat(), + lng: center.lng(), + zoom: ctrl.map.getZoom() + }; + + console.log("onBoundsChanged", data); + + scope.onBoundsChanged({ + data: data, + userOriginated: userOriginated === true + }); + } + } + + // bug: the original google code will fit bounds will add some extra space, this function will fix it + function fitBounds(map, bounds) { + var oldBounds = map.getBounds(); + + // ensure there is any change + if (oldBounds.toUrlValue() == bounds.toUrlValue()) { + return; + } + + disbaleNotifications = true; + google.maps.event.addListenerOnce(map, 'bounds_changed', function (event) { + // bugfix: this is a fix for the https://issuetracker.google.com/issues/35820423 + // the map does sometime zoom out if it gets its one bounds + + // var newSpan = map.getBounds().toSpan(); // the span of the map set by Google fitBounds (always larger by what we ask) + // var askedSpan = bounds.toSpan(); // the span of what we asked for + // var latRatio = (newSpan.lat() / askedSpan.lat()) - 1; // the % of increase on the latitude + // var lngRatio = (newSpan.lng() / askedSpan.lng()) - 1; // the % of increase on the longitude + // // if the % of increase is too big (> to a threshold) we zoom in + // if (Math.min(latRatio, lngRatio) > 0.46) { + // // 0.46 is the threshold value for zoming in. It has been established empirically by trying different values. + // this.setZoom(this.getZoom() + 1); + // } + disbaleNotifications = false; + onBoundsChanged(false); + + }); + map.fitBounds(bounds); // does the job asynchronously + } + } + }; + }]); + + mwtnTopologyApp.directive('mwtnTopologyMapSites', ['$compile', '$rootScope', function ($compile, $rootScope) { + + return { + restrict: 'E', + require: '^mwtnTopologyMap', + scope: { + sites: "=", + selectedSite: "=", + api: "=" + }, + link: function (scope, element, attrs, mwtnTopologyMapController) { + // todo: shouild come from a service + var normalIcon = { + path: google.maps.SymbolPath.CIRCLE, + scale: 10, + strokeColor: '#00ccff', + strokeOpacity: 0.8, + strokeWeight: 2, + fillColor: '#00ccff', + fillOpacity: 0.35, + zIndex: 2 + }; + + var highlightIcon = { + path: google.maps.SymbolPath.CIRCLE, + scale: 10, + strokeColor: '#eaae3c', + strokeOpacity: 0.8, + strokeWeight: 3, + fillColor: '#eaae3c', + fillOpacity: 0.65, + zIndex: 2 + }; + + var selectedIcon = { + path: google.maps.SymbolPath.CIRCLE, + scale: 10, + strokeColor: '#00FD30', + strokeOpacity: 0.8, + strokeWeight: 2, + fillColor: '#00FD30', + fillOpacity: 0.35, + zIndex: 2 + }; + + scope.displayedSites = {}; + scope.knownSites = {}; + + scope.$watch("selectedSite", function (newSiteId, oldSiteId) { + + if (oldSiteId && scope.displayedSites[oldSiteId]) { + scope.displayedSites[oldSiteId].setOptions({ + icon: normalIcon + }); + } + + if (newSiteId && scope.displayedSites[newSiteId]) { + scope.displayedSites[newSiteId].setOptions({ + icon: selectedIcon + }); + } + + }); + + if (!scope.api) return; + + /** + * Updates the google map markers + * @param addedSiteIds {string[]} The ids of the sites which are added to the scope.displayedSites dictionary. + * @param removedFromVisibleIds {string[]} The ids of sites which are removed from the visible bounding rectangle. + * @param movedFromVisibleToKnownIds {string[]} The ids of sites which are moved from the visible bounding rectangle to the extended bounding rectangle. + * @param removedFromKnownIds {string[]} The ids of sites which are removed from the extended bounding rectangle. + * @param movedFromKnownToVisibleIds {string[]} The ids of sites which are moved from the extended bounding rectangle to the visible bounding rectangle. + */ + scope.api.updateSites = function (addedSiteIds, removedFromVisibleIds, movedFromVisibleToKnownIds, removedFromKnownIds, movedFromKnownToVisibleIds) { + if (!addedSiteIds) addedSiteIds = []; + if (!removedFromVisibleIds) removedFromVisibleIds = []; + if (!movedFromVisibleToKnownIds) movedFromVisibleToKnownIds = []; + if (!removedFromKnownIds) removedFromKnownIds = []; + if (!movedFromKnownToVisibleIds) movedFromKnownToVisibleIds = []; + + removedFromVisibleIds.forEach(function (siteId) { + var marker = scope.displayedSites[siteId]; + if (marker) { + marker.setMap(null); + //delete marker; + delete scope.displayedSites[siteId]; + } + }); + + removedFromKnownIds.forEach(function (siteId) { + var marker = scope.knownSites[siteId]; + if (marker) { + marker.setMap(null); + //delete marker; + delete scope.knownSites[siteId]; + } + }); + + movedFromVisibleToKnownIds.forEach(function (siteId) { + var marker = scope.displayedSites[siteId]; + if (marker) { + marker.setVisible(false); + scope.knownSites[siteId] = marker; + delete scope.displayedSites[siteId]; + } + }); + + movedFromKnownToVisibleIds.forEach(function (siteId) { + var marker = scope.knownSites[siteId]; + if (marker) { + marker.setVisible(true); + scope.displayedSites[siteId] = marker; + delete scope.knownSites[siteId]; + } + }); + + addedSiteIds.forEach(function (newSiteId) { + var newSite = scope.sites[newSiteId]; + var newSiteNormalIcon = Object.assign({}, normalIcon, { + fillColor: (newSite.type === 'data-center') ? "#ffff00": "#00ccff", + strokeColor: (newSite.type === 'data-center') ? "#ffff00" : "#00ccff" + }); + var newSiteHighlightIcon = Object.assign({}, highlightIcon, { + fillColor: (newSite.type === 'data-center') ? "#ffff00": "#00ccff", + strokeColor: (newSite.type === 'data-center') ? "#ffff00" : "#00ccff" + }); + if (newSite && !scope.displayedSites[newSiteId]) { + + // create the marker + var marker = new google.maps.Marker({ + map: mwtnTopologyMapController.map, + position: newSite.location, + title: newSite.name, + icon: newSiteNormalIcon + }); + + // add event listeners to the marker + marker.addListener('click', function () { + // cloase all already opened windows + if (lastOpenedInfoWindow) { + lastOpenedInfoWindow.close(); + lastOpenedInfoWindow = null; + } + + // compile the content + var infoWindowTemplate = '<mwtn-topology-site-details site-id="siteId" />'; + var infoWindowScope = $rootScope.$new(); + infoWindowScope['siteId'] = newSiteId; + var infoWindowContent = $compile(infoWindowTemplate)(infoWindowScope)[0]; + + // create the info window + var infowindow = new google.maps.InfoWindow({ + content: infoWindowContent, + disableAutoPan: true + }); + + // open the window and keek a refenrece to close it if new window opens + infowindow.open(mwtnTopologyMapController.map, marker); + lastOpenedInfoWindow = infowindow; + + // remove the reference if the windows is closed + infowindow.addListener('closeclick', function () { + lastOpenedInfoWindow = null; + }); + }); + + marker.addListener('mouseover', function () { + marker.setOptions({ icon: newSiteHighlightIcon }); + }); + + marker.addListener('mouseout', function () { + marker.setOptions({ icon: newSiteNormalIcon }); + }); + + // store marker + scope.displayedSites[newSiteId] = marker; + } + }); + }; + + } + } + }]); + + mwtnTopologyApp.directive('mwtnTopologyMapSiteLinks', ['$compile', '$rootScope', function ($compile, $rootScope) { + return { + restrict: 'E', + require: '^mwtnTopologyMap', + scope: { + selectedSiteLink: "=", + siteLinks: "=", + api: "=" + }, + link: function (scope, element, attrs, mwtnTopologyMapController) { + + var normalColor = "#FF0000"; + var selectedColor = "#00FD30"; + + scope.$watch("selectedSiteLink", function (newSiteLinkId, oldSiteLinkId) { + + if (oldSiteLinkId && scope.displayedSiteLinks[oldSiteLinkId]) { + scope.displayedSiteLinks[oldSiteLinkId].setOptions({ + strokeColor: normalColor, + }); + } + + if (newSiteLinkId && scope.displayedSiteLinks[newSiteLinkId]) { + scope.displayedSiteLinks[newSiteLinkId].setOptions({ + strokeColor: selectedColor, + }); + } + + }); + + scope.displayedSiteLinks = {}; + + /** + * Updates the google map Polylines + * @param addedSiteLinkIds {string[]} The ids of sites links which are added to the scope.displayedSiteLinks dictionary and the google map. + * @param removedSiteLinkIds {string[]} The ids of sites links which are removed from the visible bounding rectangle within the google map. + */ + scope.api.updateSiteLinks = function (addedSiteLinkIds, removedSiteLinkIds) { + if (!addedSiteLinkIds) addedSiteLinkIds = []; + if (!removedSiteLinkIds) removedSiteLinkIds = []; + + removedSiteLinkIds.forEach(function (siteLinkId) { + var polyline = scope.displayedSiteLinks[siteLinkId]; + if (polyline) { + polyline.setMap(null); + //delete polyline; + delete scope.displayedSiteLinks[siteLinkId]; + } + }); + + addedSiteLinkIds.forEach(function (siteLinkId) { + var siteLink = scope.siteLinks[siteLinkId]; + console.log(siteLink); + + if (siteLink && !scope.displayedSiteLinks[siteLinkId]) { + + // create the poly line + var polyline = new google.maps.Polyline({ + map: mwtnTopologyMapController.map, + path: [siteLink.siteA.location, siteLink.siteZ.location], + strokeColor: siteLink.type === 'traffic' ? '#00ccff': '#ffff00', + strokeOpacity: 0.8, + strokeWeight: siteLink.type === 'traffic' ? 4 : 2, + zIndex: 1, + geodesic: true + }); + console.log(siteLink.type, polyline.strokeColor); + + // add event listeners to the polyline + polyline.addListener('click', function (event) { + // cloase all already opened windows + if (lastOpenedInfoWindow) { + lastOpenedInfoWindow.close(); + lastOpenedInfoWindow = null; + } + + // compile the content + var infoWindowTemplate = '<mwtn-topology-link-details link-id="linkId"></mwtn-topology-link-details>'; + var infoWindowScope = $rootScope.$new(); + infoWindowScope['linkId'] = siteLinkId; + var infoWindowContent = $compile(infoWindowTemplate)(infoWindowScope)[0]; + + // create the info window + var infowindow = new google.maps.InfoWindow({ + content: infoWindowContent, + disableAutoPan: true + }); + + // open the window and keek a refenrece to close it if new window opens + // adjust and show the info window + infowindow.setPosition(event.latLng); + infowindow.open(mwtnTopologyMapController.map); + lastOpenedInfoWindow = infowindow; + + // remove the reference if the windows is closed + infowindow.addListener('closeclick', function () { + lastOpenedInfoWindow = null; + }); + + }); + + polyline.addListener('mouseover', function () { + polyline.setOptions({ strokeWeight: 6 }); + }); + + polyline.addListener('mouseout', function () { + polyline.setOptions({ strokeWeight: 3 }); + }); + + // store the ployline + scope.displayedSiteLinks[siteLinkId] = polyline; + } + }); + }; + + } + }; + }]); + + mwtnTopologyApp.controller('mwtnTopologySiteDetailsController', ['$scope', '$timeout', '$mwtnTopology', function ($scope, $timeout, $mwtnTopology) { + var vm = this; + vm.site = null; + + $scope.$watch(function () { return vm.siteId }, function (newSiteId, oldSiteId) { + if (!newSiteId) return; + + vm.status = { + message: 'Searching...', + type: 'warning', + isWorking: true + }; + + $mwtnTopology.getSiteDetailsBySiteId(newSiteId).then(function (siteDetails) { + vm.site = siteDetails; + + vm.status = { + message: undefined, + type: 'success', + isWorking: false + }; + }, function (err) { + vm.status = { + message: err, + type: 'error', + isWorking: false + }; + }); + }); + + }]); + + mwtnTopologyApp.directive('mwtnTopologySiteDetails', function () { + return { + scope: { siteId: "=" }, + restrict: 'E', + controller: 'mwtnTopologySiteDetailsController', + controllerAs: 'vm', + bindToController: true, + templateUrl: 'src/app/mwtnTopology/templates/siteDetails.tpl.html' + }; + }); + + mwtnTopologyApp.controller('mwtnTopologyLinkDetailsController', ['$scope', '$timeout', '$mwtnTopology', function ($scope, $timeout, $mwtnTopology) { + /** @type {{ link: SiteLinkDetails } & {[key: string]: any}} */ + var vm = this; + vm.site = null; + vm.link = null; + + $scope.$watch(function () { return vm.linkId }, function (newLinkId, oldLinkId) { + if (!newLinkId) return; + + vm.status = { + message: 'Searching...', + type: 'warning', + isWorking: true + }; + + // getLinkDetailsByLinkId + $mwtnTopology.getLinkDetailsByLinkId(newLinkId).then( + /** @param {SiteLinkDetails} linkDetails*/ + function (linkDetails) { + vm.link = linkDetails; + + vm.status = { + message: undefined, + type: 'success', + isWorking: false + }; + }, function (err) { + vm.status = { + message: err, + type: 'error', + isWorking: false + }; + }); + }); + + }]); + + mwtnTopologyApp.directive('mwtnTopologyLinkDetails', function () { + return { + scope: { linkId: "=" }, + restrict: 'E', + controller: 'mwtnTopologyLinkDetailsController', + controllerAs: 'vm', + bindToController: true, + templateUrl: 'src/app/mwtnTopology/templates/linkDetails.tpl.html' + }; + }); + + mwtnTopologyApp.controller('mwtnTopologyFrameController', ['$scope', '$rootScope', '$timeout', '$state', '$window', '$mwtnTopology', function ($scope, $rootScope, $timeout, $state, $window, $mwtnTopology) { + var vm = this; + + $rootScope.section_logo = 'src/app/mwtnTopology/images/mwtnTopology.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + /** @type {{ [tabName: string] : { [parameterName : string] : any } }} */ + var tabParameters = {}; + + var tabs; + (function (tabs) { + tabs[tabs["site"] = 0] = "site"; + tabs[tabs["physical"] = 1] = "physical"; + tabs[tabs["ethernet"] = 2] = "ethernet"; + tabs[tabs["ieee1588"] = 3] = "ieee1588"; + })(tabs || (tabs = {})); + + $scope.$watch(function () { return vm.activeTab; }, function (newVal, oldVal, scope) { + if (newVal == null) return; + + var newName = tabs[newVal]; + + if (oldVal != null && tabs[oldVal]) { + var oldName = tabs[oldVal]; + tabParameters[oldName] = $state.params; + } + + var newParameters = Object.keys($state.params).reduce(function (acc, cur, ind, arr) { acc[cur] = null; return acc; }, {}); + Object.assign(newParameters, tabParameters[newName] || {}, { tab: newName, internal: false }); + + $state.go('main.mwtnTopology', newParameters, { notify: false }); + console.log("activeTab: ", newName); + }); + + $scope.$watch(function () { return $state.params.tab; }, function (newVal, oldVal, scope) { + if (newVal == oldVal) return; + if (newVal && !$state.params.internal) { + vm.activeTab = tabs[newVal || "site"]; + console.log("navigationTab: ", vm.activeTab); + } + }); + + // hide all tabs until the google api is fully loaded. + // initialize with true is the promise is resolved === 1 + vm.googleIsReady = $mwtnTopology.googleMapsApiPromise.$$state.status === 1; + + if (!vm.googleIsReady) $mwtnTopology.googleMapsApiPromise.then(function () { + $timeout(function () { + vm.googleIsReady = true; + }); + }); + + }]); + + mwtnTopologyApp.directive('mwtnTopologyFrame', function () { + return { + restrict: 'E', + controller: 'mwtnTopologyFrameController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnTopology/templates/frame.tpl.html' + }; + }); + + mwtnTopologyApp.controller('mwtnTopologySiteViewController', ['$scope', '$q', '$timeout', '$state', '$window', '$mwtnTopology', function ($scope, $q, $timeout, $state, $window, $mwtnTopology) { + var vm = this; + // Determines if a database request loop should be canceld. + var cancelRequested = false; + // Represents a defer which is resolved, if a cancel was requested and fulfilled. + var cancelDefer = $q.defer(); + // Represents the new bounding rectangle who was set with the last user action to change the map bounds. + // The value is saved until the cancel operation is fulfilled. + /** @type {{top: number, right: number, bottom: number, left: number, zoom: number}} */ + var waitForCancelMapBoundAndZoom; + // While getting all sites collect all site link ids which are available through visible and known sites. + // This dictionary will be cleared each time a new map bound is changed and a new database request loop is started. + var collectedSiteLinkIds = {}; + + vm.status = { + // Determines the bounds of the map which is manually set by the code. These are the initial values. + manualMapBounds: { + top: !Number.isNaN(+$state.params.top) ? +$state.params.top : undefined, + bottom: !Number.isNaN(+$state.params.bottom) ? +$state.params.bottom : undefined, + left: !Number.isNaN(+$state.params.left) ? +$state.params.left : undefined, + right: !Number.isNaN(+$state.params.right) ? +$state.params.right : undefined, + zoom: !Number.isNaN(+$state.params.zoom) ? +$state.params.zoom : undefined, + lat: !Number.isNaN(+$state.params.lat) ? +$state.params.lat : undefined, + lng: !Number.isNaN(+$state.params.lng) ? +$state.params.lng : undefined + }, + + // Determines if the accordeon group element for SiteMap, SiteGrid or SiteLinkGrid is open. + siteMapIsOpen: true, + siteGridIsOpen: true, + siteLinkGridIsOpen: true, + sitePathGridIsOpen: false, + + // Determines if a processing is running. + processing: false, + totalSitesInBoundingBox: 0, + loadedSitesInBoundingBox: 0, + maximumCountOfVisibleSites: 300, + + // selectet Elements + site: null, + siteLink: null, + sitePath: null + }; + + // Contains the known and visible sites as well as known site links as dictionaries. + vm.knownSites = {}; + vm.visibleSites = {}; + vm.knownSiteLinks = {}; + + // Api-Object that will be filled with update methods from the mwtnTopologyMapSites Component. + vm.mapSitesComponentApi = {}; + // Api-Object that will be filled with update methods from the mwtnTopologyMapSiteLinks Component. + vm.mapSiteLinksComponentApi = {}; + + //addedSiteLinkIds, removedSiteLinkIds + + initializeMapBounds(); + + function initializeMapBounds() { + + vm.status.manualMapBounds = { + top: !Number.isNaN(+$state.params.top) ? +$state.params.top : undefined, + bottom: !Number.isNaN(+$state.params.bottom) ? +$state.params.bottom : undefined, + left: !Number.isNaN(+$state.params.left) ? +$state.params.left : undefined, + right: !Number.isNaN(+$state.params.right) ? +$state.params.right : undefined, + zoom: !Number.isNaN(+$state.params.zoom) ? +$state.params.zoom : undefined, + lat: !Number.isNaN(+$state.params.lat) ? +$state.params.lat : undefined, + lng: !Number.isNaN(+$state.params.lng) ? +$state.params.lng : undefined + }; + + // Calculate the initial map control bound, if we have no initial bounds + if ((vm.status.manualMapBounds.top == null && vm.status.manualMapBounds.bottom == null && vm.status.manualMapBounds.right == null && vm.status.manualMapBounds.left == null && vm.status.manualMapBounds.lat == null && vm.status.manualMapBounds.lng == null && $state.params.site == null && $state.params.siteLink == null && $state.params.sitePath == null)) { + $mwtnTopology.getOuterBoundingRectangleForSites().then(function (bounds) { + // Ensures that the new value is set within a digest cycle. + vm.status.manualMapBounds = bounds; + }); + } + } + + $scope.$watch(function () { return $state.params.site; }, function (newVal, oldVal, scope) { + if (newVal) { + $mwtnTopology.getSiteDetailsBySiteId(newVal).then(function (siteDetails) { + if (siteDetails) { + // just update the location of the browser if the location has changed + $state.go('main.mwtnTopology', { + tab: "site", + lat: siteDetails.location.lat, + lng: siteDetails.location.lng, + zoom: 19, + top: null, + bottom: null, + right: null, + left: null, + site: $state.params.site, + siteLink: null, + sitePath: null, + internal: false + }, { + notify: false + }); + }; + }, function (err) { + + }); + } + }); + + $scope.$watch(function () { return $state.params.siteLink; }, function (newVal, oldVal, scope) { + if (newVal) { + $mwtnTopology.getLinkDetailsByLinkId(newVal).then(function (link) { + if (link) { + + var top = link.siteA.location.lat >= link.siteZ.location.lat ? link.siteA.location.lat : link.siteZ.location.lat; + var bottom = link.siteA.location.lat >= link.siteZ.location.lat ? link.siteZ.location.lat : link.siteA.location.lat; + + // todo: this code is not able to handle links which overlap the -100|180 ° borderline + var left = link.siteA.location.lng <= link.siteZ.location.lng ? link.siteA.location.lng : link.siteZ.location.lng; + var right = link.siteA.location.lng <= link.siteZ.location.lng ? link.siteZ.location.lng : link.siteA.location.lng; + // just update the location of the browser if the location has changed + $state.go('main.mwtnTopology', { + tab: "site", + lat: null, + lng: null, + zoom: $state.params.zoom, + top: top, + bottom: bottom, + right: right, + left: left, + site: null, + siteLink: $state.params.siteLink, + sitePath: null, + internal: false + }, { + notify: false + }); + }; + }, function (err) { + + }); + } + }); + + $scope.$watchCollection(function () { return [vm.status.siteMapIsOpen, vm.status.siteGridIsOpen, vm.status.siteLinkGridIsOpen, vm.status.sitePathGridIsOpen] }, function (newVal, oldVal) { + if (newVal[1] || newVal[2] || newVal[3]) { + $timeout(function () { + $window.dispatchEvent(new Event("resize")); + }); + } + }); + + $scope.$watchCollection(function () { return [+$state.params.top, +$state.params.bottom, +$state.params.left, +$state.params.right, +$state.params.lat, +$state.params.lng, +$state.params.zoom]; }, function (newVal, oldVal, scope) { + + if (oldVal == null || oldVal === newVal) return; // ignore initial value + + if (!vm.status.siteMapIsOpen) { + console.log("open Site Map") + vm.status.siteMapIsOpen = true; + return; + } + + vm.status.manualMapBounds = { + top: !Number.isNaN(newVal[0]) ? newVal[0] : undefined, + bottom: !Number.isNaN(newVal[1]) ? newVal[1] : undefined, + left: !Number.isNaN(newVal[2]) ? newVal[2] : undefined, + right: !Number.isNaN(newVal[3]) ? newVal[3] : undefined, + zoom: !Number.isNaN(newVal[6]) ? newVal[6] : undefined, + internal: !!$state.params.internal + }; + + if (!Number.isNaN(newVal[4]) && !Number.isNaN(newVal[5])) { + vm.status.manualMapBounds.lat = newVal[4]; + vm.status.manualMapBounds.lng = newVal[5]; + } else { + vm.status.manualMapBounds.lat = undefined; + vm.status.manualMapBounds.lng = undefined; + } + + if (!!$state.params.internal) $state.params.internal = false; + + }); + + $scope.$watchCollection(function () { return vm.status.siteMapIsOpen }, function (newVal, oldVal, scope) { + if (oldVal == newVal) return; // ignore initial value + if (newVal) { + // Map (re)-opend + initializeMapBounds(); + } else { + // Map closed + vm.status.loadedSitesInBoundingBox = 0; + vm.status.totalSitesInBoundingBox = 0; + vm.status.manualMapBounds = {}; + vm.knownSites = {}; + vm.visibleSites = {}; + vm.knownSiteLinks = {}; + }; + // tell all sub components the visuability of the map view + $scope.$broadcast('mapViewVisuability', newVal); + }); + + /* callback and helper methods */ + /** + * A callback function which is called by the map control of the user changed the bounds of the map. + * @param mapBoundsAndZoom {{top: number, right: number, bottom: number, left: number, zoom: number}} The new bounds and the new zoom level of the map control. + */ + vm.mapBoundsChanged = function (mapBoundsAndZoom, userOriginated) { + + // just update the location of the browser if the location has changed + $state.go('main.mwtnTopology', { + tab: "site", + lat: mapBoundsAndZoom.lat, + lng: mapBoundsAndZoom.lng, + zoom: mapBoundsAndZoom.zoom, + top: null, + bottom: null, + right: null, + left: null, + site: !userOriginated ? $state.params.site : null, + siteLink: !userOriginated ? $state.params.siteLink : null, + sitePath: !userOriginated ? $state.params.sitePath : null, + internal: true + }, { + notify: false + }); + console.log("handleBoundsChanged", mapBoundsAndZoom); + + if (vm.status.siteMapIsOpen) refreshAllSites(mapBoundsAndZoom); + }; + + /** + * Refreshes all visible elements in the given view port + * @param mapBoundsAndZoom {{top: number, right: number, bottom: number, left: number, zoom: number}} The new bounds and the new zoom level of the map control. + */ + function refreshAllSites(mapBoundsAndZoom) { + + // Datenbankabfragen werden werden in kleine Chunks zerlegt. + // Jeder Chunk enthält maximal ${chunkSize} (100) Sites und die Anzahl aller Sites für die spezifische Abfrage in der Antwort. + // Sind noch nicht alle Chunks von der Datenbank angefordert worden, wird zuerst der nächste Chunk angefordert. + // Der aktuell zurückgegebene Chunk wird aber erst verarbeitet, bevor in einer weiteren Callback-Situation der nächste Datenbank-Chunk abgeholt wird. + // Dadurch werden kontinuierlich alle Sites auch auf der Map ergänzt, sobald sie verarbeitet wurden und es kommt zu keiner Verzögerung im Benutzerinterface. + // Im Maximum werden aber ${vm.status.maximumCountOfVisibleSites} (2500) Sites abgerufen, um die Google Map nicht zu überlasten. + + // Fallunterscheidung: gibt es bereits eine aktive Datenbankabfrage zu den Sites? + // => Nein: Starte eine neue Datenbankabfrage + // => Ja: Breche die aktuelle Verarbeitung ab, aktualisiere den Status und starte dann eine neue Datenbankabfrage. + if (vm.status.processing) { + waitForCancelMapBoundAndZoom = mapBoundsAndZoom; + + if (cancelRequested) { + console.log("Cancel is already requested."); + return; + } + + // Request a database loop cancel. + cancelRequested = true; + console.log("New Cancel requested.") + + // Wait until the current database loos was canceled. + cancelDefer.promise.then(function () { + // The database loop is canceled. Create a new defer for the next possible cancel request. + console.log("Cancel fulfilled."); + cancelDefer = $q.defer(); + // Restart the database loop with the new bounding rectangle. + beginProcessing(waitForCancelMapBoundAndZoom); + }); + + // Do not start a database loop here - so leave the method. + return; + } + + // Start a new database loop here. + beginProcessing(mapBoundsAndZoom); + + /** + * The private function which begins a new database processing loop. + * @param mapBoundsAndZoom {{top: number, right: number, bottom: number, left: number, zoom: number}} The new bounds and the new zoom level of the map control. + */ + function beginProcessing(mapBoundsAndZoom) { + // Set the processing flag to true. + vm.status.processing = true; + + var chunkSize = 100; + var chunkSiteStartIndex = 0; + + // If a site link cannot convert its siteA or siteZ (id) Parameter to a real site object these ids will collected. + // After a subsequent database call to get these sites the queued site links will be converted. + var additionalSiteIds = []; + var queuedSiteLinksToConvert = []; + + // Entferne Sites, welche aufgrund des neuen Bounds leicht außer Sicht sind von den sichtbaren Sites. + // Hinzufügen von Sites aus den leicht außer Sicht Bereich zum sichtbaren Bereich. + var movedOrRemovedSites = refreshOutOfSightSites(mapBoundsAndZoom); + var removedFromVisibleIds = movedOrRemovedSites.removedFromVisibleIds; + var movedFromVisibleToKnownIds = movedOrRemovedSites.movedFromVisibleToKnownIds; + var removedFromKnownIds = movedOrRemovedSites.removedFromKnownIds; + var movedFromKnownToVisibleIds = movedOrRemovedSites.movedFromKnownToVisibleIds; + var removedSiteLinkIds = movedOrRemovedSites.removedSiteLinkIds; + + // While getting all sites collect all site link ids which are available through visible and known sites. + collectedSiteLinkIds = {}; + + doSiteRequestLoop(); + + /* internal function within beginProcessing */ + /** + * Starts a new database request loop to get all sites. + */ + function doSiteRequestLoop() { + requestNextSiteChunk(mapBoundsAndZoom, chunkSize, chunkSiteStartIndex).then( + /** + * @param result {{addedSiteIds: string[], total: number}} An array with the ids of the sites which are added to the vm.visibleSites dictionary. + */ + function (result) { + // update the frontend before continue with the next database request. + vm.mapSitesComponentApi.updateSites && vm.mapSitesComponentApi.updateSites(result.addedSiteIds, removedFromVisibleIds, movedFromVisibleToKnownIds, removedFromKnownIds, movedFromKnownToVisibleIds); + removedSiteLinkIds && removedSiteLinkIds.length && vm.mapSiteLinksComponentApi.updateSiteLinks && vm.mapSiteLinksComponentApi.updateSiteLinks([], removedSiteLinkIds); + // to not re-remove and re-move already removed and moved sites clear the arrays for any subsequent database requests. + removedFromVisibleIds = []; + movedFromVisibleToKnownIds = []; + removedFromKnownIds = []; + movedFromKnownToVisibleIds = []; + removedSiteLinkIds = []; + + if (cancelRequested) { + // reset the cancelRequested flag and resolve the cancel request. + cancelRequested = false; + cancelDefer.resolve(); + return; + } + + // Enforce angular to process a new digest cycle. + $timeout(function () { + vm.status.totalSitesInBoundingBox = result.total; + vm.status.loadedSitesInBoundingBox = Math.min(chunkSiteStartIndex + chunkSize, result.total); + if (chunkSiteStartIndex + chunkSize >= result.total || chunkSiteStartIndex + chunkSize >= vm.status.maximumCountOfVisibleSites) { + // This was the last database request to get sites. + // Remove all known site link ids from the collectedSiteLinkIds dictionary. + var knownSiteLinkIds = Object.keys(vm.knownSiteLinks); + knownSiteLinkIds.forEach(function (knownSiteLinkId) { + if (collectedSiteLinkIds[knownSiteLinkId]) { + delete collectedSiteLinkIds[knownSiteLinkId]; + } + }); + + // Start the request loop for site links now. + doSiteLinkRequestLoop(Object.keys(collectedSiteLinkIds)); + } else { + // There are more data, request the database again. + chunkSiteStartIndex += chunkSize; + + doSiteRequestLoop(); + } + }); + + }, processError); + } + + function endProcessing() { + vm.status.processing = false; + + $timeout(function () { + vm.status.site = $state.params.site; + vm.status.siteLink = $state.params.siteLink; + }); + } + + /** + * Starts a new database request loop to get all site links. + */ + function doSiteLinkRequestLoop(siteLinkIds) { + var requestedSiteLinkIds = siteLinkIds.splice(0, chunkSize); + + $mwtnTopology.getSiteLinksByIds(requestedSiteLinkIds).then( + /** + * Processes the database result. + * The returned site links doesn't contain site objects but site ids. + * In a subsequent step these ids will be converted into real site objects. + * @param result {{id: string, siteA: string, siteZ: string}[]} The database result. + */ + function (result) { + // Subsequent convert. + // All site links which siteA and siteZ site ids are known could be added to vm.knownSiteLinks. + // The rest has to saved until all requests are finished. + // Another database call will get the additional sites to convert these site links. + var addedSiteLinkIds = result.reduce(function (accumulator, currentSiteLink) { + var siteA = vm.visibleSites[currentSiteLink.siteA] || vm.knownSites[currentSiteLink.siteA]; + var siteZ = vm.visibleSites[currentSiteLink.siteZ] || vm.knownSites[currentSiteLink.siteZ]; + if (siteA && siteZ) { + vm.knownSiteLinks[currentSiteLink.id] = { + id: currentSiteLink.id, + siteA: siteA, + siteZ: siteZ, + type: currentSiteLink.type + }; + accumulator.push(currentSiteLink.id); + } else { + // Theoretically, only siteA or siteZ can be unknown. I still check both separately. + var isPushed = false; + if (!siteA) { + additionalSiteIds.push(currentSiteLink.siteA); + queuedSiteLinksToConvert.push(currentSiteLink); + isPushed = true; + } + if (!siteZ) { + additionalSiteIds.push(currentSiteLink.siteZ); + isPushed || queuedSiteLinksToConvert.push(currentSiteLink); + } + } + return accumulator; + }, []); + + // update the frontend before continue with the next database request. + vm.mapSiteLinksComponentApi.updateSiteLinks && vm.mapSiteLinksComponentApi.updateSiteLinks(addedSiteLinkIds); + + if (cancelRequested) { + // reset the cancelRequested flag and resolve the cancel request. + cancelRequested = false; + cancelDefer.resolve(); + return; + } + + // Enforce angular to process a new digest cycle. (And to let angular time to redraw the map.) + $timeout(function () { + if (siteLinkIds.length === 0) { + if (additionalSiteIds.length === 0) { + endProcessing(); + return; + } + + // Only get a maximum of chunkSize additional sites. + // Site links more than that will not be drawed in the map due to performance reasons. + // If the user zooms in the additional site links will be requested again. + $mwtnTopology.getSitesByIds(additionalSiteIds.splice(0, chunkSize)).then( + /** + * Processes the database result to gain new sites within the bounding box of the database request. + * @param result {{total: number, sites: {id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]}}[]}} The database result. + */ + function (result) { + var addedSiteLinkIds = queuedSiteLinksToConvert.reduce(function (accumulator, currentSiteLink) { + var siteA = vm.visibleSites[currentSiteLink.siteA] || vm.knownSites[currentSiteLink.siteA] || result.sites.find( + function (site) { + return site.id === currentSiteLink.siteA + }); + var siteZ = vm.visibleSites[currentSiteLink.siteZ] || vm.knownSites[currentSiteLink.siteZ] || result.sites.find( + function (site) { + return site.id === currentSiteLink.siteZ + }); + if (siteA && siteZ) { + vm.knownSiteLinks[currentSiteLink.id] = { + id: currentSiteLink.id, + siteA: siteA, + siteZ: siteZ, + type: currentSiteLink.type + }; + accumulator.push(currentSiteLink.id); + } + return accumulator; + }, []); + // update the frontend the last time until the user changed the map position. + vm.mapSiteLinksComponentApi.updateSiteLinks && vm.mapSiteLinksComponentApi.updateSiteLinks(addedSiteLinkIds); + + // all done - puh. + endProcessing(); + }, processError); + + } else { + // There are more data, request the database again. + doSiteLinkRequestLoop(siteLinkIds); + } + }); + + }, processError); + } + + } + }; + + /** + * Recalculates the targets site container for Sites within knownSites and visibleSites. + * @param mapBoundsAndZoom {{top: number, right: number, bottom: number, left: number, zoom: number}} The new bounds and the new zoom level of the map control. + */ + function refreshOutOfSightSites(mapBoundsAndZoom) { + var additionalWidth = (mapBoundsAndZoom.right - mapBoundsAndZoom.left) / 4; + var additionalHeight = (mapBoundsAndZoom.top - mapBoundsAndZoom.bottom) / 4; + var slightlyTop = mapBoundsAndZoom.top + additionalHeight; + var slightlyRight = mapBoundsAndZoom.right + additionalWidth; + var slightlyBottom = mapBoundsAndZoom.bottom - additionalHeight; + var slightlyLeft = mapBoundsAndZoom.left - additionalWidth; + + var removedFromVisibleIds = []; + var movedFromVisibleToKnownIds = []; + var removedFromKnownIds = []; + var movedFromKnownToVisibleIds = []; + var removedSiteLinkIds = []; + + var visibleSiteKeys = Object.keys(vm.visibleSites); + var knownSiteKeys = Object.keys(vm.knownSites); + var knownSiteLinkKeys = Object.keys(vm.knownSiteLinks); + + visibleSiteKeys.forEach(function (siteId) { + /** @var {{id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]}} site */ + var site = vm.visibleSites[siteId]; + + if (site.location.lat > slightlyTop || site.location.lng > slightlyRight || site.location.lat < slightlyBottom || site.location.lng < slightlyLeft) { + // This site is completly out of sight - so remove it and add the id to the removedFromVisibleIds list. + delete vm.visibleSites[siteId]; + removedFromVisibleIds.push(siteId); + return; + } + + if (site.location.lat > mapBoundsAndZoom.top || site.location.lng > mapBoundsAndZoom.right || site.location.lat < mapBoundsAndZoom.bottom || site.location.lng < mapBoundsAndZoom.left) { + // This site is moved from the visible map bounds to the extended map bounds and will only hide but stay in the google object. + vm.knownSites[siteId] = site; + delete vm.visibleSites[siteId]; + movedFromVisibleToKnownIds.push(siteId); + return; + } + }); + + knownSiteKeys.forEach(function (siteId) { + /** @type {{id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]}} site */ + var site = vm.knownSites[siteId]; + + if (site.location.lat > slightlyTop || site.location.lng > slightlyRight || site.location.lat < slightlyBottom || site.location.lng < slightlyLeft) { + // This site is completly out of sight - so remove it and add the id to the removedFromKnownIds list. + delete vm.knownSites[siteId]; + removedFromKnownIds.push(siteId); + return; + } + + if (site.location.lat <= mapBoundsAndZoom.top && site.location.lng <= mapBoundsAndZoom.right && site.location.lat >= mapBoundsAndZoom.bottom && site.location.lng >= mapBoundsAndZoom.left) { + // This site is moved from the extended map bounds to the visible map bounds. Therefore the hidden google maps object should set visible again. + vm.visibleSites[siteId] = site; + delete vm.knownSites[siteId]; + movedFromKnownToVisibleIds.push(siteId); + return; + } + }); + + knownSiteLinkKeys.forEach(function (siteLinkId) { + /** @type {{id: string, siteA: {id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]}}, siteZ: {id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]}}}} siteLink */ + var siteLink = vm.knownSiteLinks[siteLinkId]; + var siteA = siteLink.siteA; + var siteZ = siteLink.siteZ; + + if ((siteA.location.lat > slightlyTop || siteA.location.lng > slightlyRight || siteA.location.lat < slightlyBottom || siteA.location.lng < slightlyLeft) && + (siteZ.location.lat > slightlyTop || siteZ.location.lng > slightlyRight || siteZ.location.lat < slightlyBottom || siteZ.location.lng < slightlyLeft)) { + // This site link is completly out of sight - so remove it and add the id to the removedSiteLinkIds list. + delete vm.knownSiteLinks[siteLinkId]; + removedSiteLinkIds.push(siteLinkId); + } + }); + + return { + removedFromVisibleIds: removedFromVisibleIds, + movedFromVisibleToKnownIds: movedFromVisibleToKnownIds, + removedFromKnownIds: removedFromKnownIds, + movedFromKnownToVisibleIds: movedFromKnownToVisibleIds, + removedSiteLinkIds: removedSiteLinkIds + }; + } + + /** + * Requests a chunk of sites from the database. + * @param mapBoundsAndZoom {{top: number, right: number, bottom: number, left: number, zoom: number}} The bounds and the zoom level of the map control to request the next chunk for. + * @param chunkSize {number} The chunk size of a single database request. To big values will block the user interface, to small values will lead in to many database requests. + * @param chunkSiteStartIndex {number} The index of the first site returned by the database. + */ + function requestNextSiteChunk(mapBoundsAndZoom, chunkSize, chunkSiteStartIndex) { + var requestNextSiteChunkDefer = $q.defer(); + var addedSiteIds = []; + + // Request the next chunk. + $mwtnTopology.getSitesInBoundingBox(mapBoundsAndZoom, chunkSize, chunkSiteStartIndex).then( + /** + * Processes the database result to gain new sites within the bounding box of the database request. + * @param result {{chunkSize: number, chunkSiteStartIndex: number, total: number, sites: {id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]}}[]}} The database result. + */ + function (result) { + result.sites.forEach(function (site) { + // The map bounds may have changed since the start of the database request. + // Therefore check if the site is within the bounding rectangle. + + if (!$mwtnTopology.isInBounds(mapBoundsAndZoom, site.location)) { + return; + } + + // add all site link ids to the selectedSiteLinkIds dictionary. + site.references.siteLinks.forEach(function (siteLinkId) { + collectedSiteLinkIds[siteLinkId] = true; + }); + + // check, if the site is within the knownSites dictionary. + if (vm.knownSites[site.id]) { + delete vm.knownSites[site.id]; + } + + // check if the site is within the visibleSites dictionary. + if (vm.visibleSites[site.id]) { + // Override the site (refresh) + vm.visibleSites[site.id] = site; + } else { + // Add the site to the dictionary and remember the siteId. + vm.visibleSites[site.id] = site; + addedSiteIds.push(site.id); + } + }); + + requestNextSiteChunkDefer.resolve({ + addedSiteIds: addedSiteIds, + total: result.total + }); + }, requestNextSiteChunkDefer.reject); + + return requestNextSiteChunkDefer.promise; + } + + /** + * Handles error messages by writing the information to the javascript console. + * Resets the processing flag. + * @param error Information about the error. + */ + function processError(error) { + // Reset the processing flag. + vm.status.processing = false; + // Write the error information to the console. + console.error(error); + } + + }]); + + mwtnTopologyApp.directive('mwtnTopologySiteView', function () { + return { + restrict: 'E', + controller: 'mwtnTopologySiteViewController', + controllerAs: 'vm', + bindToController: true, + templateUrl: 'src/app/mwtnTopology/templates/siteView.tpl.html', + scope: { + initialMapBounds: "=" + } + }; + }); + + mwtnTopologyApp.controller('mwtnTopologySiteGridController', ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + var sitesAtCurrentPageCache = {}; + + vm.showAllSites = false; + + vm.onNavigateToSite = function (row) { + var site = sitesAtCurrentPageCache[row.entity.id]; + $state.go("main.mwtnTopology", { + tab: "site", + lat: site.location.lat, + lng: site.location.lng, + zoom: 19, + site: site.id, + internal: false + }, { notify: false }); + }; + + // see http://ui-grid.info/docs/#/tutorial/317_custom_templates + var buttonCellTemplate = '<div class="ui-grid-cell-contents tooltip-uigrid" title="TOOLTIP"><i ng-click="grid.appScope.vm.onNavigateToSite(row)" ng-class="{\'fa\':true, \'fa-map-marker\': true, \'{{COL_FIELD}}\':true}" aria-hidden="true"></i></div>'; + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id" + }, + { + field: "name", + type: "string", + displayName: "Name" + }, + { + field: "location", + type: "string", + displayName: "Location" + }, + { + field: "amslGround", + type: "string", + displayName: "AmslGround" + }, + { + field: "countLinks", + type: "number", + displayName: "Count (Links)" + }, + { + field: "countNetworkElements", + type: "number", + displayName: "Count (Network elements)" + }, + { + field: "buttons", + type: "string", + displayName: "", + width: 40, + enableFiltering: false, + enableSorting: false, + cellTemplate: buttonCellTemplate, + pinnedRight: true + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) + ? null + : sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ field: col.field, term: col.filters[0].term }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + $scope.$on("mapViewVisuability", function (event, data) { + vm.showAllSites = !data; + }); + + $scope.$watch("visibleSites", function (newVisibleSites, oldVisibleSites) { + console.log("watch: visibleSites"); + if (!vm.showAllSites) loadPage(); + }, true); // deep watch, maybe find a better solution; e.g. with an api object like the site in the map. + + $scope.$watch(function () { return vm.showAllSites; }, loadPage); + + function loadPage() { + if (vm.showAllSites) { + loadRemotePage(); + } else { + loadLocalPage(); + } + } + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadLocalPage() { + var siteIds = Object.keys($scope.visibleSites); + + var tempData = siteIds.filter(function (siteId, ind, arr) { + var site = $scope.visibleSites[siteId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + case "countLinks": + return (site.references.siteLinks ? site.references.siteLinks.length : 0) == +filter.term; + default: + return site[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (siteId) { + var site = $scope.visibleSites[siteId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: siteId + } + } + + switch (sortColumn.field) { + case "countLinks": + orderBy = site.references.siteLinks ? site.references.siteLinks.length : 0; + break; + case "countNetworkElements": + orderBy = site.references.networkElements ? site.references.networkElements.length : 0; + break; + case "buttons": + orderBy = siteId; + break; + default: + orderBy = site[sortColumn.field]; + break; + } + + return { + id: siteId, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedSitesAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + sitesAtCurrentPageCache = {}; + var orderedData = []; + + orderedSitesAtCurrentPage.forEach(function (orderedSite) { + var site = $scope.visibleSites[orderedSite.id]; + sitesAtCurrentPageCache[site.id] = site; + orderedData.push({ + id: orderedSite.id, + name: site.name, + location: site.location.lat.toLocaleString("en-US", { + minimumFractionDigits: 4 + }) + ", " + site.location.lng.toLocaleString("en-US", { + minimumFractionDigits: 4 + }), + amslGround: site.amslGround, + countLinks: site.references.siteLinks ? site.references.siteLinks.length : 0, + countNetworkElements: site.references.networkElements ? site.references.networkElements.length : 0 + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + /** + * Loads the page content for the grid and sets the values to the gridOprions.data object. + */ + function loadRemotePage() { + + $mwtnTopology.getSites((sortColumn && sortColumn.field), sortColumn && ((sortColumn.sort.direction && sortColumn.sort.direction === uiGridConstants.ASC) ? 'asc' : 'desc'), gridFilters, paginationPageSize, (paginationPage - 1) * paginationPageSize).then(function (result) { + sitesAtCurrentPageCache = result.sites.reduce(function (acc, cur, ind, arr) { + acc[cur.id] = cur; + return acc; + }, {}); + vm.gridOptions.data = result.sites.map(function (site) { + return { + id: site.id, + name: site.name, + location: site.location.lat.toLocaleString("en-US", { + minimumFractionDigits: 4 + }) + ", " + site.location.lng.toLocaleString("en-US", { + minimumFractionDigits: 4 + }), + amslGround: site.amslGround, + countLinks: site.references.siteLinks ? site.references.siteLinks.length : 0, + countNetworkElements: site.references.networkElements ? site.references.networkElements.length : 0 + } + }); + vm.gridOptions.totalItems = result.total; + }); + } + }]); + + mwtnTopologyApp.directive('mwtnTopologySiteGrid', function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologySiteGridController', + controllerAs: 'vm', + scope: { + visibleSites: "=" + }, + templateUrl: 'src/app/mwtnTopology/templates/siteGrid.tpl.html' + }; + }); + + mwtnTopologyApp.controller('mwtnTopologySiteLinkGridController', ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + + var linksAtCurrentPageCache = {}; + + vm.showAllLinks = false; + + vm.onNavigateToLink = function (row) { + var link = linksAtCurrentPageCache[row.entity.id]; + + var top = link.siteA.location.lat >= link.siteZ.location.lat ? link.siteA.location.lat : link.siteZ.location.lat; + var bottom = link.siteA.location.lat >= link.siteZ.location.lat ? link.siteZ.location.lat : link.siteA.location.lat; + + // todo: this code is not able to handle links which overlap the -100|180 ° borderline + var left = link.siteA.location.lng <= link.siteZ.location.lng ? link.siteA.location.lng : link.siteZ.location.lng; + var right = link.siteA.location.lng <= link.siteZ.location.lng ? link.siteZ.location.lng : link.siteA.location.lng; + + $state.go("main.mwtnTopology", { + tab: "site", + top: top, + bottom: bottom, + left: left, + right: right, + siteLink: link.id, + internal: false + }, { notify: false }); + console.log(link); + }; + + // see http://ui-grid.info/docs/#/tutorial/317_custom_templates + var buttonCellTemplate = '<div class="ui-grid-cell-contents tooltip-uigrid" title="TOOLTIP"><i ng-click="grid.appScope.vm.onNavigateToLink(row)" ng-class="{\'fa\':true, \'fa-map-marker\': true, \'{{COL_FIELD}}\':true}" aria-hidden="true"></i></div>'; + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + // enableFiltering: false, + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id" + }, + { + field: "name", + type: "string", + displayName: "Name" + }, + { + field: "siteIdA", + type: "string", + displayName: "SiteA" + }, + { + field: "siteIdZ", + type: "string", + displayName: "SiteZ" + }, + { + field: "buttons", + type: "string", + displayName: "", + width: 40, + enableFiltering: false, + enableSorting: false, + cellTemplate: buttonCellTemplate, + pinnedRight: true + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ field: col.field, term: col.filters[0].term }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + $scope.$on("mapViewVisuability", function (event, data) { + vm.showAllLinks = !data; + }); + + $scope.$watch("knownSiteLinks", function (newKnownSiteLinks, oldKnownSiteLinks) { + console.log("watch: knownSiteLinks"); + loadPage(); + }, true); // deep watch, maybe find a better solution; e.g. with an api object like the site in the map. + + $scope.$watch(function () { return vm.showAllLinks; }, loadPage); + + function loadPage() { + if (vm.showAllLinks) { + loadRemotePage(); + } else { + loadLocalPage(); + } + } + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadLocalPage() { + var linkIds = Object.keys($scope.knownSiteLinks); + + var tempData = linkIds.filter(function (linkId, ind, arr) { + var link = $scope.knownSiteLinks[linkId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + case 'siteIdA': + return link.siteA.id.contains(filter.term); + case 'siteIdZ': + return link.siteZ.id.contains(filter.term); + default: + return link[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (linkId) { + var link = $scope.knownSiteLinks[linkId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: linkId + } + } + + switch (sortColumn.field) { + case 'siteIdA': + orderBy = link.siteA.id; + break; + case 'siteIdZ': + orderBy = link.siteZ.id; + break; + default: + orderBy = link[sortColumn.field]; + break; + } + + return { + id: linkId, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedSitesAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + linksAtCurrentPageCache = {}; + var orderedData = []; + + orderedSitesAtCurrentPage.forEach(function (orderdLink) { + var link = $scope.knownSiteLinks[orderdLink.id]; + linksAtCurrentPageCache[link.id] = link; + orderedData.push({ + id: link.id, + name: link.name, + siteIdA: link.siteA.id, + siteIdZ: link.siteZ.id, + type: link.type + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + /** + * Loads the page content for the grid and sets the values to the gridOprions.data object. + */ + function loadRemotePage() { + linksAtCurrentPageCache = {}; + + // the links for one page + $mwtnTopology.getLinks((sortColumn && sortColumn.field), sortColumn && ((sortColumn.sort.direction && sortColumn.sort.direction === uiGridConstants.ASC) ? 'asc' : 'desc'), gridFilters, paginationPageSize, (paginationPage - 1) * paginationPageSize).then(function (result) { + // get all site id s + var siteIds = {}; + result.links.forEach(function (link) { + siteIds[link.siteA] = link.siteA; + siteIds[link.siteZ] = link.siteZ; + }); + + // load all sites + $mwtnTopology.getSitesByIds(Object.keys(siteIds)).then(function (sitesResult) { + var sites = sitesResult.sites.reduce(function (acc, cur, ind, arr) { + acc[cur.id] = cur; + return acc; + }, {}); + result.links.forEach(function (link) { + linksAtCurrentPageCache[link.id] = { + id: link.id, + name: link.name, + siteA: sites[link.siteA], + siteZ: sites[link.siteZ], + type: link.type + }; + }); + vm.gridOptions.data = result.links.map(function (link) { + return { + id: link.id, + name: link.name, + siteIdA: link.siteA, + siteIdZ: link.siteZ, + type: link.type + } + }); + vm.gridOptions.totalItems = result.total; + + }); + }); + } + + + }]); + + mwtnTopologyApp.directive('mwtnTopologySiteLinkGrid', function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologySiteLinkGridController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnTopology/templates/siteLinkGrid.tpl.html', + scope: { + knownSiteLinks: "=" + }, + }; + }); + + mwtnTopologyApp.controller('mwtnTopologySitePathGridController', ['$scope', function ($scope) { + var vm = this; + + vm.showAllPaths = false; + + $scope.$on("mapViewVisuability", function (event, data) { + vm.showAllPaths = !data; + }); + + }]); + + mwtnTopologyApp.directive('mwtnTopologySitePathGrid', function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologySitePathGridController', + controllerAs: 'vm', + templateUrl: 'src/app/mwtnTopology/templates/sitePathGrid.tpl.html' + }; + }); + + /********************************************* Physical ***********************************/ + + mwtnTopologyApp.controller('mwtnTopologyPhysicalViewController', ['$scope', '$q', '$timeout', '$state', '$window', '$mwtnTopology', function ($scope, $q, $timeout, $state, $window, $mwtnTopology) { + var vm = this; + vm.status = { + graphIsOpen: false, + networkElementsIsOpen: false, + LinksIsOpen: false + }; + + $scope.$watchCollection(function () { return [vm.status.graphIsOpen, vm.status.networkElementsIsOpen, vm.status.LinksIsOpen] }, function (newVal, oldVal) { + if (newVal[1] || newVal[2]) { + $timeout(function () { + $window.dispatchEvent(new Event("resize")); + }); + } + }); + + }]); + + mwtnTopologyApp.directive('mwtnTopologyPhysicalView', function () { + return { + restrict: 'E', + controller: 'mwtnTopologyPhysicalViewController', + controllerAs: 'vm', + bindToController: true, + templateUrl: 'src/app/mwtnTopology/templates/physicalView.tpl.html', + scope: { + + } + }; + }); + + /** + * Typedefinitions for the mwtnTopologyPhysicalPathData service. + * @typedef { { 'site' | 'device' | 'port' } } NodeLayerType + * @typedef { { x: number, y: number } } PositionType + * @typedef { { id: string, label: string, parent: string, grentparent: string, active: string, latitude: number, longitude: number } } NodeDataVo + * @typedef { { data: NodeDataVo, position: PositionType } } NodeVo + * @typedef { { id: string, label: string, parent: string, type: string, layer: NodeLayerType, active: boolean, latitude?: number, longitude?: number } } NodeData + * @typedef { { data: NodeData, position: PositionType } } Node + * @typedef { { id: string, source: string, target: string, label: string , lentgh: string, azimuthAZ: string , azimuthZA: string , layer: string , active: string } } EdgeData + * @typedef { { data: EdgeData } Edge + */ + mwtnTopologyApp.factory("mwtnTopologyPhysicalPathData", ['$q','$mwtnTopology', + /** @param $q { ng.IQService } */ + function ($q, $mwtnTopology) { + var colors = { + root: '#f54', + port: '#377', + device: '#252', + site: '#525', + edge: '#49a', + white: '#eed', + grey: '#555', + selected: '#ff0' + }; + + var styles = [ + { + selector: 'node', + css: { + 'content': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#666666', + 'border-color': '#000000', + 'border-width': '1px', + 'color': '#ffffff' + } + }, + { + selector: 'node[layer = "MWPS"]', + css: { + 'content': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#316ac5', + 'border-color': '#000000', + 'border-width': '1px', + 'color': '#ffffff' + } + }, + { + selector: '$node > node', + css: { + 'shape': 'roundrectangle', + 'padding-top': '10px', + 'padding-left': '10px', + 'padding-bottom': '10px', + 'padding-right': '10px', + 'text-valign': 'top', + 'text-halign': 'center', + 'background-color': '#eeeeee', + 'color': '#444444', + 'border-color': '#888888' + } + }, + { + selector: 'node[type = "site"]', + css: { + 'shape': 'roundrectangle', + 'padding-top': '10px', + 'padding-left': '10px', + 'padding-bottom': '10px', + 'padding-right': '10px', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#fefefe', + 'color': '#444444', + 'border-color': '#888888', + 'font-weight': 'bold' + } + }, + { + selector: 'node[type = "device"][active = "true"]', + css: { + 'background-color': '#316ac5', + 'background-opacity': '0.3', + 'border-color': '#316ac5', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: 'node[type = "port"][active = "true"]', + css: { + 'background-opacity': '1.0', + } + }, + { + selector: 'node[active = "false"]', + css: { + 'background-opacity': '0.3', + 'border-opacity': '0.5' + } + }, + + { + selector: 'edge', + css: { + 'content': 'data(id)', + 'target-arrow-shape': 'triangle', + 'line-color': '#666666', + 'color': '#444444' + } + }, + { + selector: 'edge[active = "false"]', + css: { + 'line-color': '#cccccc', + 'text-opacity': '0.9' + } + }, + { + selector: 'edge[layer = "MWPS"]', + css: { + 'content': 'data(id)', + 'target-arrow-shape': 'triangle', + 'width': '5px', + 'line-color': '#316ac5', + 'color': '#444444' + } + }, + { + selector: 'edge[layer = "MWPS"][active = "false"]', + css: { + 'line-color': '#C0D1EC', + 'text-opacity': '0.9' + } + }, + { + selector: ':selected', + css: { + 'background-color': 'black', + 'line-color': 'black', + 'target-arrow-color': 'black', + 'source-arrow-color': 'black' + } + } + ]; + + var events = eventsFabric(); + + /** Heplerfunction to retrive all elements from the database and convert to the structure needed */ + function getElements() { + var res = $q.defer(); + + $q.all([ + $mwtnTopology.getAllNodes(), + $mwtnTopology.getAllEdges() + ]).then(function (results) { + res.resolve({ nodes: results[0], edges: results[1] }); + }); + + return res.promise; + } + + var result = { + colors: colors, + getElements: getElements, + styles: styles, + events: events + }; + + var someMethodChangingTheElements = function () { + // @Martin: hier kannst Du die Elements ändern, anschließend mußt Du das Ereignis veröffentlichen + // das Ereigniss wird in der Directive aufgefangen und die Grig wird neu gezeichnet + + // Hinweis: Die Reihenfolge muss so bleiben und du kannst NUR result.elements ändern. + + events.publish("elementsChanged", { + elements: result.elements + }); + }; + + return result; + }]); + + mwtnTopologyApp.directive("mwtnTopologyPhysicalPathGraph", ["mwtnTopologyPhysicalPathData", "$mwtnTopology", "$mwtnCommons", function (pathGraphData, $mwtnTopology, $mwtnCommons) { + + return { + restrict: 'E', + replace: true, + template: '<div style="height:750px; width: 100%;"></div>', + controller: function () { + + }, + scope: { + + }, + link: function (scope, element, attrs, ctrl) { + + var cy = cytoscape({ + container: element[0], + + boxSelectionEnabled: false, + autounselectify: true, + + style: pathGraphData.styles, + elements: [], + layout: { + name: 'preset', + padding: 5 + } + }); + + cy.viewport({ + zoom: 0.50, + pan: { x: 100, y: 50 } + }); + + pathGraphData.getElements().then(function (elements) { + cy.json({ + elements: elements + }); + + // disable drag & drop + cy.nodes().ungrabify(); + }); + + var filterActiveMountPoints = function (mountpoints) { + return mountpoints.filter(function (mountpoint) { + if (!mountpoint) return false; + // console.warn(mountpoint['node-id'], mountpoint['netconf-node-topology:connection-status']); + return mountpoint['netconf-node-topology:connection-status'] === 'connected'; + }).map(function (mountpoint) { + return mountpoint['node-id']; + }); + }; + + var setDevicesActive = function (nodeIds) { + // console.warn(nodeIds); + cy.nodes().filter(function (node) { + node.data('active', 'false'); + return node.data('type') === 'device' && nodeIds.contains(node.data('id')); + }).map(function (node) { + node.data('active', 'true'); + }); + }; + + var setAllDevicesInactive = function () { + cy.nodes().map(function (node) { + node.data('active', 'false'); + }); + }; + + var setPortAndEdgedActive = function () { + cy.edges().map(function (edge) { + var active = 'true'; + edge.connectedNodes().map(function (port) { + // console.log(' node', JSON.stringify(edge.data())); + var parent = cy.getElementById(port.data('parent')); + if (parent.data('active') === 'false') { + port.data('active', 'false'); + edge.data('active', 'false'); + } else { + port.data('active', 'true'); + } + }); + }); + }; + + var setCss = function () { + var width = 5 / cy.zoom(); + var stroke = 1 / cy.zoom(); + cy.edges().css('width', width); + cy.nodes().css('border-width', stroke); + }; + + var init = function () { + $mwtnCommons.getMountPoints().then(function (mountpoints) { + var filtered = filterActiveMountPoints(mountpoints); + setDevicesActive(filtered); + setPortAndEdgedActive(); + }, function (error) { + setAllDevicesInactive(); + setPortAndEdgedActive(); + }); + }; + + init(); + setCss(); + + var orderLtps = function () { + var done = []; + var x = 0; + var y = 0; + var row = 0; + var offset = 100; + var selector = "[type = 'device']"; + var devices = cy.nodes(selector).sort(function (a, b) { + if (a.children().length > b.children().length) return -1; + if (a.children().length < b.children().length) return 1; + return 0; + }).map(function (device) { + device.children().filter(function (ltp) { + return done.indexOf(ltp.id()) === -1; + }).map(function (ltp) { + ltp.position({ x: x, y: y }); + y = y + offset; + var remeberX = x; + ltp.connectedEdges().map(function (edge) { + edge.connectedNodes().sort(function (a, b) { + if (a.data("parent") === device.id()) return -1; + return 1; + }).map(function (node) { + // x = remeberX + 0 * offset; + node.position({ x: x, y: y }); + x = x + 3 * offset; + y = y + offset; + done.push(node.id()); + }); + y = y - 2 * offset; + + }); + x = remeberX; + done.push(ltp.id()); + }); + y = row * 6 * offset; + x = x + 6 * offset; + + if (x > 4000) { + row = row + 1; + x = 0; + y = row * 6 * offset; + } + return device; + }); + }; + + var dragedNodes = []; + // add an event handler for 'tabdrag' for all ports + cy.on('drag', 'node[type = "port"]', function (event) { + var id = event.target.data().id; + dragedNodes.indexOf(id) <= -1 && dragedNodes.push(id); + }); + + cy.on('tap', function (event) { + if (event.target !== cy) { + console.info('click', JSON.stringify(event.target.data())); + } else { + orderLtps(); + // cy.zoom(0.1); + cy.fit(); + cy.center(); + } + }); + + cy.on('zoom', function (event) { + setCss(); + }); + + // global keyboard event handler + function handleKey(e) { + if (!e.ctrlKey && !e.commandKey) return; + switch (e.which) { + case 69: + dragedNodes = []; + cy.nodes().grabify(); + e.preventDefault(); + return false; + break; + case 83: + cy.nodes().ungrabify(); + e.preventDefault(); + var modifiedNodes = dragedNodes.map(id => ({ id: id, position: cy.nodes().getElementById(id).position() })); + $mwtnTopology.saveChangedNodes(modifiedNodes); + console.log("dragedNodes", modifiedNodes); + return false; + break; + // default: + // console.log(e.which); + // e.preventDefault(); + // return false; + // break; + } + } + + // register global keyboard event handler + window.addEventListener('keydown', handleKey, false); + + scope.$on('$destroy', function () { + // un-register global keyboard event handler + window.removeEventListener('keydown', handleKey, false); + }); + + } + } + }]); + + mwtnTopologyApp.controller("mwtnTopologyNetworkElementsGridController", ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', 'mwtnTopologyPhysicalPathData', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants, mwtnTopologyPhysicalPathData) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id" + }, + { + field: "layer", + type: "string", + displayName: "Layer", + width: 100, + }, + { + field: "active", + type: "string", + displayName: "Active", + width: 100, + }, + { + field: "latitude", + type: "string", + displayName: "Latitude", + visible: false + }, + { + field: "longitude", + type: "string", + displayName: "Longitude", + visible: false + }, + { + field: "installed", // capacity in Mbit/s + type: "number", + displayName: "Installed [Mbit/s]", + className: "number", + width: 150 + }, + { + field: "configured", // capacity in Mbit/s + type: "number", + displayName: "Configured [Mbit/s]", + className: "number", + width: 150 + }, + { + field: "effective", // capacity in Mbit/s + type: "number", + displayName: "Effective [Mbit/s]", + className: "number", + width: 150 + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ + field: col.field, + term: col.filters[0].term + }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadPage() { + + // extract all ports + var ports = mwtnTopologyPhysicalPathData.elements.nodes.filter(function (node, ind, arr) { + return node && node.data && node.data.type === 'port'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) acc[cur.data.id] = cur.data; + return acc; + }, {}); + + // get all port ids + var portIds = Object.keys(ports); + + // apply the grid filters + var tempData = portIds.filter(function (portId, ind, arr) { + var port = ports[portId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + case "active": + return port[filter.field].toString().contains(filter.term); + default: + return port[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (portId) { + var port = ports[portId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: port.id + } + } + + switch (sortColumn.field) { + case "active": + orderBy = port[sortColumn.field] ? 1 : 0; + break; + default: + orderBy = port[sortColumn.field]; + break; + } + + return { + id: port.id, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedPortsAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + portsAtCurrentPageCache = {}; + var orderedData = []; + + orderedPortsAtCurrentPage.forEach(function (orderedPort) { + var port = ports[orderedPort.id]; + portsAtCurrentPageCache[port.id] = port; + orderedData.push({ + id: orderedPort.id, + layer: port.layer, + active: port.active, + latitude: port.latitude.toLocaleString("en-US", { + minimumFractionDigits: 4 + }), + longitude: port.longitude.toLocaleString("en-US", { + minimumFractionDigits: 4 + }), + installed: 0, + configured: 0, + effective: 0 + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + // subscribe to the elementsChanged event to reload the grid page if the data in the service has chenged + mwtnTopologyPhysicalPathData.events.subscribe("elementsChanged", function (data) { + loadPage(); + }); + + }]); + + mwtnTopologyApp.directive("mwtnTopologyNetworkElementsGrid", [function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologyNetworkElementsGridController', + controllerAs: 'vm', + scope: { + + }, + templateUrl: 'src/app/mwtnTopology/templates/networkElementsGrid.tpl.html' + }; + }]); + + mwtnTopologyApp.controller("mwtnTopologyLinksGridController", ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', 'mwtnTopologyPhysicalPathData', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants, mwtnTopologyPhysicalPathData) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id" + }, + { + field: "source", + type: "string", + displayName: "PortA" + }, + { + field: "target", + type: "string", + displayName: "PortZ" + }, + { + field: "layer", + type: "string", + displayName: "Layer" + }, + { + field: "length", + type: "string", + displayName: "Length" + }, + { + field: "azimuthAZ", + type: "string", + displayName: "azimuthAZ" + }, + { + field: "azimuthZA", + type: "string", + displayName: "azimuthZA" + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ + field: col.field, + term: col.filters[0].term + }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadPage() { + // extract all ports + var ports = mwtnTopologyPhysicalPathData.elements.nodes.filter(function (node, ind, arr) { + return node && node.data && node.data.type === 'port'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) acc[cur.data.id] = cur.data; + return acc; + }, {}); + + // extract all links + var links = mwtnTopologyPhysicalPathData.elements.edges.filter(function (node, ind, arr) { + return true; // node && node.data && node.data.type === 'port'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) { + + if (cur.data.layer === 'MWPS') { + var portA = ports[cur.data.source]; + var portZ = ports[cur.data.target]; + + // calculate length + cur.data.length = (portA && portZ) ? $mwtnTopology.getDistance(portA.latitude, portA.longitude, portZ.latitude, portZ.longitude) : 0; + cur.data.azimuthAZ = (portA && portZ) ? $mwtnTopology.bearing(portA.latitude, portA.longitude, portZ.latitude, portZ.longitude) : 0; + cur.data.azimuthZA = (portA && portZ) ? $mwtnTopology.bearing(portZ.latitude, portZ.longitude, portA.latitude, portA.longitude) : 0; + + } else { + cur.data.length = 0; + cur.data.azimuthAZ = 0; + cur.data.azimuthZA = 0; + } + acc[cur.data.id] = cur.data; + } + return acc; + }, {}); + + // get all link ids + var linkIds = Object.keys(links); + + // apply the grid filters + var tempData = linkIds.filter(function (linkId, ind, arr) { + var link = links[linkId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + case "length": + case "azimuthAZ": + case "azimuthZA": + return true; + default: + return link[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (linkId) { + var link = links[linkId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: link.id + } + } + + switch (sortColumn.field) { + default: + orderBy = link[sortColumn.field]; + break; + } + + return { + id: link.id, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedLinksAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + linksAtCurrentPageCache = {}; + var orderedData = []; + + orderedLinksAtCurrentPage.forEach(function (orderedLink) { + var link = links[orderedLink.id]; + linksAtCurrentPageCache[link.id] = link; + orderedData.push({ + id: orderedLink.id, + source: link.source, + target: link.target, + layer: link.layer, + length: link.length, + azimuthAZ: link.azimuthAZ.toLocaleString("en-US", { + minimumFractionDigits: 4 + }), + azimuthZA: link.azimuthZA.toLocaleString("en-US", { + minimumFractionDigits: 4 + }), + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + // subscribe to the elementsChanged event to reload the grid page if the data in the service has chenged + var subscription = mwtnTopologyPhysicalPathData.events.subscribe("elementsChanged", function (data) { + loadPage(); + // to unsubscribe call subscription.remove(); + }); + + }]); + + mwtnTopologyApp.directive("mwtnTopologyLinksGrid", [function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologyLinksGridController', + controllerAs: 'vm', + scope: { + + }, + templateUrl: 'src/app/mwtnTopology/templates/linksGrid.tpl.html' + }; + }]); + + /********************************************* Ethernet ***********************************/ + + mwtnTopologyApp.controller('mwtnTopologyEthernetViewController', ['$scope', '$q', '$timeout', '$state', '$window', '$mwtnTopology', function ($scope, $q, $timeout, $state, $window, $mwtnTopology) { + var vm = this; + vm.status = { + topologyIsOpen: false, + portsOpen: false, + ethConnectionsIsOpen: false + } + + $scope.$watchCollection(function () { return [vm.status.topologyIsOpen, vm.status.portsOpen, vm.status.ethConnectionsIsOpen] }, function (newVal, oldVal) { + if (newVal[1] || newVal[2]) { + $timeout(function () { + $window.dispatchEvent(new Event("resize")); + }); + } + }); + + }]); + + mwtnTopologyApp.directive('mwtnTopologyEthernetView', function () { + return { + restrict: 'E', + controller: 'mwtnTopologyEthernetViewController', + controllerAs: 'vm', + bindToController: true, + templateUrl: 'src/app/mwtnTopology/templates/ethernetView.tpl.html', + scope: { + + } + }; + }); + + mwtnTopologyApp.factory("mwtnTopologyEthernetPathData", function () { + var colors = { + root: '#f54', + port: '#377', + device: '#252', + site: '#525', + edge: '#49a', + white: '#eed', + grey: '#555', + selected: '#ff0' + }; + + var styles = [ + { + selector: 'node', + css: { + 'content': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#eeeeee', + 'border-color': '#000000', + 'border-width': '1px', + 'color': '#000000' + } + }, + { + selector: 'node[type = "label"]', + css: { + 'content': 'data(label)', + 'border-width': '0px', + 'background-color': '#ffffff', + 'font-size': '50px', + 'text-valign': 'bottom', + 'text-halign': 'right', + + } + }, + + { + selector: 'node[layer = "MWPS"]', + css: { + 'content': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#316ac5', + 'border-color': '#000000', + 'border-width': '1px', + 'color': '#ffffff' + } + }, + { + selector: 'node[layer = "ETH-TTP"]', + css: { + 'content': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#008800', + 'border-color': '#004400', + 'border-width': '1px', + 'color': '#ffffff' + } + }, + { + selector: '$node > node', + css: { + 'shape': 'roundrectangle', + 'padding-top': '10px', + 'padding-left': '10px', + 'padding-bottom': '10px', + 'padding-right': '10px', + 'text-valign': 'top', + 'text-halign': 'center', + 'background-color': '#eeeeee', + 'color': '#444444', + 'border-color': '#888888' + } + }, + { + selector: 'node[type = "site"]', + css: { + 'shape': 'roundrectangle', + 'padding-top': '10px', + 'padding-left': '10px', + 'padding-bottom': '10px', + 'padding-right': '10px', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#fefefe', + 'color': '#444444', + 'border-color': '#888888', + 'font-weight': 'bold' + } + }, + { + selector: 'node[type = "device"]', + css: { + 'background-color': '#eeeeee', + 'background-opacity': '0.1', + 'border-color': '#888888', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: 'node[type = "device"][active = "true"]', + css: { + 'background-color': '#316ac5', + 'background-opacity': '0.1', + 'border-color': '#316ac5', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: 'node[type = "port"][active = "true"]', + css: { + 'background-opacity': '1.0', + } + }, + { + selector: 'node[path = "working"]', + css: { + 'background-color': '#FFA500', + 'border-color': '#FFA500', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: 'node[path = "protection"]', + css: { + 'background-color': '#ffffff', + 'border-color': '#FFA500', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: '$node > node[path = "working"]', + css: { + 'background-color': '#FFA500', + 'border-color': '#FFA500', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: '$node > node[path = "protection"]', + css: { + 'border-color': '#FFA500', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: 'node[active = "false"]', + css: { + 'background-opacity': '0.3', + 'border-opacity': '0.5' + } + }, + { + selector: 'edge', + css: { + 'content': 'data(id)', + 'target-arrow-shape': 'triangle', + 'line-color': '#666666', + 'color': '#444444' + } + }, + { + selector: 'edge[active = "false"]', + css: { + 'line-color': '#cccccc', + 'text-opacity': '0.9' + } + }, + { + selector: 'edge[layer = "ETC"]', + css: { + 'content': 'data(id)', + 'target-arrow-shape': 'triangle', + 'width': '3px', + 'line-color': '#316ac5', + 'color': '#444444' + } + }, + { + selector: 'edge[layer = "ETH"]', + css: { + 'content': '', + 'target-arrow-shape': 'triangle', + 'width': '2px', + 'line-color': '#FFA500', + 'color': '#000000' + } + }, { + selector: 'edge[layer = "ETC"][active = "false"]', + css: { + 'line-color': '#C0D1EC', + 'text-opacity': '0.9' + } + }, + + { + selector: 'edge[layer = "ETH"][path = "false"]', + css: { + 'opacity': '0.0' + } + }, + { + selector: 'edge[path = "working"]', + css: { + 'line-color': '#FFA500', + 'width': '5px', + 'opacity': '1.0' + } + }, + { + selector: 'edge[path = "protection"]', + css: { + 'line-color': '#FFA500', + 'line-style': 'dashed', + 'width': '3px', + 'opacity': '1.0' + } + }, + { + selector: ':selected', + css: { + 'background-color': 'black', + 'line-color': 'black', + 'target-arrow-color': 'black', + 'source-arrow-color': 'black' + } + } + ]; + + var elements = { + nodes: [ + { data: { id: 'label', label : '' , type: 'label' }, position: { x: -259, y: -167 } }, + + { data: { id: 'north', label : 'north' , type: 'site', latitude: 50.734916, longitude: 7.137636 } }, + { data: { id: 'north-east', label : 'north-east' , type: 'site', latitude: 50.733028, longitude: 7.151086 } }, + { data: { id: 'north-west', label : 'north-west' , type: 'site', latitude: 50.730230, longitude: 7.126017 } }, + { data: { id: 'east', label : 'east' , type: 'site', latitude: 50.725672, longitude: 7.158488 } }, + { data: { id: 'west', label : 'west' , type: 'site', latitude: 50.721914, longitude: 7.120521 } }, + { data: { id: 'south-east', label : 'south-east' , type: 'site', latitude: 50.717158, longitude: 7.155506 } }, + { data: { id: 'south-west', label : 'south-west' , type: 'site', latitude: 50.714359, longitude: 7.130437 } }, + { data: { id: 'south', label : 'south' , type: 'site', latitude: 50.712472, longitude: 7.143887 } }, + + { data: { id: 'ADVA-Y', label : 'ADVA-Y' , parent : 'north-east', type: 'device', active: 'true' , latitude: 50.733028, longitude: 7.151086 } }, + { data: { id: 'ADVA-Z', label : 'ADVA-Z' , parent : 'south', type: 'device', active: 'true' , latitude: 50.712472, longitude: 7.143887 } }, + { data: { id: 'Aviat-A', label : 'Aviat-A' , parent : 'north-east', type: 'device', active: 'true' , latitude: 50.733028, longitude: 7.151086 } }, + { data: { id: 'Aviat-Z', label : 'Aviat-Z' , parent : 'east', type: 'device', active: 'true' , latitude: 50.725672, longitude: 7.158488 } }, + { data: { id: 'Ceragon-A', label : 'Ceragon-A' , parent : 'north-west', type: 'device', active: 'true' , latitude: 50.730230, longitude: 7.126017 } }, + { data: { id: 'Ceragon-Z', label : 'Ceragon-Z' , parent : 'west', type: 'device', active: 'true' , latitude: 50.721914, longitude: 7.120521 } }, + { data: { id: 'DragonWave-A', label : 'DragonWave-A' , parent : 'south-west', type: 'device', active: 'true' , latitude: 50.714359, longitude: 7.130437 } }, + { data: { id: 'DragonWave-Z', label : 'DragonWave-Z' , parent : 'south', type: 'device', active: 'true' , latitude: 50.712472, longitude: 7.143887 } }, + { data: { id: 'ELVA-1-A', label : 'ELVA-1-A' , parent : 'north', type: 'device', active: 'true' , latitude: 50.734916, longitude: 7.137636 } }, + { data: { id: 'ELVA-1-Z', label : 'ELVA-1-Z' , parent : 'south-west', type: 'device', active: 'true' , latitude: 50.714359, longitude: 7.130437 } }, + { data: { id: 'Ericsson-A', label : 'Ericsson-A' , parent : 'north-east', type: 'device', active: 'true' , latitude: 50.733028, longitude: 7.151086 } }, + { data: { id: 'Ericsson-Z', label : 'Ericsson-Z' , parent : 'east', type: 'device', active: 'true' , latitude: 50.725672, longitude: 7.158488 } }, + { data: { id: 'Fujitsu-A', label : 'Fujitsu-A' , parent : 'east', type: 'device', active: 'true' , latitude: 50.725672, longitude: 7.158488 } }, + { data: { id: 'Fujitsu-Z', label : 'Fujitsu-Z' , parent : 'south-east', type: 'device', active: 'true' , latitude: 50.717158, longitude: 7.155506 } }, + { data: { id: 'Huawei-A', label : 'Huawei-A' , parent : 'south-west', type: 'device', active: 'true' , latitude: 50.714359, longitude: 7.130437 } }, + { data: { id: 'Huawei-Z', label : 'Huawei-Z' , parent : 'south', type: 'device', active: 'true' , latitude: 50.712472, longitude: 7.143887 } }, + { data: { id: 'Intracom-A', label : 'Intracom-A' , parent : 'south', type: 'device', active: 'true' , latitude: 50.712472, longitude: 7.143887 } }, + { data: { id: 'Intracom-Z', label : 'Intracom-Z' , parent : 'south-east', type: 'device', active: 'true' , latitude: 50.717158, longitude: 7.155506 } }, + { data: { id: 'NEC-A', label : 'NEC-A' , parent : 'north', type: 'device', active: 'true' , latitude: 50.734916, longitude: 7.137636 } }, + { data: { id: 'NEC-Z', label : 'NEC-Z' , parent : 'north-east', type: 'device', active: 'true' , latitude: 50.733028, longitude: 7.151086 } }, + { data: { id: 'Nokia-A', label : 'Nokia-A' , parent : 'west', type: 'device', active: 'fasel' , latitude: 50.721914, longitude: 7.120521 } }, + { data: { id: 'Nokia-Z', label : 'Nokia-Z' , parent : 'south-west', type: 'device', active: 'true' , latitude: 50.714359, longitude: 7.130437 } }, + { data: { id: 'SIAE-A', label : 'SIAE-A' , parent : 'south', type: 'device', active: 'true' , latitude: 50.712472, longitude: 7.143887 } }, + { data: { id: 'SIAE-Z', label : 'SIAE-Z' , parent : 'south-east', type: 'device', active: 'true' , latitude: 50.717158, longitude: 7.155506 } }, + { data: { id: 'ZTE-A', label : 'ZTE-A' , parent : 'north-west', type: 'device', active: 'true' , latitude: 50.730230, longitude: 7.126017 } }, + { data: { id: 'ZTE-Z', label : 'ZTE-Z' , parent : 'north', type: 'device', active: 'true' , latitude: 50.734916, longitude: 7.137636 } }, + + { data: { id: 'Aviat-Z#5', label : '#5' , parent : 'Aviat-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1984, y: 390 } }, + { data: { id: 'Aviat-Z#6', label : '#6' , parent : 'Aviat-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1984, y: 321 } }, + { data: { id: 'Ericsson-Z#5', label : '#5' , parent : 'Ericsson-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1777, y: 393 } }, + { data: { id: 'Ericsson-Z#6', label : '#6' , parent : 'Ericsson-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1765, y: 325 } }, + { data: { id: 'Fujitsu-A#5', label : '#5' , parent : 'Fujitsu-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1859, y: 567 } }, + { data: { id: 'Fujitsu-A#6', label : '#6' , parent : 'Fujitsu-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1859, y: 647 } }, + { data: { id: 'ELVA-1-A#2', label : '#2' , parent : 'ELVA-1-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 895, y: 150 } }, + { data: { id: 'ELVA-1-A#6', label : '#6' , parent : 'ELVA-1-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 815, y: 150 } }, + { data: { id: 'NEC-A#3', label : '#3' , parent : 'NEC-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 955, y: -52 } }, + { data: { id: 'NEC-A#6', label : '#6' , parent : 'NEC-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 1035, y: -52 } }, + { data: { id: 'ZTE-Z#4', label : '#4' , parent : 'ZTE-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 707, y: -67 } }, + { data: { id: 'ZTE-Z#5', label : '#5' , parent : 'ZTE-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 747, y: -27 } }, + { data: { id: 'ZTE-Z#6', label : '#6' , parent : 'ZTE-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.734916, longitude: 7.137636 }, position: { x: 667, y: -27 } }, + // { data: { id: 'ADVA-Y#1', label : '#1' , parent : 'ADVA-Y' , type:'port', layer:'ETY', active:'true', latitude:50.733028, longitude:7.151086}, position: { x: 1392, y: 229 } }, + { data: { id: 'ADVA-Y#2', label : '#2' , parent : 'ADVA-Y' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: 172 } }, + { data: { id: 'ADVA-Y#3', label : '#3' , parent : 'ADVA-Y' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1392, y: 172 } }, + { data: { id: 'ADVA-Y#4', label : '#4' , parent : 'ADVA-Y' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: 229 } }, + { data: { id: 'Aviat-A#5', label : '#5' , parent : 'Aviat-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1654, y: -47 } }, + { data: { id: 'Aviat-A#6', label : '#6' , parent : 'Aviat-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1654, y: 22 } }, + { data: { id: 'Ericsson-A#4', label : '#4' , parent : 'Ericsson-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1605, y: 229 } }, + { data: { id: 'Ericsson-A#5', label : '#5' , parent : 'Ericsson-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1605, y: 172 } }, + { data: { id: 'Ericsson-A#6', label : '#6' , parent : 'Ericsson-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1664, y: 226 } }, + // { data: { id: 'NEC-Z#3', label : '#3' , parent : 'NEC-Z' , type:'port', layer:'ETY', active:'true', latitude:50.733028, longitude:7.151086}, position: { x: 1392, y: 16 } }, + { data: { id: 'NEC-Z#4', label : '#4' , parent : 'NEC-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: 16 } }, + { data: { id: 'NEC-Z#2', label : '#2' , parent : 'NEC-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: -41 } }, + { data: { id: 'NEC-Z#6', label : '#6' , parent : 'NEC-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1382, y: -23 } }, + { data: { id: 'Ceragon-A#5', label : '#5' , parent : 'Ceragon-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.730230, longitude: 7.126017 }, position: { x: 195, y: 312 } }, + { data: { id: 'Ceragon-A#6', label : '#6' , parent : 'Ceragon-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.730230, longitude: 7.126017 }, position: { x: 136, y: 366 } }, + { data: { id: 'ZTE-A#5', label : '#5' , parent : 'ZTE-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.730230, longitude: 7.126017 }, position: { x: 345, y: 108 } }, + { data: { id: 'ZTE-A#6', label : '#6' , parent : 'ZTE-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.730230, longitude: 7.126017 }, position: { x: 408, y: 99 } }, + { data: { id: 'ADVA-Z#1', label : '#1' , parent : 'ADVA-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1139, y: 1001 } }, + // { data: { id: 'ADVA-Z#2', label : '#2' , parent : 'ADVA-Z' , type:'port', layer:'ETY', active:'true', latitude:50.712472, longitude:7.143887}, position: { x: 1196, y: 944 } }, + // { data: { id: 'ADVA-Z#3', label : '#3' , parent : 'ADVA-Z' , type:'port', layer:'ETY', active:'true', latitude:50.712472, longitude:7.143887}, position: { x: 1139, y: 944 } }, + { data: { id: 'ADVA-Z#4', label : '#4' , parent : 'ADVA-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1196, y: 1001 } }, + { data: { id: 'DragonWave-Z#2', label : '#2' , parent : 'DragonWave-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1133, y: 1252 } }, + { data: { id: 'DragonWave-Z#6', label : '#6' , parent : 'DragonWave-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1053, y: 1252 } }, + { data: { id: 'Huawei-Z#3', label : '#3' , parent : 'Huawei-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1046, y: 1094 } }, + // { data: { id: 'Huawei-Z#4', label : '#4' , parent : 'Huawei-Z' , type:'port', layer:'ETY', active:'true', latitude:50.712472, longitude:7.143887}, position: { x: 989, y: 1094 } }, + { data: { id: 'Huawei-Z#5', label : '#5' , parent : 'Huawei-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1058, y: 1123 } }, + { data: { id: 'Huawei-Z#6', label : '#6' , parent : 'Huawei-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 978, y: 1123 } }, + { data: { id: 'Intracom-A#2', label : '#2' , parent : 'Intracom-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1203, y: 1252 } }, + { data: { id: 'Intracom-A#6', label : '#6' , parent : 'Intracom-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1283, y: 1252 } }, + { data: { id: 'SIAE-A#4', label : '#4' , parent : 'SIAE-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1289, y: 1094 } }, + { data: { id: 'SIAE-A#5', label : '#5' , parent : 'SIAE-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1278, y: 1123 } }, + { data: { id: 'SIAE-A#6', label : '#6' , parent : 'SIAE-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1346, y: 1094 } }, + { data: { id: 'Fujitsu-Z#5', label : '#5' , parent : 'Fujitsu-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1855, y: 821 } }, + { data: { id: 'Fujitsu-Z#6', label : '#6' , parent : 'Fujitsu-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1855, y: 741 } }, + { data: { id: 'Intracom-Z#5', label : '#5' , parent : 'Intracom-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1755, y: 998 } }, + { data: { id: 'Intracom-Z#6', label : '#6' , parent : 'Intracom-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1714, y: 1018 } }, + { data: { id: 'SIAE-Z#4', label : '#4' , parent : 'SIAE-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1590, y: 784 } }, + { data: { id: 'SIAE-Z#5', label : '#5' , parent : 'SIAE-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1647, y: 784 } }, + { data: { id: 'SIAE-Z#6', label : '#6' , parent : 'SIAE-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1588, y: 838 } }, + { data: { id: 'DragonWave-A#2', label : '#2' , parent : 'DragonWave-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 455, y: 1178 } }, + { data: { id: 'DragonWave-A#6', label : '#6' , parent : 'DragonWave-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 535, y: 1178 } }, + { data: { id: 'ELVA-1-Z#2', label : '#2' , parent : 'ELVA-1-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 455, y: 878 } }, + { data: { id: 'ELVA-1-Z#6', label : '#6' , parent : 'ELVA-1-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 535, y: 878 } }, + { data: { id: 'Huawei-A#5', label : '#5' , parent : 'Huawei-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 605, y: 1028 } }, + { data: { id: 'Huawei-A#6', label : '#6' , parent : 'Huawei-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 685, y: 1028 } }, + { data: { id: 'Nokia-Z33', label : '33' , parent : 'Nokia-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 385, y: 1028 } }, + { data: { id: 'Nokia-Z#6', label : '#6' , parent : 'Nokia-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.714359, longitude: 7.130437 }, position: { x: 305, y: 1028 } }, + { data: { id: 'Ceragon-Z#4', label : '#4' , parent : 'Ceragon-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.721914, longitude: 7.120521 }, position: { x: -159, y: 547 } }, + { data: { id: 'Ceragon-Z#5', label : '#5' , parent : 'Ceragon-Z' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.721914, longitude: 7.120521 }, position: { x: -159, y: 604 } }, + { data: { id: 'Ceragon-Z#6', label : '#6' , parent : 'Ceragon-Z' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.721914, longitude: 7.120521 }, position: { x: -130, y: 536 } }, + // { data: { id: 'Nokia-A13', label : '13' , parent : 'Nokia-A' , type:'port', layer:'ETY', active:'true', latitude:50.721914, longitude:7.120521}, position: { x: 40, y: 801 } }, + // { data: { id: 'Nokia-A34', label : '34' , parent : 'Nokia-A' , type:'port', layer:'ETY', active:'true', latitude:50.721914, longitude:7.120521}, position: { x: 28, y: 772 } }, + { data: { id: 'Nokia-A11', label : '11' , parent : 'Nokia-A' , type: 'port', layer: 'ETY', active: 'true', latitude: 50.721914, longitude: 7.120521 }, position: { x: -29, y: 772 } }, + { data: { id: 'Nokia-A#6', label : '#6' , parent : 'Nokia-A' , type: 'port', layer: 'ETC', active: 'true', latitude: 50.721914, longitude: 7.120521 }, position: { x: 28, y: 829 } }, + + { data: { id: 'Spirent#1', label : '#1' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service13' }, position: { x: 707, y: -167 } }, + { data: { id: 'Spirent#2', label : '#2' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service24' }, position: { x: -259, y: 547 } }, + { data: { id: 'Spirent#3', label : '#3' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service13' }, position: { x: 1292, y: 172 } }, + { data: { id: 'Spirent#4', label : '#4' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service24' }, position: { x: 1490, y: 784 } }, + { data: { id: 'Spirent#5', label : '#5' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service56' }, position: { x: 1754, y: -47 } }, + { data: { id: 'Spirent#6', label : '#6' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service56' }, position: { x: 455, y: 1278 } }, + { data: { id: 'Spirent#7', label : '#7' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service78' }, position: { x: 895, y: 250 } }, + { data: { id: 'Spirent#8', label : '#8' , parent : 'Spirent' , type: 'host', layer: 'ETH-TTP', active: 'true', service: 'service78' }, position: { x: 455, y: 778 } }, + + ], + edges: [ + + { data: { id: '21', source: 'Aviat-A#6', target: 'Aviat-Z#6', label: '21', layer: 'ETC' , active: 'true' } }, + { data: { id: '31', source: 'Ceragon-A#6', target: 'Ceragon-Z#6', label: '31', layer: 'ETC' , active: 'true' } }, + { data: { id: '41', source: 'DragonWave-A#6', target: 'DragonWave-Z#6', label: '41', layer: 'ETC' , active: 'true' } }, + { data: { id: '121', source: 'ELVA-1-A#6', target: 'ELVA-1-Z#6', label: '121' , layer: 'ETC' , active: 'true' } }, + { data: { id: 'ERI1', source: 'Ericsson-A#6', target: 'Ericsson-Z#6', label: 'ERI1', layer: 'ETC' , active: 'true' } }, + { data: { id: '61', source: 'Fujitsu-A#6', target: 'Fujitsu-Z#6', label: '61', layer: 'ETC' , active: 'true' } }, + { data: { id: '71', source: 'Huawei-A#6', target: 'Huawei-Z#6', label: '71', layer: 'ETC' , active: 'true' } }, + { data: { id: '131', source: 'Intracom-A#6', target: 'Intracom-Z#6', label: '131', layer: 'ETC' , active: 'true' } }, + { data: { id: '81', source: 'NEC-A#6', target: 'NEC-Z#6', label: '81', layer: 'ETC' , active: 'true' } }, + { data: { id: '91', source: 'Nokia-A#6', target: 'Nokia-Z#6', label: '91', layer: 'ETC' , active: 'true' } }, + { data: { id: '101', source: 'SIAE-A#6', target: 'SIAE-Z#6', label: '101', layer: 'ETC' , active: 'true' } }, + { data: { id: '111', source: 'ZTE-A#6', target: 'ZTE-Z#6', label: '111', layer: 'ETC' , active: 'true' } }, + + // { data: { id: 'ETY01', source: 'ADVA-A#1', target: 'Nokia-A34', label: 'ADVA-A#1-Nokia-A34' , layer: 'ETY' , active: 'true' } }, + // { data: { id: 'ETY02', source: 'ADVA-A#2', target: 'ZTE-A#4', label: 'ADVA-A#2-ZTE-A#4' , layer: 'ETY' , active: 'false' } }, + // { data: { id: 'ETY03', source: 'ADVA-B#1', target: 'Nokia-A13', label: 'ADVA-B#1-Nokia-A13' , layer: 'ETY' , active: 'true' } }, + // { data: { id: 'ETY04', source: 'ADVA-B#2', target: 'ZTE-A#3', label: 'ADVA-B#2-ZTE-A#3' , layer: 'ETY' , active: 'true' } }, + // { data: { id: 'ETY05', source: 'ADVA-Y#1', target: 'Huawei-Z#4', label: 'ADVA-Y#1-Huawei-Z#4' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY06', source: 'ADVA-Y#2', target: 'NEC-Z#4', label: 'ADVA-Y#2-NEC-Z#4' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY07', source: 'ADVA-Y#3', target: 'Spirent#3', label: 'ADVA-Y#3-Spirent#3' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY08', source: 'ADVA-Y#4', target: 'Ericsson-A#4', label: 'ADVA-Y#4-Ericsson-A#4' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY09', source: 'ADVA-Z#1', target: 'Huawei-Z#3', label: 'ADVA-Z#1-Huawei-Z#3' , layer: 'ETY' , active: 'true' } }, + // { data: { id: 'ETY10', source: 'ADVA-Z#2', target: 'NEC-Z#3', label: 'ADVA-Z#2-NEC-Z#3' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY11', source: 'ADVA-Z#4', target: 'SIAE-A#4', label: 'ADVA-Z#4-SIAE-A#4' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY12', source: 'Aviat-A#5', target: 'Spirent#5', label: 'Aviat-A#5-Spirent#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY13', source: 'Aviat-Z#5', target: 'Fujitsu-A#5', label: 'Aviat-Z#5-Fujitsu-A#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY14', source: 'Ceragon-A#5', target: 'ZTE-A#5', label: 'Ceragon-A#5-ZTE-A#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY15', source: 'Ceragon-Z#4', target: 'Spirent#2', label: 'Ceragon-Z#4-Spirent#2' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY16', source: 'Ceragon-Z#5', target: 'Nokia-A11', label: 'Ceragon-Z#5-Nokia-A11' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY17', source: 'DragonWave-A#2', target: 'Spirent#6', label: 'DragonWave-A#2-Spirent#6' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY18', source: 'DragonWave-Z#2', target: 'Intracom-A#2', label: 'DragonWave-Z#2-Intracom-A#2' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY19', source: 'ELVA-1-A#2', target: 'Spirent#7', label: 'ELVA-1-A#2-Spirent#7' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY20', source: 'ELVA-1-Z#2', target: 'Spirent#8', label: 'ELVA-1-Z#2-Spirent#8' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY21', source: 'Ericsson-A#5', target: 'NEC-Z#2', label: 'Ericsson-A#5-NEC-Z#2' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY22', source: 'Ericsson-Z#5', target: 'SIAE-Z#5', label: 'Ericsson-Z#5-SIAE-Z#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY23', source: 'Fujitsu-Z#5', target: 'Intracom-Z#5', label: 'Fujitsu-Z#5-Intracom-Z#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY24', source: 'Huawei-A#5', target: 'Nokia-Z33', label: 'Huawei-A#5-Nokia-Z33' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY25', source: 'Huawei-Z#5', target: 'SIAE-A#5', label: 'Huawei-Z#5-SIAE-A#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY26', source: 'NEC-A#3', target: 'ZTE-Z#5', label: 'NEC-A#3-ZTE-Z#5' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY27', source: 'SIAE-Z#4', target: 'Spirent#4', label: 'SIAE-Z#4-Spirent#4' , layer: 'ETY' , active: 'true' } }, + { data: { id: 'ETY28', source: 'ZTE-Z#4', target: 'Spirent#1', label: 'Spirent#1-ZTE-Z#4' , layer: 'ETY' , active: 'true' } }, + + { data: { id: 'ADVA-Y#2-ETH-13<->ADVA-Y#3-ETH-13', source: 'ADVA-Y#2', target: 'ADVA-Y#3', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'protection' } }, + { data: { id: 'ADVA-Y#2-ETH-24<->ADVA-Y#4-ETH-24', source: 'ADVA-Y#2', target: 'ADVA-Y#4', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'ADVA-Y#3-ETH-13<->ADVA-Y#4-ETH-13', source: 'ADVA-Y#3', target: 'ADVA-Y#4', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Aviat-A#5-ETH-56<->Aviat-A#6-ETH-56', source: 'Aviat-A#5', target: 'Aviat-A#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'Aviat-Z#5-ETH-56<->Aviat-Z#6-ETH-56', source: 'Aviat-Z#5', target: 'Aviat-Z#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'Ceragon-A#5-ETH-13<->Ceragon-A#6-ETH-13', source: 'Ceragon-A#5', target: 'Ceragon-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Ceragon-A#5-ETH-24<->Ceragon-A#6-ETH-24', source: 'Ceragon-A#5', target: 'Ceragon-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'Ceragon-Z#4-ETH-24<->Ceragon-Z#5-ETH-24', source: 'Ceragon-Z#4', target: 'Ceragon-Z#5', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'Ceragon-Z#4-ETH-24<->Ceragon-Z#6-ETH-24', source: 'Ceragon-Z#4', target: 'Ceragon-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'Ceragon-Z#5-ETH-13<->Ceragon-Z#6-ETH-13', source: 'Ceragon-Z#5', target: 'Ceragon-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'DragonWave-A#2-ETH-56<->DragonWave-A#6-ETH-56', source: 'DragonWave-A#2', target: 'DragonWave-A#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'DragonWave-Z#2-ETH-56<->DragonWave-Z#6-ETH-56', source: 'DragonWave-Z#2', target: 'DragonWave-Z#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'ELVA-1-A#2-ETH-78<->ELVA-1-A#6-ETH-78', source: 'ELVA-1-A#2', target: 'ELVA-1-A#6', label: 'service78' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service78' , rule: 'working' } }, + { data: { id: 'ELVA-1-Z#2-ETH-78<->ELVA-1-Z#6-ETH-78', source: 'ELVA-1-Z#2', target: 'ELVA-1-Z#6', label: 'service78' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service78' , rule: 'working' } }, + { data: { id: 'Ericsson-A#4-ETH-13<->Ericsson-A#6-ETH-13', source: 'Ericsson-A#4', target: 'Ericsson-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Ericsson-A#4-ETH-24<->Ericsson-A#6-ETH-24', source: 'Ericsson-A#4', target: 'Ericsson-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'Ericsson-Z#5-ETH-13<->Ericsson-Z#6-ETH-13', source: 'Ericsson-Z#5', target: 'Ericsson-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Ericsson-Z#5-ETH-24<->Ericsson-Z#6-ETH-24', source: 'Ericsson-Z#5', target: 'Ericsson-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'Fujitsu-A#5-ETH-56<->Fujitsu-A#6-ETH-56', source: 'Fujitsu-A#5', target: 'Fujitsu-A#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'Fujitsu-Z#5-ETH-56<->Fujitsu-Z#6-ETH-56', source: 'Fujitsu-Z#5', target: 'Fujitsu-Z#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'Huawei-A#5-ETH-13<->Huawei-A#6-ETH-13', source: 'Huawei-A#5', target: 'Huawei-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Huawei-A#5-ETH-24<->Huawei-A#6-ETH-24', source: 'Huawei-A#5', target: 'Huawei-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'Huawei-Z#5-ETH-13<->Huawei-Z#6-ETH-13', source: 'Huawei-Z#5', target: 'Huawei-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Huawei-Z#5-ETH-24<->Huawei-Z#6-ETH-24', source: 'Huawei-Z#5', target: 'Huawei-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'Intracom-A#2-ETH-56<->Intracom-A#6-ETH-56', source: 'Intracom-A#2', target: 'Intracom-A#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'Intracom-Z#5-ETH-56<->Intracom-Z#6-ETH-56', source: 'Intracom-Z#5', target: 'Intracom-Z#6', label: 'service56' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service56' , rule: 'working' } }, + { data: { id: 'NEC-A#3-ETH-13<->NEC-A#6-ETH-13', source: 'NEC-A#3', target: 'NEC-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'protection' } }, + { data: { id: 'NEC-A#3-ETH-24<->NEC-A#6-ETH-24', source: 'NEC-A#3', target: 'NEC-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'NEC-Z#4-ETH-13<->NEC-Z#6-ETH-13', source: 'NEC-Z#4', target: 'NEC-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'protection' } }, + { data: { id: 'NEC-Z#4-ETH-24<->NEC-Z#6-ETH-24', source: 'NEC-Z#4', target: 'NEC-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'Nokia-A11-ETH-13<->Nokia-A#6-ETH-13', source: 'Nokia-A11', target: 'Nokia-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Nokia-A11-ETH-24<->Nokia-A#6-ETH-24', source: 'Nokia-A11', target: 'Nokia-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'Nokia-Z33-ETH-13<->Nokia-Z#6-ETH-13', source: 'Nokia-Z33', target: 'Nokia-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'Nokia-Z33-ETH-24<->Nokia-Z#6-ETH-24', source: 'Nokia-Z33', target: 'Nokia-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'SIAE-A#5-ETH-13<->SIAE-A#6-ETH-13', source: 'SIAE-A#5', target: 'SIAE-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'SIAE-A#5-ETH-24<->SIAE-A#6-ETH-24', source: 'SIAE-A#5', target: 'SIAE-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'SIAE-Z#4-ETH-24<->SIAE-Z#6-ETH-24', source: 'SIAE-Z#4', target: 'SIAE-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'working' } }, + { data: { id: 'SIAE-Z#4-ETH-24<->SIAE-Z#5-ETH-24', source: 'SIAE-Z#4', target: 'SIAE-Z#5', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'SIAE-Z#5-ETH-13<->SIAE-Z#6-ETH-13', source: 'SIAE-Z#5', target: 'SIAE-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'ZTE-A#5-ETH-13<->ZTE-A#6-ETH-13', source: 'ZTE-A#5', target: 'ZTE-A#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'ZTE-A#5-ETH-24<->ZTE-A#6-ETH-24', source: 'ZTE-A#5', target: 'ZTE-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'ZTE-A#5-ETH-24<->ZTE-A#6-ETH-24', source: 'ZTE-A#5', target: 'ZTE-A#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + { data: { id: 'ZTE-Z#4-ETH-13<->ZTE-Z#6-ETH-13', source: 'ZTE-Z#4', target: 'ZTE-Z#6', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'working' } }, + { data: { id: 'ZTE-Z#4-ETH-13<->ZTE-Z#5-ETH-13', source: 'ZTE-Z#4', target: 'ZTE-Z#5', label: 'service13' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service13' , rule: 'protection' } }, + { data: { id: 'ZTE-Z#5-ETH-24<->ZTE-Z#6-ETH-24', source: 'ZTE-Z#5', target: 'ZTE-Z#6', label: 'service24' , layer: 'ETH' , active: 'true' , path: 'false' , service: 'service24' , rule: 'protection' } }, + ] + }; + + var events = eventsFabric(); + + var result = { + colors: colors, + elements: elements, + styles: styles, + events: events + }; + + var someMethodChangingTheElements = function () { + // @Martin: hier kannst Du die Elements ändern, anschließend mußt Du das Ereignis veröffentlichen + // das Ereigniss wird in der Directive aufgefangen und die Grig wird neu gezeichnet + + // Hinweis: Die Reihenfolge muss so bleiben und du kannst NUR result.elements ändern. + + events.publish("elementsChanged", { + elements: result.elements + }); + }; + + return result; + }); + + mwtnTopologyApp.directive("mwtnTopologyEthernetPathGraph", ["mwtnTopologyEthernetPathData", '$mwtnCommons', function (mwtnTopologyEthernetPathData, $mwtnCommons) { + + return { + restrict: 'E', + replace: true, + template: '<div id="cy" style="height: 750px; width: 100%;"></div>', + controller: function () { + + }, + scope: { + + }, + link: function (scope, element, attrs, ctrl) { + + var cy = cytoscape({ + container: element[0], + + boxSelectionEnabled: false, + autounselectify: true, + + style: mwtnTopologyEthernetPathData.styles, + elements: mwtnTopologyEthernetPathData.elements, + layout: { + name: 'preset', + padding: 5 + } + }); + + // @ Martin: Hier wird das Ereignis aus dem Service aboniert. + // Es ist möglich mehrere Ereignisse zu definieren. + mwtnTopologyEthernetPathData.events.subscribe("elementsChanged", function (data) { + + // @Martin: cy aktualisiert sich mit Hilfe der Referenz auf die Elemente aus dem Service + cy.json({ + elements: mwtnTopologyEthernetPathData.elements // oder data.elements + }); + + }); + + // pathGraphData.events.subscribe("styleChanged", function () { + // cy.json({ + // style: mwtnTopologyEthernetPathData.styles + // }); + // }); + + cy.viewport({ + zoom: 0.5, + pan: { x: 150, y: 100 } + }); + + var clearService = function () { + var lable = cy.getElementById('label'); + lable.data('label', ''); + + var pathState = ['working', 'protection', 'hidden']; + pathState.map(function (state) { + var selector = "[path = '" + state + "']"; + cy.elements(selector).map(function (element) { + element.data('path', 'false'); + }); + }); + }; + + var highlightService = function (service) { + var lable = cy.getElementById('label'); + lable.data('label', service); + + var selector = "[service = '" + service + "']"; + // start and end service node (host, traffic analyser) + cy.nodes(selector).map(function (node) { + // console.log(node.id()); + node.data('path', 'working'); + }); + + ['protection', 'working'].map(function (state) { + selector = "[service = '" + service + "'][rule = '" + state + "']"; + cy.edges(selector).map(function (edge) { + edge.connectedNodes().map(function (node) { + node.data('path', edge.data('rule')); + }); + }); + return state; + }).reverse().map(function (state) { + selector = "[path = '" + state + "']"; + cy.nodes(selector).connectedEdges().filter(function (edge) { + return edge.data('service') === service || edge.data('layer') !== "ETH"; + }).map(function (edge) { + edge.data('path', state); + }); + }); + }; + var filterActiveMountPoints = function (mountpoints) { + return mountpoints.filter(function (mountpoint) { + if (!mountpoint) return false; + // console.warn(mountpoint['node-id'], mountpoint['netconf-node-topology:connection-status']); + return mountpoint['netconf-node-topology:connection-status'] === 'connected'; + }).map(function (mountpoint) { + return mountpoint['node-id']; + }); + }; + + var setDevicesActive = function (nodeIds) { + // console.warn(nodeIds); + cy.nodes().filter(function (node) { + node.data('active', 'false'); + return node.data('type') === 'device' && nodeIds.contains(node.data('id')); + }).map(function (node) { + node.data('active', 'true'); + }); + }; + + var setAllDevicesInactive = function () { + cy.nodes().map(function (node) { + node.data('active', 'false'); + }); + }; + + var setPortAndEdgedActive = function () { + cy.edges().map(function (edge) { + var active = 'true'; + edge.connectedNodes().map(function (port) { + // console.log(' node', JSON.stringify(edge.data())); + var parent = cy.getElementById(port.data('parent')); + if (parent.data('active') === 'false') { + port.data('active', 'false'); + edge.data('active', 'false'); + } else { + port.data('active', 'true'); + } + }); + }); + }; + + var init = function () { + var timerName = 'init ethernet'; + console.time(timerName); + $mwtnCommons.getMountPoints().then(function (mountpoints) { + var filtered = filterActiveMountPoints(mountpoints); + setDevicesActive(filtered); + setPortAndEdgedActive(); + console.timeEnd(timerName); + }, function (error) { + setAllDevicesInactive(); + setPortAndEdgedActive(); + console.timeEnd(timerName); + }); + + }; + init(); + + cy.on('tap', function (event) { + clearService(); + if (event.target !== cy) { + if (event.target.data('service')) { + highlightService(event.target.data('service')); + } + } else { + init(); + } + }); + } + } + }]); + + mwtnTopologyApp.controller("mwtnTopologyPortsGridController", ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', 'mwtnTopologyEthernetPathData', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants, mwtnTopologyEthernetPathData) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id" + }, + { + field: "layer", + type: "string", + displayName: "Layer" + }, + { + field: "active", + type: "string", + displayName: "Active" + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ + field: col.field, + term: col.filters[0].term + }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadPage() { + + // extract all ports + var ports = mwtnTopologyEthernetPathData.elements.nodes.filter(function (node, ind, arr) { + return node && node.data && node.data.type === 'port'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) acc[cur.data.id] = cur.data; + return acc; + }, {}); + + // get all port ids + var portIds = Object.keys(ports); + + // apply the grid filters + var tempData = portIds.filter(function (portId, ind, arr) { + var port = ports[portId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + case "active": + return port[filter.field].toString().contains(filter.term); + default: + return port[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (portId) { + var port = ports[portId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: port.id + } + } + + switch (sortColumn.field) { + case "active": + orderBy = port[sortColumn.field] ? 1 : 0; + break; + default: + orderBy = port[sortColumn.field]; + break; + } + + return { + id: port.id, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedPortsAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + portsAtCurrentPageCache = {}; + var orderedData = []; + + orderedPortsAtCurrentPage.forEach(function (orderedPort) { + var port = ports[orderedPort.id]; + portsAtCurrentPageCache[port.id] = port; + orderedData.push({ + id: orderedPort.id, + layer: port.layer, + active: port.active + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + // subscribe to the elementsChanged event to reload the grid page if the data in the service has chenged + mwtnTopologyEthernetPathData.events.subscribe("elementsChanged", function (data) { + loadPage(); + }); + + }]); + + mwtnTopologyApp.directive("mwtnTopologyPortsGrid", [function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologyPortsGridController', + controllerAs: 'vm', + scope: { + + }, + templateUrl: 'src/app/mwtnTopology/templates/portsGrid.tpl.html' + }; + }]); + + mwtnTopologyApp.controller("mwtnTopologyEthConnectionsGridController", ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', 'mwtnTopologyEthernetPathData', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants, mwtnTopologyEthernetPathData) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id", + width: 400 + }, + { + field: "source", + type: "string", + displayName: "PortA", + width: 200 + }, + { + field: "target", + type: "string", + displayName: "PortZ", + width: 200 + }, + { + field: "layer", + type: "string", + displayName: "Layer", + width: 80 + }, + { + field: "service", + type: "string", + displayName: "Service", + width: 150 + }, + { + field: "rule", + type: "string", + displayName: "Rule", + width: 150 + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ + field: col.field, + term: col.filters[0].term + }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadPage() { + + // extract all links + var links = mwtnTopologyEthernetPathData.elements.edges.filter(function (link, ind, arr) { + // return true; // node && node.data && node.data.type === 'port'; + return link.data.layer === 'ETH'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) { + acc[cur.data.id] = cur.data; + } + return acc; + }, {}); + + // get all relevant link ids + var linkIds = Object.keys(links); + + // apply the grid filters + var tempData = linkIds.filter(function (linkId, ind, arr) { + var link = links[linkId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + default: + return link[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (linkId) { + var link = links[linkId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: link.id + } + } + + switch (sortColumn.field) { + default: + orderBy = link[sortColumn.field]; + break; + } + + return { + id: link.id, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedLinksAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + linksAtCurrentPageCache = {}; + var orderedData = []; + + orderedLinksAtCurrentPage.forEach(function (orderedLink) { + var link = links[orderedLink.id]; + linksAtCurrentPageCache[link.id] = link; + orderedData.push({ + id: orderedLink.id, + source: link.source, + target: link.target, + layer: link.layer, + service: link.service, + rule: link.rule + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + // subscribe to the elementsChanged event to reload the grid page if the data in the service has chenged + var subscription = mwtnTopologyEthernetPathData.events.subscribe("elementsChanged", function (data) { + loadPage(); + // to unsubscribe call subscription.remove(); + }); + + }]); + + mwtnTopologyApp.directive("mwtnTopologyEthConnectionsGrid", [function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologyEthConnectionsGridController', + controllerAs: 'vm', + scope: { + + }, + templateUrl: 'src/app/mwtnTopology/templates/ethConnectionsGrid.tpl.html' + }; + }]); + + /********************************************* IEEE 1588v2 (PTP) **************************/ + + mwtnTopologyApp.controller('mwtnTopologyIeee1588ViewController', ['$scope', '$q', '$timeout', '$state', '$window', '$mwtnTopology', function ($scope, $q, $timeout, $state, $window, $mwtnTopology) { + var vm = this; + vm.status = { + topologyIsOpen: false, + portsOpen: false, + ethConnectionsIsOpen: false + } + + $scope.$watchCollection(function () { return [vm.status.topologyIsOpen, vm.status.portsOpen, vm.status.ethConnectionsIsOpen] }, function (newVal, oldVal) { + if (newVal[1] || newVal[2]) { + $timeout(function () { + $window.dispatchEvent(new Event("resize")); + }); + } + }); + }]); + + mwtnTopologyApp.directive('mwtnTopologyIeee1588View', function () { + return { + restrict: 'E', + controller: 'mwtnTopologyIeee1588ViewController', + controllerAs: 'vm', + bindToController: true, + templateUrl: 'src/app/mwtnTopology/templates/ieee1588View.tpl.html', + scope: { + + } + }; + }); + + mwtnTopologyApp.factory("mwtnTopologyIeee1588PathData", function () { + var colors = { + root: '#f54', + port: '#377', + device: '#252', + site: '#525', + edge: '#49a', + white: '#eed', + grey: '#555', + selected: '#ff0' + }; + + var styles = [ + { + selector: 'node', + css: { + 'content': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#aaaaaa', + 'border-color': '#000000', + 'border-width': '1px', + 'color': '#ffffff' + } + }, + { + selector: '$node > node', + css: { + 'shape': 'roundrectangle', + 'padding-top': '10px', + 'padding-left': '10px', + 'padding-bottom': '10px', + 'padding-right': '10px', + 'text-valign': 'top', + 'text-halign': 'center', + 'background-color': '#eeeeee', + 'color': '#444444', + 'border-color': '#888888' + } + }, + { + selector: 'node[type = "site"]', + css: { + 'shape': 'roundrectangle', + 'padding-top': '10px', + 'padding-left': '10px', + 'padding-bottom': '10px', + 'padding-right': '10px', + 'text-valign': 'center', + 'text-halign': 'center', + 'background-color': '#fefefe', + 'color': '#444444', + 'border-color': '#888888', + 'font-weight': 'bold' + } + }, + { + selector: 'node[type = "ptp-clock"][active = "true"]', + css: { + 'background-color': '#316ac5', + 'background-opacity': '0.2', + 'border-color': '#316ac5', + 'border-opacity': '0.8', + 'border-width': '2px', + 'color': '#444444' + } + }, + { + selector: 'node[type = "port"][active = "true"]', + css: { + 'background-opacity': '1.0', + } + }, + { + selector: 'node[active = "false"]', + css: { + 'background-opacity': '0.3', + 'border-opacity': '0.5' + } + }, + { + selector: 'node[path = "true"]', + css: { + 'background-color': '#ff00ff', + 'background-opacity': '0.9', + 'border-color': '#880088', + } + }, + { + selector: '$node > node[path = "true"]', + css: { + 'background-color': '#ff00ff', + 'background-opacity': '0.3', + 'border-color': '#ff00ff', + 'border-opacity': '1.0', + 'border-width': '2px', + } + }, + { + selector: 'edge', + css: { + 'content': 'data(id)', + 'target-arrow-shape': 'triangle', + 'line-color': '#666666', + 'color': '#444444' + } + }, + { + selector: 'edge[active = "false"]', + css: { + 'line-color': '#cccccc', + 'text-opacity': '0.9' + } + }, + { + selector: 'edge[path = "true"]', + css: { + 'line-color': '#ff00ff', + 'width': '5px' + } + }, + { + selector: ':selected', + css: { + 'background-color': 'black', + 'line-color': 'black', + 'target-arrow-color': 'black', + 'source-arrow-color': 'black' + } + }]; + + var elements = { + nodes: [ + { data: { id: 'north', label: 'north', type: 'site', latitude: 50.734916, longitude: 7.137636 } }, + { data: { id: 'north-east', label: 'north-east', type: 'site', latitude: 50.733028, longitude: 7.151086 } }, + { data: { id: 'north-west', label: 'north-west', type: 'site', latitude: 50.730230, longitude: 7.126017 } }, + { data: { id: 'east', label: 'east', type: 'site', latitude: 50.725672, longitude: 7.158488 } }, + { data: { id: 'west', label: 'west', type: 'site', latitude: 50.721914, longitude: 7.120521 } }, + { data: { id: 'south-east', label: 'south-east', type: 'site', latitude: 50.717158, longitude: 7.155506 } }, + { data: { id: 'south-west', label: 'south-west', type: 'site', latitude: 50.714359, longitude: 7.130437 } }, + { data: { id: 'south', label: 'south', type: 'site', latitude: 50.712472, longitude: 7.143887 } }, + + { data: { id: 'ADVA-A', label : 'ADVA-A' , parent : 'west', type: 'ptp-clock', base64: 'AIDq//6MFzA=', hex: '0x47 0x4D 0x30 0x30 0x30 0x30 0x30 0x31', active: 'true' , latitude: 50.721914, longitude: 7.120521, parentDs: '', path: 'false' } }, + { data: { id: 'ADVA-B', label : 'ADVA-B' , parent : 'north-west', type: 'ptp-clock', base64: 'AIDq//6MGDA=', hex: '0x47 0x4D 0x30 0x30 0x30 0x30 0x30 0x32', active: 'true' , latitude: 50.730230, longitude: 7.126017, parentDs: '', path: 'false' } }, + { data: { id: 'ADVA-Y', label : 'ADVA-Y' , parent : 'north-east', type: 'ptp-clock', base64: 'AIDqb0hQAAE=', hex: '0x53 0x4C 0x41 0x56 0x45 0x30 0x30 0x31', active: 'true' , latitude: 50.733028, longitude: 7.151086, parentDs: 'NEC-Z#4', path: 'false' } }, + { data: { id: 'ADVA-Z', label : 'ADVA-Z' , parent : 'south', type: 'ptp-clock', base64: 'AIDqb0mAAAA=', hex: '0x53 0x4C 0x41 0x56 0x45 0x30 0x30 0x32', active: 'true' , latitude: 50.712472, longitude: 7.143887, parentDs: 'Huawei-Z#3', path: 'false' } }, + { data: { id: 'Ericsson-A', label : 'Ericsson-A' , parent : 'north-east', type: 'ptp-clock', base64: 'BE4G//4jsio=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x31', active: 'true' , latitude: 50.733028, longitude: 7.151086, parentDs: 'NEC-Z#2', path: 'false' } }, + { data: { id: 'Ericsson-Z', label : 'Ericsson-Z' , parent : 'east', type: 'ptp-clock', base64: 'BE4G//4jtBA=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x32', active: 'true' , latitude: 50.725672, longitude: 7.158488, parentDs: 'Ericsson-A#6', path: 'false' } }, + { data: { id: 'Huawei-A', label : 'Huawei-A' , parent : 'south-west', type: 'ptp-clock', base64: 'ACWeIQAJq6A=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x33', active: 'true' , latitude: 50.714359, longitude: 7.130437, parentDs: 'Nokia-Z33', path: 'false' } }, + { data: { id: 'Huawei-Z', label : 'Huawei-Z' , parent : 'south', type: 'ptp-clock', base64: 'ACWeIQAJAm8=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x34', active: 'true' , latitude: 50.712472, longitude: 7.143887, parentDs: 'Huawei-A#6', path: 'false' } }, + { data: { id: 'NEC-A', label : 'NEC-A' , parent : 'north', type: 'ptp-clock', base64: 'jN+d//5XDuA=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x35', active: 'true' , latitude: 50.734916, longitude: 7.137636, parentDs: 'ZTE-Z#5', path: 'false' } }, + { data: { id: 'NEC-Z', label : 'NEC-Z' , parent : 'north-east', type: 'ptp-clock', base64: 'jN+d//5XDwA=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x36', active: 'true' , latitude: 50.733028, longitude: 7.151086, parentDs: 'NEC-A#6', path: 'false' } }, + { data: { id: 'Nokia-A', label : 'Nokia-A' , parent : 'west', type: 'ptp-clock', base64: 'ACGu//4Crac=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x37', active: 'true' , latitude: 50.721914, longitude: 7.120521, parentDs: 'ADVA-A#1', path: 'false' } }, + { data: { id: 'Nokia-Z', label : 'Nokia-Z' , parent : 'south-west', type: 'ptp-clock', base64: 'ACGu//4CrZY=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x38', active: 'true' , latitude: 50.714359, longitude: 7.130437, parentDs: 'Nokia-A#6', path: 'false' } }, + { data: { id: 'SIAE-A', label : 'SIAE-A' , parent : 'south', type: 'ptp-clock', base64: 'ALCs//4R6K8=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x30 0x39', active: 'true' , latitude: 50.712472, longitude: 7.143887, parentDs: 'Huawei-Z#5', path: 'false' } }, + { data: { id: 'SIAE-Z', label : 'SIAE-Z' , parent : 'south-east', type: 'ptp-clock', base64: 'ALCs//4RucQ=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x31 0x30', active: 'true' , latitude: 50.717158, longitude: 7.155506, parentDs: 'SIAE-A#6', path: 'false' } }, + { data: { id: 'ZTE-A', label : 'ZTE-A' , parent : 'north-west', type: 'ptp-clock', base64: 'DBJi//7Zdpo=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x31 0x31', active: 'true' , latitude: 50.730230, longitude: 7.126017, parentDs: 'ADVA-B#2', path: 'false' } }, + { data: { id: 'ZTE-Z', label : 'ZTE-Z' , parent : 'north', type: 'ptp-clock', base64: 'DBJi//7ZdqQ=', hex: '0x42 0x43 0x30 0x30 0x30 0x30 0x31 0x32', active: 'true' , latitude: 50.734916, longitude: 7.137636, parentDs: 'ZTE-A#6', path: 'false' } }, + + { data: { id: 'ADVA-A#1', label: '#1', parent: 'ADVA-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.721914, longitude: 7.120521 }, position: { x: 124, y: 564 } }, + { data: { id: 'ADVA-A#2', label: '#2', parent: 'ADVA-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.721914, longitude: 7.120521 }, position: { x: 124, y: 507 } }, + { data: { id: 'ADVA-B#1', label: '#1', parent: 'ADVA-B', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.730230, longitude: 7.126017 }, position: { x: 380, y: 381 } }, + { data: { id: 'ADVA-B#2', label: '#2', parent: 'ADVA-B', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.730230, longitude: 7.126017 }, position: { x: 380, y: 301 } }, + { data: { id: 'ADVA-Y#1', label: '#1', parent: 'ADVA-Y', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1392, y: 229 } }, + { data: { id: 'ADVA-Y#2', label: '#2', parent: 'ADVA-Y', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: 172 } }, + { data: { id: 'ADVA-Z#1', label: '#1', parent: 'ADVA-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1139, y: 1001 } }, + { data: { id: 'ADVA-Z#2', label: '#2', parent: 'ADVA-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1196, y: 944 } }, + { data: { id: 'Ericsson-A#5', label: '#5', parent: 'Ericsson-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1605, y: 172 } }, + { data: { id: 'Ericsson-A#6', label: '#6', parent: 'Ericsson-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1664, y: 226 } }, + { data: { id: 'Ericsson-Z#6', label: '#6', parent: 'Ericsson-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.725672, longitude: 7.158488 }, position: { x: 1765, y: 325 } }, + { data: { id: 'Huawei-A#5', label: '#5', parent: 'Huawei-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.714359, longitude: 7.130437 }, position: { x: 605, y: 1028 } }, + { data: { id: 'Huawei-A#6', label: '#6', parent: 'Huawei-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.714359, longitude: 7.130437 }, position: { x: 685, y: 1028 } }, + { data: { id: 'Huawei-Z#3', label: '#3', parent: 'Huawei-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1046, y: 1094 } }, + { data: { id: 'Huawei-Z#4', label: '#4', parent: 'Huawei-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 989, y: 1094 } }, + { data: { id: 'Huawei-Z#5', label: '#5', parent: 'Huawei-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1058, y: 1123 } }, + { data: { id: 'Huawei-Z#6', label: '#6', parent: 'Huawei-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 978, y: 1123 } }, + { data: { id: 'NEC-A#3', label: '#3', parent: 'NEC-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.734916, longitude: 7.137636 }, position: { x: 955, y: -52 } }, + { data: { id: 'NEC-A#6', label: '#6', parent: 'NEC-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.734916, longitude: 7.137636 }, position: { x: 1035, y: -52 } }, + { data: { id: 'NEC-Z#2', label: '#2', parent: 'NEC-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: -41 } }, + { data: { id: 'NEC-Z#3', label: '#3', parent: 'NEC-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1392, y: 16 } }, + { data: { id: 'NEC-Z#4', label: '#4', parent: 'NEC-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1449, y: 16 } }, + { data: { id: 'NEC-Z#6', label: '#6', parent: 'NEC-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.733028, longitude: 7.151086 }, position: { x: 1382, y: -23 } }, + { data: { id: 'Nokia-A13', label: '13', parent: 'Nokia-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.721914, longitude: 7.120521 }, position: { x: 40, y: 801 } }, + { data: { id: 'Nokia-A34', label: '34', parent: 'Nokia-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.721914, longitude: 7.120521 }, position: { x: 28, y: 772 } }, + { data: { id: 'Nokia-A#6', label: '#6', parent: 'Nokia-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.721914, longitude: 7.120521 }, position: { x: 28, y: 829 } }, + { data: { id: 'Nokia-Z33', label: '33', parent: 'Nokia-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.714359, longitude: 7.130437 }, position: { x: 385, y: 1028 } }, + { data: { id: 'Nokia-Z#6', label: '#6', parent: 'Nokia-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.714359, longitude: 7.130437 }, position: { x: 305, y: 1028 } }, + { data: { id: 'SIAE-A#5', label: '#5', parent: 'SIAE-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1278, y: 1123 } }, + { data: { id: 'SIAE-A#6', label: '#6', parent: 'SIAE-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.712472, longitude: 7.143887 }, position: { x: 1346, y: 1094 } }, + { data: { id: 'SIAE-Z#6', label: '#6', parent: 'SIAE-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.717158, longitude: 7.155506 }, position: { x: 1588, y: 838 } }, + { data: { id: 'ZTE-A#3', label: '#3', parent: 'ZTE-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.730230, longitude: 7.126017 }, position: { x: 380, y: 168 } }, + { data: { id: 'ZTE-A#4', label: '#4', parent: 'ZTE-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.730230, longitude: 7.126017 }, position: { x: 345, y: 148 } }, + { data: { id: 'ZTE-A#6', label: '#6', parent: 'ZTE-A', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.730230, longitude: 7.126017 }, position: { x: 408, y: 99 } }, + { data: { id: 'ZTE-Z#5', label: '#5', parent: 'ZTE-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.734916, longitude: 7.137636 }, position: { x: 747, y: -27 } }, + { data: { id: 'ZTE-Z#6', label: '#6', parent: 'ZTE-Z', type: 'port', layer: 'PTP', active: 'true', path: 'false', latitude: 50.734916, longitude: 7.137636 }, position: { x: 667, y: -27 } }, + + ], + edges: [ + { data: { id: 'ERI1', source: 'Ericsson-A#6', target: 'Ericsson-Z#6', label: 'ERI1', layer: 'PTP', active: 'true' } }, + { data: { id: '71', source: 'Huawei-A#6', target: 'Huawei-Z#6', label: '71', layer: 'PTP', active: 'true' } }, + { data: { id: '81', source: 'NEC-A#6', target: 'NEC-Z#6', label: '81', layer: 'PTP', active: 'true' } }, + { data: { id: '91', source: 'Nokia-A#6', target: 'Nokia-Z#6', label: '91', layer: 'PTP', active: 'true' } }, + { data: { id: '101', source: 'SIAE-A#6', target: 'SIAE-Z#6', label: '101', layer: 'PTP', active: 'true' } }, + { data: { id: '111', source: 'ZTE-A#6', target: 'ZTE-Z#6', label: '111', layer: 'PTP', active: 'true' } }, + + { data: { id: 'ETY01', source: 'ADVA-A#1', target: 'Nokia-A34', label: 'ADVA-A#1-Nokia-A34', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY02', source: 'ADVA-A#2', target: 'ZTE-A#4', label: 'ADVA-A#2-ZTE-A#4', layer: 'PTP', active: 'false' } }, + { data: { id: 'ETY03', source: 'ADVA-B#1', target: 'Nokia-A13', label: 'ADVA-B#1-Nokia-A13', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY04', source: 'ADVA-B#2', target: 'ZTE-A#3', label: 'ADVA-B#2-ZTE-A#3', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY05', source: 'ADVA-Y#1', target: 'Huawei-Z#4', label: 'ADVA-Y#1-Huawei-Z#4', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY06', source: 'ADVA-Y#2', target: 'NEC-Z#4', label: 'ADVA-Y#2-NEC-Z#4', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY09', source: 'ADVA-Z#1', target: 'Huawei-Z#3', label: 'ADVA-Z#1-Huawei-Z#3', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY10', source: 'ADVA-Z#2', target: 'NEC-Z#3', label: 'ADVA-Z#2-NEC-Z#3', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY21', source: 'Ericsson-A#5', target: 'NEC-Z#2', label: 'Ericsson-A#5-NEC-Z#2', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY24', source: 'Huawei-A#5', target: 'Nokia-Z33', label: 'Huawei-A#5-Nokia-Z33', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY25', source: 'Huawei-Z#5', target: 'SIAE-A#5', label: 'Huawei-Z#5-SIAE-A#5', layer: 'PTP', active: 'true' } }, + { data: { id: 'ETY26', source: 'NEC-A#3', target: 'ZTE-Z#5', label: 'NEC-A#3-ZTE-Z#5', layer: 'PTP', active: 'true' } }, + + ] + }; + + var events = eventsFabric(); + + var result = { + colors: colors, + elements: elements, + styles: styles, + events: events + }; + + var someMethodChangingTheElements = function () { + // @Martin: hier kannst Du die Elements ändern, anschließend mußt Du das Ereignis veröffentlichen + // das Ereigniss wird in der Directive aufgefangen und die Grig wird neu gezeichnet + + // Hinweis: Die Reihenfolge muss so bleiben und du kannst NUR result.elements ändern. + + events.publish("elementsChanged", { + elements: result.elements + }); + }; + + return result; + }); + + mwtnTopologyApp.directive("mwtnTopologyIeee1588PathGraph", ["mwtnTopologyIeee1588PathData", "$mwtnPtp", function (mwtnTopologyIeee1588PathData, $mwtnPtp) { + + return { + restrict: 'E', + replace: true, + template: '<div style="height: 750px; width: 100%;"></div>', + controller: function () { + + }, + scope: { + + }, + link: function (scope, element, attrs, ctrl) { + + var cy = cytoscape({ + container: element[0], + + boxSelectionEnabled: false, + autounselectify: true, + + style: mwtnTopologyIeee1588PathData.styles, + elements: mwtnTopologyIeee1588PathData.elements, + layout: { + name: 'preset', + padding: 5 + } + }); + + // @ Martin: Hier wird das Ereignis aus dem Service aboniert. + // Es ist möglich mehrere Ereignisse zu definieren. + mwtnTopologyIeee1588PathData.events.subscribe("elementsChanged", function (data) { + + // @Martin: cy aktualisiert sich mit Hilfe der Referenz auf die Elemente aus dem Service + cy.json({ + elements: mwtnTopologyIeee1588PathData.elements // oder data.elements + }); + }); + + // pathGraphData.events.subscribe("styleChanged", function () { + // cy.json({ + // style: mwtnTopologyIeee1588PathData.styles + // }); + // }); + + cy.viewport({ + zoom: 0.5, + pan: { x: 150, y: 100 } + }); + + var clearPtpPath = function () { + var selector = "[path = 'true']"; + cy.elements(selector).map(function (element) { + element.data('path', 'false'); + }); + }; + + var highlightPtpMaster = function (id) { + var selector = "[id = '" + id + "']"; + cy.nodes(selector).map(function (node) { + if (node.data('parentDs') && node.data('parentDs') != '') { + // console.warn('parentDs', node.data('parentDs')); + var parentNode = node.data('parentDs').slice(0, -2); + if (parentNode !== id) { + highlightPtpMaster(parentNode); + + // highlight edge + selector = "[id = '" + node.data('parentDs') + "']"; + cy.nodes(selector).connectedEdges().map(function (edge) { + edge.data('path', 'true'); + edge.connectedNodes().map(function (node) { + node.data('path', 'true'); + }); + }); + } + } + }); + }; + + var setAllDevicesInactive = function () { + cy.nodes().map(function (node) { + node.data('active', 'false'); + }); + }; + + var setPortAndEdgedActive = function () { + cy.edges().map(function (edge) { + var active = 'true'; + edge.connectedNodes().map(function (port) { + // console.log(' node', JSON.stringify(edge.data())); + var parent = cy.getElementById(port.data('parent')); + if (parent.data('active') === 'false') { + port.data('active', 'false'); + edge.data('active', 'false'); + } else { + port.data('active', 'true'); + } + }); + }); + }; + + var init = function () { + setAllDevicesInactive(); + $mwtnPtp.getPtpClocks().then(function (clocks) { + // setDevicesActive(Object.keys(clocks)); + var hex = true; + // update clock ids first + Object.keys(clocks).map(function (key) { + var clock = clocks[key]; + var graphClock = cy.getElementById(key); + graphClock.data('active', 'true') + graphClock.data('base64', clock.getIdentity()); + graphClock.data('hex', clock.getIdentity(hex)); + }); + // update rest + Object.keys(clocks).map(function (key) { + var clock = clocks[key]; + var graphClock = cy.getElementById(key); + var graphParentDs = nodeId(clock.getParent().slice(0, -2)); + graphClock.data('parentDs', graphParentDs + clock.getParent().slice(-2)); + graphClock.data('grandMaster', nodeId(clock.getGrandMaster())); + + // clock.getPtpPorts().map(function(port){ + // // console.warn(port.getId(), port.getNumber(), port.getState(), port.isSlave(), port.isMaster(), port.getLogicalTerminationPointReference()); + // var portKey = [key, port.getNumber() < 10 ? '#' : '', port.getNumber()].join(''); + // var graphPort = cy.getElementById(portKey); + // // console.warn(JSON.stringify(graphPort.data())); + // if (graphPort === undefined) { + // console.error('PtpPort not found in graph:' , portKey); + // } else { + // console.info('PtpPort found in graph:' , portKey); + // } + + // }); + }); + setPortAndEdgedActive(); + }, function (error) { + setPortAndEdgedActive(); + console.error(JSON.stringify(error)); + }); + }; + // init(); + + var getNodeId = function (base64) { + if (base64 === undefined || base64 === '') return ''; + + var selector = "[type = 'ptp-clock']"; + var result = cy.nodes(selector).filter(function (graphClock) { + // console.error(base64, graphClock.data('base64'), graphClock.data('base64') === base64); + return graphClock.data('base64') === base64; + }); + if (result.length === 0) { + console.warn('Clock', base64, 'not found!'); + return ''; + } else { + return result[0].id(); + } + }; + + var getParentClock = function (nodeId) { + $mwtnPtp.getParent(nodeId).then(function (parentPortIdentity) { + var parentNode = getNodeId(parentPortIdentity['clock-identity']); + console.log(JSON.stringify(parentPortIdentity), parentNode); + if (parentNode) { + getParentClock(parentNode); + } + }); + }; + + cy.on('tap', function (event) { + console.log('tap'); + clearPtpPath(); + if (event.target !== cy) { + if (event.target.data('type') === 'ptp-clock') { + getParentClock(event.target.id()); + // highlightPtpMaster(event.target.id()); + } else if (event.target.data('type') === 'port') { + var parent = cy.getElementById(event.target.data('parent')); + // highlightPtpMaster(parent.id()); + getParentClock(event.target.id()); + } + } else { + // init(); + } + }); + + } + } + }]); + + mwtnTopologyApp.controller("mwtnTopologyClocksGridController", ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', 'mwtnTopologyIeee1588PathData', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants, mwtnTopologyIeee1588PathData) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Node id", + width: 120 + }, + { + field: "hex", + type: "string", + displayName: "Clock identity in hex", + width: 300 + }, { + field: "base64", + type: "string", + displayName: "... in base64", + width: 150 + }, + { + field: "parentDs", + type: "string", + displayName: "parentDs", + width: 150 + }, + { + field: "grandMaster", + type: "string", + displayName: "grandmaster", + width: 300 + }, + { + field: "active", + type: "string", + displayName: "Active", + width: 80 + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ + field: col.field, + term: col.filters[0].term + }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadPage() { + + // extract all ports + var ports = mwtnTopologyIeee1588PathData.elements.nodes.filter(function (node, ind, arr) { + return node && node.data && node.data.type === 'ptp-clock'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) acc[cur.data.id] = cur.data; + return acc; + }, {}); + + // get all port ids + var portIds = Object.keys(ports); + + // apply the grid filters + var tempData = portIds.filter(function (portId, ind, arr) { + var port = ports[portId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + case "active": + return port[filter.field].toString().contains(filter.term); + default: + return port[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (portId) { + var port = ports[portId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: port.id + } + } + + switch (sortColumn.field) { + case "active": + orderBy = port[sortColumn.field] ? 1 : 0; + break; + default: + orderBy = port[sortColumn.field]; + break; + } + + return { + id: port.id, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedPortsAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + portsAtCurrentPageCache = {}; + var orderedData = []; + + orderedPortsAtCurrentPage.forEach(function (orderedPort) { + var port = ports[orderedPort.id]; // TODO [sko] varible port should be renamed to clock + portsAtCurrentPageCache[port.id] = port; + orderedData.push({ + id: orderedPort.id, + layer: port.layer, + active: port.active, + hex: port.hex, + base64: port.base64, + parentDs: port.parentDs, + grandMaster: port.grandMaster + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + // subscribe to the elementsChanged event to reload the grid page if the data in the service has chenged + mwtnTopologyIeee1588PathData.events.subscribe("elementsChanged", function (data) { + loadPage(); + }); + + }]); + + mwtnTopologyApp.directive("mwtnTopologyClocksGrid", [function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologyClocksGridController', + controllerAs: 'vm', + scope: { + + }, + templateUrl: 'src/app/mwtnTopology/templates/clocksGrid.tpl.html' + }; + }]); + + mwtnTopologyApp.controller("mwtnTopologyPtpLinksGridController", ['$scope', '$timeout', '$state', '$mwtnCommons', '$mwtnTopology', 'uiGridConstants', 'mwtnTopologyIeee1588PathData', function ($scope, $timeout, $state, $mwtnCommons, $mwtnTopology, uiGridConstants, mwtnTopologyIeee1588PathData) { + var vm = this; + + // The page number to show in the grid. + var paginationPage = 1; + // The page size. + var paginationPageSize = 100; + // The grid column object with current sorting informations. + var sortColumn = null; + // The grid column object with current sorting informations. + var gridFilters = []; + // caches all sites at the current grid page + + vm.gridOptions = Object.assign({}, $mwtnCommons.gridOptions, { + showGridFooter: false, // disable the grid footer because the pagination component sets its own. + paginationPageSizes: [10, 25, 50, 100], + paginationPageSize: paginationPageSize, + useExternalPagination: true, + useExternalFiltering: true, + useExternalSorting: true, + totalItems: 0, + columnDefs: [{ + field: "id", + type: "string", + displayName: "Id" + }, + { + field: "source", + type: "string", + displayName: "PortA" + }, + { + field: "target", + type: "string", + displayName: "PortZ" + }, + { + field: "active", + type: "string", + displayName: "active" + } + ], + data: [], + onRegisterApi: function (gridApi) { + // http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi + vm.gridApi = gridApi; + + vm.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) { + // Save the current sort column for later use. + sortColumn = (!sortColumns || sortColumns.length === 0) ? + null : + sortColumns[0]; + loadPage(); + }); + + vm.gridApi.pagination.on.paginationChanged($scope, function (newPage, newPageSize) { + // Save the pagination informations for later use. + paginationPage = newPage; + paginationPageSize = newPageSize; + loadPage(); + }); + + vm.gridApi.core.on.filterChanged($scope, function () { + // Save the all filters for later use. + var filters = []; + this.grid.columns.forEach(function (col, ind) { + if (col.filters[0] && col.filters[0].term) { + filters.push({ + field: col.field, + term: col.filters[0].term + }); + } + }); + gridFilters = filters; + loadPage(); + }); + + loadPage(); + } + }); + + /** + * Calculates the page content of the grid and sets the values to the gridOprions.data object. + */ + function loadPage() { + + // extract all links + var links = mwtnTopologyIeee1588PathData.elements.edges.filter(function (node, ind, arr) { + return true; // node && node.data && node.data.type === 'port'; + }).reduce(function (acc, cur, ind, arr) { + if (cur.data) { + acc[cur.data.id] = cur.data; + } + return acc; + }, {}); + + // get all link ids + var linkIds = Object.keys(links); + + // apply the grid filters + var tempData = linkIds.filter(function (linkId, ind, arr) { + var link = links[linkId]; + return gridFilters.map(function (filter) { + switch (filter.field) { + default: + return link[filter.field].contains(filter.term); + } + }).and(true); + }).map(function (linkId) { + var link = links[linkId]; + var orderBy; + + if (!sortColumn || !sortColumn.sort.direction) { + return { + id: link.id + } + } + + switch (sortColumn.field) { + case "active": + orderBy = link[sortColumn.field] ? 1 : 0; + default: + orderBy = link[sortColumn.field]; + break; + } + + return { + id: link.id, + orderBy: orderBy + }; + }); + + if (sortColumn && sortColumn.sort.direction) { + tempData.sort(function (left, right) { + if (left === right || left.orderBy === right.orderBy) { + return 0; + } + if (left.orderBy > right.orderBy) { + return (sortColumn.sort.direction === uiGridConstants.ASC) ? 1 : -1; + } + return (sortColumn.sort.direction === uiGridConstants.ASC) ? -1 : 1; + }); + } + + var maxPageNumber = Math.max(1, Math.ceil(tempData.length / paginationPageSize)); + var currentPage = Math.min(maxPageNumber, paginationPage); + var orderedLinksAtCurrentPage = tempData.slice((currentPage - 1) * paginationPageSize, currentPage * paginationPageSize); + + linksAtCurrentPageCache = {}; + var orderedData = []; + + orderedLinksAtCurrentPage.forEach(function (orderedLink) { + var link = links[orderedLink.id]; + linksAtCurrentPageCache[link.id] = link; + orderedData.push({ + id: orderedLink.id, + source: link.source, + target: link.target, + active: link.active + }); + }); + + $timeout(function () { + vm.gridOptions.data = orderedData; + vm.gridOptions.totalItems = tempData.length; + }); + } + + // subscribe to the elementsChanged event to reload the grid page if the data in the service has chenged + var subscription = mwtnTopologyIeee1588PathData.events.subscribe("elementsChanged", function (data) { + loadPage(); + // to unsubscribe call subscription.remove(); + }); + + }]); + + mwtnTopologyApp.directive("mwtnTopologyPtpLinksGrid", [function () { + return { + restrict: 'E', + replace: false, + controller: 'mwtnTopologyPtpLinksGridController', + controllerAs: 'vm', + scope: { + + }, + templateUrl: 'src/app/mwtnTopology/templates/ptpLinksGrid.tpl.html' + }; + }]); + + mwtnTopologyApp.filter('coordinateFilter', coordinateFilter); + + function coordinateFilter($sce) { + + return function (coordinate, conversion, type, places) { + + // The filter will be running as we type values into the input boxes, which returns undefined + // and brings up an error in the console. Here wait until the coordinate is defined + if (coordinate != undefined) { + + // Check for user input that is a positive or negative number with the option + // that it is a float. Match only the numbers and not the white space or other characters + var pattern = /[-+]?[0-9]*\.?[0-9]+/g + var match = String(coordinate).match(pattern); + + if (conversion === "toDD" && match && coordinateIsValid(match, type)) { + // If the match array only has one item, the user has provided decimal degrees + // and we can just return what the user typed in + if (match.length === 1) { + return parseFloat(match); + } + + // If the match array has a length of three then we know degrees, minutes, and seconds + // were provided so we can convert it to decimal degrees + if (match.length === 3) { + return toDecimalDegrees(match); + } + } + + else if (conversion === 'toDMS' && match && coordinateIsValid(match, type)) { + // When converting from decimal degrees to degrees, minutes and seconds, if + // the match array has one item we know the user has input decimal degrees + // so we can convert it to degrees, minutes and seconds + if (match.length === 1) { + return toDegreesMinutesSeconds(match, type); + } + + // To properly format the converted coordinates we will need to add in HTML entities + // which means we'll need to bind the returned string as HTML and thus we need + // to use $sce (Strict Contextual Escaping) to say that we trust what is being bound as HTML + if (match.length === 3) { + return $sce.trustAsHtml(match[0] + '° ' + match[1] + '′ ' + match[2] + '″ '); + } + } + + // Output a notice that the coordinates are invalid if they are + else if (!coordinateIsValid(match, type)) { + return "Invalid Coordinate!"; + } + + function toDecimalDegrees(coord) { + // Setup for all parts of the DMS coordinate and the necessary math to convert + // from DMS to DD + var degrees = parseInt(coord[0]); + var minutes = parseInt(coord[1]) / 60; + var seconds = parseInt(coord[2]) / 3600; + + // When the degrees value is negative, the math is a bit different + // than when the value is positive. This checks whether the value is below zero + // and does subtraction instead of addition if it is. + if (degrees < 0) { + var calculated = degrees - minutes - seconds; + return calculated.toFixed(places || 4); + } + else { + var calculated = degrees + minutes + seconds + return calculated.toFixed(places || 4); + } + } + + // This function converts from DD to DMS. Math.abs is used a lot because + // for the minutes and seconds, negative values aren't valid + function toDegreesMinutesSeconds(decimal_degrees, type) { + + var dd = decimal_degrees[0]; + var direction = 'E'; + + if (type === 'lat') { + if (dd < 0) { + direction = 'S'; + } else { + direction = 'N' + } + } else { + if (dd < 0) { + direction = 'W'; + } else { + direction = 'E' + } + } + + dd = Math.abs(dd); + var degrees = Math.floor(dd); + var frac = dd - degrees; // get fractional part + var min = Math.floor(frac * 60); + var sec = frac * 3600 - min * 60; + + var formated = [degrees, '° ', ("0" + min).slice(-2), '\' ', ("0" + sec.toFixed(4)).slice(-7), '\" ', direction]; + return formated.join(''); + + // var degrees = coordinate[0].split('.')[0]; + // var minutes = Math.abs(Math.floor(60 * (Math.abs(coordinate[0]) - Math.abs(degrees)))); + // var seconds = 3600 * (Math.abs(coordinate[0]) - Math.abs(degrees) - Math.abs(minutes) / 60).toFixed(2); + + // return $sce.trustAsHtml(degrees + '° ' + minutes + '\' ' + seconds + '\" '); + + } + + // This function checks whether the coordinate value the user enters is valid or not. + // If the coordinate doesn't pass one of these rules, the function will return false + // which will then alert the user that the coordinate is invalid. + function coordinateIsValid(coordinate, type) { + if (coordinate) { + + // The degree values of latitude coordinates have a range between -90 and 90 + if (coordinate[0] && type === 'lat') { + if (!(-90 <= +(coordinate[0]) <= 90)) return false; + } + // The degree values longitude coordinates have a range between -180 and 180 + else if (coordinate[0] && type === 'lon') { + if (!(-180 <= +(coordinate[0]) <= 180)) return false; + } + // Minutes and seconds can only be between 0 and 60 + if (coordinate[1]) { + if (!(0 <= +(coordinate[1]) <= 60)) return false; + } + if (coordinate[2]) { + if (!(0 <= +(coordinate[2]) <= 60)) return false; + } + } + + // If the coordinate made it through all the rules above, the function + // returns true because the coordinate is good + return true; + } + } + } + } +});
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.module.js new file mode 100755 index 00000000..db795d22 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.module.js @@ -0,0 +1,57 @@ +/* + * 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 mwtnTopologyApp = angular.module('app.mwtnTopology', ['app.core', 'ui.router.state', 'ui.grid', 'ui.grid.pagination', 'ui.grid.selection', 'ui.bootstrap', 'config', 'app.mwtnCommons']); + + mwtnTopologyApp.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + // // AF/MF: Warum? (Remove as soon as possible) + // mwtnTopologyApp.register = { + // controller: $controllerProvider.register, + // directive: $compileProvider.directive, + // factory: $provide.factory, + // service: $provide.service + // }; + + NavHelperProvider.addControllerUrl('app/mwtnTopology/mwtnTopology.controller'); + NavHelperProvider.addToMenu('mwtnTopology', { + "link": "#/pnfTopology/site", + "active": "main.mwtnTopology", + "title": "pnf Topology", + "icon": "fa fa-connectdevelop", // Add navigation icon css class here + "page": { + "title": "pnf Topology", + "description": "mwtnTopology" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.mwtnTopology', { + url: 'pnfTopology/:tab?&top&bottom&right&left&lat&lng&zoom&site&siteLink&sitePath', + reloadOnSearch: false, + access: access.admin, + params: { + internal: false + }, + views: { + content: { + template: '<mwtn-topology-frame />' + } + } + }); + + }); + + return mwtnTopologyApp; +});
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.rest b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.rest new file mode 100755 index 00000000..323b13ad --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.rest @@ -0,0 +1,209 @@ +###
+# get outer bounding box for all sites.
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "aggregations": {
+ "top": {
+ "max": {
+ "field": "location.lat"
+ }
+ },
+ "right": {
+ "max": {
+ "field": "location.lon"
+ }
+ },
+ "bottom": {
+ "min": {
+ "field": "location.lat"
+ }
+ },
+ "left": {
+ "min": {
+ "field": "location.lon"
+ }
+ }
+ },
+ "size": 0
+}
+
+###
+# get sites in bounding box
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "geo_bounding_box": {
+ "location": {
+ "top": -10.681254175812176,
+ "right": -48.3738302863769,
+ "bottom": -10.736012963621369,
+ "left": -48.433356043212834
+ }
+ }
+ },
+ "size": 100
+}
+
+###
+# get single site by id
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "bool": {
+ "must": [
+ {
+ "term": {
+ "id": "vivsp"
+ }
+ }
+ ]
+ }
+ }
+}
+
+###
+# get sites with site links
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "bool": {
+ "must": {
+ "exists": {
+ "field": "references.site-links"
+ }
+ }
+ }
+ },
+ "size": 100
+}
+
+###
+# get the first 3 site links
+POST http://03-wtp-poc:9200/mwtn/site-link/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "match_all": {}
+ },
+ "size": 3
+}
+
+###
+# get site links where siteA or siteZ refers to a list ob site ids.
+POST http://03-wtp-poc:9200/mwtn/site-link/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "bool": {
+ "filter": {
+ "term": {
+ "siteA": "atdrj"
+ }
+ }
+ }
+ }
+}
+
+###
+# get site links where siteLinkId is one of the ids in given List.
+POST http://03-wtp-poc:9200/mwtn/site-link/_search
+content-type: application/json
+
+{
+ "query": {
+ "bool": {
+ "should": [
+ {"term": {"id" : "aaapb:aacal"}},
+ {"term": {"id" : "site-6:site-7"}},
+ {"term": {"id" : "site-7:site-8"}}
+ ]
+ }
+ }
+}
+
+###
+# get the first 3 site links
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "match_all": {}
+ },
+ "sort" : {
+ "name": {
+ "order": "asc"
+ }
+ },
+ "size": 30
+}
+
+###
+# get the first 3 site links
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "match_all": {}
+ },
+ "sort" : {
+ "_script" : {
+ "script" : {
+ "lang": "expression",
+ "inline" : "doc['references'].value['site-links'].length"
+ } ,
+ "type" : "number",
+ "order" : "desc"
+ }
+ },
+ "size": 30
+}
+
+
+###
+# get the first 3 site links
+POST http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "from":0,
+ "size":10,
+ "sort": {
+ "id":{
+ "order":"asc"
+ }
+ },
+ "query":{
+ "regexp":{
+ "name":".*00.*"
+ }
+ }
+}
+
+
+###
+# get the first 3 site links
+GET http://03-wtp-poc:9200/mwtn/site/_search HTTP/1.1
+content-type: application/json
+
+{
+ "query": {
+ "function_score": {
+ "script_score": {
+ "script": "Math.pow(2, 2)",
+ "lang": "groovy"
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.services.js new file mode 100755 index 00000000..195c08f0 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/mwtnTopology.services.js @@ -0,0 +1,1020 @@ +/* + * 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 + */ + +/** Type Definitions + * @typedef {{id: string, siteLink: string, radio: string, polarization: string }} AirInterfaceLink + * @typedef {{id: string, siteA: string, siteZ: string, siteNameA: string, siteNameZ: string, airInterfaceLinks: AirInterfaceLink[] }} DbLink + * @typedef {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: DbLink, _type: string}[], max_score: number, total: number}}, status: number}} DbLinkResult */ + +define(['app/mwtnTopology/mwtnTopology.module'], function (mwtnTopologyApp) { +// module.exports = function () { +// const mwtnTopologyApp = require('app/mwtnTopology/mwtnTopology.module'); +// const mwtnTopologyCommons = require('app/mwtnCommons/mwtnCommons.service'); + + mwtnTopologyApp.factory('$mwtnTopology', function ($q, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + var service = {}; + + // AF/MF: Obsolete - will removed soon. All data access function + service.getRequiredNetworkElements = $mwtnCommons.getRequiredNetworkElements; + service.gridOptions = $mwtnCommons.gridOptions; + service.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader; + service.getAllData = $mwtnDatabase.getAllData; + + + /** + * Since not all browsers implement this we have our own utility that will + * convert from degrees into radians + * + * @param deg - The degrees to be converted into radians + * @return radians + */ + var _toRad = function (deg) { + return deg * Math.PI / 180; + }; + + /** + * Since not all browsers implement this we have our own utility that will + * convert from radians into degrees + * + * @param rad - The radians to be converted into degrees + * @return degrees + */ + var _toDeg = function (rad) { + return rad * 180 / Math.PI; + }; + + // public functions + /** + * Calculate the bearing between two positions as a value from 0-360 + * + * @param lat1 - The latitude of the first position + * @param lng1 - The longitude of the first position + * @param lat2 - The latitude of the second position + * @param lng2 - The longitude of the second position + * + * @return int - The bearing between 0 and 360 + */ + service.bearing = function (lat1, lng1, lat2, lng2) { + var dLon = (lng2 - lng1); + var y = Math.sin(dLon) * Math.cos(lat2); + var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon); + var brng = _toDeg(Math.atan2(y, x)); + return 360 - ((brng + 360) % 360); + }, + + + /** + * Gets the geospatial distance between two points + * @param lat1 {number} The latitude of the first point. + * @param lon1 {number} The longitude of the first point. + * @param lat2 {number} The latitude of the second point. + * @param lon2 {number} The longitude of the second point. + * @returns {number} The distance between the two given points. + */ + service.getDistance = function (lat1, lon1, lat2, lon2) { + var R = 6371; // km + var φ1 = _toRad(lat1); + var φ2 = _toRad(lat2); + var Δφ = _toRad(lat2 - lat1); + var Δλ = _toRad(lon2 - lon1); + + var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + + Math.cos(φ1) * Math.cos(φ2) * + Math.sin(Δλ / 2) * Math.sin(Δλ / 2); + var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return (R * c).toFixed(3); + }; + + /** + * Gets a promise which is resolved if the database has been calculated the bounds containing all sites. + * @returns {promise} The promise which is resolved if the database has completed its calculation. + */ + service.getOuterBoundingRectangleForSites = function () { + var getOuterBoundingRectangleForSitesDefer = $q.defer(); + var aggregation = { + "aggregations": { + "top": { + "max": { + "field": "location.lat" + } + }, + "right": { + "max": { + "field": "location.lon" + } + }, + "bottom": { + "min": { + "field": "location.lat" + } + }, + "left": { + "min": { + "field": "location.lon" + } + } + }, + "size": 0 + }; + + $mwtnDatabase.getAggregatedData('mwtn', 'site', aggregation).then(function (result) { + getOuterBoundingRectangleForSitesDefer.resolve({ + top: result.data.aggregations.top.value, + right: result.data.aggregations.right.value, + bottom: result.data.aggregations.bottom.value, + left: result.data.aggregations.left.value + }); + }, function (error) { + getOuterBoundingRectangleForSitesDefer.reject(error); + }); + + return getOuterBoundingRectangleForSitesDefer.promise; + }; + + /** + * Gets a promise which resolved with an array of sites within the given bounding box. + * @param boundingBox {{top: number, right: number, bottom: number, left: number}} The bounding box to get all sites for. + * @param chunkSize {number} The maximum count of sites who should return. + * @param chunkSiteStartIndex {number} The index of the first site element to get. + */ + service.getSitesInBoundingBox = function (boundingBox, chunkSize, chunkSiteStartIndex) { + var resultDefer = $q.defer(); + + var filter = { + "geo_bounding_box": { + "location": { + "top": boundingBox.top, + "right": boundingBox.right, + "bottom": boundingBox.bottom, + "left": boundingBox.left + } + } + }; + + $mwtnDatabase.getFilteredData("mwtn", "site", chunkSiteStartIndex, chunkSize, filter) + .then(processResult, resultDefer.reject); + + return resultDefer.promise; + + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, name: string, location: {lat: number, lon: number}, "amsl-ground": number, references: {"network-elements": string[], "site-links": string[]}}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function processResult(result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + var total = hits.total; + var sites = []; + + for (var hitIndex = 0; hitIndex < hits.hits.length; ++hitIndex) { + var site = hits.hits[hitIndex]; + sites.push({ + id: site._source.id, + name: site._source.name, + type: site._source.type, + location: { + lat: site._source.location.lat, + lng: site._source.location.lon + }, + amslGround: site._source["amsl-ground"], + references: { + siteLinks: site._source.references["site-links"] + } + }); + } + + resultDefer.resolve({ + chunkSize: chunkSize, + chunkSiteStartIndex: chunkSiteStartIndex, + total: total, + sites: sites + }) + } + }; + + /** + * Gets a promise which is resolved with an array of sites filtered by given site ids. + * This function does not use chunks! + * @param siteIds {string[]} The ids of the sites to return. + */ + service.getSitesByIds = function (siteIds) { + var resultDefer = $q.defer(); + + if (!siteIds || siteIds.length === 0) { + resultDefer.resolve([]); + return resultDefer.promise; + } + + var query = { + bool: { + should: siteIds.map(function (siteId) { + return { term: { id: siteId } }; + }) + } + }; + + $mwtnDatabase.getFilteredData("mwtn", "site", 0, siteIds.length, query) + .then(processResult, resultDefer.reject); + + return resultDefer.promise; + + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, name: string, location: {lat: number, lon: number}, "amsl-ground": number, references: {"network-elements": string[], "site-links": string[]}}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function processResult(result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + var total = hits.total; + var sites = []; + + for (var hitIndex = 0; hitIndex < hits.hits.length; ++hitIndex) { + var site = hits.hits[hitIndex]; + sites.push({ + id: site._source.id, + name: site._source.name, + type: site._source.type, + location: { + lat: site._source.location.lat, + lng: site._source.location.lon + }, + amslGround: site._source["amsl-ground"], + references: { + siteLinks: site._source.references["site-links"] + } + }); + } + + resultDefer.resolve({ + total: total, + sites: sites + }) + } + }; + + /** + * Gets a promise which is resolved with an array of sites using the given filter expression. + */ + service.getSites = function (sortColumn, sortDirection, filters, chunkSize, chunkSiteStartIndex) { + var resultDefer = $q.defer(); + + // determine the sort parameter + var sort = null; + if (sortColumn != null && sortDirection != null) { + sort = {}; + switch (sortColumn) { + case 'countNetworkElements': + case 'countLinks': + sort = null; + break; + case 'amslGround': + sort['amsl-ground'] = { + order: sortDirection === 'desc' ? 'desc' : 'asc' + } + break; + default: + sort[sortColumn] = { + order: sortDirection === 'desc' ? 'desc' : 'asc' + } + break; + } + } + + // determine the query parameter + var query = {}; + if (filters == null || filters.length == 0) { + query["match_all"] = {}; + } else { + var regexp = {}; + filters.forEach(function (filter) { + if (filter && filter.field) { + regexp[filter.field] = '.*'+ filter.term + '.*'; + } + }); + query["regexp"] = regexp; + } + + + if (sort) { + $mwtnDatabase.getFilteredSortedData("mwtn", "site", chunkSiteStartIndex, chunkSize, sort, query).then(processResult, resultDefer.reject); + } else { + $mwtnDatabase.getFilteredData("mwtn", "site", chunkSiteStartIndex, chunkSize, query).then(processResult, resultDefer.reject); + } + + return resultDefer.promise; + + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, name: string, location: {lat: number, lon: number}, "amsl-ground": number, references: {"network-elements": string[], "site-links": string[]}}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function processResult(result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + var total = hits.total; + var sites = []; + + for (var hitIndex = 0; hitIndex < hits.hits.length; ++hitIndex) { + var site = hits.hits[hitIndex]; + sites.push({ + id: site._source.id, + name: site._source.name, + type: site._source.type, + location: { + lat: site._source.location.lat, + lng: site._source.location.lon + }, + amslGround: site._source["amsl-ground"], + references: { + siteLinks: site._source.references["site-links"] + } + }); + } + + resultDefer.resolve({ + total: total, + sites: sites + }) + } + }; + + /** + * Gets a promise which resolved with an array of site links referenced by given sites. + * @param sites {({id: string, name: string, location: {lat: number, lng: number}, amslGround: number, references: {siteLinks: string[]})[]} + * @param chunkSize {number} The maximum count of site links who should return. + * @param chunkSiteLinkStartIndex {number} The index of the first site link element to get. + */ + service.getSiteLinksForSites = function (sites, chunkSize, chunkSiteLinkStartIndex) { + var resultDefer = $q.defer(); + + if (!sites || sites.length === 0) { + resultDefer.resolve([]); + return resultDefer.promise; + } + + var siteLinkIds = Object.keys(sites.reduce(function (accumulator, currentSite) { + // Add all site link ids referenced by the current site to the accumulator object. + currentSite.references.siteLinks.forEach(function (siteLinkId) { + // The value "true"" isnt important, i only use the key (siteLinkId) later. + // But this way i dont have to check, if the key is already known. + accumulator[siteLinkId] = true; + }); + return accumulator; + }, {})).map(function (siteLinkId) { + return { term: { id: siteLinkId } }; + }); + + var query = { + bool: { should: siteLinkIds } + }; + + $mwtnDatabase.getFilteredData("mwtn", "site-link", chunkSiteLinkStartIndex, chunkSize, query).then( + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, siteA: string, siteZ: string, siteNameA: string, siteNameZ: string, airInterfaceLinks: {id: string, siteLink: string, radio: string, polarization: string }[] }, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function (result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + if (hits.total === 0) { + resultDefer.resolve([]); + return; + } + + // get additional sites that wont be given in the sites array but are referenced by the site links. + // get all sites, referenced by the site links. + var allReferencedSiteIds = hits.hits.reduce(function (accumulator, currentSiteLink) { + accumulator[currentSiteLink._source.siteA] = true; + accumulator[currentSiteLink._source.siteZ] = true; + return accumulator; + }, {}); + // remove all known sites + sites.forEach(function (site) { + if (allReferencedSiteIds.hasOwnProperty(site.id)) { + delete allReferencedSiteIds[site.id]; + } + }); + + var additionalReferencedSiteIds = Object.keys(allReferencedSiteIds).map(function (referencedSiteId) { + return { term: { id: referencedSiteId } }; + }); + + if (additionalReferencedSiteIds.length > 0) { + query = { + bool: { should: additionalReferencedSiteIds } + }; + + $mwtnDatabase.getFilteredData("mwtn", "site", 0, 400, query).then( + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, name: string, location: {lat: number, lon: number}, "amsl-ground": number, references: {"network-elements": string[], "site-links": string[]}}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function (result) { + var siteHits = result && result.data && result.data.hits; + if (!siteHits) { + resultDefer.reject("Invalid result."); + return; + } + + var additionalSites = siteHits.hits.map(function (site) { + return { + id: site._source.id, + name: site._source.name, + type: site._source.type, + location: { + lat: site._source.location.lat, + lng: site._source.location.lon + }, + amslGround: site._source["amsl-ground"], + type: site._source.type, + references: { + siteLinks: site._source.references["site-links"] + } + }; + }); + + var siteLinks = hits.hits.map(function (siteLink) { + return { + id: siteLink._source.id, + siteA: sites.find(function (site) { return site.id === siteLink._source.siteA; }) || additionalSites.find(function (site) { return site.id === siteLink._source.siteA; }), + siteZ: sites.find(function (site) { return site.id === siteLink._source.siteZ; }) || additionalSites.find(function (site) { return site.id === siteLink._source.siteZ; }), + type: siteLink._source.type, + length: 5000 // AF/MF: the length will be served from the database in the next version. + }; + }); + + resultDefer.resolve(siteLinks); + }, + resultDefer.reject); + + return; + } + + var siteLinks = hits.hits.map(function (siteLink) { + return { + id: siteLink._source.id, + siteA: sites.find(function (site) { return site.id === siteLink._source.siteA; }), + siteZ: sites.find(function (site) { return site.id === siteLink._source.siteZ; }), + type: siteLink._source.type, + length: 5000 // AF/MF: the length will be served from the database in the next version. + }; + }); + + resultDefer.resolve(siteLinks); + }, + resultDefer.reject); + + return resultDefer.promise; + }; + + /** + * Gets a promise which is resolved with an array of planned filtered by given network element ids. + * This function does not use chunks! + * @param neIds {string[]} The ids of the site links to return. + */ + service.getPlannedNetworkElementsByIds = function (neIds) { + var resultDefer = $q.defer(); + + if (!neIds || neIds.length === 0) { + resultDefer.resolve([]); + return resultDefer.promise; + } + + var query = { + bool: { + should: neIds.map(function (neId) { + return { term: { id: neId } }; + }) + } + }; + + $mwtnDatabase.getFilteredData("mwtn", "planned-network-elements", 0, neIds.length, query).then( + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, name: string, type: string}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function (result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + if (hits.total === 0) { + resultDefer.resolve([]); + return; + } + + var plannedNetworkElements = hits.hits.map(function (plannedNetworkElement) { + return { + id: plannedNetworkElement._source.id, + name: plannedNetworkElement._source.name, + type: plannedNetworkElement._source.radioType + }; + }); + + resultDefer.resolve(plannedNetworkElements); + }, resultDefer.reject); + + return resultDefer.promise; + }; + + + /** + * Gets a promise which is resolved with an array of site links filtered by given site link ids. + * This function does not use chunks! + * @param siteLinkIds {string[]} The ids of the site links to return. + */ + service.getSiteLinksByIds = function (siteLinkIds) { + var resultDefer = $q.defer(); + + if (!siteLinkIds || siteLinkIds.length === 0) { + resultDefer.resolve([]); + return resultDefer.promise; + } + + var query = { + bool: { + should: siteLinkIds.map(function (siteLinkId) { + return { term: { id: siteLinkId } }; + }) + } + }; + + $mwtnDatabase.getFilteredData("mwtn", "site-link", 0, siteLinkIds.length, query).then( + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, siteA: string, siteZ: string}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function (result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + if (hits.total === 0) { + resultDefer.resolve([]); + return; + } + + var siteLinks = hits.hits.map(function (siteLink) { + return { + id: siteLink._source.id, + siteA: siteLink._source.siteA, + siteZ: siteLink._source.siteZ, + azimuthAz: siteLink._source.azimuthAZ, + azimuthZa: siteLink._source.azimuthZA, + length: siteLink._source.length, + type: siteLink._source.type + }; + }); + + resultDefer.resolve(siteLinks); + }, resultDefer.reject); + + return resultDefer.promise; + }; + + /** + * Gets a promise with all details for a given site by its id. + * @param siteId {string} The id of the site to request the details for. + */ + service.getSiteDetailsBySiteId = function (siteId) { + var resultDefer = $q.defer(); + + var siteQuery = { + "bool": { + "must": [ + { + "term": { + "id": siteId + } + } + ] + } + }; + + // get all site details + $mwtnDatabase.getFilteredData("mwtn", "site", 0, 1, siteQuery).then( + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, name: string, location: {lat: number, lon: number}, "amsl-ground": number, references: {"network-elements": string[], "site-links": string[]}}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function (result) { + if (result.data.hits.total != 1) { + // todo: handle this error + resultDefer.reject("Error loading details for " + siteId + ((result.data.hits.total) ? ' Too many recoeds found.' : ' No record found.')); + } + var site = result.data.hits.hits[0]; + var siteDetails = { + id: site._source.id, + name: site._source.name, + type: site._source.type, + location: { + lat: site._source.location.lat, + lng: site._source.location.lon + }, + amslGround: site._source["amsl-ground"], + references: { + siteLinks: site._source.references["site-links"], + networkElements: site._source.references["network-elements"] + } + }; + + service.getSiteLinksByIds(siteDetails.references.siteLinks).then( + /** Callback for the database request. + * @param result {{id: string, siteA: string, siteZ: string }[]} + */ + function (result) { + siteDetails.siteLinks = result; + resultDefer.resolve(siteDetails); + }); + + service.getPlannedNetworkElementsByIds(siteDetails.references.networkElements).then( + /** Callback for the database request. + * @param result {{id: string, name: string, type: string }[]} + */ + function (result) { + siteDetails.plannedNetworkElements = result; + resultDefer.resolve(siteDetails); + }); + } + ); + return resultDefer.promise; + }; + + /** + * Gets a promise with all details for a given link by its id. + * @param siteId {string} The id of the link to request the details for. + */ + service.getLinkDetailsByLinkId = function (linkId) { + var resultDefer = $q.defer(); + + var linkQuery = { + "bool": { + "must": [ + { + "term": { + "id": linkId + } + } + ] + } + }; + + // get all site details + $mwtnDatabase.getFilteredData("mwtn", "site-link", 0, 1, linkQuery).then( + /** + * Callback for the database request. + * @param result { DbLinkResult } The database result. + */ + function (result) { + if (result.data.hits.total != 1) { + // todo: handle this error + resultDefer.reject("Error loading details for " + siteId + ((result.data.hits.total) ? ' Too many recoeds found.' : ' No record found.')); + } + var link = result.data.hits.hits[0]; + var linkDetails = { + id: link._source.id, + siteA: link._source.siteA, + siteZ: link._source.siteZ, + siteNameA: link._source.siteNameA, + siteNameZ: link._source.siteNameZ, + length: link._source.length, + azimuthA: link._source.azimuthAZ, + azimuthB: link._source.azimuthZA, + airInterfaceLinks: link._source.airInterfaceLinks, + type: link._source.type, + airInterfaceLinks: link._source.airInterfaceLinks + }; + + service.getSitesByIds([link._source.siteA, link._source.siteZ]).then( + /** Callback for the database request. + * @param result {{ total: number, sites: { id: string, name: string } []}} + */ + function (result) { + var siteA = result.sites.find(function (site) { return site.id == linkDetails.siteA }); + var siteZ = result.sites.find(function (site) { return site.id == linkDetails.siteZ }); + if (result.total != 2 || !siteA || !siteZ) { + resultDefer.reject("Could not load Sites for link "+linkDetails.id); + } + linkDetails.siteA = siteA; + linkDetails.siteZ = siteZ; + + resultDefer.resolve(linkDetails); + }) + } + ); + return resultDefer.promise; + } + + /** + * Gets a promise which is resolved with an array of links using the given filter expression. + */ + service.getLinks = function (sortColumn, sortDirection, filters, chunkSize, chunkSiteStartIndex) { + var resultDefer = $q.defer(); + + // determine the sort parameter + var sort = null; + if (sortColumn != null && sortDirection != null) { + sort = {}; + switch (sortColumn) { + case 'siteIdA': + sort['siteA'] = { + order: sortDirection === 'desc' ? 'desc' : 'asc' + } + break; + case 'siteIdZ': + sort['siteZ'] = { + order: sortDirection === 'desc' ? 'desc' : 'asc' + } + break; + default: + sort[sortColumn] = { + order: sortDirection === 'desc' ? 'desc' : 'asc' + } + break; + } + } + + // determine the query parameter + var query = {}; + if (filters == null || filters.length == 0) { + query["match_all"] = {}; + } else { + var regexp = {}; + filters.forEach(function (filter) { + if (filter && filter.field) { + switch (filter.field) { + case 'siteIdA': + regexp['siteIdA'] = '.*' + filter.term + '.*'; + break; + case 'siteIdZ': + regexp['siteZ'] = '.*' + filter.term + '.*'; + break; + default: + regexp[filter.field] = '.*' + filter.term + '.*'; + break; + } + } + }); + query["regexp"] = regexp; + } + + + if (sort) { + $mwtnDatabase.getFilteredSortedData("mwtn", "site-link", chunkSiteStartIndex, chunkSize, sort, query).then(processResult, resultDefer.reject); + } else { + $mwtnDatabase.getFilteredData("mwtn", "site-link", chunkSiteStartIndex, chunkSize, query).then(processResult, resultDefer.reject); + } + + /** + * Callback for the database request. + * @param result {{data: {hits: {hits: {_id: string, _index: string, _score: number, _source: {id: string, siteA: string, siteZ: string}, _type: string}[], max_score: number, total: number}}, status: number}} The database result. + */ + function processResult (result) { + var hits = result && result.data && result.data.hits; + if (!hits) { + resultDefer.reject("Invalid result."); + return; + } + + var total = hits.total; + var links = []; + + var siteLinks = hits.hits.map(function (siteLink) { + return { + id: siteLink._source.id, + siteA: siteLink._source.siteA, + siteZ: siteLink._source.siteZ, + type: siteLink._source.type, + }; + }); + + resultDefer.resolve({ + total: total, + links: siteLinks + }); + } + + return resultDefer.promise; + + + }; + + /** + * Determines if a coordinate is in a bounding box + * @param bounds {{ top: number, left: number, right: number, bottom: number}} The bounding box. + * @param coordinate {{ lat: number, lng: number }} The coordinate. + * @return if the bounding box contains the coordinate + */ + service.isInBounds = function(bounds, coordinate) { + var isLongInRange = (bounds.right < bounds.left) + ? coordinate.lng >= bounds.left || coordinate.lng <= bounds.right + : coordinate.lng >= bounds.left && coordinate.lng <= bounds.right ; + + return coordinate.lat >= bounds.bottom && coordinate.lat <= bounds.top && isLongInRange; + } + + service.getAllEdges = function () { + var edges = []; + return getGenericChunk("edge", edges).then(function () { + return edges; + }); + }; + + /** + * Retrieves all nodes. + * @return a Promis containing an array of nodes + */ + service.getAllNodes = function () { + var resultDefer = $q.defer(); + var nodes = []; + getGenericChunk("node", nodes).then(function () { + + // recreate the tree structure from the flat list + var finalNodes = nodes.reduce( + /** @param acc { Node[] } */ + function (acc, cur, ind, arr) { + // the site will be added with the first device, so it can not be missing after the first device is in + if (!acc.some(node => node.data.type == "site" && node.data.id == cur.data.grandparent)) { + acc.push({ + data: { + type: "site", + id: cur.data.grandparent, + label: cur.data.grandparent, + active: cur.data.active + } + }); + } + if (!acc.some(node => node.data.type == "device" && node.data.id == cur.data.parent)) { + acc.push({ + data: { + _parent: cur.data.grandparent, + type: "device", + id: cur.data.parent, + get parent() { return cur.data.grandparent }, + set parent(val) { debugger; }, + label: cur.data.parent, + active: cur.data.active + } + }); + } + acc.push({ + data: Object.keys(cur.data).reduce(function (obj, key) { + if (key == 'grandparent') { + obj['type'] = 'port' + } else { + cur.data.hasOwnProperty(key) && (obj[key] = cur.data[key]); + } + return obj; + }, {}), + position: cur.position + }); + return acc; + }, []); + + resultDefer.resolve(finalNodes); + }, function (err) { + console.error(err); + resultDefer.reject(err); + }); + return resultDefer.promise; + } + + /** @param nodes {{id: string,position:{ x:number, y:number}}}[]} */ + service.saveChangedNodes = function (nodes) { + return $mwtnDatabase.getBase('topology').then(function (base) { + var resultDefer = $q.when(); + + nodes.forEach(function (node) { + resultDefer = resultDefer.then(function () { + return $mwtnDatabase.genericRequest({ + method: 'POST', + base: base.base, + index: base.index, + docType: 'node', + command: encodeURI(node.id) +'/_update', + data: { + "doc": { + "position": node.position + } + } + }); + }) + }); + return resultDefer; + }); + } + + // Start to initialize google maps api and save the returned promise. + service.googleMapsApiPromise = initializeGoogleMapsApi(); + + return service; + + // private helper functions of $mwtnTopology + + function getGenericChunk(docType, target) { + var size = 30; + return $mwtnDatabase.getAllData('topology', docType, target.length || 0, size, undefined) + .then(function (result) { + if (result.status === 200 && result.data) { + var total = (result.data.hits && result.data.hits.total) || 0; + var hits = (total && result.data.hits.hits) || []; + hits.forEach(function (hit) { + target.push(hit._source || {}); + }); + if (total > target.length) { + return getGenericChunk(docType, target); + } + return $q.resolve(true); + } else { + return $q.reject("Could not load " + docType + "."); + } + }, function (err) { + resultDefer.reject(err); + }); + + return resultDefer.promise; + } + + + /** + * Gets a promise which is resolved if the google maps api initialization is completed. + * @returns {promise} The promise which is resolved if the initialization is completed. + */ + function initializeGoogleMapsApi() { + var googleMapsApiDefer = $q.defer(); + window.googleMapsApiLoadedEvent = new Event("googleMapsApiLoaded"); + + window.addEventListener("googleMapsApiLoaded", function (event) { + + /** + * Calculates the bounds this map would display at a given zoom level. + * + * @member google.maps.Map + * @method boundsAt + * @param {Number} zoom Zoom level to use for calculation. + * @param {google.maps.LatLng} [center] May be set to specify a different center than the current map center. + * @param {google.maps.Projection} [projection] May be set to use a different projection than that returned by this.getProjection(). + * @param {Element} [div] May be set to specify a different map viewport than this.getDiv() (only used to get dimensions). + * @return {google.maps.LatLngBounds} the calculated bounds. + * + * @example + * var bounds = map.boundsAt(5); // same as map.boundsAt(5, map.getCenter(), map.getProjection(), map.getDiv()); + */ + google.maps.Map.prototype.boundsAt = function (zoom, center, projection, div) { + var p = projection || this.getProjection(); + if (!p) return undefined; + var d = $(div || this.getDiv()); + var zf = Math.pow(2, zoom) * 2; + var dw = d.getStyle('width').toInt() / zf; + var dh = d.getStyle('height').toInt() / zf; + var cpx = p.fromLatLngToPoint(center || this.getCenter()); + return new google.maps.LatLngBounds( + p.fromPointToLatLng(new google.maps.Point(cpx.x - dw, cpx.y + dh)), + p.fromPointToLatLng(new google.maps.Point(cpx.x + dw, cpx.y - dh))); + } + + googleMapsApiDefer.resolve(); + }); + + var head = document.getElementsByTagName('head')[0]; + + var callbackScript = document.createElement("script"); + callbackScript.appendChild(document.createTextNode("function googleMapsApiLoadedCallback() { window.dispatchEvent(window.googleMapsApiLoadedEvent); };")); + + var googleScript = document.createElement('script'); + googleScript.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyBWyNNhRUhXxQpvR7i-Roh23PaWqi-kNdQ&callback=googleMapsApiLoadedCallback"; + + head.appendChild(callbackScript); + head.appendChild(googleScript); + + return googleMapsApiDefer.promise; + } + + }); + +});
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/accordeonHeader.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/accordeonHeader.tpl.html new file mode 100755 index 00000000..21b2a28c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/accordeonHeader.tpl.html @@ -0,0 +1,13 @@ +<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle"
+ ng-click="toggleOpen()" uib-accordion-transclude="heading" ng-disabled="isDisabled" uib-tabindex-toggle>
+ <i class="pull-left fa" ng-class="{'fa-chevron-down': isOpen, 'fa-chevron-right': !isOpen}"></i>
+ <span uib-accordion-header ng-class="{'text-muted': isDisabled}">{{heading}}</span>
+ </a>
+ </h4>
+</div>
+<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse"
+ uib-collapse="!isOpen">
+ <div class="panel-body" ng-transclude></div>
+</div>
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/clocksGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/clocksGrid.tpl.html new file mode 100755 index 00000000..b5d3cbc7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/clocksGrid.tpl.html @@ -0,0 +1 @@ +<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ethConnectionsGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ethConnectionsGrid.tpl.html new file mode 100755 index 00000000..b5d3cbc7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ethConnectionsGrid.tpl.html @@ -0,0 +1 @@ +<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ethernetView.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ethernetView.tpl.html new file mode 100755 index 00000000..7f234477 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ethernetView.tpl.html @@ -0,0 +1,18 @@ +<uib-accordion close-others="false">
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.topologyIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Topology' | translate }}">
+ <mwtn-topology-ethernet-path-graph ng-if="vm.status.topologyIsOpen" />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.portsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Ports' | translate}}">
+ <mwtn-topology-ports-grid />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.ethConnectionsIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'ETH connections' | translate}}">
+ <mwtn-topology-eth-connections-grid />
+ </div>
+
+</uib-accordion>
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/frame.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/frame.tpl.html new file mode 100755 index 00000000..7e15cfb9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/frame.tpl.html @@ -0,0 +1,34 @@ +<ht-header help-link='sdnr/mwtnTopology/0.4.0/README.md'></ht-header> +<div class="owl"> + <!-- Display a loading indicator as long as google isn't initialized. --> + <div class="bbg" ng-if="!vm.googleIsReady"> + <i class="fa fa-spinner fa-pulse" aria-hidden="true"></i> + <span>{{'MWTN_LOADING' | translate}}</span> + </div> + + <uib-tabset id="mwtnTopology" active="vm.activeTab" ng-if="vm.googleIsReady"> + + <uib-tab index="0" heading="{{'MWTN_SITE' | translate}}"> + <mwtn-topology-site-view /> + </uib-tab> + + <uib-tab index="1" heading="{{'MWTN_AIR_INTERFACE' | translate}}"> + <mwtn-topology-physical-view /> + </uib-tab> + + <!-- [sko] no data for TST + <uib-tab index="2" heading="{{'MWTN_ETHERNET' | translate}}"> + <mwtn-topology-ethernet-view /> + </uib-tab> + + <uib-tab index="3" heading="{{'MWTN_PTP' | translate}}"> + <mwtn-topology-ieee1588-view /> + </uib-tab> --> + + </uib-tabset> + + <hr /> + <div class="owl"> + <span>ONAP SDN-R | ONF Wireless for @distversion@ - Build: @buildtime@</span> + </div> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ieee1588View.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ieee1588View.tpl.html new file mode 100755 index 00000000..4551aa6e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ieee1588View.tpl.html @@ -0,0 +1,18 @@ +<uib-accordion close-others="false">
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.topologyIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Graph' | translate }}">
+ <mwtn-topology-ieee1588-path-graph ng-if="vm.status.topologyIsOpen" />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.portsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Clocks' | translate}}">
+ <mwtn-topology-clocks-grid />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.ethConnectionsIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'PTP links' | translate}}">
+ <mwtn-topology-ptp-links-grid />
+ </div>
+
+</uib-accordion>
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/linkDetails.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/linkDetails.tpl.html new file mode 100755 index 00000000..e26979a1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/linkDetails.tpl.html @@ -0,0 +1,110 @@ +<div>
+ <uib-alert type="{{status.type}}" ng-show="status.message"> <i ng-show="status.isWorking" class="fa fa-spinner fa-pulse"></i>
+ <b><span>{{status.message}}</span></b>
+ </uib-alert>
+ <div ng-show="!status.message">
+ <p>
+ <span>Sitelink name: </span>
+ <b>{{vm.link.name || vm.link.id }}</b>
+ <br/>
+ <span>Length: </span>
+ <b> {{vm.link.length || 0 | number:3 }} </b>
+ <span> km</span>
+ <br/>
+ <span>Type: </span>
+ <b> {{vm.link.type || 'traffic' }} </b>
+ <span> </span>
+ </p>
+ <table>
+ <caption class="text-left">
+ <b>{{'SITE' | translate}} A</b>
+ </caption>
+ <tbody>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">{{'MWTN_SITE_ID' | translate}}:</td>
+ <td class="text-left">
+ <b>{{vm.link.siteA.id}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">{{'MWTN_NAME' | translate}}:</td>
+ <td class="text-left">
+ <b>{{vm.link.siteA.name}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">Lat/Lon:</td>
+ <td class="text-left">
+ <b>{{vm.link.siteA.location.lat | coordinateFilter:'toDMS':'lat'}} | {{vm.link.siteA.location.lng | coordinateFilter:'toDMS':'lon'}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">Azimuth:</td>
+ <td class="text-left">
+ <b> {{vm.link.azimuthA || 0 | number:1 }} </b>
+ <span> °</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <table>
+ <caption class="text-left">
+ <b>{{'MWTN_SITE' | translate}} Z</b>
+ </caption>
+ <tbody>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">{{'MWTN_SITE_ID' | translate}}:</td>
+ <td class="text-left">
+ <b>{{vm.link.siteZ.id}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">Site-Name:</td>
+ <td class="text-left">
+ <b>{{vm.link.siteZ.name}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">Lat/Lon:</td>
+ <td class="text-left">
+ <b>{{vm.link.siteZ.location.lat | coordinateFilter:'toDMS':'lat'}} | {{vm.link.siteZ.location.lng | coordinateFilter:'toDMS':'lon'}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td class="text-right" style="padding-right: 5px;">Azimuth:</td>
+ <td class="text-left">
+ <b> {{vm.link.azimuthB || 0 | number:1 }} </b>
+ <span> °</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <br/>
+ <br/>
+ <table class='table table-striped' ng-show="vm.link.airInterfaceLinks && vm.link.airInterfaceLinks.length">
+ <caption class="text-left">
+ <b>{{'MWTN_AIR_INTERFACE_LINKS' | translate}}</b>
+ </caption>
+ <thead>
+ <tr>
+ <th>{{'MWTN_ID' | translate}}</th>
+ <th>{{'MWTN_RADIO' | translate}}</th>
+ <th>{{'MWTN_BAND' | translate}}</th>
+ <th>{{'MWTN_POLARIZATION' | translate}}</th>
+ <th>{{'MWTN_STATUS' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="airIf in vm.link.airInterfaceLinks">
+ <td> {{ airIf.id}} </td>
+ <td> {{ airIf.radio}} </td>
+ <td> {{ airIf.bandDesignator }} </td>
+ <td> {{ airIf.polarization }} </td>
+ <td> {{ airIf.mainStatus }} </td>
+
+
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/links.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/links.tpl.html new file mode 100755 index 00000000..8299a834 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/links.tpl.html @@ -0,0 +1,2 @@ +<div id="mwtnNodesGrid" ui-grid="gridOptionsLinks" ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns ui-grid-move-columns + class="mwtnTopologyGrid"></div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/linksGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/linksGrid.tpl.html new file mode 100755 index 00000000..b5d3cbc7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/linksGrid.tpl.html @@ -0,0 +1 @@ +<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/maps.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/maps.tpl.html new file mode 100755 index 00000000..71e6c0ee --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/maps.tpl.html @@ -0,0 +1,59 @@ +<!-- +<ui-gmap-google-map bounds="mapObjects.map.bounds" + center="mapObjects.map.center" + control="mapObjects.map.control" + dragging="mapObjects.map.dragging" + events="mapObjects.map.events" + options="mapObjects.map.options" + zoom="mapObjects.map.zoom"> + + <ui-gmap-markers + models="mapObjects.sites.models" + idkey="marker.id" + fit="true" + coords="'self'" + options="'options'" + icon="mapObjects.sites.icon" + doCluster="doGoogleCluster" + events="mapObjects.sites.events" + > + </ui-gmap-markers> + + <ui-gmap-window + coords="mapObjects.sites.tooltip" + options="mapObjects.sites.tooltipOptions" + show="mapObjects.sites.tooltip.show"> + </ui-gmap-window>--> + + <!-- siteLinks --> +<!-- + <ui-gmap-polylines + models="mapObjects.siteLinks.models" + events="mapObjects.siteLinks.events" + path="'path'" + stroke="'stroke'" + geodesic="'geodesic'" + editable="'editable'" + draggable="'draggable'" + static="true" + visible="mapObjects.siteLinks.visible" + zindex="'zIndex'" + > + </ui-gmap-polylines> + +</ui-gmap-google-map>--> + +<map center="{{mapObjects.map.center}}" + map-type-id=“MapTypeId.HYBRID” + street-view-control="false"> + + <marker data-ng-repeat="mapObjects.sites.models" + position="{{}}" + /> +</map> + +<!-- + <sigma-topology drag-nodes="true" topology-data="topologyData" trigger-resize-sigma="triggerResizeSigma" panel="panel" + topology-custfunc="topologyCustfunc"> + </sigma-toppology> + --> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/networkElementsGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/networkElementsGrid.tpl.html new file mode 100755 index 00000000..b5d3cbc7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/networkElementsGrid.tpl.html @@ -0,0 +1 @@ +<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/nodes.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/nodes.tpl.html new file mode 100755 index 00000000..826e7dd9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/nodes.tpl.html @@ -0,0 +1,2 @@ +<div id="mwtnNodesGrid" ui-grid="gridOptionsNodes" ui-grid-exporter ui-grid-selection ui-grid-pinning ui-grid-resize-columns ui-grid-move-columns + class="mwtnTopologyGrid"></div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/physicalView.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/physicalView.tpl.html new file mode 100755 index 00000000..dfeabe4e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/physicalView.tpl.html @@ -0,0 +1,18 @@ +<uib-accordion close-others="false">
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.graphIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'MWTN_GRAPH' | translate }}">
+ <mwtn-topology-physical-path-graph ng-if="vm.status.graphIsOpen" />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.networkElementsIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'MWTN_AIR_INTERFACES' | translate}}">
+ <mwtn-topology-network-elements-grid />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.LinksIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'MWTN_LINKS' | translate}}">
+ <mwtn-topology-links-grid />
+ </div>
+
+</uib-accordion>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/portsGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/portsGrid.tpl.html new file mode 100755 index 00000000..b5d3cbc7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/portsGrid.tpl.html @@ -0,0 +1 @@ +<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ptpLinksGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ptpLinksGrid.tpl.html new file mode 100755 index 00000000..b5d3cbc7 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/ptpLinksGrid.tpl.html @@ -0,0 +1 @@ +<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteDetails.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteDetails.tpl.html new file mode 100755 index 00000000..3a06fa8d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteDetails.tpl.html @@ -0,0 +1,77 @@ +<div class="owl">
+ <uib-alert type="{{status.type}}" ng-show="status.message">
+ <i ng-show="status.isWorking" class="fa fa-spinner fa-pulse" aria-hidden="true"></i>
+ <b><span>{{status.message}}</span></b>
+ </uib-alert>
+ <div ng-show="!status.message">
+ <p>
+ <span>{{'MWTN_SITE_ID' | translate}}: </span>
+ <b>{{vm.site.id}}</b>
+ </p>
+ <hr />
+ <p>
+ <span>{{'MWTN_SITE_NAME' | translate}}: </span>
+ <b>{{vm.site.name}}</b>
+ <br />
+ <span>{{'MWTN_LAT_LON' | translate}}</span>
+ <b>{{ vm.site.location.lat | coordinateFilter:'toDMS':'lat'}} | {{ vm.site.location.lng | coordinateFilter:'toDMS':'lon'}}</b>
+ <br />
+ <span>{{'MWTN_AMSL_GRD' | translate}}: </span>
+ <b> {{vm.site.amslGround | number:2 }} </b>
+ <span> [m]</span>
+ <br />
+ <span>{{'MWTN_TYPE' | translate}}: </span>
+ <b> {{vm.site.type || 'pyhsical-network-function' }} </b>
+ <span> </span>
+ </p>
+ <p>
+ <b>Site-Links ({{vm.site.siteLinks.length}}): </b>
+ <span style="color: #337ab7;" class="pointer glyphicon glyphicon-plus-sign" aria-hidden="true" ng-class="{'selected-site' : createNewLinkMode}"
+ ng-show="showNewLinkButton" ng-click="toggleCreateNewLinkMode()"></span>
+ <p />
+ <table class='table table-striped' ng-show="vm.site.siteLinks.length">
+ <thead>
+ <tr>
+ <th class='text-left'>Site-Link-Name</th>
+ <th class='text-right'>Azimuth A [°]</th>
+ <th class='text-right'>Azimuth Z [°]</th>
+ <th class='text-right'>Length [km]</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat='siteLink in vm.site.siteLinks'>
+ <td class='text-left'>
+ <a href='/ux/#/siteLinks/{{siteIndex}}/{{siteLink._source.id.high}}/{{siteLink._source.id.low}}' target='htSolutions'>{{siteLink.id}}</a>
+ </td>
+ <td class='text-right'>{{ siteLink.azimuthAz | number : 1 }}</td>
+ <td class='text-right'>{{ siteLink.azimuthZa | number : 1 }}</td>
+ <td class='text-right'>{{ siteLink.length | number : 3 }}</td>
+ </tr>
+ </tbody>
+ </table>
+ <p>
+ <b>Network elements ({{vm.site.plannedNetworkElements.length}}): </b>
+ <!--
+ <span style="color: #337ab7;" class="pointer glyphicon glyphicon-plus-sign" aria-hidden="true" ng-class="{'selected-site' : createNewLinkMode}"
+ ng-show="showNewLinkButton" ng-click="toggleCreateNewLinkMode()"></span> -->
+ <p />
+ <table class='table table-striped' ng-show="vm.site.plannedNetworkElements.length">
+ <thead>
+ <tr>
+ <th class='text-left'>{{'MWTN_ID' | translate}}</th>
+ <th class='text-left'>{{'MWTN_NAME' | translate}}</th>
+ <th class='text-left'>{{'MWTN_TYPE' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat='ne in vm.site.plannedNetworkElements'>
+ <td class='text-left'>
+ <a href='#/pnfInventory/{{ne.id}}' target='htSolutions'>{{ne.id}}</a>
+ </td>
+ <td class='text-left'>{{ ne.name }}</td>
+ <td class='text-left'>{{ ne.type }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteGrid.tpl.html new file mode 100755 index 00000000..612fb92e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteGrid.tpl.html @@ -0,0 +1,9 @@ +<!--<h1 style="color:#000">Here is the sites grid</h1>-->
+<div class="checkbox">
+ <label>
+ <input type="checkbox" ng-model="vm.showAllSites">
+ Show all sites
+ </label>
+</div>
+
+<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteLinkGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteLinkGrid.tpl.html new file mode 100755 index 00000000..ba4f270c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteLinkGrid.tpl.html @@ -0,0 +1,8 @@ +<div class="checkbox">
+ <label>
+ <input type="checkbox" ng-model="vm.showAllLinks">
+ Show all links
+ </label>
+</div>
+
+<div class="mwtnTopologyGrid" ui-grid="vm.gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-selection ui-grid-resize-columns ui-grid-move-columns></div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/sitePathGrid.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/sitePathGrid.tpl.html new file mode 100755 index 00000000..bc1372e6 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/sitePathGrid.tpl.html @@ -0,0 +1 @@ +<h1 style="color:#000">Here is the site paths grid</h1>
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteView.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteView.tpl.html new file mode 100755 index 00000000..e56a2273 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/siteView.tpl.html @@ -0,0 +1,31 @@ +<uib-accordion close-others="false">
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.siteMapIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Map (' + vm.status.loadedSitesInBoundingBox + ' of ' + vm.status.totalSitesInBoundingBox + ' sites loaded)'}}">
+
+ <mwtn-topology-map ng-if="vm.status.siteMapIsOpen" manual-map-bounds="vm.status.manualMapBounds" on-bounds-changed="vm.mapBoundsChanged(data, userOriginated)">
+ <mwtn-topology-map-sites sites="vm.visibleSites" selected-site="vm.status.site" api="vm.mapSitesComponentApi" />
+ <mwtn-topology-map-site-links site-links="vm.knownSiteLinks" selected-site-link="vm.status.siteLink"
+ api="vm.mapSiteLinksComponentApi" />
+ </mwtn-topology-map>
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.siteGridIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Sites' | translate}}">
+
+ <mwtn-topology-site-grid visible-sites="vm.visibleSites" />
+ </div>
+
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.siteLinkGridIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Site links' | translate}}">
+
+ <mwtn-topology-site-link-grid known-site-links="vm.knownSiteLinks" />
+ </div>
+
+ <!-- [sko, 2017-06-23] TODO deferred
+ <div uib-accordion-group="" class="panel-primary" is-open="vm.status.sitePathGridIsOpen" template-url="src/app/mwtnTopology/templates/accordeonHeader.tpl.html"
+ heading="{{'Site paths' | translate}}">
+
+ <mwtn-topology-site-path-grid />
+ </div> -->
+</uib-accordion>
diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/topology.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/topology.tpl.html new file mode 100755 index 00000000..6a71bbf8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/mwtnTopology-module/src/main/resources/mwtnTopology/templates/topology.tpl.html @@ -0,0 +1,2 @@ + <sigma-topology drag-nodes="true" topology-data="topologyData" trigger-resize-sigma="triggerResizeSigma" panel="panel" topology-custfunc="topologyCustfunc"> + </sigma-toppology> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/pom.xml new file mode 100644 index 00000000..0131f51c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/mwtnTopology/pom.xml @@ -0,0 +1,27 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtn</artifactId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtnTopology</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>mwtnTopology-module</module> + <module>mwtnTopology-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-bundle/pom.xml new file mode 100644 index 00000000..87ebbd3c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-bundle/pom.xml @@ -0,0 +1,116 @@ +<?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>odlChat</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>odlChat-bundle</artifactId> + <name>${prefix} ${project.artifactId}</name> + <packaging>bundle</packaging> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>odlChat-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>odlChat-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..ad015bd2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="odlChat"/> + <property name="url" value="/src/app/odlChat"/> + <property name="directory" value="/odlChat"/> + <property name="requireJs" value="app/odlChat/odlChat.module"/> + <property name="angularJs" value="app.odlChat"/> + <property name="cssDependencies"> + <list> + <value>src/app/odlChat/odlChat-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/pom.xml new file mode 100644 index 00000000..730c40b1 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/pom.xml @@ -0,0 +1,14 @@ +<?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>odlChat</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>odlChat-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/odlChat/odlChat-module/src/main/resources/odlChat/logo_chat.gif b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/logo_chat.gif Binary files differnew file mode 100644 index 00000000..deb44fd2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/logo_chat.gif diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat-custom.css new file mode 100644 index 00000000..4d9f8d24 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat-custom.css @@ -0,0 +1,3 @@ +/** + * Add your application related css here + */
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.controller.js new file mode 100644 index 00000000..310e05d5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.controller.js @@ -0,0 +1,69 @@ +/* + * 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/odlChat/odlChat.module', 'app/odlChat/odlChat.services' ], + function(odlChatApp) { + + var main = function($scope, $rootScope, $odlChat) { + + $rootScope.section_logo = 'src/app/odlChat/odlChat.png'; + + $scope.collection = []; + $scope.chat = { + nickname : 'anonymous', + message : "Hey, what's up?!" + }; + + var listenToNotifications = function(socketLocation) { + try { + var notificatinSocket = new WebSocket(socketLocation); + + notificatinSocket.onmessage = function(event) { + // we process our received event here + $odlChat.getData(event, function(info, tweet) { + $scope.collection.push(tweet); + if ($scope.collection.length > 20) { + $scope.collection.shift(); + } + + $scope.chat.message = info; + }); + }; + notificatinSocket.onerror = function(error) { + console.log("Socket error: " + JSON.stringify(error)); + }; + notificatinSocket.onopen = function(event) { + console.log("Socket connection opened."); + }; + notificatinSocket.onclose = function(event) { + console.log("Socket connection closed."); + }; + // if there is a problem on socket creation we get + // exception (i.e. when socket address is incorrect) + } catch (e) { + alert("Error when creating WebSocket" + e); + } + }; + + $scope.send = function(chat) { + $odlChat.send(chat, function(info) { + console.log(info); + }); + }; + + var path = "/opendaylight-inventory:nodes/opendaylight-inventory:node[opendaylight-inventory:id='odlChat']"; + $odlChat.register(path, function(socketLocation) { + listenToNotifications(socketLocation); + }); + }; + + odlChatApp.register.controller('odlChatCtrl', [ '$scope', '$rootScope', + '$odlChat', main ]); + + });
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.module.js new file mode 100644 index 00000000..6bd5387f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.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 odlChatApp = angular.module('app.odlChat', ['app.core', 'ui.router.state','config']); + + odlChatApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + odlChatApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + + }; + + + NavHelperProvider.addControllerUrl('app/odlChat/odlChat.controller'); + NavHelperProvider.addToMenu('odlChat', { + "link" : "#/odlChat", + "active" : "main.odlChat", + "title" : "Chat", + "icon" : "fa-comments", // Add navigation icon css class here + "page" : { + "title" : "Chat", + "description" : "odlChat" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.odlChat', { + url: 'odlChat', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/odlChat/odlChat.tpl.html', + controller: 'odlChatCtrl' + } + } + }); + + }); + + return odlChatApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.png Binary files differnew file mode 100755 index 00000000..3b79097e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.services.js new file mode 100644 index 00000000..1a137f5c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.services.js @@ -0,0 +1,103 @@ +/* + * 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/mwtnCommons/mwtnCommons.module', 'app/odlChat/odlChat.module'],function(odlChatApp) { + + odlChatApp.register.factory('$odlChat', function($http, $mwtnCommons) { + + var createStream = function(streamName, callback) { + var request = { + method : 'GET', + url : [ service.base, 'streams/stream/', streamName ].join('') + }; + $http(request).then(function successCallback(response) { + console.log(response.headers('Location')); + callback(response.headers('Location')); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + callback(); + }); + }; + + var service = { + base : window.location.origin + "/restconf/", + }; + + + service.getData = function(event, callback) { + + var request = { + method : 'GET', + url : [ service.base, + 'config/opendaylight-inventory:nodes/node/odlChat/' ].join('') + }; + $http(request).then(function successCallback(response) { + tweet = { + nickname : response.data.node[0]['flow-node-inventory:manufacturer'], + message : response.data.node[0]['flow-node-inventory:description'], + time : JSON.stringify(new Date()).split('T')[1].substring(0, 5) + }; + callback('', tweet); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + callback('ERROR while sending ;('); + }); + + }; + + service.register = function(path, callback) { + var request = { + method : 'POST', + url : [ service.base, + 'operations/sal-remote:create-data-change-event-subscription' ] + .join(''), + data : { + "input" : { + "path" : path, + "sal-remote-augment:datastore" : "CONFIGURATION", + "sal-remote-augment:scope" : "SUBTREE" + } + } + }; + $http(request).then( + function successCallback(response) { + createStream(response.data.output['stream-name'], function( + socketLocation) { + callback(socketLocation); + }); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + }); + }; + + service.send = function(chat, callback) { + var request = { + method : 'PUT', + url : [ service.base, + 'config/opendaylight-inventory:nodes/node/odlChat' ].join(''), + data : { + "node" : [ { + "id" : "odlChat", + "flow-node-inventory:manufacturer" : chat.nickname, + "flow-node-inventory:software" : "", + "flow-node-inventory:serial-number" : "", + "flow-node-inventory:hardware" : "", + "flow-node-inventory:description" : chat.message + } ] + } + }; + $http(request).then(function successCallback(response) { + callback('send successfully'); + }, function errorCallback(response) { + console.error(JSON.stringify(response)); + callback('ERROR while sending ;('); + }); + }; + return service; + }); +});
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.tpl.html new file mode 100644 index 00000000..c3d90ae3 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/odlChat-module/src/main/resources/odlChat/odlChat.tpl.html @@ -0,0 +1,102 @@ +<!-- This is the landing page of you application, Update the content as per your requirements --> +<div class="owl container" style="width: 800px"> + + <div class="row"> + <div class="col-md-11"> + <h4>Simple chat application based on (ODL) WebSockets</h4> + </div> + </div> + + <div class="row"> + <div class="col-md-11"> + <hr/ > + </div> + </div> + + <div class="row"> + <div class="col-md-11"> + <p> + <span class="white">The beauty of WebSockets within OpenDaylight.</span> + </p> + <p> + <span class="white">Useful links:</span> + <ul> + <li> + <a href="https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Restconf:Change_event_notification_subscription"> + <span class="white">https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Restconf:Change_event_notification_subscription</span> + </a> + </li> + <li> + <a href="https://wiki.opendaylight.org/view/OpenDaylight_DLUX:Create_application_with_archetype"> + <span class="white">https://wiki.opendaylight.org/view/OpenDaylight_DLUX:Create_application_with_archetype</span> + </a> + </li> + </ul> + </p> + <p> + <span class="white">Code:</span> + <ul> + <li> + <a href="https://github.com/OpenNetworkingFoundation/CENTENNIAL/tree/master/code/ux/odlChat"> + <span class="white">https://github.com/OpenNetworkingFoundation/CENTENNIAL/tree/master/code/ux/odlChat</span> + </a> + </li> + </ul> + </p> + + + </div> + </div> + + <div class="row"> + <div class="col-md-11"> + <hr/ > + </div> + </div> + + <div class="row" ng-repeat="tweet in collection"> + <div class="col-md-2 text-right"> + <span class="white">{{tweet.nickname}}:</span> + </div> + <div class="col-md-8"> + <span class="white"> + <b>{{tweet.message}}</b> + </span> + </div> + <div class="col-md-1"> + <span>{{tweet.time}}</span> + </div> + </div> + + <div class="row"> + <div class="col-md-11"> + <hr/ > + </div> + </div> + + <div class="row"> + <div class="col-md-2 text-right"> + <input class="form-control" type="text" step="1" ng-model="chat.nickname" /> + </div> + <div class="col-md-8 text-right"> + <input class="form-control" type="text" step="1" ng-model="chat.message" /> + </div> + <div class="col-md-1"> + <button class="btn btn-primary" type="submit" ng-click="send(chat)">{{'MWTN_SEND' | translate}}</button> + </div> + </div> + + <div class="row"> + <div class="col-md-2 text-right"> + <span class="white">{{'MWTN_NICKNAME' | translate}} </span> + </div> + <div class="col-md-8 text-right"> + <span class="white">{{'MWTN_MESSAGE' | translate}} </span> + </div> + <div class="col-md-1"></div> + </div> +</div> +<hr /> +<div class="owl"> + <span class="white">ONAP SDN-R | ONF Wireless for @distversion@ - Build: @buildtime@</span> +</div> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/pom.xml new file mode 100644 index 00000000..f81b02ed --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/odlChat/pom.xml @@ -0,0 +1,27 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>odlChat</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>odlChat-module</module> + <module>odlChat-bundle</module> + </modules> +</project>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-bundle/pom.xml new file mode 100644 index 00000000..3a409fe8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>onapAai</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>onapAai-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>onapAai-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>onapAai-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..1a2ab2ed --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="onapAai"/> + <property name="url" value="/src/app/onapAai"/> + <property name="directory" value="/onapAai"/> + <property name="requireJs" value="app/onapAai/onapAai.module"/> + <property name="angularJs" value="app.onapAai"/> + <property name="cssDependencies"> + <list> + <value>src/app/onapAai/onapAai-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/pom.xml new file mode 100644 index 00000000..6c2eef33 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/pom.xml @@ -0,0 +1,14 @@ +<?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>onapAai</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>onapAai-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/onapAai/onapAai-module/src/main/resources/onapAai/images/onapAai.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/images/onapAai.png Binary files differnew file mode 100755 index 00000000..a3724882 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/images/onapAai.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai-custom.css new file mode 100644 index 00000000..fc314684 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai-custom.css @@ -0,0 +1,58 @@ +/** + * Add your application related css here + */ +.onapAaiGrid { + height: 600px; + background-color: white; +} + +.onapAaiGrid span { + color: #393939; +} +.ht-pagination span { + color: #393939; +} +.ht-pagination span.dark { + color: #393939; +} +.dark { + color: #393939; +} + + + +.onapAaiGrid div.debug { + color: #393939; + background-color: white; +} +.onapAaiGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.onapAaiGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.onapAaiGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.controller.js new file mode 100644 index 00000000..6c5685e9 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.controller.js @@ -0,0 +1,49 @@ +/* + * 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/onapAai/onapAai.module', + 'app/onapAai/onapAai.services'], + function (onapAaiApp) { + + onapAaiApp.register.controller('onapAaiCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$onapAai', '$mwtnLog', + function (uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $onapAai, $mwtnLog) { + + var COMPONENT = 'onapAaiCtrl'; + $mwtnLog.info({ component: COMPONENT, message: 'onapAaiCtrl started!' }); + + $rootScope.section_logo = 'src/app/onapAai/images/onapAai.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.highlightFilteredHeader = $onapAai.highlightFilteredHeader; + + // Grid + $scope.gridOptions = JSON.parse(JSON.stringify($onapAai.gridOptions)); + $scope.gridOptions.columnDefs = [ + { field: 'pnf-id', type: 'string', displayName: 'ID', headerCellClass: $scope.highlightFilteredHeader, width: 170 }, + { field: 'pnf-name', type: 'string', displayName: 'Name', headerCellClass: $scope.highlightFilteredHeader, width: 200 }, + { field: 'equip-type', type: 'string', displayName: 'Type', headerCellClass: $scope.highlightFilteredHeader, width: 160 }, + { field: 'equip-vendor', type: 'string', displayName: 'Vendor', headerCellClass: $scope.highlightFilteredHeader, width: 100 }, + { field: 'equip-model', type: 'string', displayName: 'Model', headerCellClass: $scope.highlightFilteredHeader, width: 160 }, + { field: 'ipaddress-v4-oam', type: 'string', displayName: 'If OAM', headerCellClass: $scope.highlightFilteredHeader, width: 140 }, + { field: 'in-maint', type: 'string', displayName: 'Maintenance', headerCellClass: $scope.highlightFilteredHeader, width: 100 }, + { field: 'interfaces', type: 'string', displayName: '#p-interfaces', headerCellClass: $scope.highlightFilteredHeader, width: 100, visible: false }, + { field: 'resourceVersion', type: 'string', displayName: 'Resource version', headerCellClass: $scope.highlightFilteredHeader, width: 100, visible: false } + ]; + + $onapAai.getAaiPnfs().then(function(success){ + $scope.gridOptions.data = success.data.pnf; + $scope.gridOptions.data.map(function(item){ + item.interfaces = 1; + }); + }, function(error) { + console.log('error'); + $scope.error = error; + }); + + }]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.module.js new file mode 100644 index 00000000..a3deb333 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.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 onapAaiApp = angular.module('app.onapAai', ['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', 'ui.grid.infiniteScroll','ui.grid.pagination' ]); + + onapAaiApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + onapAaiApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/onapAai/onapAai.controller'); + NavHelperProvider.addToMenu('onapAai', { + "link" : "#/onapAai/", + "active" : "main.onapAai", + "title" : "ONAP AAI", + "icon" : "fa fa-th", // Add navigation icon css class here + "page" : { + "title" : "ONAP AAI", + "description" : "Open Network Automation Platform (ONAP) - Active and Available Inventory (AAI)" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.onapAai', { + url: 'onapAai/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/onapAai/onapAai.tpl.html', + controller: 'onapAaiCtrl' + } + } + }); + + }); + + return onapAaiApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.services.js new file mode 100644 index 00000000..dfbbf473 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.services.js @@ -0,0 +1,162 @@ +/* + * 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/onapAai/onapAai.module', 'app/mwtnCommons/mwtnCommons.services'], function (onapAaiApp) { + + onapAaiApp.register.factory('$onapAai', function ($q, $http, Base64, $mwtnCommons, $mwtnDatabase, $mwtnLog, Device) { + + var service = {}; + + var functionId = "mwtn"; + var docType = "device"; + var from = 0; + var size = 9999; + var sort = undefined; + var deviceLookup = {}; + $mwtnDatabase.getAllData(functionId, docType, from, size, sort).then( + function successCallback(response) { + response.data.hits.hits.map(function(device){ + deviceLookup[device._id] = new Device(device._source); + }); + }, function errorCallback(response) { + deviceLookup = {}; + }); + + service.checkModules = $mwtnCommons.checkModules; + service.getMwtnWebSocketUrl = $mwtnCommons.getMwtnWebSocketUrl; + service.gridOptions = $mwtnCommons.gridOptions; + service.formatData = $mwtnCommons.formatData; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.deleteDocType = $mwtnDatabase.deleteDocType; + + + var transactionId = 1; + var getHeaders = function () { + return { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-TransactionId': transactionId++ + } + }; + + // create or modify a pnf in aai + service.createPnf = function (pnfId, doc) { + var base = window.location.origin; + var getIp = function (extension) { + return extension.filter(function (item) { + return item['value-name'] === 'neIpAddress'; + }).map(function (item) { + return item.value; + })[0]; + } + + var device = deviceLookup[pnfId]; + if (!device) device = new Device({"id":pnfId,"name":pnfId,"mediator-ipv4":"127.0.0.1","netconf-port":"830","oam-ipv4":"127.0.0.1","site":"unknown","controller":"this","controller-site":"unknown","vendor":"unknown","type":"unknown","model":"unknown","version":"0.0"}); + var data = { + "pnf-name": pnfId, + "pnf-id": doc.connect.host + ':' + doc.connect.port, + "equip-type": device.getType(), + "equip-model": device.getModel(), + "equip-vendor": device.getVendor(), + "ipaddress-v4-oam": getIp(doc['core-model:network-element'].extension) | doc.connect.host, + "in-maint": false + }; + console.info('pnf', data); + var request = { + method: 'PUT', + url: base + '/aai/network/pnfs/pnf/' + pnfId, // to es config + // withCredentials: true, + headers: getHeaders(), + data: data + }; + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + service.deletePnf = function (pnfId) { + // curl -X DELETE http://localhost:8282/aai/network/pnfs/pnf/Ericsson-A1 --insecure -v -u AAI:AAI -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'X-FromAppId: SDNR' -H 'X-TransactionId: 9999' + var base = window.location.origin; + var request = { + method: 'DELETE', + url: base + '/aai/network/pnfs/pnf/' + pnfId, // to es config + // withCredentials: true, + headers: getHeaders() + }; + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + service.getAaiPnfs = function () { + // curl https://10.31.1.55:8443/network/pnfs -k -v -u abc:def -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'X-FromAppId: SDNR' -H 'X-TransactionId: 9999' + + var base = window.location.origin; + var request = { + method: 'GET', + url: base + '/aai/network/pnfs', // to es config + // withCredentials: true, + headers: getHeaders(), + }; + + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + return service; + }); + + // Class Device + onapAaiApp.register.factory('Device', function () { + var Device = function (data) { + if (!data) { + data = {id:new Date(), type: 'unknown', name:'unknonw', model: 'unkonwn', vendor:'unknonw', version:'unkonwn'}; + } + this.data = data; + this.getData = function () { + return this.data; + }; + this.getId = function () { + return this.getData().id; + }; + this.getType = function () { + return this.getData().type; + }; + this.getName = function () { + return this.getData().name; + }; + this.getModel = function () { + return this.getData().model; + }; + this.getVendor = function () { + return this.getData().vendor; + }; + this.getVersion = function () { + return this.getData().version; + }; + }; + return Device; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.tpl.html new file mode 100644 index 00000000..c121b6d5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/onapAai-module/src/main/resources/onapAai/onapAai.tpl.html @@ -0,0 +1,12 @@ +<ht-header help-link='sdnr/onapAai/0.4.0/README.md'></ht-header> +<pre ng-if="error">{{ error | json }}</pre> + + +<div id="onapAaiGrid" ui-grid="gridOptions" ui-grid-exporter ui-grid-selection ui-grid-pinning + ui-grid-resize-columns ui-grid-move-columns class="onapAaiGrid" ng-if="!error"></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/onapAai/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/pom.xml new file mode 100644 index 00000000..6049029a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapAai/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>onapAai</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>onapAai-module</module> + <module>onapAai-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-bundle/pom.xml new file mode 100644 index 00000000..ca91f481 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>onapDcae</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>onapDcae-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>onapDcae-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>onapDcae-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..18c3ba0e --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="onapDcae"/> + <property name="url" value="/src/app/onapDcae"/> + <property name="directory" value="/onapDcae"/> + <property name="requireJs" value="app/onapDcae/onapDcae.module"/> + <property name="angularJs" value="app.onapDcae"/> + <property name="cssDependencies"> + <list> + <value>src/app/onapDcae/onapDcae-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/pom.xml new file mode 100644 index 00000000..63916944 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/pom.xml @@ -0,0 +1,14 @@ +<?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>onapDcae</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>onapDcae-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/onapDcae/onapDcae-module/src/main/resources/onapDcae/images/onap-5g-architecture.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/images/onap-5g-architecture.png Binary files differnew file mode 100755 index 00000000..368bdd47 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/images/onap-5g-architecture.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/images/onapDcae.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/images/onapDcae.png Binary files differnew file mode 100755 index 00000000..a7f1dc25 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/images/onapDcae.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae-custom.css new file mode 100644 index 00000000..ff7de9a0 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae-custom.css @@ -0,0 +1,58 @@ +/** + * Add your application related css here + */ +.onapDcaeGrid { + height: 600px; + background-color: white; +} + +.onapDcaeGrid span { + color: #393939; +} +.ht-pagination span { + color: #393939; +} +.ht-pagination span.dark { + color: #393939; +} +.dark { + color: #393939; +} + + + +.onapDcaeGrid div.debug { + color: #393939; + background-color: white; +} +.onapDcaeGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.onapDcaeGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.onapDcaeGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.controller.js new file mode 100644 index 00000000..565ce3a2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.controller.js @@ -0,0 +1,23 @@ +/* + * 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/onapDcae/onapDcae.module', + 'app/onapDcae/onapDcae.services'], + function (onapDcaeApp) { + + onapDcaeApp.register.controller('onapDcaeCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$onapDcae', '$mwtnLog', + function (uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $onapDcae, $mwtnLog) { + + var COMPONENT = 'onapDcaeCtrl'; + $mwtnLog.info({ component: COMPONENT, message: 'onapDcaeCtrl started!' }); + + $rootScope.section_logo = 'src/app/onapDcae/images/onapDcae.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + }]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.module.js new file mode 100644 index 00000000..579d740c --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.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 onapDcaeApp = angular.module('app.onapDcae', ['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', 'ui.grid.infiniteScroll','ui.grid.pagination' ]); + + onapDcaeApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + onapDcaeApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/onapDcae/onapDcae.controller'); + NavHelperProvider.addToMenu('onapDcae', { + "link" : "#/onapDcae/", + "active" : "main.onapDcae", + "title" : "ONAP DCAE", + "icon" : "fa fa-line-chart", // Add navigation icon css class here + "page" : { + "title" : "ONAP DCAE", + "description" : "Open Network Automation Platform (ONAP) - Data Collection, Analytics and Events (DCAE)" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.onapDcae', { + url: 'onapDcae/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/onapDcae/onapDcae.tpl.html', + controller: 'onapDcaeCtrl' + } + } + }); + + }); + + return onapDcaeApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.services.js new file mode 100644 index 00000000..ad875c6a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.services.js @@ -0,0 +1,20 @@ +/* + * 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/onapDcae/onapDcae.module', 'app/mwtnCommons/mwtnCommons.services'], function (onapDcaeApp) { + + onapDcaeApp.register.factory('$onapDcae', function ($q, $http, Base64, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.checkModules = $mwtnCommons.checkModules; + + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.tpl.html new file mode 100644 index 00000000..144bccc5 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/onapDcae-module/src/main/resources/onapDcae/onapDcae.tpl.html @@ -0,0 +1,13 @@ +<ht-header help-link='sdnr/onapDcae/0.4.0/README.md'></ht-header> + + +<h3>5G Architecture</h3> +<img src="src/app/onapDcae/images/onap-5g-architecture.png" class="img-rounded" alt="5G Architecture" width"1200"> + +<h1 style="margin-top: -440px; color: red; transform: rotate(-30deg);">Candidate for ONAP Beijing PoC June25</h1> +<br/><br/><br/><br/><br/> + +<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/onapDcae/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/pom.xml new file mode 100644 index 00000000..b32c1efc --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapDcae/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>onapDcae</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>onapDcae-module</module> + <module>onapDcae-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-bundle/pom.xml new file mode 100644 index 00000000..dd43c81d --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>onapSo</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>onapSo-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>onapSo-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>onapSo-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..e44af850 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="onapSo"/> + <property name="url" value="/src/app/onapSo"/> + <property name="directory" value="/onapSo"/> + <property name="requireJs" value="app/onapSo/onapSo.module"/> + <property name="angularJs" value="app.onapSo"/> + <property name="cssDependencies"> + <list> + <value>src/app/onapSo/onapSo-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/pom.xml new file mode 100644 index 00000000..f5d04d8f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/pom.xml @@ -0,0 +1,14 @@ +<?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>onapSo</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>onapSo-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/onapSo/onapSo-module/src/main/resources/onapSo/images/onap-end-to-end-slicing.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/images/onap-end-to-end-slicing.png Binary files differnew file mode 100755 index 00000000..c798dc1a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/images/onap-end-to-end-slicing.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/images/onapSo.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/images/onapSo.png Binary files differnew file mode 100755 index 00000000..f2a595f3 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/images/onapSo.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo-custom.css new file mode 100644 index 00000000..f2aaeb7b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo-custom.css @@ -0,0 +1,78 @@ +/** + * Add your application related css here + */ + + .app-onapSo * { + box-sizing: border-box; +} + +.app-onapSo .col { +height: 70px; +width: 12.5%; +float: left; +padding: 15px; +} + +.app-onapSo .row::after { + content: ""; + clear: both; + display: table; +} + + + +.onapSoGrid { + height: 600px; + background-color: white; +} + +.onapSoGrid span { + color: #393939; +} +.ht-pagination span { + color: #393939; +} +.ht-pagination span.dark { + color: #393939; +} +.dark { + color: #393939; +} + + + +.onapSoGrid div.debug { + color: #393939; + background-color: white; +} +.onapSoGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.onapSoGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.onapSoGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.controller.js new file mode 100644 index 00000000..cb07fc78 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.controller.js @@ -0,0 +1,84 @@ +/* + * 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/onapSo/onapSo.module', + 'app/onapSo/onapSo.services'], + function (onapSoApp) { + + onapSoApp.register.controller('onapSoCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$onapSo', '$mwtnLog', + function (uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $onapSo, $mwtnLog) { + + var COMPONENT = 'onapSoCtrl'; + $mwtnLog.info({ component: COMPONENT, message: 'onapSoCtrl started!' }); + + $rootScope.section_logo = 'src/app/onapSo/images/onapSo.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.highlightFilteredHeader = $onapSo.highlightFilteredHeader; + + $scope.pnf = { + pnfName: { id: 'pnfName', labelId: 'PNF_NAME', value: 'New-PNF' }, + pnfId: { id: 'pnfId', labelId: 'PNF_IDENTIFIER', value: 'New-PNF network unique identifier' }, + equipType: { id: 'equipType', labelId: 'PNF_EQUIPMENT_TYPE', value: 'Fancy equipment type' }, + equipModel: { id: 'equipModel', labelId: 'PNF_EQUIPMENT_MODEL', value: 'Best in class' }, + equipVendor: { id: 'equipVendor', labelId: 'PNF_EQUIPMENT_VENDOR', value: 'ONAP SDN-R Community' }, + ipaddressV4Oam: { id: 'ipaddressV4Oam', labelId: 'PNF_IPv4ADDRESS', value: '10.10.10.10' }, + inMaintenance: { id: 'inMaintenance', labelId: 'PNF_MAINTENANCE_MODE', value: false }, + resourceVersion: { id: 'resourceVersion', labelId: 'PNF_RESOURCE_VERSION', value: '' } + } + + $scope.createPnfInAai = function () { + + var data = { + "pnf-name": $scope.pnf.pnfName.value, + "pnf-id": $scope.pnf.pnfId.value, + "equip-type": $scope.pnf.equipType.value, + "equip-model": $scope.pnf.equipModel.value, + "equip-vendor": $scope.pnf.equipVendor.value, + "ipaddress-v4-oam": $scope.pnf.ipaddressV4Oam.value, + "in-maint": $scope.pnf.inMaintenance.value + } + + $onapSo.createPnf(data).then(function (response) { + console.info('successfully created: ', data['pnf-name']); + $onapSo.getPnf(data).then(function (success) { + // console.info('success', JSON.stringify(success.data)); + $scope.pnf.resourceVersion.value = success.data['resource-version']; + }, function (error) { + console.log('error1', JSON.stringify(error.data)); + $scope.error = error; + }); + }, function (error) { + console.log('error2', JSON.stringify(error.data)); + $scope.error = error; + }); + } + + $scope.deletePnfInAai = function () { + var data = { + "pnf-name": $scope.pnf.pnfName.value, + } + $onapSo.getPnf(data).then(function (success) { + console.info('success', JSON.stringify(success.data)); + $scope.pnf.resourceVersion.value = success.data['resource-version']; + data['resource-version'] = success.data['resource-version']; + $onapSo.deletePnf(data).then(function (success) { + console.info('success', JSON.stringify(success)); + $scope.pnf.resourceVersion.value = success.data['resource-version']; + }, function (error) { + console.log('error', JSON.stringify(error.data)); + $scope.error = error; + }); + }, function (error) { + console.log('error', JSON.stringify(error.data)); + $scope.error = error; + }); + } + + }]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.module.js new file mode 100644 index 00000000..b2bfec44 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.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 onapSoApp = angular.module('app.onapSo', ['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', 'ui.grid.infiniteScroll','ui.grid.pagination' ]); + + onapSoApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + onapSoApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/onapSo/onapSo.controller'); + NavHelperProvider.addToMenu('onapSo', { + "link" : "#/onapSo/", + "active" : "main.onapSo", + "title" : "ONAP SO", + "icon" : "fa fa-music", // Add navigation icon css class here + "page" : { + "title" : "ONAP SO", + "description" : "Open Network Automation Platform (ONAP) - Master Service Orchestrator (MSO)" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.onapSo', { + url: 'onapSo/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/onapSo/onapSo.tpl.html', + controller: 'onapSoCtrl' + } + } + }); + + }); + + return onapSoApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.services.js new file mode 100644 index 00000000..3e14e7c2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.services.js @@ -0,0 +1,162 @@ +/* + * 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/onapSo/onapSo.module', 'app/mwtnCommons/mwtnCommons.services'], function (onapSoApp) { + + onapSoApp.register.factory('$onapSo', function ($q, $http, Base64, $mwtnCommons, $mwtnDatabase, $mwtnLog, Device) { + + var service = {}; + + var functionId = "mwtn"; + var docType = "device"; + var from = 0; + var size = 9999; + var sort = undefined; + var deviceLookup = {}; + $mwtnDatabase.getAllData(functionId, docType, from, size, sort).then( + function successCallback(response) { + response.data.hits.hits.map(function(device){ + deviceLookup[device._id] = new Device(device._source); + }); + }, function errorCallback(response) { + deviceLookup = {}; + }); + + service.checkModules = $mwtnCommons.checkModules; + service.getMwtnWebSocketUrl = $mwtnCommons.getMwtnWebSocketUrl; + service.gridOptions = $mwtnCommons.gridOptions; + service.formatData = $mwtnCommons.formatData; + service.formatTimeStamp = $mwtnCommons.formatTimeStamp; + service.deleteDocType = $mwtnDatabase.deleteDocType; + + + var transactionId = 1; + var getHeaders = function () { + return { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-TransactionId': transactionId++ + } + }; + + // create or modify a pnf in aai + service.createPnf = function (pnf) { + var base = window.location.origin; + var request = { + method: 'PUT', + url: base + '/aai/network/pnfs/pnf/' + pnf['pnf-name'], + // withCredentials: true, + headers: getHeaders(), + data: pnf + }; + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + service.deletePnf = function (pnf) { + // curl -X DELETE http://localhost:8282/aai/network/pnfs/pnf/Ericsson-A1 --insecure -v -u AAI:AAI -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'X-FromAppId: SDNR' -H 'X-TransactionId: 9999' + var base = window.location.origin; + var request = { + method: 'DELETE', + url: base + '/aai/network/pnfs/pnf/' + pnf['pnf-name'] + '/?resource-version=' + pnf['resource-version'], + // withCredentials: true, + headers: getHeaders() + }; + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + service.getPnf = function (pnf) { + + console.log('get', JSON.stringify(pnf)); + var base = window.location.origin; + var request = { + method: 'GET', + url: base + '/aai/network/pnfs/pnf/' + pnf['pnf-name'], + // withCredentials: true, + headers: getHeaders() + }; + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + service.getAaiPnfs = function () { + // curl https://10.31.1.55:8443/network/pnfs -k -v -u abc:def -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'X-FromAppId: SDNR' -H 'X-TransactionId: 9999' + + var base = window.location.origin; + var request = { + method: 'GET', + url: base + '/aai/network/pnfs', // to es config + // withCredentials: true, + headers: getHeaders(), + }; + + var deferred = $q.defer(); + $http(request).then(function successCallback(response) { + deferred.resolve(response); + }, function errorCallback(response) { + deferred.reject(response); + }); + + return deferred.promise; + }; + + return service; + }); + + // Class Device + onapSoApp.register.factory('Device', function () { + var Device = function (data) { + if (!data) { + data = {id:new Date(), type: 'unknown', name:'unknonw', model: 'unkonwn', vendor:'unknonw', version:'unkonwn'}; + } + this.data = data; + this.getData = function () { + return this.data; + }; + this.getId = function () { + return this.getData().id; + }; + this.getType = function () { + return this.getData().type; + }; + this.getName = function () { + return this.getData().name; + }; + this.getModel = function () { + return this.getData().model; + }; + this.getVendor = function () { + return this.getData().vendor; + }; + this.getVersion = function () { + return this.getData().version; + }; + }; + return Device; + }); + +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.tpl.html new file mode 100644 index 00000000..777e2713 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/onapSo-module/src/main/resources/onapSo/onapSo.tpl.html @@ -0,0 +1,103 @@ +<ht-header help-link='sdnr/onapSo/0.4.0/README.md'></ht-header> + +<!-- +"pnf-name": "@pnfId@", +"pnf-id": "@pnfId@", +"equip-type": "@type@", +"equip-model": "@model@", +"equip-vendor": "@vendor@", +"ipaddress-v4-oam": "@oamIp@", +"in-maint": true, +--> + +<div class="app-onapSo container owl"> + + <div class="row"> + + <div class="col-md-12"> + <h3>Design Phase</h3> + <h4>Create PNF via SO in A&AI</h4> + </div> + + </div> + <div class="row"> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.pnfName.id }}">{{ pnf.pnfName.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.pnfName.id }}" ng-model="pnf.pnfName.value"> + </div> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.pnfId.id }}">{{ pnf.pnfId.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.pnfId.id }}" ng-model="pnf.pnfId.value"> + </div> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.equipType.id }}">{{ pnf.equipType.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.equipType.id }}" ng-model="pnf.equipType.value"> + </div> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.equipModel.id }}">{{ pnf.equipModel.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.equipModel.id }}" ng-model="pnf.equipModel.value"> + </div> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.equipVendor.id }}">{{ pnf.equipVendor.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.equipVendor.id }}" ng-model="pnf.equipVendor.value"> + </div> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.ipaddressV4Oam.id }}">{{ pnf.ipaddressV4Oam.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.ipaddressV4Oam.id }}" ng-model="pnf.ipaddressV4Oam.value"> + </div> + + <div class="col-md-3 form-check"> + <input type="checkbox" class="form-check-input" id="{{ pnf.inMaintenance.id }}" ng-model="pnf.inMaintenance.value"> + <label class="form-check-label" for="{{ pnf.inMaintenance.id }}"> + <span>{{ pnf.inMaintenance.labelId | translate }}</span> + </label> + </div> + + <div class="col-md-3 form-group"> + <label for="{{ pnf.resourceVersion.id }}">{{ pnf.resourceVersion.labelId | translate }}</label> + <br/> + <input type="text" class="form-control" id="{{ pnf.resourceVersion.id }}" ng-model="pnf.resourceVersion.value"> + </div> + + </div> + + <div class="row"> + + <div class="col-md-12"> + <button type="button" class="btn btn-primary" ng-click="createPnfInAai()"> + <i class="fa fa-plus" aria-hidden="true"></i> + <span>{{'PNF_CREATE_IN_AAI' | translate}}</span> + </button> + </div> + + </div> + <!-- api gateway must be enhanced to support query + <div class="row"> + + <div class="col-md-12"> + <button type="button" class="btn btn-danger" ng-click="deletePnfInAai()"> + <i class="fa fa-minus" aria-hidden="true"></i> + <span>{{'PNF_DELETE_IN_AAI' | translate}}</span> + </button> + </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/onapSo/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/pom.xml new file mode 100644 index 00000000..6dc13ae8 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/onapSo/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>onapSo</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>onapSo-module</module> + <module>onapSo-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-bundle/pom.xml new file mode 100644 index 00000000..25624e32 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-bundle/pom.xml @@ -0,0 +1,115 @@ +<?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>otnBrowser</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>otnBrowser-bundle</artifactId> + <packaging>bundle</packaging> + <name>${prefix} ${project.artifactId}</name> + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${osgi.core.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>${apache.felix.compendium}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>${dlux.loader.version}</version> + </dependency> + <dependency> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>otnBrowser-module</artifactId> + <version>0.5.1-SNAPSHOT</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.6</version> + <executions> + <!--loader Resources --> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <includeArtifactIds>otnBrowser-module</includeArtifactIds> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + <!-- <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>copy-resources</id> + <!- - here the phase you need - -> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>../../deploy</outputDirectory> + <resources> + <resource> + <directory>target</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> --> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..745b231b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="otnBrowser"/> + <property name="url" value="/src/app/otnBrowser"/> + <property name="directory" value="/otnBrowser"/> + <property name="requireJs" value="app/otnBrowser/otnBrowser.module"/> + <property name="angularJs" value="app.otnBrowser"/> + <property name="cssDependencies"> + <list> + <value>src/app/otnBrowser/otnBrowser-custom.css</value> + </list> + </property> + </bean> +</blueprint>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/pom.xml new file mode 100644 index 00000000..78e9affb --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/pom.xml @@ -0,0 +1,14 @@ +<?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>otnBrowser</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <artifactId>otnBrowser-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/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/images/otnBrowser.png b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/images/otnBrowser.png Binary files differnew file mode 100755 index 00000000..f7538980 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/images/otnBrowser.png diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser-custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser-custom.css new file mode 100644 index 00000000..e2123e95 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser-custom.css @@ -0,0 +1,58 @@ +/** + * Add your application related css here + */ +.otnBrowserGrid { + height: 600px; + background-color: white; +} + +.otnBrowserGrid span { + color: #393939; +} +.ht-pagination span { + color: #393939; +} +.ht-pagination span.dark { + color: #393939; +} +.dark { + color: #393939; +} + + + +.otnBrowserGrid div.debug { + color: #393939; + background-color: white; +} +.otnBrowserGrid div.error { + color: #ff0000; + background-color: #ffeeee; + font-weight: bold; +} + +.otnBrowserGrid div.info { + color: #3276b1; + background-color: #eeeeff; +} + +.otnBrowserGrid div.warning { + color: #ffa500; + background-color: #ffeedd; +} + +.rotated { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); +} + +h3.modal-title { + color: #393939; +} + +.modal-body span { + color: #393939; +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.controller.js new file mode 100644 index 00000000..8dc0fdb2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.controller.js @@ -0,0 +1,25 @@ +/* + * 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/otnBrowser/otnBrowser.module', + 'app/otnBrowser/otnBrowser.services'], + function (otnBrowserApp) { + + otnBrowserApp.register.controller('otnBrowserCtrl', ['uiGridConstants', '$uibModal', '$scope', '$rootScope', '$window', '$timeout', '$otnBrowser', '$mwtnLog', + function (uiGridConstants, $uibModal, $scope, $rootScope, $window, $timeout, $otnBrowser, $mwtnLog) { + + var COMPONENT = 'otnBrowserCtrl'; + $mwtnLog.info({ component: COMPONENT, message: 'otnBrowserCtrl started!' }); + + $rootScope.section_logo = 'src/app/otnBrowser/images/otnBrowser.png'; // Add your topbar logo location here such as 'assets/images/logo_topology.gif' + + $scope.highlightFilteredHeader = $otnBrowser.highlightFilteredHeader; + + }]); + + }); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.module.js new file mode 100644 index 00000000..7dc6802a --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.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 otnBrowserApp = angular.module('app.otnBrowser', ['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', 'ui.grid.infiniteScroll','ui.grid.pagination' ]); + + otnBrowserApp.config(function($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $translateProvider) { + otnBrowserApp.register = { + controller : $controllerProvider.register, + directive : $compileProvider.directive, + factory : $provide.factory, + service : $provide.service + }; + + + NavHelperProvider.addControllerUrl('app/otnBrowser/otnBrowser.controller'); + NavHelperProvider.addToMenu('otnBrowser', { + "link" : "#/otnBrowser/", + "active" : "main.otnBrowser", + "title" : "OTN Config", + "icon" : "fa fa-cogs", // Add navigation icon css class here + "page" : { + "title" : "OTN Config", + "description" : "Optical Transport Network (OTN) - Configuration" + } + }); + + var access = routingConfig.accessLevels; + + $stateProvider.state('main.otnBrowser', { + url: 'otnBrowser/:nodeId', + access: access.admin, + views : { + 'content' : { + templateUrl: 'src/app/otnBrowser/otnBrowser.tpl.html', + controller: 'otnBrowserCtrl' + } + } + }); + + }); + + return otnBrowserApp; +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.services.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.services.js new file mode 100644 index 00000000..64b87729 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.services.js @@ -0,0 +1,20 @@ +/* + * 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/otnBrowser/otnBrowser.module', 'app/mwtnCommons/mwtnCommons.services'], function (otnBrowserApp) { + + otnBrowserApp.register.factory('$otnBrowser', function ($q, $http, Base64, $mwtnCommons, $mwtnDatabase, $mwtnLog) { + + var service = {}; + + service.checkModules = $mwtnCommons.checkModules; + + + return service; + }); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.tpl.html new file mode 100644 index 00000000..c5d55444 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/otnBrowser-module/src/main/resources/otnBrowser/otnBrowser.tpl.html @@ -0,0 +1,9 @@ +<ht-header help-link='sdnr/otnBrowser/0.4.0/README.md'></ht-header> + +<h1 style="color: red; transform: rotate(-30deg);">Under Construction</h1> +<br/><br/><br/><br/><br/> + +<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/otnBrowser/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/pom.xml new file mode 100644 index 00000000..c363ee55 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/otnBrowser/pom.xml @@ -0,0 +1,24 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>mwtn</artifactId> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <version>0.5.1-SNAPSHOT</version> + </parent> + <packaging>pom</packaging> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>otnBrowser</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>${prefix} ${project.artifactId}</name> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>otnBrowser-module</module> + <module>otnBrowser-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/pom.xml new file mode 100644 index 00000000..1aa61d8f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/pom.xml @@ -0,0 +1,139 @@ +<?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> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>odlparent</artifactId> + <version>1.8.1-Carbon</version> + <relativePath /> + </parent> + + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtn</artifactId> + <version>0.5.1-SNAPSHOT</version> + <name>ONF :: Wireless :: ${project.artifactId}</name> + <packaging>pom</packaging> + + <prerequisites> + <maven>3.3.3</maven> + </prerequisites> + + <properties> + <prefix>ONF :: Wireless :: </prefix> + + <apache.felix.compendium>1.4.0</apache.felix.compendium> + <decanter.version>1.1.0</decanter.version> + <elasticsearch.version>2.2.0</elasticsearch.version> + <osgi.core.version>5.0.0</osgi.core.version> + + <dlux.version>0.5.1-Carbon</dlux.version> + <mdsal.version>1.5.1-Carbon</mdsal.version> + <mdsal.model.version>0.10.1-Carbon</mdsal.model.version> + <restconf.version>1.5.1-Carbon</restconf.version> + <yangtools.version>1.1.1-Carbon</yangtools.version> + <openflow.plugin.version>0.4.1-Carbon</openflow.plugin.version> + <netconf.version>1.2.1-Carbon</netconf.version> + <l2switch.version>0.5.1-Carbon</l2switch.version> + <dlux.loader.version>0.5.1-Carbon</dlux.loader.version> + + <configfile.directory>etc/opendaylight/karaf</configfile.directory> + + <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format> + <buildtime>${maven.build.timestamp} UTC</buildtime> + <distversion>OpenDaylight Carbon-SR1</distversion> + + </properties> + + <modules> + <module>mwtnCommons</module> + <module>mwtnConnect</module> + <module>onapAai</module> + <module>onapDcae</module> + <module>onapSo</module> + + <!-- <module>ethService</module> + <module>otnBrowser</module> --> + + <module>mwtnFault</module> + <module>mwtnBrowser</module> + <module>mwtnPerformanceCurrent</module> + <module>mwtnPerformanceHistory</module> + <module>mwtnPerformanceLink</module> + <module>security</module> + + <module>mwtnInventory</module> + <!-- <module>emergency</module> --> + + <module>mwtnTopology</module> + + <module>mwtnTdm</module> + + <!-- sko not updated to core-model 1.2 + <module>mwtnCompare</module> + <module>mwtnSpectrum</module> + <module>mwtnClosedLoop</module> --> + + <module>mwtnMediator</module> + <module>mwtnEvents</module> + <module>mwtnTest</module> + <module>mwtnLog</module> + + <module>odlChat</module> + + <module>help</module> + <module>features</module> + + </modules> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>false</skip> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <configuration> + <skip>false</skip> + </configuration> + </plugin> + <plugin> + <groupId>com.google.code.maven-replacer-plugin</groupId> + <artifactId>replacer</artifactId> + <version>1.5.3</version> + <executions> + <execution> + <phase>prepare-package</phase> + <goals> + <goal>replace</goal> + </goals> + </execution> + </executions> + <configuration> + <basedir>${project.basedir}/target/classes</basedir> + <includes> + <include>**/*.html</include> + <include>**/*.js</include> + <include>**/*.css</include> + </includes> + <replacements> + <replacement> + <token>@distversion@</token> + <value>${distversion}</value> + </replacement> + <replacement> + <token>@buildtime@</token> + <value>${buildtime}</value> + </replacement> + </replacements> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/pom.xml new file mode 100644 index 00000000..8973079b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/pom.xml @@ -0,0 +1,28 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.highstreet.technologies.odl.dlux</groupId> + <artifactId>mwtn</artifactId> + <version>0.5.1-SNAPSHOT</version> + <relativePath>../</relativePath> + </parent> + + <groupId>org.onap.sdnc.dluxapps</groupId> + <artifactId>security</artifactId> + <!-- <name> formatting is used by autorelease to parse and notify projects on + build failure. Please do not modify this unless you have a good reason. --> + <name>${prefix} ${project.artifactId}</name> + <version>0.5.1</version> + <packaging>pom</packaging> + + <prerequisites> + <maven>3.0</maven> + </prerequisites> + + <modules> + <module>security-module</module> + <module>security-bundle</module> + </modules> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-bundle/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-bundle/pom.xml new file mode 100644 index 00000000..34358bbe --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-bundle/pom.xml @@ -0,0 +1,80 @@ +<?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> + <groupId>org.onap.sdnc.dluxapps</groupId> + <artifactId>security</artifactId> + <version>0.5.1</version> + </parent> + + <groupId>org.onap.sdnc.dluxapps</groupId> + <artifactId>security-bundle</artifactId> + <packaging>bundle</packaging> + <!-- <name> formatting is used by autorelease to parse and notify projects on + build failure. Please do not modify this unless you have a good reason. --> + <name>${prefix} ${project.artifactId}</name> + + <dependencies> + <dependency> + <groupId>org.opendaylight.dlux</groupId> + <artifactId>loader</artifactId> + <version>0.5.1-Carbon</version> + </dependency> + <dependency> + <groupId>org.onap.sdnc.dluxapps</groupId> + <artifactId>security-module</artifactId> + <version>0.5.1</version> + <scope>provided</scope> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>target/generated-resources</directory> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <!--loader Resources--> + <execution> + <id>unpack-loader-resources</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> + <groupId>org.onap.sdnc.dluxapps</groupId> + <includeArtifactIds>security-module</includeArtifactIds> + <!-- <includes>security/src\/**</includes> --> + <excludes>META-INF\/**</excludes> + <excludeTransitive>true</excludeTransitive> + <ignorePermissions>false</ignorePermissions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>org.osgi.service.http, + org.osgi.framework;version="1.0.0", + org.opendaylight.dlux.loader + </Import-Package> + <Export-Package></Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..65ef78a3 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,19 @@ +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/> + <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/> + + <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule"> + <property name="httpService" ref="httpService"/> + <property name="loader" ref="loader"/> + <property name="moduleName" value="security"/> + <property name="url" value="/src/app/security"/> + <property name="directory" value="/security/src"/> + <property name="requireJs" value="app/security/security.module"/> + <property name="angularJs" value="app.security"/> + <property name="cssDependencies"> + <list> + <value>src/app/security/security.custom.css</value> + </list> + </property> + </bean> +</blueprint> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/pom.xml b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/pom.xml new file mode 100644 index 00000000..95ae27b2 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/pom.xml @@ -0,0 +1,18 @@ +<?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>security</artifactId> + <groupId>org.onap.sdnc.dluxapps</groupId> + <version>0.5.1</version> + <relativePath>../</relativePath> + </parent> + <groupId>org.onap.sdnc.dluxapps</groupId> + <artifactId>security-module</artifactId> + <name>${prefix} ${project.artifactId}</name> + <version>0.5.1</version> + <packaging>jar</packaging> + + </project> diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/build.config.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/build.config.js new file mode 100644 index 00000000..c8396a3f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/build.config.js @@ -0,0 +1,42 @@ +/** + * This file/module contains all configuration for the build process. + */ +module.exports = { + build_dir: 'build', + app_dir: 'app', + + app_files: { + js: [ + 'src/*/**/*.js', + '!node/**/*.*', + '!node_modules/**/*.*', + '!src/vendor/**/*.*' + ], + root_js: [ + 'src/*.js' + ], + less: [ + 'src/assets/less/*.less' + ], + img: [ + 'src/assets/img/*.*' + ], + + templates: [ + 'src/*/**/*.tpl.html', + 'src/*.tpl.html' + ] + }, + + assets_files: { + less: [], + css: [], + data: [] + }, + + vendor_files: { + js: [], + css: [], + fonts: [] + } +}; diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/gulpfile.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/gulpfile.js new file mode 100644 index 00000000..c3a15c45 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/gulpfile.js @@ -0,0 +1,142 @@ +var gulp = require('gulp'), + del = require('del'), + gutil = require('gulp-util'), + concat = require('gulp-concat'), + runSequence = require('run-sequence'), + install = require("gulp-install"), + connect = require('gulp-connect'), + open = require('gulp-open'), + argv = require('yargs').argv, + less = require('gulp-less'), + debug = require('gulp-debug'), + replace = require('gulp-replace-task'); + +var config = require( './build.config.js'); + + +/** + * Task for cleaning build directory + */ +gulp.task('clean', function() { + // You can use multiple globbing patterns as you would with `gulp.src` + return del(config.build_dir); +}); + +/** + * Copy assets + */ +gulp.task('copyAssetsCss', function () { + return gulp.src(config.assets_files.css) + .pipe( + gulp.dest( + (config.build_dir) + '/assets/css' + ) + ); +}); + +gulp.task('copyAssetsData', function () { + return gulp.src(config.assets_files.data) + .pipe(gulp.dest((config.build_dir) + '/assets/data')); +}); + +/** + * Copy app files + */ +gulp.task('copyTemplates', function () { + gutil.log(gutil.colors.cyan('INFO :: copying APP Template files')); + // Copy html + return gulp.src(config.app_files.templates) + .pipe(gulp.dest(config.build_dir)); +}); + +gulp.task('copyAppJs', function () { + gutil.log(gutil.colors.cyan('INFO :: copying APP Controller JS files')); + return gulp.src(config.app_files.js) + .pipe(gulp.dest(config.build_dir)); +}); + +gulp.task('copyRootJs', function () { + gutil.log(gutil.colors.cyan('INFO :: copying APP Root JS files')); + return gulp.src(config.app_files.root_js) + .pipe(gulp.dest(config.build_dir)); +}); + +/** + * Compile css from less files + */ +gulp.task('less', function () { + gutil.log(gutil.colors.cyan('INFO :: compiling LESS file')); + return gulp.src(config.app_files.less) + .pipe(less()) + .pipe(gulp.dest((config.build_dir) + '/assets/css')); +}); + +/** + * Copy app assets images + */ +gulp.task('copyAppImgs', function () { + gutil.log(gutil.colors.cyan('INFO :: copying image files')); + return gulp.src(config.app_files.img) + .pipe(gulp.dest((config.build_dir) + '/assets/img')); + +}); + +/** + * Copy vendor files + */ +gulp.task('copyVendorCss', function () { + gutil.log(gutil.colors.cyan('INFO :: copying VENDOR css')); + return gulp.src(config.vendor_files.css, { cwd : 'node_modules/**' }) + .pipe(gulp.dest((config.build_dir) + '/vendor')); +}); + +gulp.task('copyVendorFonts', function () { + gutil.log(gutil.colors.cyan('INFO :: copying VENDOR fonts')); + return gulp.src(config.vendor_files.fonts, { cwd : 'node_modules/**' }) + .pipe(gulp.dest((config.build_dir) + '/vendor')); +}); + +gulp.task('copyVendorJs', function () { + gutil.log(gutil.colors.cyan('INFO :: copying VENDOR js files')); + return gulp.src(config.vendor_files.js, { cwd : 'node_modules/**' }) + .pipe(gulp.dest((config.build_dir) + '/vendor')); +}); + +/** + * Copy task aggregated + */ +gulp.task('copy', function() { + runSequence('less', [ + 'copyAssetsCss', + 'copyAssetsData', + 'copyTemplates', + 'copyAppJs', + 'copyRootJs', + 'copyVendorCss', + 'copyVendorFonts', + 'copyAppImgs' + ], 'copyVendorJs'); +}); + +/** + * Build task + */ +gulp.task('build', function(){ + runSequence('clean', 'copy'); +}); + + +/** + * Live preview main task for development + * argument --live should be used to force build task to build only live preview + */ +gulp.task('default', function (){ + + if (!argv.live) { + gutil.log(gutil.colors.red('ERROR :: --live argument must be used for live preview!')); + } + + gutil.log(gutil.colors.cyan('INFO :: opening new browser tab live:' + argv.live)); + + runSequence('build'); +}); diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/package.json b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/package.json new file mode 100644 index 00000000..2fb0b713 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/package.json @@ -0,0 +1,29 @@ +{ + "name": "odl-dluxapps-security", + "version": "0.5.1", + "main": "main.js", + "devDependencies": { + "gulp-bower": "0.0.13" + }, + "dependencies": { + "del": "^2.2.0", + "gulp": "^3.9.1", + "gulp-concat": "^2.6.0", + "gulp-connect": "^5.0.0", + "gulp-debug": "^3.0.0", + "gulp-install": "^0.6.0", + "gulp-less": "^3.1.0", + "gulp-open": "^2.0.0", + "gulp-replace-task": "^0.11.0", + "gulp-util": "^3.0.7", + "run-sequence": "^1.1.5" + }, + "repository": { + "type": "git", + "url": "https://git.opendaylight.org/gerrit/dluxapps" + }, + "license": "EPL", + "keywords": [ + "odl" + ] +} diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.controller.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.controller.js new file mode 100644 index 00000000..e7f12c22 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.controller.js @@ -0,0 +1,149 @@ +define("security.service", ["require", "exports", "angularAMD"], function (require, exports, angular) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var security = angular.module('app.security'); + var SecurityService = /** @class */ (function () { + function SecurityService($q, $http, $window, env) { + this.$q = $q; + this.$http = $http; + this.$window = $window; + this.env = env; + this.ensureCrendentials(); + } + SecurityService.prototype.ensureCrendentials = function () { + var credentialsDefer = this.$q.defer(); + this.credentials = credentialsDefer.promise; + var url = this.env.getBaseURL('MD_SAL') + "/oauth2/token"; + this.$http({ + method: "POST", + url: url, + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + data: "grant_type=password&username=" + this.$window.sessionStorage.odlUser + "&password=" + this.$window.sessionStorage.odlPass + "&scope=sdn" + }).then(function (res) { + credentialsDefer.resolve(res.data && res.data.access_token); + }, function (err) { + credentialsDefer.reject(err); + }); + }; + Object.defineProperty(SecurityService.prototype, "token", { + get: function () { + return this.credentials; + }, + enumerable: true, + configurable: true + }); + SecurityService.prototype.getAllUsers = function () { + var _this = this; + var url = this.env.getBaseURL('MD_SAL') + "/auth/v1/users"; + return this.token.then(function (token) { + return _this.$http({ + method: "GET", + url: url, + headers: { 'Authorization': "Bearer " + token } + }).then(function (result) { return result.data && result.data.users; }); + }); + }; + SecurityService.prototype.getAllRoles = function () { + var _this = this; + var url = this.env.getBaseURL('MD_SAL') + "/auth/v1/roles"; + return this.token.then(function (token) { + return _this.$http({ + method: "GET", + url: url, + headers: { 'Authorization': "Bearer " + token } + }).then(function (result) { return result.data && result.data.roles; }); + }); + }; + SecurityService.prototype.getUserById = function (userId) { + var _this = this; + var url = this.env.getBaseURL('MD_SAL') + "/auth/v1/users/" + userId; + return this.token.then(function (token) { + return _this.$http({ + method: "GET", + url: url, + headers: { 'Authorization': "Bearer " + token } + }).then(function (result) { return result.data && result.data; }); + }); + }; + SecurityService.prototype.getRolesForDomainUser = function (userId, domain) { + var _this = this; + if (domain === void 0) { domain = "sdn"; } + var url = this.env.getBaseURL('MD_SAL') + "/auth/v1/domains/" + domain + "/users/" + userId + "/roles"; + return this.token.then(function (token) { + return _this.$http({ + method: "GET", + url: url, + headers: { 'Authorization': "Bearer " + token } + }).then(function (result) { return result.data && result.data.roles; }); + }); + }; + return SecurityService; + }()); + exports.SecurityService = SecurityService; + security.service('securityService', ['$q', '$http', '$window', 'ENV', SecurityService]); +}); +define( ["require", "exports", "security.service"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var security = angular.module('app.security'); + var UserDetailsCtrl = /** @class */ (function () { + function UserDetailsCtrl($scope, $uibModalInstance, userid, roles) { + var _this = this; + this.$uibModalInstance = $uibModalInstance; + this.userid = userid; + this.roles = roles; + this.ok = function () { + _this.$uibModalInstance.close( /* Parameter*/); + }; + this.cancel = function () { + _this.$uibModalInstance.dismiss('cancel'); + }; + } + return UserDetailsCtrl; + }()); + security.controller('userDetailsCtrl', ['$scope', '$uibModalInstance', 'userid', 'roles', UserDetailsCtrl]); + var SecurityCtrl = /** @class */ (function () { + function SecurityCtrl($scope, $timeout, $q, $uibModal, $document, $mwtnCommons, securityService) { + this.$q = $q; + this.$uibModal = $uibModal; + this.$document = $document; + this.securityService = securityService; + $scope.message = "Empty"; + $scope.users = []; + $scope.roles = []; + $scope.currentUser = {}; + $scope.getCurrentUserById = function (id) { + id !== null && securityService.getRolesForDomainUser(id).then(function (roles) { + var parentElem = angular.element($document[0].querySelector('#security')); + var modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/security/templates/userDetails.html', + controller: 'userDetailsCtrl', + controllerAs: 'vm', + appendTo: parentElem, + size: 'sm', + resolve: { + roles: function () { return roles; }, + userid: function () { return id; }, + } + }); + }); + }; + securityService.token.then(function (res) { + $q.all([ + securityService.getAllUsers(), + securityService.getAllRoles() + ]).then(function (_a) { + var users = _a[0], roles = _a[1]; + $scope.users = users; + $scope.roles = roles; + }); + }); + } + return SecurityCtrl; + }()); + security.controller('securityCtrl', ['$scope', '$timeout', '$q', '$uibModal', '$document', '$mwtnCommons', 'securityService', SecurityCtrl]); +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJpdHkuY29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VjdXJpdHkvc2VjdXJpdHkuc2VydmljZS50cyIsInNyYy9hcHAvc2VjdXJpdHkvc2VjdXJpdHkuY29udHJvbGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7SUFFQSxJQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBdUJoRDtRQUdFLHlCQUFvQixFQUFnQixFQUFVLEtBQXNCLEVBQVUsT0FBTyxFQUFVLEdBQWdCO1lBQTNGLE9BQUUsR0FBRixFQUFFLENBQWM7WUFBVSxVQUFLLEdBQUwsS0FBSyxDQUFpQjtZQUFVLFlBQU8sR0FBUCxPQUFPLENBQUE7WUFBVSxRQUFHLEdBQUgsR0FBRyxDQUFhO1lBQzdHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzVCLENBQUM7UUFFTyw0Q0FBa0IsR0FBMUI7WUFDRSxJQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFVLENBQUM7WUFDakQsSUFBSSxDQUFDLFdBQVcsR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7WUFFNUMsSUFBTSxHQUFHLEdBQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLGtCQUFlLENBQUM7WUFDNUQsSUFBSSxDQUFDLEtBQUssQ0FBMkI7Z0JBQ25DLE1BQU0sRUFBRSxNQUFNO2dCQUNkLEdBQUcsRUFBRSxHQUFHO2dCQUNSLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxtQ0FBbUMsRUFBRTtnQkFDaEUsSUFBSSxFQUFFLGtDQUFnQyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxPQUFPLGtCQUFhLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLE9BQU8sZUFBWTthQUN0SSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsR0FBRztnQkFDVCxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzlELENBQUMsRUFBRSxVQUFBLEdBQUc7Z0JBQ0osZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQy9CLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHNCQUFXLGtDQUFLO2lCQUFoQjtnQkFDRSxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7WUFDMUIsQ0FBQzs7O1dBQUE7UUFFTSxxQ0FBVyxHQUFsQjtZQUFBLGlCQVNDO1lBUkMsSUFBTSxHQUFHLEdBQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLG1CQUFnQixDQUFDO1lBQzdELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBQSxLQUFLO2dCQUMxQixPQUFPLEtBQUksQ0FBQyxLQUFLLENBQW9CO29CQUNuQyxNQUFNLEVBQUUsS0FBSztvQkFDYixHQUFHLEVBQUUsR0FBRztvQkFDUixPQUFPLEVBQUUsRUFBRSxlQUFlLEVBQUUsWUFBVSxLQUFPLEVBQUU7aUJBQ2hELENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQSxNQUFNLElBQUksT0FBQSxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFoQyxDQUFnQyxDQUFDLENBQUE7WUFDckQsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRU0scUNBQVcsR0FBbEI7WUFBQSxpQkFTQztZQVJDLElBQU0sR0FBRyxHQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxtQkFBZ0IsQ0FBQztZQUM3RCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQUEsS0FBSztnQkFDMUIsT0FBTyxLQUFJLENBQUMsS0FBSyxDQUFvQjtvQkFDbkMsTUFBTSxFQUFFLEtBQUs7b0JBQ2IsR0FBRyxFQUFFLEdBQUc7b0JBQ1IsT0FBTyxFQUFFLEVBQUUsZUFBZSxFQUFFLFlBQVUsS0FBTyxFQUFFO2lCQUNoRCxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsTUFBTSxJQUFJLE9BQUEsTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBaEMsQ0FBZ0MsQ0FBQyxDQUFBO1lBQ3JELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVNLHFDQUFXLEdBQWxCLFVBQW1CLE1BQWM7WUFBakMsaUJBU0M7WUFSQyxJQUFNLEdBQUcsR0FBTSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsdUJBQWtCLE1BQVEsQ0FBQztZQUN2RSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQUEsS0FBSztnQkFDMUIsT0FBTyxLQUFJLENBQUMsS0FBSyxDQUFPO29CQUN0QixNQUFNLEVBQUUsS0FBSztvQkFDYixHQUFHLEVBQUUsR0FBRztvQkFDUixPQUFPLEVBQUUsRUFBRSxlQUFlLEVBQUUsWUFBVSxLQUFPLEVBQUU7aUJBQ2hELENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQSxNQUFNLElBQUksT0FBQSxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEVBQTFCLENBQTBCLENBQUMsQ0FBQTtZQUMvQyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFTSwrQ0FBcUIsR0FBNUIsVUFBNkIsTUFBYyxFQUFFLE1BQXFCO1lBQWxFLGlCQVNDO1lBVDRDLHVCQUFBLEVBQUEsY0FBcUI7WUFDaEUsSUFBTSxHQUFHLEdBQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLHlCQUFvQixNQUFNLGVBQVUsTUFBTSxXQUFRLENBQUM7WUFDL0YsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFBLEtBQUs7Z0JBQzFCLE9BQU8sS0FBSSxDQUFDLEtBQUssQ0FBb0I7b0JBQ25DLE1BQU0sRUFBRSxLQUFLO29CQUNiLEdBQUcsRUFBRSxHQUFHO29CQUNSLE9BQU8sRUFBRSxFQUFFLGVBQWUsRUFBRSxZQUFVLEtBQU8sRUFBRTtpQkFDaEQsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFBLE1BQU0sSUFBSSxPQUFBLE1BQU0sQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQWhDLENBQWdDLENBQUMsQ0FBQTtZQUNyRCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDSCxzQkFBQztJQUFELENBQUMsQUF2RUQsSUF1RUM7SUF2RVksMENBQWU7SUF5RTVCLFFBQVEsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQzs7Ozs7SUM1RnhGLElBQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7SUFFaEQ7UUFDRSx5QkFBWSxNQUFNLEVBQVUsaUJBQWlCLEVBQVMsTUFBYyxFQUFTLEtBQWE7WUFBMUYsaUJBRUM7WUFGMkIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFBO1lBQVMsV0FBTSxHQUFOLE1BQU0sQ0FBUTtZQUFTLFVBQUssR0FBTCxLQUFLLENBQVE7WUFJbkYsT0FBRSxHQUFHO2dCQUNWLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUMsY0FBYyxDQUFDLENBQUM7WUFDL0MsQ0FBQyxDQUFDO1lBRUssV0FBTSxHQUFHO2dCQUNkLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0MsQ0FBQyxDQUFDO1FBUkYsQ0FBQztRQVNILHNCQUFDO0lBQUQsQ0FBQyxBQVpELElBWUM7SUFFRCxRQUFRLENBQUMsVUFBVSxDQUFDLGlCQUFpQixFQUFFLENBQUMsUUFBUSxFQUFFLG1CQUFtQixFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQztJQUU1RztRQUNFLHNCQUFZLE1BQU0sRUFBRSxRQUFRLEVBQVUsRUFBZ0IsRUFBVSxTQUFTLEVBQVUsU0FBK0IsRUFBRyxZQUFZLEVBQVUsZUFBZ0M7WUFBckksT0FBRSxHQUFGLEVBQUUsQ0FBYztZQUFVLGNBQVMsR0FBVCxTQUFTLENBQUE7WUFBVSxjQUFTLEdBQVQsU0FBUyxDQUFzQjtZQUF5QixvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7WUFDekssTUFBTSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7WUFDekIsTUFBTSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDbEIsTUFBTSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDbEIsTUFBTSxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUM7WUFFeEIsTUFBTSxDQUFDLGtCQUFrQixHQUFHLFVBQVUsRUFBVTtnQkFDOUMsRUFBRSxLQUFLLElBQUksSUFBSSxlQUFlLENBQUMscUJBQXFCLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsS0FBSztvQkFDakUsSUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7b0JBQzVFLElBQU0sYUFBYSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUM7d0JBQ25DLFNBQVMsRUFBRSxJQUFJO3dCQUNmLGNBQWMsRUFBRSxhQUFhO3dCQUM3QixlQUFlLEVBQUUsWUFBWTt3QkFDN0IsV0FBVyxFQUFFLDZDQUE2Qzt3QkFDMUQsVUFBVSxFQUFFLGlCQUFpQjt3QkFDN0IsWUFBWSxFQUFFLElBQUk7d0JBQ2xCLFFBQVEsRUFBRSxVQUFVO3dCQUNwQixJQUFJLEVBQUUsSUFBSTt3QkFDVixPQUFPLEVBQUU7NEJBQ1AsS0FBSyxFQUFFLGNBQU0sT0FBQSxLQUFLLEVBQUwsQ0FBSzs0QkFDbEIsTUFBTSxFQUFFLGNBQU0sT0FBQSxFQUFFLEVBQUYsQ0FBRTt5QkFDakI7cUJBQ0YsQ0FBQyxDQUFBO2dCQUNKLENBQUMsQ0FBQyxDQUFBO1lBQ0osQ0FBQyxDQUFDO1lBRUYsZUFBZSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBQSxHQUFHO2dCQUM1QixFQUFFLENBQUMsR0FBRyxDQUFDO29CQUNMLGVBQWUsQ0FBQyxXQUFXLEVBQUU7b0JBQzdCLGVBQWUsQ0FBQyxXQUFXLEVBQUU7aUJBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFDLEVBQWM7d0JBQWIsYUFBSyxFQUFFLGFBQUs7b0JBQ2pELE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO29CQUNyQixNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztnQkFDekIsQ0FBQyxDQUFDLENBQUE7WUFDSixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDSCxtQkFBQztJQUFELENBQUMsQUFwQ0QsSUFvQ0M7SUFFRCxRQUFRLENBQUMsVUFBVSxDQUFDLGNBQWMsRUFBRSxDQUFDLFFBQVEsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBQyxXQUFXLEVBQUUsY0FBYyxFQUFFLGlCQUFpQixFQUFFLFlBQVksQ0FBRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhbmd1bGFyIGZyb20gJ2FuZ3VsYXJBTUQnO1xuXG5jb25zdCBzZWN1cml0eSA9IGFuZ3VsYXIubW9kdWxlKCdhcHAuc2VjdXJpdHknKTtcblxuaW50ZXJmYWNlIElFbnZTZXJ2aWNlIHtcbiAgZ2V0QmFzZVVSTChwb3J0OiBzdHJpbmcpOiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIFVzZXIgPSB7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGRvbWFpbmlkOiBzdHJpbmc7XG4gIGVtYWlsOiBzdHJpbmc7XG4gIGVuYWJsZWQ6IGJvb2xlYW47XG4gIHBhc3N3b3JkOiBzdHJpbmc7XG4gIHNhbHQ6IHN0cmluZztcbiAgdXNlcmlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIFJvbGUgPSB7XG4gIHJvbGVpZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGRvbWFpbmlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTZWN1cml0eVNlcnZpY2Uge1xuICBwcml2YXRlIGNyZWRlbnRpYWxzOiBuZy5JUHJvbWlzZTxzdHJpbmc+O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgJHE6IG5nLklRU2VydmljZSwgcHJpdmF0ZSAkaHR0cDogbmcuSUh0dHBTZXJ2aWNlLCBwcml2YXRlICR3aW5kb3csIHByaXZhdGUgZW52OiBJRW52U2VydmljZSkge1xuICAgIHRoaXMuZW5zdXJlQ3JlbmRlbnRpYWxzKCk7XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZUNyZW5kZW50aWFscygpIHtcbiAgICBjb25zdCBjcmVkZW50aWFsc0RlZmVyID0gdGhpcy4kcS5kZWZlcjxzdHJpbmc+KCk7XG4gICAgdGhpcy5jcmVkZW50aWFscyA9IGNyZWRlbnRpYWxzRGVmZXIucHJvbWlzZTtcblxuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuZW52LmdldEJhc2VVUkwoJ01EX1NBTCcpfS9vYXV0aDIvdG9rZW5gO1xuICAgIHRoaXMuJGh0dHA8eyBhY2Nlc3NfdG9rZW46IHN0cmluZyB9Pih7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgdXJsOiB1cmwsXG4gICAgICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyB9LFxuICAgICAgZGF0YTogYGdyYW50X3R5cGU9cGFzc3dvcmQmdXNlcm5hbWU9JHt0aGlzLiR3aW5kb3cuc2Vzc2lvblN0b3JhZ2Uub2RsVXNlcn0mcGFzc3dvcmQ9JHt0aGlzLiR3aW5kb3cuc2Vzc2lvblN0b3JhZ2Uub2RsUGFzc30mc2NvcGU9c2RuYFxuICAgIH0pLnRoZW4ocmVzID0+IHtcbiAgICAgIGNyZWRlbnRpYWxzRGVmZXIucmVzb2x2ZShyZXMuZGF0YSAmJiByZXMuZGF0YS5hY2Nlc3NfdG9rZW4pO1xuICAgIH0sIGVyciA9PiB7XG4gICAgICBjcmVkZW50aWFsc0RlZmVyLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldCB0b2tlbigpIHtcbiAgICByZXR1cm4gdGhpcy5jcmVkZW50aWFscztcbiAgfVxuXG4gIHB1YmxpYyBnZXRBbGxVc2VycygpOiBuZy5JUHJvbWlzZTxVc2VyW10+IHtcbiAgICBjb25zdCB1cmwgPSBgJHt0aGlzLmVudi5nZXRCYXNlVVJMKCdNRF9TQUwnKX0vYXV0aC92MS91c2Vyc2A7XG4gICAgcmV0dXJuIHRoaXMudG9rZW4udGhlbih0b2tlbiA9PiB7XG4gICAgICByZXR1cm4gdGhpcy4kaHR0cDx7IHVzZXJzOiBVc2VyW10gfT4oe1xuICAgICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBoZWFkZXJzOiB7ICdBdXRob3JpemF0aW9uJzogYEJlYXJlciAke3Rva2VufWAgfVxuICAgICAgfSkudGhlbihyZXN1bHQgPT4gcmVzdWx0LmRhdGEgJiYgcmVzdWx0LmRhdGEudXNlcnMpXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0QWxsUm9sZXMoKTogbmcuSVByb21pc2U8Um9sZVtdPiB7XG4gICAgY29uc3QgdXJsID0gYCR7dGhpcy5lbnYuZ2V0QmFzZVVSTCgnTURfU0FMJyl9L2F1dGgvdjEvcm9sZXNgO1xuICAgIHJldHVybiB0aGlzLnRva2VuLnRoZW4odG9rZW4gPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuJGh0dHA8eyByb2xlczogUm9sZVtdIH0+KHtcbiAgICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgaGVhZGVyczogeyAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHt0b2tlbn1gIH1cbiAgICAgIH0pLnRoZW4ocmVzdWx0ID0+IHJlc3VsdC5kYXRhICYmIHJlc3VsdC5kYXRhLnJvbGVzKVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldFVzZXJCeUlkKHVzZXJJZDogc3RyaW5nKTogbmcuSVByb21pc2U8VXNlcj4ge1xuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuZW52LmdldEJhc2VVUkwoJ01EX1NBTCcpfS9hdXRoL3YxL3VzZXJzLyR7dXNlcklkfWA7XG4gICAgcmV0dXJuIHRoaXMudG9rZW4udGhlbih0b2tlbiA9PiB7XG4gICAgICByZXR1cm4gdGhpcy4kaHR0cDxVc2VyPih7XG4gICAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0F1dGhvcml6YXRpb24nOiBgQmVhcmVyICR7dG9rZW59YCB9XG4gICAgICB9KS50aGVuKHJlc3VsdCA9PiByZXN1bHQuZGF0YSAmJiByZXN1bHQuZGF0YSlcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRSb2xlc0ZvckRvbWFpblVzZXIodXNlcklkOiBzdHJpbmcsIGRvbWFpbjogc3RyaW5nPSBcInNkblwiKTogbmcuSVByb21pc2U8Um9sZVtdPiB7XG4gICAgY29uc3QgdXJsID0gYCR7dGhpcy5lbnYuZ2V0QmFzZVVSTCgnTURfU0FMJyl9L2F1dGgvdjEvZG9tYWlucy8ke2RvbWFpbn0vdXNlcnMvJHt1c2VySWR9L3JvbGVzYDtcbiAgICByZXR1cm4gdGhpcy50b2tlbi50aGVuKHRva2VuID0+IHtcbiAgICAgIHJldHVybiB0aGlzLiRodHRwPHsgcm9sZXM6IFJvbGVbXSB9Pih7XG4gICAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0F1dGhvcml6YXRpb24nOiBgQmVhcmVyICR7dG9rZW59YCB9XG4gICAgICB9KS50aGVuKHJlc3VsdCA9PiByZXN1bHQuZGF0YSAmJiByZXN1bHQuZGF0YS5yb2xlcylcbiAgICB9KTtcbiAgfVxufVxuXG5zZWN1cml0eS5zZXJ2aWNlKCdzZWN1cml0eVNlcnZpY2UnLCBbJyRxJywgJyRodHRwJywgJyR3aW5kb3cnLCAnRU5WJywgU2VjdXJpdHlTZXJ2aWNlXSk7IiwiZGVjbGFyZSB2YXIgYW5ndWxhcjogYW5ndWxhci5JQW5ndWxhclN0YXRpYzsgXG5cbmltcG9ydCB7IFNlY3VyaXR5U2VydmljZSwgUm9sZSB9IGZyb20gXCIuL3NlY3VyaXR5LnNlcnZpY2VcIjsgXG5cbmltcG9ydCBcIi4vc2VjdXJpdHkuc2VydmljZVwiO1xuXG5jb25zdCBzZWN1cml0eSA9IGFuZ3VsYXIubW9kdWxlKCdhcHAuc2VjdXJpdHknKTtcblxuY2xhc3MgVXNlckRldGFpbHNDdHJsIHtcbiAgY29uc3RydWN0b3IoJHNjb3BlLCBwcml2YXRlICR1aWJNb2RhbEluc3RhbmNlLCBwdWJsaWMgdXNlcmlkOiBzdHJpbmcsIHB1YmxpYyByb2xlczogUm9sZVtdKSB7XG5cbiAgfVxuXG4gIHB1YmxpYyBvayA9ICgpID0+IHtcbiAgICB0aGlzLiR1aWJNb2RhbEluc3RhbmNlLmNsb3NlKC8qIFBhcmFtZXRlciovKTtcbiAgfTtcblxuICBwdWJsaWMgY2FuY2VsID0gKCkgPT4ge1xuICAgIHRoaXMuJHVpYk1vZGFsSW5zdGFuY2UuZGlzbWlzcygnY2FuY2VsJyk7XG4gIH07XG59XG5cbnNlY3VyaXR5LmNvbnRyb2xsZXIoJ3VzZXJEZXRhaWxzQ3RybCcsIFsnJHNjb3BlJywgJyR1aWJNb2RhbEluc3RhbmNlJywgJ3VzZXJpZCcsICdyb2xlcycsIFVzZXJEZXRhaWxzQ3RybF0pO1xuXG5jbGFzcyBTZWN1cml0eUN0cmwge1xuICBjb25zdHJ1Y3Rvcigkc2NvcGUsICR0aW1lb3V0LCBwcml2YXRlICRxOiBuZy5JUVNlcnZpY2UsIHByaXZhdGUgJHVpYk1vZGFsLCBwcml2YXRlICRkb2N1bWVudCA6IG5nLklEb2N1bWVudFNlcnZpY2UsICAkbXd0bkNvbW1vbnMsIHByaXZhdGUgc2VjdXJpdHlTZXJ2aWNlOiBTZWN1cml0eVNlcnZpY2UpIHtcbiAgICAkc2NvcGUubWVzc2FnZSA9IFwiRW1wdHlcIjtcbiAgICAkc2NvcGUudXNlcnMgPSBbXTtcbiAgICAkc2NvcGUucm9sZXMgPSBbXTtcbiAgICAkc2NvcGUuY3VycmVudFVzZXIgPSB7fTtcblxuICAgICRzY29wZS5nZXRDdXJyZW50VXNlckJ5SWQgPSBmdW5jdGlvbiAoaWQ6IHN0cmluZykge1xuICAgICAgaWQgIT09IG51bGwgJiYgc2VjdXJpdHlTZXJ2aWNlLmdldFJvbGVzRm9yRG9tYWluVXNlcihpZCkudGhlbihyb2xlcyA9PiB7XG4gICAgICAgIGNvbnN0IHBhcmVudEVsZW0gPSBhbmd1bGFyLmVsZW1lbnQoJGRvY3VtZW50WzBdLnF1ZXJ5U2VsZWN0b3IoJyNzZWN1cml0eScpKTtcbiAgICAgICAgY29uc3QgbW9kYWxJbnN0YW5jZSA9ICR1aWJNb2RhbC5vcGVuKHtcbiAgICAgICAgICBhbmltYXRpb246IHRydWUsXG4gICAgICAgICAgYXJpYUxhYmVsbGVkQnk6ICdtb2RhbC10aXRsZScsXG4gICAgICAgICAgYXJpYURlc2NyaWJlZEJ5OiAnbW9kYWwtYm9keScsXG4gICAgICAgICAgdGVtcGxhdGVVcmw6ICdzcmMvYXBwL3NlY3VyaXR5L3RlbXBsYXRlcy91c2VyRGV0YWlscy5odG1sJyxcbiAgICAgICAgICBjb250cm9sbGVyOiAndXNlckRldGFpbHNDdHJsJyxcbiAgICAgICAgICBjb250cm9sbGVyQXM6ICd2bScsXG4gICAgICAgICAgYXBwZW5kVG86IHBhcmVudEVsZW0sXG4gICAgICAgICAgc2l6ZTogJ3NtJyxcbiAgICAgICAgICByZXNvbHZlOiB7XG4gICAgICAgICAgICByb2xlczogKCkgPT4gcm9sZXMsXG4gICAgICAgICAgICB1c2VyaWQ6ICgpID0+IGlkLFxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIH0pXG4gICAgfTsgIFxuXG4gICAgc2VjdXJpdHlTZXJ2aWNlLnRva2VuLnRoZW4ocmVzID0+IHtcbiAgICAgICRxLmFsbChbXG4gICAgICAgIHNlY3VyaXR5U2VydmljZS5nZXRBbGxVc2VycygpLFxuICAgICAgICBzZWN1cml0eVNlcnZpY2UuZ2V0QWxsUm9sZXMoKV0pLnRoZW4oKFt1c2Vycywgcm9sZXNdKSA9PiB7XG4gICAgICAgICAgJHNjb3BlLnVzZXJzID0gdXNlcnM7XG4gICAgICAgICAgJHNjb3BlLnJvbGVzID0gcm9sZXM7XG4gICAgICB9KVxuICAgIH0pO1xuICB9XG59XG5cbnNlY3VyaXR5LmNvbnRyb2xsZXIoJ3NlY3VyaXR5Q3RybCcsIFsnJHNjb3BlJywgJyR0aW1lb3V0JywgJyRxJywgJyR1aWJNb2RhbCcsJyRkb2N1bWVudCcsICckbXd0bkNvbW1vbnMnLCAnc2VjdXJpdHlTZXJ2aWNlJywgU2VjdXJpdHlDdHJsIF0pOyJdfQ==
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.controller.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.controller.ts new file mode 100644 index 00000000..49315319 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.controller.ts @@ -0,0 +1,63 @@ +declare var angular: angular.IAngularStatic; + +import { SecurityService, Role } from "./security.service"; + +import "./security.service"; + +const security = angular.module('app.security'); + +class UserDetailsCtrl { + constructor($scope, private $uibModalInstance, public userid: string, public roles: Role[]) { + + } + + public ok = () => { + this.$uibModalInstance.close(/* Parameter*/); + }; + + public cancel = () => { + this.$uibModalInstance.dismiss('cancel'); + }; +} + +security.controller('userDetailsCtrl', ['$scope', '$uibModalInstance', 'userid', 'roles', UserDetailsCtrl]); + +class SecurityCtrl { + constructor($scope, $timeout, private $q: ng.IQService, private $uibModal, private $document : ng.IDocumentService, $mwtnCommons, private securityService: SecurityService) { + $scope.message = "Empty"; + $scope.users = []; + $scope.roles = []; + $scope.currentUser = {}; + + $scope.getCurrentUserById = function (id: string) { + id !== null && securityService.getRolesForDomainUser(id).then(roles => { + const parentElem = angular.element($document[0].querySelector('#security')); + const modalInstance = $uibModal.open({ + animation: true, + ariaLabelledBy: 'modal-title', + ariaDescribedBy: 'modal-body', + templateUrl: 'src/app/security/templates/userDetails.html', + controller: 'userDetailsCtrl', + controllerAs: 'vm', + appendTo: parentElem, + size: 'sm', + resolve: { + roles: () => roles, + userid: () => id, + } + }) + }) + }; + + securityService.token.then(res => { + $q.all([ + securityService.getAllUsers(), + securityService.getAllRoles()]).then(([users, roles]) => { + $scope.users = users; + $scope.roles = roles; + }) + }); + } +} + +security.controller('securityCtrl', ['$scope', '$timeout', '$q', '$uibModal','$document', '$mwtnCommons', 'securityService', SecurityCtrl ]);
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.custom.css b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.custom.css new file mode 100644 index 00000000..67bd4579 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.custom.css @@ -0,0 +1,11 @@ +#security table > thead > tr > th { + background: #ddd +} + +#security table > tbody > tr > td { + background: #ddd +} + +#security table > tbody > tr:nth-child(odd) > td { + background: #eee +}
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.module.js b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.module.js new file mode 100644 index 00000000..dfd7e229 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.module.js @@ -0,0 +1,33 @@ +define( ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.security = angular.module('app.security', ['app.core']); + exports.security.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + //$translatePartialLoaderProvider.addPart('app/security/locale/locale'); + NavHelperProvider.addControllerUrl('app/security/security.controller'); + NavHelperProvider.addToMenu('security', { + "link": "#/security", + "active": "main.security", + "title": "Security", + "icon": "fa fa-shield", + "page": { + "title": "Security", + "description": "security" + } + }); + $stateProvider.state('main.security', { + url: 'security', + access: 2, + views: { + 'content': { + templateUrl: 'src/app/security/security.tpl.html', + controller: 'securityCtrl' + } + } + }); + }); +}); +/* non ES6 export */ +// export = security; +// export default security; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJpdHkubW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2FwcC9zZWN1cml0eS9zZWN1cml0eS5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0lBR2EsUUFBQSxRQUFRLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBRXJFLGdCQUFRLENBQUMsTUFBTSxDQUFDLFVBQVUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLG1CQUFtQixFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxhQUFhLEVBQUUsa0JBQWtCLEVBQUUsK0JBQStCO1FBRTlLLHdFQUF3RTtRQUV4RSxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO1FBQ3ZFLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUU7WUFDdEMsTUFBTSxFQUFFLFlBQVk7WUFDcEIsUUFBUSxFQUFFLGVBQWU7WUFDekIsT0FBTyxFQUFFLFVBQVU7WUFDbkIsTUFBTSxFQUFFLGVBQWU7WUFDdkIsTUFBTSxFQUFFO2dCQUNOLE9BQU8sRUFBRSxVQUFVO2dCQUNuQixhQUFhLEVBQUUsVUFBVTthQUMxQjtTQUNGLENBQUMsQ0FBQztRQUVILGNBQWMsQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFO1lBQ3BDLEdBQUcsRUFBRSxVQUFVO1lBQ2YsTUFBTSxFQUFFLENBQUM7WUFDVCxLQUFLLEVBQUU7Z0JBQ0wsU0FBUyxFQUFFO29CQUNULFdBQVcsRUFBRSxvQ0FBb0M7b0JBQ2pELFVBQVUsRUFBRSxjQUFjO2lCQUMzQjthQUNGO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7O0FBRUgsb0JBQW9CO0FBQ3BCLHFCQUFxQjtBQUNyQiwyQkFBMkIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBpbXBvcnQgKiBhcyBhbmd1bGFyIGZyb20gJ2FuZ3VsYXJBTUQnO1xuZGVjbGFyZSB2YXIgYW5ndWxhcjogYW5ndWxhci5JQW5ndWxhclN0YXRpYzsgXG5cbmV4cG9ydCBjb25zdCBzZWN1cml0eSA9IGFuZ3VsYXIubW9kdWxlKCdhcHAuc2VjdXJpdHknLCBbJ2FwcC5jb3JlJ10pO1xuXG5zZWN1cml0eS5jb25maWcoZnVuY3Rpb24gKCRzdGF0ZVByb3ZpZGVyLCAkY29tcGlsZVByb3ZpZGVyLCAkY29udHJvbGxlclByb3ZpZGVyLCAkcHJvdmlkZSwgTmF2SGVscGVyUHJvdmlkZXIsICRodHRwUHJvdmlkZXIsICR0cmFuc2xhdGVQcm92aWRlciwgJHRyYW5zbGF0ZVBhcnRpYWxMb2FkZXJQcm92aWRlcikge1xuXG4gIC8vJHRyYW5zbGF0ZVBhcnRpYWxMb2FkZXJQcm92aWRlci5hZGRQYXJ0KCdhcHAvc2VjdXJpdHkvbG9jYWxlL2xvY2FsZScpO1xuXG4gIE5hdkhlbHBlclByb3ZpZGVyLmFkZENvbnRyb2xsZXJVcmwoJ2FwcC9zZWN1cml0eS9zZWN1cml0eS5jb250cm9sbGVyJyk7XG4gIE5hdkhlbHBlclByb3ZpZGVyLmFkZFRvTWVudSgnc2VjdXJpdHknLCB7XG4gICAgXCJsaW5rXCI6IFwiIy9zZWN1cml0eVwiLFxuICAgIFwiYWN0aXZlXCI6IFwibWFpbi5zZWN1cml0eVwiLFxuICAgIFwidGl0bGVcIjogXCJTZWN1cml0eVwiLFxuICAgIFwiaWNvblwiOiBcImZhICBmYS1zaGllbGRcIiwgIC8vIEFkZCBuYXZpZ2F0aW9uIGljb24gY3NzIGNsYXNzIGhlcmVcbiAgICBcInBhZ2VcIjoge1xuICAgICAgXCJ0aXRsZVwiOiBcIlNlY3VyaXR5XCIsXG4gICAgICBcImRlc2NyaXB0aW9uXCI6IFwic2VjdXJpdHlcIlxuICAgIH1cbiAgfSk7XG5cbiAgJHN0YXRlUHJvdmlkZXIuc3RhdGUoJ21haW4uc2VjdXJpdHknLCB7XG4gICAgdXJsOiAnc2VjdXJpdHknLFxuICAgIGFjY2VzczogMixcbiAgICB2aWV3czoge1xuICAgICAgJ2NvbnRlbnQnOiB7XG4gICAgICAgIHRlbXBsYXRlVXJsOiAnc3JjL2FwcC9zZWN1cml0eS9zZWN1cml0eS50cGwuaHRtbCcsXG4gICAgICAgIGNvbnRyb2xsZXI6ICdzZWN1cml0eUN0cmwnXG4gICAgICB9XG4gICAgfVxuICB9KTtcbn0pO1xuXG4vKiBub24gRVM2IGV4cG9ydCAqL1xuLy8gZXhwb3J0ID0gc2VjdXJpdHk7XG4vLyBleHBvcnQgZGVmYXVsdCBzZWN1cml0eTsiXX0=
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.module.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.module.ts new file mode 100644 index 00000000..e06ae9ac --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.module.ts @@ -0,0 +1,36 @@ +// import * as angular from 'angularAMD'; +declare var angular: angular.IAngularStatic; + +export const security = angular.module('app.security', ['app.core']); + +security.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) { + + //$translatePartialLoaderProvider.addPart('app/security/locale/locale'); + + NavHelperProvider.addControllerUrl('app/security/security.controller'); + NavHelperProvider.addToMenu('security', { + "link": "#/security", + "active": "main.security", + "title": "Security", + "icon": "fa fa-shield", // Add navigation icon css class here + "page": { + "title": "Security", + "description": "security" + } + }); + + $stateProvider.state('main.security', { + url: 'security', + access: 2, + views: { + 'content': { + templateUrl: 'src/app/security/security.tpl.html', + controller: 'securityCtrl' + } + } + }); +}); + +/* non ES6 export */ +// export = security; +// export default security;
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.service.ts b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.service.ts new file mode 100644 index 00000000..c881c53f --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.service.ts @@ -0,0 +1,99 @@ +import * as angular from 'angularAMD'; + +const security = angular.module('app.security'); + +interface IEnvService { + getBaseURL(port: string): string; +} + +export type User = { + description: string; + domainid: string; + email: string; + enabled: boolean; + password: string; + salt: string; + userid: string; +} + +export type Role = { + roleid: string; + name: string; + description: string; + domainid: string; +} + +export class SecurityService { + private credentials: ng.IPromise<string>; + + constructor(private $q: ng.IQService, private $http: ng.IHttpService, private $window, private env: IEnvService) { + this.ensureCrendentials(); + } + + private ensureCrendentials() { + const credentialsDefer = this.$q.defer<string>(); + this.credentials = credentialsDefer.promise; + + const url = `${this.env.getBaseURL('MD_SAL')}/oauth2/token`; + this.$http<{ access_token: string }>({ + method: "POST", + url: url, + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + data: `grant_type=password&username=${this.$window.sessionStorage.odlUser}&password=${this.$window.sessionStorage.odlPass}&scope=sdn` + }).then(res => { + credentialsDefer.resolve(res.data && res.data.access_token); + }, err => { + credentialsDefer.reject(err); + }); + } + + public get token() { + return this.credentials; + } + + public getAllUsers(): ng.IPromise<User[]> { + const url = `${this.env.getBaseURL('MD_SAL')}/auth/v1/users`; + return this.token.then(token => { + return this.$http<{ users: User[] }>({ + method: "GET", + url: url, + headers: { 'Authorization': `Bearer ${token}` } + }).then(result => result.data && result.data.users) + }); + } + + public getAllRoles(): ng.IPromise<Role[]> { + const url = `${this.env.getBaseURL('MD_SAL')}/auth/v1/roles`; + return this.token.then(token => { + return this.$http<{ roles: Role[] }>({ + method: "GET", + url: url, + headers: { 'Authorization': `Bearer ${token}` } + }).then(result => result.data && result.data.roles) + }); + } + + public getUserById(userId: string): ng.IPromise<User> { + const url = `${this.env.getBaseURL('MD_SAL')}/auth/v1/users/${userId}`; + return this.token.then(token => { + return this.$http<User>({ + method: "GET", + url: url, + headers: { 'Authorization': `Bearer ${token}` } + }).then(result => result.data && result.data) + }); + } + + public getRolesForDomainUser(userId: string, domain: string= "sdn"): ng.IPromise<Role[]> { + const url = `${this.env.getBaseURL('MD_SAL')}/auth/v1/domains/${domain}/users/${userId}/roles`; + return this.token.then(token => { + return this.$http<{ roles: Role[] }>({ + method: "GET", + url: url, + headers: { 'Authorization': `Bearer ${token}` } + }).then(result => result.data && result.data.roles) + }); + } +} + +security.service('securityService', ['$q', '$http', '$window', 'ENV', SecurityService]);
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.tpl.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.tpl.html new file mode 100644 index 00000000..ea08892b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/security.tpl.html @@ -0,0 +1,50 @@ +<div id="security"> + <h2>Users</h2> + <table class="table"> + <thead> + <tr> + <th>UserID</th> + <th>Name</th> + <th>Description</th> + <th>Enabled</th> + <th>eMail</th> + <th>Domain</th> + <th>Actions</th> + </tr> + </thead> + <tbody> + <tr ng-repeat="user in users"> + <td>{{user.userid}}</td> + <td>{{user.name}}</td> + <td>{{user.description}}</td> + <td>{{user.enabled}}</td> + <td>{{user.email}}</td> + <td>{{user.domainid}}</td> + <td> + <button class="btn btn-sm btn-success" + ng-click="getCurrentUserById(user.userid)">Info</button></td> + </tr> + </tbody> + </table> +<h2>Roles</h2> +<table class="table"> + <thead> + <tr> + <th>RoleID</th> + <th>Name</th> + <th>Description</th> + <th>Domain</th> + <!-- <th>Actions</th> --> + </tr> + </thead> + <tbody> + <tr ng-repeat="role in roles"> + <td>{{role.roleid}}</td> + <td>{{role.name}}</td> + <td>{{role.description}}</td> + <td>{{role.domainid}}</td> + <!-- <td><button class="btn btn-sm btn-success">Info</button></td> --> + </tr> + </tbody> +</table> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/templates/userDetails.html b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/templates/userDetails.html new file mode 100644 index 00000000..5589263b --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/security/security-module/src/main/resources/security/src/templates/userDetails.html @@ -0,0 +1,14 @@ +<div class="modal-header"> + <h3 class="modal-title" id="modal-title" style="color: #333;">{{ vm.userid }}</h3> +</div> +<div class="modal-body" id="modal-body"> + <div><b>Roles</b></div> + <ul> + <li ng-repeat="role in vm.roles">{{ role.name }}</li> + </ul> + +</div> +<div class="modal-footer"> + <button class="btn btn-primary" type="button" ng-click="vm.ok()">OK</button> + <button class="btn btn-warning" type="button" ng-click="vm.cancel()">Cancel</button> +</div>
\ No newline at end of file diff --git a/sdnr/wireless-transport/code-Carbon-SR1/ux/ux-dev.sh b/sdnr/wireless-transport/code-Carbon-SR1/ux/ux-dev.sh new file mode 100755 index 00000000..b34f8718 --- /dev/null +++ b/sdnr/wireless-transport/code-Carbon-SR1/ux/ux-dev.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# build ux +mvn clean install -DskipTests + +# clean +rm -rf ~/.m2/repository/com/highstreet/technologies/odl/app/closedLoopAutomation-karaf/ +rm -rf ~/.m2/repository/com/highstreet/technologies/odl/app/spectrum/scheduler-karaf/ +find ~/.m2/repository/org/opendaylight/mwtn/* -type d -name "*-module" -exec rm -rf {} \; +find ~/.m2/repository/com/highstreet/* -type d -name "*-module" -exec rm -rf {} \; +rm -rf ../dist/cache/schema/tailf*.yang +rm -rf ../dist/cache/schema/yuma*.yang +# rm -rf ../dist/data/log/* +rm -rf ../dist/system/org/opendaylight/mwtn +rm -rf ../dist/system/com/highstreet + +# deploy +cp -R ~/.m2/repository/org/opendaylight/mwtn ../dist/system/org/opendaylight +cp -R ~/.m2/repository/com/highstreet ../dist/system/com + +# uninstall bundles +## declare array of bundleNames +declare -a bundleNames=( + "ONF :: Wireless :: odlChat-bundle" + "ONF :: Wireless :: help-bundle" + "ONF :: Wireless :: mwtnLog-bundle" + "ONF :: Wireless :: mwtnTest-bundle" + "ONF :: Wireless :: mwtnMediator-bundle" + "ONF :: Wireless :: mwtnEvents-bundle" + "ONF :: Wireless :: mwtnClosedLoop-bundle" + "ONF :: Wireless :: mwtnSpectrum-bundle" + "ONF :: Wireless :: mwtnCompare-bundle" + "ONF :: Wireless :: mwtnTdm-bundle" + "ONF :: Wireless :: mwtnTopology-bundle" + "ONF :: Wireless :: mwtnInventory-bundle" + "ONF :: Wireless :: mwtnPerformanceLink-bundle" + "ONF :: Wireless :: mwtnPerformanceHistory-bundle" + "ONF :: Wireless :: mwtnPerformanceCurrent-bundle" + "ONF :: Wireless :: mwtnFault-bundle" + "ONF :: Wireless :: mwtnBrowser-bundle" + "ONF :: Wireless :: otnBrowser-bundle" + "ONF :: Wireless :: ethService-bundle" + "ONF :: Wireless :: onapMso-bundle" + "ONF :: Wireless :: onapDcae-bundle" + "ONF :: Wireless :: onapAai-bundle" + "ONF :: Wireless :: mwtnConnect-bundle" + "ONF :: Wireless :: mwtnCommons-bundle" +) + +## execute bundle uninstall +names="" +for bundleName in "${bundleNames[@]}" +do + names+="\"$bundleName\" " +done +../dist/bin/client -u karaf "bundle:uninstall $names" + +# install bundles +## declare array of bundleNames +declare -a bundles=( + mvn:com.highstreet.technologies.odl.dlux/mwtnCommons-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnConnect-bundle/0.5.1-SNAPSHOT + + mvn:com.highstreet.technologies.odl.dlux/onapAai-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/onapDcae-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/onapMso-bundle/0.5.1-SNAPSHOT + + # mvn:com.highstreet.technologies.odl.dlux/ethService-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/otnBrowser-bundle/0.5.1-SNAPSHOT + + mvn:com.highstreet.technologies.odl.dlux/mwtnFault-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnBrowser-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnPerformanceCurrent-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnPerformanceHistory-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnPerformanceLink-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnInventory-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnTopology-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/mwtnTdm-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/mwtnCompare-bundle/0.5.1-SNAPSHOT + # mvn:cn.com.zte.odl.dlux/mwtnSpectrum-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/mwtnClosedLoop-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/mwtnEvents-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/mwtnTest-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/mwtnMediator-bundle/0.5.1-SNAPSHOT + mvn:com.highstreet.technologies.odl.dlux/help-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/mwtnLog-bundle/0.5.1-SNAPSHOT + # mvn:com.highstreet.technologies.odl.dlux/odlChat-bundle/0.5.1-SNAPSHOT +) + +## execute bundle uninstall +bundleMvns="" +for bundle in "${bundles[@]}" +do + bundleMvns+="$bundle " +done +../dist/bin/client -u karaf "bundle:install -s $bundleMvns" + +# open brwoser +x-www-browser http://localhost:8181/index.html + +# remove target folders for easy search functionality +mvn clean +find * -type d -name "target-ide" -exec rm -rf {} \;
\ No newline at end of file |