Create wt-odlux directory

Include odlux apps, helpserver and readthedocs

Issue-ID: CCSDK-3970
Change-Id: I1aee1327e7da12e8f658185b9a985a5204ad6065
Signed-off-by: Ravi Pendurty <ravi.pendurty@highstreet-technologies.com>
diff --git a/sdnr/wt-odlux/helpserver/pom.xml b/sdnr/wt-odlux/helpserver/pom.xml
new file mode 100755
index 0000000..e0eaa31
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property.
+  ~ All rights reserved.
+  ~ ================================================================================
+  ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-helpserver-top</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+
+    <modules>
+        <module>provider</module>
+    </modules>
+
+</project>
diff --git a/sdnr/wt-odlux/helpserver/provider/README.md b/sdnr/wt-odlux/helpserver/provider/README.md
new file mode 100644
index 0000000..d35aeb5
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/README.md
@@ -0,0 +1,34 @@
+##Creating help files
+
+#### Link and references to pictures.
+
+All links are relative to the current md-file.
+
+Link to pages located in the same directory:
+
+```
+[linkname](file.md)
+```
+
+Link to subpages located in subdirectories:
+
+```
+[linkname](subfolder/file.md)
+```
+
+External Links:
+
+```
+[linkname](linkurl "linktitle")
+```
+
+Images:
+
+```
+![SDN-R in ONAP](./ONAP-SDN-R.png "SDN-R in ONAP")
+```
+
+#### Supported formates
+
+md-format:
+Picture formats: PNG
diff --git a/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/meta.json b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/meta.json
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/meta.json
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.css b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.css
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.css
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.eps b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.eps
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.eps
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.pdf b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.pdf
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test.pdf
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test/test.txt b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test/test.txt
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/bitnami/nginx/help/test/test.txt
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/help/meta.json b/sdnr/wt-odlux/helpserver/provider/help/meta.json
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/help/meta.json
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/help/test/test.txt b/sdnr/wt-odlux/helpserver/provider/help/test/test.txt
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/help/test/test.txt
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/pom.xml b/sdnr/wt-odlux/helpserver/provider/pom.xml
new file mode 100644
index 0000000..4caaa4a
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/pom.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : ccsdk features
+  ~ ================================================================================
+  ~ Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+  ~ All rights reserved.
+  ~ ================================================================================
+  ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+	<artifactId>sdnr-odlux-helpserver-provider</artifactId>
+	<version>1.7.0-SNAPSHOT</version>
+	<packaging>jar</packaging>
+
+	<name>SDNR ODLUX :: ${project.artifactId}</name>
+
+	<properties>
+		<maven.javadoc.skip>true</maven.javadoc.skip>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<log4j.version>2.17.1</log4j.version>
+		<log4j2.version>2.17.1</log4j2.version>
+		<junit.version>4.13.2</junit.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>jakarta.servlet</groupId>
+			<artifactId>jakarta.servlet-api</artifactId>
+			<version>4.0.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.json</groupId>
+			<artifactId>json</artifactId>
+			<version>20201115</version>
+		</dependency>
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-log4j12</artifactId>
+			<version>1.7.29</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>3.5.11</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.13.2</version>
+			<scope>test</scope>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<plugins>
+			<!-- fixed bug for sonarcube -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+					<useSystemClassLoader>false</useSystemClassLoader>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/helpserver/HelpServlet.java b/sdnr/wt-odlux/helpserver/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/helpserver/HelpServlet.java
new file mode 100644
index 0000000..bf93109
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/helpserver/HelpServlet.java
@@ -0,0 +1,179 @@
+/*
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+package org.onap.ccsdk.features.sdnr.wt.helpserver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.nio.file.Path;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.onap.ccsdk.features.sdnr.wt.helpserver.data.HelpInfrastructureObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HelpServlet extends HttpServlet implements AutoCloseable {
+
+    private static Logger LOG = LoggerFactory.getLogger(HelpServlet.class);
+    private static final long serialVersionUID = -4285072760648493461L;
+
+    private static final String BASEURI = "/help";
+
+    private final Path basePath;
+
+    public HelpServlet() {
+        LOG.info("Starting HelpServlet instance {}", this.hashCode());
+//        HelpInfrastructureObject.createFilesFromResources();
+//        this.basePath = HelpInfrastructureObject.getHelpDirectoryBase();
+        this.basePath = Path.of("bitnami/nginx/help");
+    }
+
+    @Override
+    public void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        resp.addHeader("Access-Control-Allow-Origin", "*");
+        resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
+        resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length");
+    }
+
+    @Override
+    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        String query = req.getQueryString();
+        resp.addHeader("Access-Control-Allow-Origin", "*");
+        resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
+        resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length");
+//        if (query != null && query.contains("meta")) {
+//
+//            File f = new File(HelpInfrastructureObject.KARAFHELPDIRECTORY, "meta.json");
+//            if (f.exists()) {
+//                LOG.debug("found local meta file");
+//                try (BufferedReader rd = new BufferedReader(new FileReader(f));) {
+//                    String line = rd.readLine();
+//                    while (line != null) {
+//                        resp.getOutputStream().println(line);
+//                        line = rd.readLine();
+//                    }
+//                    rd.close();
+//                } catch (IOException e) {
+//                    LOG.debug("Can not read meta file", e);
+//                }
+//            } else {
+//                LOG.debug("start walking from path=" + basePath.toAbsolutePath().toString());
+//                HelpInfrastructureObject o = null;
+//                try {
+//                    o = new HelpInfrastructureObject(this.basePath);
+//                } catch (URISyntaxException e) {
+//                    LOG.debug("Can not relsolve URI. ", e);
+//                }
+//                resp.getOutputStream().println(o != null ? o.toString() : "");
+//            }
+//            resp.setHeader("Content-Type", "application/json");
+//        } else 
+        {
+            LOG.debug("received get with uri=" + req.getRequestURI());
+            String uri = URLDecoder.decode(req.getRequestURI().substring(BASEURI.length()), "UTF-8");
+            if (uri.startsWith("/")) {
+                uri = uri.substring(1);
+            }
+            Path p = basePath.resolve(uri);
+            File f = p.toFile();
+            if (f.isFile() && f.exists()) {
+                LOG.debug("found file for request");
+                if (this.isTextFile(f)) {
+                    resp.setHeader("Content-Type", "application/text");
+                    resp.setHeader("charset", "utf-8");
+                } else if (this.isImageFile(f)) {
+                    resp.setHeader("Content-Type", "image/*");
+                } else if (this.ispdf(f)) {
+                    resp.setHeader("Content-Type", "application/pdf");
+                } else {
+                    LOG.debug("file is not allowed to deliver");
+                    resp.setStatus(404);
+                    return;
+                }
+                LOG.debug("delivering file");
+                try (OutputStream out = resp.getOutputStream()) {
+                    try (FileInputStream in = new FileInputStream(f)) {
+
+                        byte[] buffer = new byte[1024];
+                        int len;
+                        while ((len = in.read(buffer)) != -1) {
+                            out.write(buffer, 0, len);
+                        }
+                        in.close();
+                        out.flush();
+                        out.close();
+                    }
+                } catch (IOException e) {
+                    LOG.warn("Can not write meta file", e);
+                    resp.setStatus(500);
+                }
+            } else {
+                LOG.debug("found not file for request");
+                resp.setStatus(404);
+            }
+        }
+    }
+
+    private boolean ispdf(File f) {
+        return f != null && this.ispdf(f.getName());
+    }
+
+    private boolean ispdf(String name) {
+        return name != null && name.toLowerCase().endsWith("pdf");
+    }
+
+    private boolean isImageFile(File f) {
+        return f != null && this.isImageFile(f.getName());
+    }
+
+    private boolean isImageFile(String name) {
+
+        return name != null
+                ? name.toLowerCase().endsWith("png") || name.toLowerCase().endsWith("jpg")
+                        || name.toLowerCase().endsWith("jpeg") || name.toLowerCase().endsWith("svg")
+                        || name.toLowerCase().endsWith("eps")
+                : false;
+    }
+
+    private boolean isTextFile(File f) {
+        return f != null && this.isTextFile(f.getName());
+
+    }
+
+    private boolean isTextFile(String name) {
+        return name != null
+                ? name.toLowerCase().endsWith("md") || name.toLowerCase().endsWith("txt")
+                        || name.toLowerCase().endsWith("html") || name.toLowerCase().endsWith("htm")
+                        || name.toLowerCase().endsWith("js") || name.toLowerCase().endsWith("css")
+                : false;
+    }
+
+	@Override
+	public void close() throws Exception {
+
+	}
+
+}
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/helpserver/data/HelpInfrastructureObject.java b/sdnr/wt-odlux/helpserver/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/helpserver/data/HelpInfrastructureObject.java
new file mode 100644
index 0000000..5075b92
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/helpserver/data/HelpInfrastructureObject.java
@@ -0,0 +1,174 @@
+/*
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+package org.onap.ccsdk.features.sdnr.wt.helpserver.data;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import org.json.JSONObject;
+//import org.osgi.framework.Bundle;
+//import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HelpInfrastructureObject extends JSONObject {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HelpInfrastructureObject.class);
+    private static String HELPBASE = "help";
+
+    public static class VersionObject extends JSONObject {
+        private static Comparator<VersionObject> comp;
+        private final String mVersion;
+
+        public String getVersion() {
+            return this.mVersion;
+        }
+
+        public VersionObject(String path, String date, String label, String version) {
+            this.mVersion = version;
+            this.put("path", path);
+            this.put("date", date);
+            this.put("label", label);
+        }
+
+        public static Comparator<VersionObject> getComparer() {
+            if (comp == null) {
+                comp = (o1, o2) -> o1.getVersion().compareTo(o2.getVersion());
+            }
+            return comp;
+        }
+
+        public VersionObject cloneAsLatest() {
+            return new VersionObject(this.getString("path"), this.getString("date"), this.getString("label"), "latest");
+        }
+
+        public VersionObject cloneAsCurrent() {
+            return new VersionObject(this.getString("path"), this.getString("date"), this.getString("label"),
+                    "current");
+        }
+    }
+    public static class NodeObject extends JSONObject {
+        public NodeObject(Path base, File dir, String label, ArrayList<VersionObject> versions) {
+            this.put("label", label);
+            if (versions != null && !versions.isEmpty()) {
+                JSONObject o = new JSONObject();
+                this.put("versions", o);
+                for (VersionObject version : versions) {
+                    o.put(version.getVersion(), version);
+                }
+
+            }
+            File[] list = dir.listFiles();
+            if (list == null) {
+                return;
+            }
+            for (File f : list) {
+                if (f.isDirectory()) {
+                    ArrayList<VersionObject> versions2 = findReadmeVersionFolders(base, f.toPath(), true);
+                    if (versions2 != null && !versions2.isEmpty()) {
+                        JSONObject nodes;
+                        if (!this.has("nodes")) {
+                            this.put("nodes", new JSONObject());
+                        }
+                        nodes = this.getJSONObject("nodes");
+
+                        NodeObject o = new NodeObject(base, f, f.getName(), versions2);
+                        nodes.put(o.getString("label").toLowerCase(), o);
+                    }
+                }
+            }
+        }
+
+    }
+
+    public HelpInfrastructureObject(Path pRoot) throws URISyntaxException {
+        File root = pRoot.toFile();
+        File[] list = root.listFiles();
+        if (list == null) {
+            return;
+        }
+        for (File f : list) {
+            if (f.isDirectory()) {
+                ArrayList<VersionObject> versions = findReadmeVersionFolders(root.toPath(), f.toPath(), true);
+                if (versions != null && !versions.isEmpty()) {
+                    NodeObject o = new NodeObject(pRoot, f, f.getName(), versions);
+                    this.put(o.getString("label").toLowerCase(), o);
+                }
+            }
+        }
+    }
+
+    private static ArrayList<VersionObject> findReadmeVersionFolders(Path base, Path root, boolean appendCurrent) {
+        ArrayList<VersionObject> list = new ArrayList<>();
+        File[] files = root.toFile().listFiles();
+        int baselen = base.toFile().getAbsolutePath().length();
+        if (files != null) {
+            for (File f : files) {
+                if (f.isDirectory() && new File(f.getAbsolutePath() + "/README.md").exists()) {
+                    list.add(new VersionObject(f.getAbsolutePath().substring(baselen + 1) + "/README.md", "", "",
+                            f.getName()));
+                }
+            }
+        }
+        Collections.sort(list, VersionObject.getComparer());
+        Collections.reverse(list);
+        if (!list.isEmpty() && appendCurrent) {
+            list.add(list.get(0).cloneAsCurrent());
+        }
+        return list;
+    }
+
+
+//    public static void createFilesFromResources() {
+//
+//        if (KARAFHELPDIRECTORY.exists()) {
+//            LOG.debug("Delete existing directory");
+//            try {
+//                ExtactBundleResource.deleteRecursively(KARAFHELPDIRECTORY);
+//            } catch (IOException e1) {
+//                LOG.warn(e1.toString());
+//            }
+//        }
+//
+//        LOG.debug("Extract");
+//        try {
+//            Bundle b = FrameworkUtil.getBundle(HelpInfrastructureObject.class);
+//            if (b == null) {
+//                LOG.debug("No bundlereference: Use target in filesystem.");
+//                // URL helpRessource =
+//                // JarFileUtils.stringToJarURL("target/helpserver-impl-0.4.0-SNAPSHOT.jar",KARAFBUNDLERESOURCEHELPROOT);
+//
+//            } else {
+//                LOG.debug("Bundle location:{} State:{}", b.getLocation(), b.getState());
+//                LOG.debug("Write files from Resource");
+//                ExtactBundleResource.copyBundleResoucesRecursively(b, "data/cache/com.highstreet.technologies.",
+//                        KARAFBUNDLERESOURCEHELPROOT);
+//            }
+//        } catch (IOException e) {
+//            LOG.warn("No help files available. Exception: " + e.toString());
+//        }
+//    }
+//
+//    public static Path getHelpDirectoryBase() {
+//        return KARAFHELPDIRECTORY.toPath();
+//    }
+}
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/README.md
new file mode 100644
index 0000000..c99967d
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/README.md
@@ -0,0 +1,144 @@
+# MediatorServer
+
+## Description
+The mediator server is the physical device on which multiple instances of the [mediators](mediator/README.md) are running. Additionally a small webserver provides an API to control and create the mediators via HTTP-API. These mediators are translating the requests and responses between the SDN-Controller(netconf) and the device(snmp). Because of the restricted snmp protocol (port 162 only) we have to implement a prerouting automatism that forwards the alarms sent by the devices to another local port so that each mediator only gets the alarms of its device.
+
+
+
+## Config-File
+
+```
+/etc/mediatorserver.conf
+```
+
+```
+#global config file for mediatorserver
+
+#Home Directory
+home=/opt/snmp
+
+#HOST IP
+host=192.168.178.89
+port=7071
+
+#Port range for Netconf
+ncrangemin=4000
+ncrangemax=6000
+
+#Port Range for SNMP
+snmprangemin=10000
+snmprangemax=12000
+
+#PortRange for JMX
+jmxrangemin=6001
+jmxrangemax=7000
+
+#Log (ERROR | WARN | DEBUG | INFO | TRACE )
+loglevel=DEBUG
+logfile=/var/log/mediatorserver.log
+
+#=====================================
+#global MediatorConfig
+
+#set LogLevel (ERROR | WARN | DEBUG | INFO | TRACE )
+MediatorLogLevel=DEBUG
+
+#set ping timeout in milliseconds
+MediatorDevicePingTimeout=2000
+
+#set latency for snmp requests
+MediatorSnmpLatency=2000
+
+#set java memory for mediator instance
+MediatorMemory="-Xmx256m -Xms128m"
+```
+
+## HTTP-API
+
+```
+http://<host>:<port>/api/?task=<task>
+```
+
+| Task | additional Parameters | Description | Response (Success) |
+| ---- | --------------------- | ----------- | ------------------ |
+| create       | config=&lt;config-object&gt;  | create new mediator instance | {"code":1,"data":"&lt;string&gt;"}|
+| delete       | name=&lt;name&gt; | delete mediator instance | \{"code":1,"data":&lt;string&gt;"} |
+| start        | name=&lt;name&gt; | start mediator instance | \{"code":1,"data":"&lt;string&gt;"} |
+| stop         | name=&lt;name&gt; | stop mediator instance | \{"code":1,"data":"&lt;string&gt;"} |
+| getconfig    | name=&lt;name&gt;(optional) | Get current Config for all instances / named mediator instance | \{"code":1,"data":[&lt;config-objects&gt;]}|
+| getlog       | name=&lt;name&gt;(optional) | Get LogEntries for all instances / named mediator instance | \{"code":1,"data":[]} |
+| clearlock    | name=&lt;name&gt; | Clear Mediator Lock File | \{"code":1,"data":"&lt;string&gt;"} |
+| getnemodels  | - | get all Network Element Template Filenames | \{"code":1,"data":[&lt;string-array&gt;]} |
+| getncports   | limit=&lt;limit&gt;(optional) | get next free ports for Netconf Connections | \{"code":1,"data":[&lt;int-array&gt;]} |
+| getsnmpports | limit=&lt;limit&gt;(optional) | get next free ports for SNMP Traps | \{"code":1,"data":[&lt;int-array&gt;]} |
+| version      | - | get version info of server and mediator |  \{"code":1,"data":\{"server":"0.1.0","mediator":"0.1.1"\}\}|
+| repair       | - | try to fix corrupted configs | \{"code":1,"data":[&lt;config-status-objects&gt;]}|
+
+HTTP-Response is always a json-formatted String with 2 Elements:
+
+* code ... 1:success 0:failure
+* data ... if code==0: &lt;string&gt; else &lt;string | object&gt;
+
+
+### JSON-Objects
+
+Config-Object
+```
+{
+  Name:<String>,
+  DeviceType:<enum>,
+  DeviceIp:<String>,
+  DevicePort: <int>,
+  TrapsPort:<Int>,
+  NeModel:<XML Filename>,
+  NcPort:<int>,
+  ODLConfig:[
+    {
+      Server:<String>,
+      Port:<int>,
+      User:<String>,
+      Password:<String>
+    }
+  ],
+  PID:<int>,
+  IsLocked:<boolean>,
+  AutoRun:<boolean>,
+  FwActive:<boolean>,
+  IsNetconfConnected:<boolean>,
+  IsNeConnected:<boolean>
+}
+```
+
+Log-Object
+```
+{
+  ts:"<Timestamp>",
+  lvl:"<LogLevel>",
+  src:"<Source>",
+  msg:"<Message"
+}
+```
+
+
+## Usage
+
+All functionality which is not automated can be executed by the control script
+```
+bin/control.sh
+```
+
+| parameter     | description                                      |
+| ------------- | ------------------------------------------------ |
+|checkout       | get latest code from git repo                    |
+|cpsrc          | copy binary files from source                    |
+|cpxml          | copy xml files from source                       |
+|build          | build sources                                    |
+|make           | build sources and install bins and ressources    |
+|start          | start server                                     |
+|stop           | stop server                                      |
+|stopall        | stop all mediators, then the server              |
+|startmed [med] | start mediator with name [med]                   |
+|stopmed [med]  | stop mediator with name [med]                    |
+|status         | print status                                     |
+|repair         | repair config files if corrupted                 |
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/installation/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/installation/README.md
new file mode 100644
index 0000000..6fdcbae
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/installation/README.md
@@ -0,0 +1,246 @@
+# MediatorServer
+
+## Manual Installation
+
+### Install prerequisites
+
+```
+sudo apt-get install jq curl
+```
+Installing Java
+
+for production
+```
+sudo apt-get install openjdk-8-jre
+
+```
+
+for development
+```
+sudo apt-get install openjdk-8-jdk
+sudo apt-get install git maven
+
+```
+
+### Create user
+```
+useradd mediators
+```
+
+### Choose a home directory for all mediatorserver files
+```
+mkdir /opt/snmp
+
+```
+
+### Create folder infrastructure
+```
+cd /opt/snmp
+mkdir bin
+mkdir mediators
+mkdir nemodel
+mkdir yang
+mkdir source (only for dev-env)
+
+```
+
+### Copy files to folders
+```
+bin/control.sh
+bin/clean_all.sh
+bin/debug.sh
+bin/mediatorserver.sh
+bin/Netconf2SNMPMediator.sh
+bin/Netconf2SNMPMediator.jar
+bin/init_script.sh
+bin/firewall_status.sh
+bin/unlock_all.sh
+bin/firewall.sh
+bin/MediatorServer.jar
+bin/stop_all.sh
+bin/start_all.sh
+```
+
+```
+nemodel/DragonWave-HCP.xml
+nemodel/ActionTEC_ECB6200.xml
+nemodel/ActionTEC_ECB6000.xml
+nemodel/DVM_MWCore12_BasicAir.xml
+nemodel/DragonWave-HQ.xml
+nemodel/DragonWave-HQdev.xml
+nemodel/CommScope.xml
+```
+
+```
+yang/yangNeModel
+yang/yangNeModel/G_874_1_model-Imported_Information_Object_Classes-Q_822@2016-08-11.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-PureEthernetStructure@2016-09-02.yang
+yang/yangNeModel/yuma-proc@2012-10-10.yang
+yang/yangNeModel/nc-notifications@2008-07-14.yang
+yang/yangNeModel/CoreModel-CoreFoundationModule-TypeDefinitions@2016-07-01.yang
+yang/yangNeModel/ietf-inet-types@2010-09-24.yang
+yang/yangNeModel/onf-ptp-dataset@2017-05-08.yang
+yang/yangNeModel/yuma-system@2014-11-27.yang
+yang/yangNeModel/onf-ethernet-conditional-packages@2017-04-02.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-SuperClasses@2016-08-09.yang
+yang/yangNeModel/ietf-ptp-dataset@2017-02-08.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-TdmContainer@2016-09-02.yang
+yang/yangNeModel/ietf-netconf-acm@2012-02-22.yang
+yang/yangNeModel/MicrowaveModel-Notifications@2016-08-09.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-HybridMwStructure@2016-09-02.yang
+yang/yangNeModel/microwave-model@2017-03-24.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-AirInterfaceDiversity@2016-09-02.yang
+yang/yangNeModel/G_874_1_model-Type_Definitions@2016-07-10.yang
+yang/yangNeModel/CoreModel-CoreFoundationModule-StateModel@2016-08-09.yang
+yang/yangNeModel/G_874_1_model-Imported_Information_Object_Classes-X_739@2016-07-10.yang
+yang/yangNeModel/ietf-system@2014-08-06.yang
+yang/yangNeModel/G_874_1_model-Imported_Information_Object_Classes-X_721@2016-07-10.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-AirInterface@2016-09-01.yang
+yang/yangNeModel/onf-core-model-conditional-packages@2017-04-02.yang
+yang/yangNeModel/MicrowaveModel-NetworkElement-CurrentProblemList@2016-11-20.yang
+yang/yangNeModel/core-model@2017-03-20.yang
+yang/yangNeModel/g.874.1-model@2017-03-20.yang
+yang/yangNeModel/ietf-yang-library@2016-04-09.yang
+yang/yangNeModel/yuma-time-filter@2011-08-13.yang
+yang/yangNeModel/yuma-mysession@2010-05-10.yang
+yang/yangNeModel/G_874_1_model-Imported_Data_Types@2016-07-10.yang
+yang/yangNeModel/yuma-ncx@2012-01-13.yang
+yang/yangNeModel/ietf-yang-types@2013-07-15.yang
+yang/yangNeModel/MicrowaveModel-ObjectClasses-EthernetContainer@2016-09-02.yang
+yang/yangNeModel/notifications@2008-07-14.yang
+yang/yangNeModel/ietf-netconf-monitoring@2010-10-04.yang
+yang/yangNeModel/CoreModel-CoreFoundationModule-SuperClassesAndCommonPackages@2016-07-10.yang
+yang/yangNeModel/ietf-restconf@2013-10-19.yang
+yang/yangNeModel/yuma-app-common@2012-08-16.yang
+yang/yangNeModel/yuma-types@2012-06-01.yang
+yang/yangNeModel/CoreModel-CoreNetworkModule-ObjectClasses@2016-08-11.yang
+yang/yangNeModel/MicrowaveModel-TypeDefinitions@2016-09-02.yang
+yang/yangNeModel/ietf-netconf-with-defaults@2011-06-01.yang
+yang/yangNeModel/ietf-netconf@2011-06-01.yang
+yang/yangNeModel/ietf-netconf-partial-lock@2009-10-19.yang
+yang/yangNeModel/G_874_1_model-Object_Classes@2016-07-10.yang
+yang/yangNeModel/ietf-inet-types@2013-07-15.yang
+yang/yangNeModel/CoreModel-CoreNetworkModule-TypeDefinitions@2016-07-10.yang
+yang/yangNeModel/yuma-arp@2012-01-13.yang
+yang/yangNeModel/iana-crypt-hash@2014-04-04.yang
+yang/notification
+yang/notification/readme.md
+yang/notification/notifications@2008-07-14.yang
+```
+
+and change all rights to the extra created user
+```
+sudo chown -R mediators:mediators /opt/snmp
+```
+
+### Create mediatorserver config file
+
+```
+sudo nano /etc/mediatorserver.conf
+```
+example:
+```
+#Home Directory
+home=/opt/snmp
+
+#HOST IP
+host=192.168.178.89
+port=7070
+
+#Port range for Netconf
+ncrangemin=4000
+ncrangemax=6000
+
+#Port Range for SNMP
+snmprangemin=10000
+snmprangemax=12000
+
+#PortRange for JMX
+jmxrangemin=6001
+jmxrangemax=7000
+
+#Log (ERROR | WARN | DEBUG | INFO | TRACE )
+loglevel=WARN
+logfile=/var/log/mediatorserver.log
+
+#=====================================
+#global MediatorConfig
+
+#set LogLevel (ERROR | WARN | DEBUG | INFO | TRACE )
+MediatorLogLevel=DEBUG
+
+#set ping timeout in milliseconds
+MediatorDevicePingTimeout=2000
+
+#set latency for snmp requests
+MediatorSnmpLatency=2000
+
+#set java memory for mediator instance
+MediatorMemory="-Xmx256m -Xms128m"
+
+#====================================
+```
+
+
+### Create mediatorserver systemd daemon
+
+```
+sudo nano /etc/systemd/system/mediatorserver.service
+```
+
+```
+[Unit]
+Description=mediatorserver
+After=network.target
+
+[Service]
+WorkingDirectory=/opt/snmp/
+SyslogIdentifier=MediatorServer
+ExecStart=/opt/snmp/bin/mediatorserver.sh
+User=mediators
+Type=oneshot
+
+[Install]
+WantedBy=multi-user.target
+
+```
+
+### Initial create mediator server logfile with correct file permissions
+```
+sudo touch /var/log/mediatorserver.log
+sudo chown mediators:mediators /var/log/mediatorserver.log
+```
+
+### Activate mediatorserver systemd daemon
+```
+systemctl enable mediatorserver.service
+systemctl daemon-reload
+```
+
+Now you can start and stop the service as you like
+```
+sudo service mediatorserver [start | stop]
+```
+
+### Install cron jobs
+```
+sudo crontab -e
+```
+```
+*/2 * * * * /bin/bash /opt/snmp/bin/firewall.sh >> /var/log/firewall.log
+*/2 * * * * /bin/bash /opt/snmp/bin/clean_all.sh > /dev/null 2>&1
+```
+
+### Test Accessibility of the HTTP-API with console 
+```
+curl http://localhost:7070/api/?task=version
+```
+or directly in your browser
+```
+http://<mediator-server-ip>:7070/api/?task=version
+```
+should respond with something like this:
+```
+{"code":1,"data":{"server":"0.1.0","mediator":"0.1.1"}}
+```
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/mediator/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/mediator/README.md
new file mode 100644
index 0000000..9fa43a4
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/mediatorserver/mediator/README.md
@@ -0,0 +1,66 @@
+# Mediator
+
+## Description
+
+
+The mediator is a piece of software to translate get and set requests between the SDN-Controller and the device. In our case we translate from netconf to snmp and back. Additionally the mediator is listening for snmp traps to push them forward to the SDN-Controller.
+
+## Usage
+
+Standalone:
+```
+./Netconf2SNMPMediator.sh [--cli] ../test.config ../yang/yangNeModel
+```
+[MediatorServer](../../mediatorserver/):
+```
+./mediators/<name>/start.sh
+```
+
+## Config-File
+```
+{
+    "Name":"<mediatorname-in-odl>",
+    "DeviceType":<int-of-enum of device type>,
+    "DeviceIP":"<remote Ip Address>",
+    "TrapPort":<trap port>,
+    "NeXMLFile":"<rel-path-to-xml-ne-filename>",
+    "NcPort":<netconf-port>,
+    "ODLConfig":[{"Server":"<odl-server-ip>","Port":<odl-http-port>,"User":"<odl-username>","Password":"<odl-password>"}],
+    "IsNCConnected":false
+}
+```
+
+## XML Ne File
+
+The xml network element file is the central element of the mediator. It contains all information about the interfaces, their capabilities and everything else of information which get requested through netconf. To connect specific netconf values to device specific snmp values we use the xml attributes of the node element.
+
+Attributes:
+
+|Name | Value | Description |
+| ----| ----  | ----------  |
+|oid | &lt;oid dotted string&gt; | Attribute with SNMP mapping for given oid. For NETCONF-get, request content from Device|
+|access | read-only / read-write | decides if only snmp-get or get and set-requests are allowed|
+|conversion | &lt;conv-method&gt; | Convert the snmp-value to netconf-value and back|
+|default | &lt;any value&gt; | the default netconf value if there is no response from the device |
+|validator | regex | to validate the netconf value to avoid protocol errors |
+
+
+Conversion methods:
+
+Hint: All conversations shown here are the snmp-to-netconf value conversations. Some of these are working in both directions, some not.
+
+
+| Conversion | bi-directional | Description | Example |
+| ---------- |: -------------- :| ----------- | ------- |
+|int-to-boolean | yes | Convert 1-true and not 1-false between boolean and int| 1=\>true, 0=\>false |
+|int-to-boolean-dd,dd,dd-true | no | Convert listed numbers to true | |
+|int-to-boolean-dd,dd,dd-false | no | Convert listed numbers to false|  |
+|if-dd,dd,dd-term1-term2 | no | if value listed, result is *term1*, if not *term2*| |
+|map-dd1,dd2,dd3-term1-term2 | yes | Bidirectional map dd1 to term1, dd2 to term2 and soon | |
+|divide-dd1 | yes | Divide value by dd1| divide-10: 99 =\> 9.9 =\> 10|
+|dividen-dd1 | yes | Divide value by (-1*dd1)| dividen-10: 99 =\> -9.9 =\> -10|
+|internal | yes | use inernally hardcoded conversion method | qpsk =\> 4, 16qam =\> 16 |
+
+
+## Alarms
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/meta.json b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/meta.json
new file mode 100644
index 0000000..208bee0
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/meta.json
@@ -0,0 +1,261 @@
+{
+    "sdnr": {
+        "nodes": {
+            "connectApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/connect/README.md",
+                        "label": "Connect"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/connect/README.md",
+                        "label": "Connect"
+                    }
+                },
+                "label": "Connect"
+            },
+            "faultApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfFault/README.md",
+                        "label": "Fault"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfFault/README.md",
+                        "label": "Fault"
+                    }
+                },
+                "label": "Fault"
+            },
+            "maintenanceApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-09-13",
+                        "path": "sdnr/pnfMaintenance/README.md",
+                        "label": "Maintenance"
+                    },
+                    "current": {
+                        "date": "2018-09-13",
+                        "path": "sdnr/pnfMaintenance/README.md",
+                        "label": "Maintenance"
+                    }
+                },
+                "label": "Maintenance"
+            },
+            "configurationApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfConfig/README.md",
+                        "label": "Config"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfConfig/README.md",
+                        "label": "Config"
+                    }
+                },
+                "label": "Config"
+            },
+            "performanceHistoryApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfPerformance/README.md",
+                        "label": "Performance"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfPerformance/README.md",
+                        "label": "Performance"
+                    }
+                },
+                "label": "Performance"
+            },
+            "inventoryApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfInventory/README.md",
+                        "label": "Inventory"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfInventory/README.md",
+                        "label": "Inventory"
+                    }
+                },
+                "label": "Inventory"
+            },
+            "mediatorApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfMediator/README.md",
+                        "label": "Mediator"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/pnfMediator/README.md",
+                        "label": "Mediator"
+                    }
+                },
+                "label": "Mediator"
+            },
+            "eventLogApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2020-02-03",
+                        "path": "sdnr/pnfEventLog/README.md",
+                        "label": "EventLog"
+                    },
+                    "current": {
+                        "date": "2020-02-03",
+                        "path": "sdnr/pnfEventLog/README.md",
+                        "label": "EventLog"
+                    }
+                },
+                "label": "EventLog"
+            },
+            "networkApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/networkMap/README.md",
+                        "label": "NetworkMap"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/networkMap/README.md",
+                        "label": "NetworkMap"
+                    }
+                },
+                "label": "NetworkMap"
+            },
+            "linkCalculationApp": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/linkCalculator/README.md",
+                        "label": "LinkCalculator"
+                    },
+                    "current": {
+                        "date": "2018-02-24",
+                        "path": "sdnr/linkCalculator/README.md",
+                        "label": "LinkCalculator"
+                    }
+                },
+                "label": "LinkCalculator"
+            }
+        },
+        "versions": {
+            "0.4.0": {
+                "date": "2018-02-24",
+                "path": "sdnr/README.md",
+                "label": "SDN-R"
+            },
+            "current": {
+                "date": "2018-02-24",
+                "path": "sdnr/README.md",
+                "label": "SDN-R"
+            }
+        },
+        "label": "SDN-R"
+    },
+    "mediatorserver": {
+        "nodes": {
+            "installation": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "",
+                        "path": "mediatorserver/installation/README.md",
+                        "label": ""
+                    },
+                    "current": {
+                        "date": "",
+                        "path": "mediatorserver/installation/README.md",
+                        "label": ""
+                    }
+                },
+                "label": "Installation"
+            },
+            "mediator": {
+                "versions": {
+                    "0.4.0": {
+                        "date": "",
+                        "path": "mediatorserver/mediator/README.md",
+                        "label": ""
+                    },
+                    "current": {
+                        "date": "",
+                        "path": "mediatorserver/mediator/README.md",
+                        "label": ""
+                    }
+                },
+                "label": "Mediator"
+            }
+        },
+        "versions": {
+            "0.4.0": {
+                "date": "",
+                "path": "mediatorserver/README.md",
+                "label": ""
+            },
+            "current": {
+                "date": "",
+                "path": "mediatorserver/README.md",
+                "label": ""
+            }
+        },
+        "label": "MediatorServer"
+    },
+    "faq": {
+        "versions": {
+            "0.4.0": {
+                "date": "2018-02-24",
+                "path": "sdnr/faq.md",
+                "label": "FAQ"
+            },
+            "current": {
+                "date": "2018-02-24",
+                "path": "sdnr/faq.md",
+                "label": "FAQ"
+            }
+        },
+        "label": "FAQ"
+    },
+    "abbreviations": {
+        "versions": {
+            "0.4.0": {
+                "date": "2018-02-24",
+                "path": "sdnr/abbreviations.md",
+                "label": "Abbreviations"
+            },
+            "current": {
+                "date": "2018-02-24",
+                "path": "sdnr/abbreviations.md",
+                "label": "Abbreviations"
+            }
+        },
+        "label": "Abbreviations"
+    },
+    "general": {
+        "versions": {
+            "0.4.0": {
+                "date": "2018-02-24",
+                "path": "sdnr/general.md",
+                "label": "General Functionality"
+            },
+            "current": {
+                "date": "2018-02-24",
+                "path": "sdnr/general.md",
+                "label": "General Functionality"
+            }
+        },
+        "label": "General Functionality"
+    }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/ONAP-SDN-R.png b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/ONAP-SDN-R.png
new file mode 100644
index 0000000..6a9f2fa
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/ONAP-SDN-R.png
Binary files differ
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/README.md
new file mode 100644
index 0000000..fa8ce0d
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/README.md
@@ -0,0 +1,8 @@
+# SDN controller for 'Radio' (SDN-R)
+
+SDN-R adds features and functionality to the OpenDaylight-based ONAP controller 'CCSDK/SDNC'. It is built on the Common Controller Framework to control and manage wireless resources. Wireless resources are virtual network functions (e.g. vBBU, vEPC) or physical network functions (e.g. microwave and millimeter wave radios, eNodeB, RRH, DAS equipment).
+
+SDN-R is integrated into ONAP using DMaaP APIs. It is interfacing with PNFs and VNFs and with other ONAP components, such as A&AI, DCAE and SO.  
+[See abbreviations](abbreviations.md)
+
+![SDN-R in ONAP](./ONAP-SDN-R.png "SDN-R in ONAP")
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/abbreviations.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/abbreviations.md
new file mode 100644
index 0000000..120d685
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/abbreviations.md
@@ -0,0 +1,212 @@
+# Abbreviations
+
+|**Abbreviation**|**Description**|
+|----------------|---------------|
+| AAF            | [Application Authorization Framework](https://wiki.onap.org/display/DW/Application+Authorization+Framework+Project) |
+| A&AI           | [Active & Available Inventory](https://wiki.onap.org/display/DW/Active+and+Available+Inventory+Project) |
+| AAA            | [Authentication, Authorization and Accounting](https://en.wikipedia.org/wiki/AAA_(computer_security)) |
+| AEC            | AT&T Edge Cloud |
+| AIC            | AT&T Integrated Cloud |
+| AID            | Architecture Integration Document |
+| APPC           | [Application Controller](https://wiki.onap.org/display/DW/Application+Controller+Project) |
+| BPEL           | Business Process Execution Language |
+| BPMN           | [Business Process Model and Notation or Business Process Management Notation](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) |
+| BRMS           | Business Rules Management System |
+| BSS            | Business Support System |
+| CCSDK          | Common Controller SDK project |
+| CDAP           | [Cask Data Application Platform](https://cdap.io/) |
+| CDR            | Charging Data Record |
+| CDS            | Controller Design Studio |
+| CI/CD          | Continuous Integration / Continuous Delivery |
+| Cinder         | OpenStack Block Storage |
+| CL             | Control Loop |
+| CLAMP          | Closed Loop Automation Management Platform (project) |
+| CLI            | [Command Line Interface (project)](https://wiki.onap.org/display/DW/Command+Line+Interface+Project) |
+| CMA            | Change Management Application (within ONAP) |
+| CN             | Core Network |
+| CNF            | Cloud Native network Function. |
+| COE            | Container Orchestration Engine |
+| CPE            | Customer Premise Equipment |
+| CSAR           | [Cloud Service ARchive (link)](http://openbaton.github.io/documentation/tosca-CSAR-onboarding/) |
+| CU             | Centralized Unit |
+| DAO            | [Data Access Object](https://en.wikipedia.org/wiki/Data_access_object) |
+| DCAE           | [Data Collection Analytics and Events](https://wiki.onap.org/pages/viewpage.action?pageId=6592895) |
+| DDoS           | Distributed Denial-of-Service attack |
+| DG             | Directed Graph |
+| DG Builder     | Directed Graph Builder |
+| DMaaP          | [Data Movement as a Platform](https://wiki.onap.org/display/DW/DMaaP) |
+| DME            | [Direct Messaging Engine (common service within ONAP)](https://wiki.onap.org/display/DW/Common+Services) |
+| DMIP           | Device Management Interface Profile |
+| DNS            | Domain Name System |
+| DPDK           | Data Plane Development Kit |
+| DU             | Distributed Unit |
+| ECA            | External Content Adapter |
+| ECOMP          | Enhanced, Control, Orchestration, Management and Policy |
+| EELF           | [Event&Error LoggingFramework](https://wiki.onap.org/display/DW/Common+Services) |
+| EMS            | [Element Management System](https://en.wikipedia.org/wiki/Element_management_system) |
+| ESR            | [External System Register](https://wiki.onap.org/pages/viewpage.action?pageId=5734948) |
+| ETSI           | [European Telecommunications Standards Institute](http://www.etsi.org/technologies-clusters/technologies/689-network-functions-virtualisation) |
+| EUAG           | [ONAP End User Advisory Group](https://wiki.lfnetworking.org/pages/viewpage.action?pageId=2916362) |
+| FCAPS          | Fault Configuration Accounting Performance Security |
+| FM             | Fault Management |
+| FQDN           | Fully Qualified Domain Name |
+| GBP            | [Group-Based Policy ](https://wiki.openstack.org/wiki/GroupBasedPolicy) |
+| Glance         | OpenStack Image repository |
+| GNFC           | [Genric Network Function Controller](https://wiki.onap.org/download/attachments/45300148/ONAP_GNF_ControllersSOL003.pptx?version=1&modificationDate=1548619943000&api=v2) |
+| GUI            | [Graphical User Interface](https://en.wikipedia.org/wiki/Graphical_user_interface) |
+| HAS            | [Homing and Allocation Service](https://wiki.onap.org/pages/viewpage.action?pageId=16005528) |
+| HDFS           | Hadoop Distributed File System |
+| Horizon        | OpenStack GUI |
+| HPA            | Hardware Platform Awareness |
+| HTTP           | HyperText Transfer Protococol |
+| HV VES         | [High Volume Virtual function Event Stream](https://wiki.onap.org/display/DW/High+Volume+VES+Collector) |
+| IAM/IDAM       | Identity and Access Management |
+| ICE            | Incubation and Certification Environment |
+| ICMMS          | Syniverse Inter-carrier messaging solution |
+| IDS            | [Intrusion Detection System](https://en.wikipedia.org/wiki/Intrusion_detection_system) |
+| IETF           | [Internet Engineering Task Force](http://www.ietf.org) |
+| IKE            | [Internet KeyExchange](https://en.wikipedia.org/wiki/Internet_Key_Exchange) |
+| IPS            | [Intrusion Prevention System](https://en.wikipedia.org/wiki/Intrusion_detection_system) |
+| IPSEC          | [Internet Protocol Security](https://en.wikipedia.org/wiki/IPsec) |
+| JAR            | [Java Archive](https://en.wikipedia.org/wiki/JAR_(file_format)) |
+| JSC            | [JavaServiceContainer](https://wiki.onap.org/display/DW/Common+Services) |
+| JSON           | JavaScript  Object  Notation |
+| Keystone       | OpenStack Authorization Project |
+| KVM            | Kernel-based Virtual machine |
+| LCM            | Life Cycle Management |
+| LDAP           | Lightweight Directory Access Protocol |
+| LFN CVC        | [Linux Foundation Networking Compliance/Verification Committee](https://wiki.onap.org/display/DW/LFN+CVC+Testing+in+VNFSDK) |
+| LFN CVP        | [Linux Foundation Networking Compliance/Verification Program](https://wiki.onap.org/display/DW/LFN+CVC+Testing+in+VNFSDK) |
+| LRM            | Local Resource Monitor |
+| M0             | Release Kick-off milestone. See also Release Lifecycle |
+| M1             | Release Planning milestone. See also Release Lifecycle |
+| M2             | Release Functionality Freeze milestone. See also Release Lifecycle |
+| M3             | Release API Freeze milestone. See also Release Lifecycle |
+| M4             | Release Code Freeze milestone. See also Release Lifecycle |
+| MACD           | (Vendor specific) Move Add Change Delete/Disconnect |
+| MANO           | MANagement and Organization of NFV |
+| MD-SAL         | Model Driven Service Abstraction Layer |
+| MIND           | Master Integrated Network Directory |
+| MR             | Message Router (a Common Service of ONAP) |
+| MOP            | Method of Procedure |
+| MOTS           | Mechanized Operations Tracking System |
+| MSB            | Microservice Bus |
+| MSO            | [Master Service Orchestrator](https://wiki.onap.org/pages/viewpage.action?pageId=1015834) |
+| MVP            | [Minimum ViableProduct](https://en.wikipedia.org/wiki/Minimum_viable_product) |
+| NAI            | Network Artificial Intelligence |
+| NANCSP         | Network Cloud Service Provider |
+| NBI            | North Bound Interface |
+| NEP            | Network Equipment Provider |
+| NETCONF        | [Network Configuration Protocol](https://en.wikipedia.org/wiki/NETCONF) |
+| Neutron        | OpenStack Networking |
+| NFMF           | Network Function Management Function |
+| NFV            | [Network Function Virtualization](https://en.wikipedia.org/wiki/Network_function_virtualization) |
+| NFVI           | [network functions virtualization infrastructure](https://www.sdxcentral.com/nfv/definitions/nfv-mano/) |
+| NOD            | Network On Demand |
+| Nova           | OpenStack compute |
+| NS             | Network Services |
+| NS             | (Vendor Specific) New Start |
+| NSI            | Network Slice Subnet Instance |
+| NSMF           | Network Slice Management Function |
+| NSSMF          | Network Slice Subnet Management Function |
+| O-RAN          | [O-RAN Alliance , OperatorDefined NextGeneration RadioAccessNetworksAlliance ](https://www.o-ran.org) |
+| O-RAN-SC       | [O-RAN SoftwareCommunity](https://o-ran-sc.org) |
+| OAM            | Operation and Maintenance |
+| OA&M           | Operations, Administration and Management |
+| OMF            | Operational Management Framework (of ONAP) |
+| OMSA           | ONAP Microservice Architecture |
+| ONAP           | [Open Network Automation Platform](https://wiki.onap.org/pages/viewpage.action?pageId=1015843) |
+| OOF            | ONAP Optimization Framework |
+| ODL            | [OpenDaylight](https://www.opendaylight.org/) |
+| OOM            | [ONAP Operations Manager](https://wiki.onap.org/display/DW/OOM+User+Guide) |
+| OpenStack      | A cloud operating system |
+| OPNFV          | [Open Platform for NFV Project](https://www.sdxcentral.com/nfv/definitions/opnfv/) |
+| Originato      | MMSC Any Non-AT&T MMSC that originally sent the request to ICMMS |
+| OSAM           | [Open Source Access Manager](https://wiki.onap.org/display/DW/OpenSource+Access+Manager+%28OSAM%29+Use+Case) |
+| OSC            | O-RAN Software Community or Optical Supervisory Channel |
+| OSS            | Operations Support System |
+| PAP            | Policy Administration Point (ONAP) |
+| PCE            | Path Computation and Element (ONAP) |
+| PCI            | Physical Cell ID |
+| pCPE           | physical Customer Premise Equipment |
+| PDP-x          | Policy Decision Point - XACML (ONAP) |
+| PDP-d          | Policy Decision Point - Drools (ONAP) |
+| PM             | Performance Management |
+| PNDA           | [OpensourcePlatform  for  Network DataAnalytics](https://wiki.onap.org/display/DW/Integrating+PNDA) |
+| PNF            | Physical Network Function |
+| PnP            | Plug and Play |
+| PO             | Platform Orchestrator |
+| PoC            | Proof of Concept |
+| POMBA          | [Post Orchestration Model Based Audit](https://wiki.onap.org/display/DW/POMBA) |
+| PRH            | Phyiical Network Function Registration Handler |
+| Pub/Sub        | Publisher/Subscriber |
+| RAN            | Radio Access Network |
+| RCA            | Root Cause Analysis |
+| RCT            | Reference Connection Tool |
+| REST           | [Representational State Transfer](https://en.wikipedia.org/wiki/Representational_state_transfer) |
+| RESTCONF       | A protocol based on HTTP for configuring data defined in YANG |
+| RO             | Resource Orchestrator |
+| RPC            | Remote Procedure Call |
+| RU             | Radio Unit |
+| RRH            | Remote Radio Head |
+| S3P            | [Stability, Security, Scalability, Performance](https://wiki.onap.org/pages/viewpage.action?pageId=16003367) |
+| SDC            | Service Design and Creation (component of ONAP for visual modeling and design) |
+| SDN            | [Software-defined networking](https://en.wikipedia.org/wiki/Software-defined_networking) |
+| SDN-C          | [SDN-Controller](https://wiki.onap.org/display/DW/SDN+Controller+Development+Guide) |
+| SDN-R          | [SDN-Radio, Router, ROADM - a set of model-driven application based on SDN-C](https://wiki.onap.org/display/DW/SDN-R) |
+| SDN-GP         | Software Defined Network - Global Platform |
+| SEBA           | SDN-Enabled Broadband Access, see also |
+| SLA            | Service Level Agreement |
+| SLI            | Service Logic Interpreter |
+| SME            | Subject Matter Expert |
+| SMTP           | Simple Mail Transfer Protocol |
+| SNMP           | Simple Network Management Protocol |
+| SO             | [Service Orchestrator (project)](https://wiki.onap.org/display/DW/Service+Orchestrator+Project) |
+| SON            | Self-Organizing Networks |
+| SOT            | Source Of Truth |
+| SR-IOV         | [Single-Root Input/Output Virtualization](https://en.wikipedia.org/wiki/Single-root_input/output_virtualization) |
+| SRS            | Software Requirements Specification |
+| SSL            | [SecureSocketsLayer](https://en.wikipedia.org/wiki/Transport_Layer_Security) |
+| SUPP           | (Vendor Specific) short for supplement, changing a connection before activation |
+| Swagger        | legacy name for the OpenAPI Specification |
+| Swift          | OpenStack Object storage |
+| TCP            | Transmission Control Protocol |
+| TEM            | Telecom Electronics Manufacturer |
+| TLS            | [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) |
+| TN             | Transport Network |
+| TOSCA          | [Topology and Orchestration Specification for Cloud Applications](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=tosca) |
+| TPS            | Transactions Per Second |
+| TSC            | Technical Steering Committee |
+| U-UI           | [Usecase UserInterface](https://wiki.onap.org/display/DW/Usecase+UI+Project) |
+| UI             | [User Interface](https://en.wikipedia.org/wiki/User_interface) |
+| UUI            | User to User Information |
+| UX             | [User Experience](https://en.wikipedia.org/wiki/User_experience) |
+| vCE            | virtual CE (Customer Edge) router (an example VNF) |
+| vCPE           | Virtual Customer Premise Equipment |
+| vDNS           | Virtual Domain Name Server (an example VNF) |
+| VDU            | [Virtualisation Deployment Unit](https://wiki.onap.org/display/DW/Comparison+of+Current+R3+Clean+Version+with+IFA011+v2.5.1) |
+| VES            | [Virtual function EventStream](https://wiki.opnfv.org/download/attachments/6819329/OPNVF%20VES.pptx?version=4&modificationDate=1466395653000&api=v2) |
+| vF             | Virtual Firewall (an example VNF) |
+| VF             | Virtual Function |
+| VFC            | [Virtual Function Controller](https://wiki.onap.org/display/DW/Virtual+Function+Controller+Project) |
+| VFC            | Virtual Function Component (Resource Onboarding) |
+| vfModule       | Virtual Function Module |
+| VID            | Virtual Instantiation Deployment |
+| VID            | [Virtual Infrastructure Deployment (Project)](https://wiki.onap.org/display/DW/Virtual+Infrastructure+Deployment+Project) |
+| VIM            | Virtualized Infrastructure Manager |
+| VLAN           | Virtual Local Area Network |
+| VM             | Virtual Machine |
+| VNF            | [Virtual Network Function](http://searchsdn.techtarget.com/definition/virtual-network-functions) |
+| VNFC           | Virtual Network Function Component |
+| VNFD           | [VNF Descriptor](https://wiki.onap.org/pages/viewpage.action?pageId=8226059) |
+| VNFM           | VNF Manager |
+| VNO            | Virtual Network Operator |
+| vPE            | virtual PE (Provider Edge) router (an example of a VNF) |
+| VPP            | [Vector Packet Processing](https://wiki.fd.io/view/VPP/What_is_VPP%3F) |
+| VSP            | Vendor Software Product (from SDC Demo Guide) |
+| VTP            | [VNF Test Platform](https://wiki.onap.org/pages/viewpage.action?pageId=43386304) |
+| VVP            | [VNF Validation Program](https://wiki.onap.org/display/DW/VNF+Validation+Program+Project) |
+| WAR            | [Web application Archive](https://en.wikipedia.org/wiki/WAR_(file_format)) |
+| xNF            | The combination of PNF and VNF; Network Function |
+| YANG           | Yet Another Next Generation - a Data Modeling Language for the Network Configuration Protocol (NETCONF) |
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/connect/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/connect/README.md
new file mode 100644
index 0000000..584fcdf
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/connect/README.md
@@ -0,0 +1,19 @@
+# Connect
+
+The 'Connect' application on OpenDaylight provides up-to-date connectivity information about the network nodes exposing a NETCONF/YANG interface. It automatically displays new Nodes and their connection status. Usually, the NETCONF servers of the Nodes mount themselves. If necessary, they can be mounted manually by right-clicking on the row representing a node and selecting the 'mount' action. For better understanding of alarms and status, a connection status log lists all the connection status changes of OpenDaylight mount points.
+
+## Views
+
+The graphical user interface is divided into two sections.
+
+### Nodes
+
+Nodes are network functions with a NETCONF/YANG management and control interface. A table view shows all configured and connected NETCONF Servers of the SDN-R cluster. This view also allows to manually configure/mount a node via the '+' button. The SDN controller will start connecting to the NETCONF server.
+
+Nodes can be marked as 'required'. If a node is required, it will stay available even if disconnected. If a node is not required, it will be deleted once disconnected.
+
+By right-clicking on a row representing a node, an action menu opens. The menu allows to mount, unmount, view the details, edit and remove the node. Additionally, it links to several applications like Fault and Configure, which will be filtered to display information relevant to the selected node.
+
+### Connection Status Log
+
+The log lists the connection status changes between SDN Controller and NETCONF servers (devices, Network Elements, network functions).
\ No newline at end of file
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/faq.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/faq.md
new file mode 100644
index 0000000..f9d5e50
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/faq.md
@@ -0,0 +1,72 @@
+# Frequently asked questions
+
+
+
+## Which browser should I use to operate Opendaylight SDN-R User interface?
+
+An actual version of [Google Chromium](https://www.chromium.org/getting-involved/download-chromium "Download Chromium") or 
+[Google Chrome](https://www.google.de/search?q=chrome+download&oq=chrome+download&aqs=chrome..69i57j0l5.2718j0j4&sourceid=chrome&ie=UTF-8 "Download Chrome") is recommended.
+
+- - -
+
+
+## How to enable detailed logs in karaf for SDN-R applications
+
+If you like to see more details in karaf logs for the NetConf communication between ODL and NetConf servers (mediators/devices) please invoke the following commands in the karaf console.
+
+```
+# Logging settings (on)
+log:set DEBUG org.opendaylight.mwtn
+log:set TRACE org.opendaylight.netconf
+log:set TRACE com.highstreet.technologies.odl.app
+```
+
+Please note, setting the debug level to 'TRACE' may impact the performance on the controller. In production environment make sure to set back the debug level to 'INFO' as soon possible.
+
+
+```
+# Logging settings (off)
+log:set INFO org.opendaylight.mwtn
+log:set INFO org.opendaylight.netconf
+log:set INFO com.highstreet.technologies.odl.app
+```
+
+- - -
+
+## Which commands should be used to analyse karaf logs?
+
+```
+cd $ODL_KARAF_HOME/data/log
+rm *.txt
+grep -anr --include=*.log* "| ERROR |" . | grep 2018 >> 01-error.txt
+grep -anr --include=*.log* "RemoteDevice{" . | grep 2018 >> 02-devices.txt
+grep -anr --include=*.log* "RemoteDevice{" . | grep "Unable to build schema context, unsatisfied imports" | grep 2018 >> 03-schema-issue.txt
+grep -anr --include=*.log* "Matched request:" . | grep 2018 >> 04-matched-request.txt
+grep -anr --include=*.log* "network-element" . | grep 2018 >> 05-network-element.txt
+grep -anr --include=*.log* "urn:onf:params:xml:ns:yang:core-model" . | grep 2018 >> 06-core-module.txt
+grep -anr --include=*.log* "PerformanceManagerTask" . | grep 2018 >> 07-pm-tick.txt
+grep -anr --include=*.log* "Unable to read NE data for mountpoint" . | grep 2018 >> 08-unable-to-read.txt
+grep -anr --include=*.log* "LKCYFL79Q01M01MSS801" . | grep 2018 >> 09-LKCYFL79Q01M01MSS801.txt
+```
+
+
+## How to report an odlux issue
+
+If you would like to report an odlux issue which you have noticed in the Graphical User Interface, please provide the following information:
+
+1. **Description**: In which application you have noticed the issue?
+
+2. **Environment**: 
+    - Which browser is used and the version of the browser.  eg: *Google chrome - version 71.0.3578.80  / Mozilla Firefox.*
+    - Which Operating system and version. eg: *Linux/ Windows 10 -  version 1803.* 
+    - In which language you are using the application. 
+    - The application URL which is available on the browser address bar.  eg: *http://hostname/odlux/index.html#/connectApp* 
+
+3. **Expected Result**: What is the expected result you are looking for?
+
+4. **Actual Result**: What is the actual result you got?
+
+5. **Steps to reproduce**: Describe the steps to reproduce the scenario. If possible, please provide the screenshots
+ 
+The above information helps us to analyze the problem quicker.
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/general.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/general.md
new file mode 100644
index 0000000..a91b485
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/general.md
@@ -0,0 +1,25 @@
+# General functionality
+
+The following functionality is common to all applications.
+
+### Table data export
+
+Every table can export its data via the   '&#65049;'  button.
+The data, which gets exported is the currently viewed data in the table. As the default pagination is set to 10, only the first 10 rows or filtered rows will be exported. To increase the number of exported rows, change the pagination.
+
+The behavior of the export can vary based on the browser:
+
+a) Some browsers allow you to save the file with the predefined name export.csv. In case your browser does not offer this function please use the 'Save as...' option and define the filename with extension csv.
+
+b) Some browsers save the file automatically with the alphanumeric name but without an extension. In such a case navigate to the downloaded file location and rename the file. The extension (csv) must be appended to the name. The result should look like 'export_file.csv'.
+
+### Table filters
+
+The following filters are supported by all tables based on the data type of the column.
+
+|Data type | Possible Filter | Example |
+| ---------|---------------|---------|
+| Text | Any characters or numbers, matches exactly unless a * or a ? are used. Both special characters act as wildcards, which can be used for contains, ends with and begins with queries. The * matches any number of characters whereas the ? matches exactly one character. Both wildcards can be used in the same query. |Test, T*, *st, Te?t, ?est |
+| Numeric | < or <= or > or >= or exact number |>5000, 20, <=82 |
+| Boolean |None (no filter set), true or false |true, false |
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfConfig/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfConfig/README.md
new file mode 100644
index 0000000..62bf907
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfConfig/README.md
@@ -0,0 +1,22 @@
+# Configuration
+
+The application rely on yang-specifications provided by the device. It is Generic and generated user interface, generated by yang specs and capabilites of a device. Each view of a functional element is divided into capabilities, configuration, status, current problem, current performance and history performance information according to TR-532.
+
+A separate window is available for modifying the configuration. All changes made are sent to the device in a single NetConf bulk request. The operator is notified about successfully configuring the device.
+
+### Features
+
+Read yang specifications and generate related User interface out of it
+
+  - Provide yang description as tool tip for fields
+
+  - Consider specified type for input fields
+  
+  - Provide read and write access
+
+## Implementation
+
+The application is implemented as ODLUX web application using the RestConf northbound interface of the SDN controller. The key frameworks are: Typescript, React and material-ui.
+
+Connection status information is updated automatically using a web socket for notifications from OpenDaylight to the browser.
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfEventLog/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfEventLog/README.md
new file mode 100644
index 0000000..e289f42
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfEventLog/README.md
@@ -0,0 +1,6 @@
+# Event Log
+
+The 'EventLog'  application displays application logs and messages automatically created by the different active applications.
+SDN-R offers a common log service so that PNFs or other ONAP components can log their data and users can analyze and export the data in a common way.
+
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfFault/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfFault/README.md
new file mode 100644
index 0000000..cfac06d
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfFault/README.md
@@ -0,0 +1,31 @@
+# Fault Management
+
+To operate a network, it is important to get an overview about the currently raised alarms. The application offers basic fault management of devices supporting ONF-TR-532. The alarms are classified according to the severity level (warning, minor, major, critical).
+
+## Views
+
+The graphical user interface is separated into three views.
+
+### Current Problem List
+
+Lists all current active faults in the network. In addition, it also lists alarms sent by the SDN controller itself, which detects connection losses to the NetConf server (connectionLossOAM) or to a device via a mediator to a device (connectionLossNeOAM).
+
+### Alarm Notifications
+
+As long as the view is open, all alarm notifications received by the SDN Controller are listed. Please note that refreshing the view will start the collection again. Previous alarm notification can be viewed in the alarm log.
+
+### Alarm Log
+
+Next to the current active alarms an alarm log lists all alarm notifications of the past.
+
+## Implementation
+
+The application has two parts. While the server is listening for NetConf notifications to store them in the database, the client retrieves the information from the database and displays them in a table.
+
+The server synchronizes with the current alarm lists of the devices. Based on raised and cleared notifications, the current alarm status of the network is calculated. The current alarms are stored in a database. In addition, all Problem Notifications received by the SDN controller are stored. There is no logic implemented on the client side.
+
+An alarm status bar in the header of the web application informs the operator about the health status of the network.
+
+The ODLUX web application uses web sockets to update the graphical user interface of the Alarm Notifications (devices) and Connection Status Notifications in real-time.
+
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfInventory/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfInventory/README.md
new file mode 100644
index 0000000..1f2dd88
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfInventory/README.md
@@ -0,0 +1,30 @@
+# Inventory
+
+The application offers basic inventory management of devices supporting ONF-TR-512 and ietf-hardware.
+
+## Views
+
+The inventory application offers two different ways to visualize inventory data.
+
+### Tableview
+
+The view displays the inventory data of the network element – for example, serial-numbers and part-numbers according to the containment of the equipment – as a table. By right-clicking on an entry, the element can be viewed in the treeview.
+
+### Treeview
+
+The treeview visualizes relations between the inventory data of a network element. To load all relations, a '*' can be entered in the search-field.
+
+
+##### Inventory Export:
+
+The '&#65049;' button in the upper right corner of the table allows exporting the inventory data as a CSV file.
+
+Only the currently viewed table data is exported. As the default pagination is set to 10, only the first 10 rows or filtered rows would be exported. To increase the number of exported rows change the pagination.
+
+The behavior of the export can vary based on different browsers:
+
+a) Some browsers allow you to save the file with the predefined name export.csv. In case your browser does not offer this function please use the 'Save as...' option and define the filename with extension csv.
+
+b) Some browsers save the file automatically with the alphanumeric name but without an extension. In such a case navigate to the downloaded file location and rename the file. The extension (csv) must be appended to the name. The result should look like export_file.csv.
+
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfMaintenance/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfMaintenance/README.md
new file mode 100644
index 0000000..f6bf538
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfMaintenance/README.md
@@ -0,0 +1,7 @@
+# Maintenance
+
+The 'Maintenance' application on OpenDaylight provides information about planned maintenances of Network Elements, currently or in the future. Users can manage devices to set the maintenance mode so that no unnecessary alarms are created. When the device is in maintenance mode, alarms are not forwarded to DCAE. As soon as the maintenance is finished, the alarms will start flowing again.
+
+The 'active' field in the table shows if the Network Element is currently in maintenance mode or not. If it is 'active' it means the Network Element is currently undergoing maintenance, if 'not active' it means maintenance might have been set for a future date or is already completed.
+
+Users can disable the maintenance mode or change its start and end dates by using the available options in the actions column.
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfMediator/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfMediator/README.md
new file mode 100644
index 0000000..ef20c15
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfMediator/README.md
@@ -0,0 +1,7 @@
+# Mediator
+
+Some device vendors (Altiostar, CommScope, Dragonwave-X) use the [generic mediator framework](https://github.com/Melacon/NetConf2SNMP). Such mediators offer an API to create, delete, start and stop mediator instances.
+
+New mediator servers can be added via the '+' button. Afterward, a server can be selected to view all available mediator instances.
+
+A mediator instance can be started, stopped and deleted using the available actions. Additionally, its details can be viewed. The '+' button allows the user to add a new instance. During the creation, at least one 'ODL auto connect' configuration must be added.
diff --git a/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfPerformance/README.md b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfPerformance/README.md
new file mode 100644
index 0000000..c217b5c
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/main/resources/help/sdnr/pnfPerformance/README.md
@@ -0,0 +1,14 @@
+# Performance
+
+Performance Monitoring values measured by the devices are necessary to analyze and optimize the network. Therefore the application automatically retrieves all historical performance values from the devices and stores them in a database. The client retrieves the values from the database and displays them in a graphical user interface.
+
+## Performance history values
+
+After selecting a connected PNF supporting ONF-TR-532 and a physical interface, the application collects the received and centralized stored performance values for this interface.
+
+The values are visualized using two views: a line chart and a table, with the chart always shown first. To switch between them, toggle buttons can be used. The chart view offers a filter to quickly limit the shown values. To keep both views in sync, the filters of the chart and the table are connected. If one view is filtered, the other one gets updated in the background.
+
+
+
+
+
diff --git a/sdnr/wt-odlux/helpserver/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/helpserver/test/TestMyServlet.java b/sdnr/wt-odlux/helpserver/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/helpserver/test/TestMyServlet.java
new file mode 100644
index 0000000..b7a1dcc
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/helpserver/test/TestMyServlet.java
@@ -0,0 +1,177 @@
+/*
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+package org.onap.ccsdk.features.sdnr.wt.helpserver.test;
+
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.CREATE_NEW;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.ccsdk.features.sdnr.wt.helpserver.HelpServlet;
+
+
+public class TestMyServlet extends Mockito {
+
+    private static final String GETHELPDIRECTORYBASE = "data";
+    private static final String CONTENT = "abbccdfkamaosie aksdmais";
+
+    public static void createHelpFile(String filename, String content) {
+        File file = new File("bitnami/nginx/help" + filename);
+        File folder = file.getParentFile();
+        if (!folder.exists()) {
+            folder.mkdirs();
+        }
+        try {
+            if (file.exists()) {
+                file.delete();
+            }
+            Files.write(file.toPath(), content.getBytes(),
+                    new OpenOption[] {WRITE, CREATE_NEW, CREATE, TRUNCATE_EXISTING});
+        } catch (IOException e1) {
+            fail(e1.getMessage());
+        }
+    }
+
+//    @Before
+//    public void init() {
+//        try {
+//            ExtactBundleResource.deleteRecursively(new File(GETHELPDIRECTORYBASE));
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+
+   // @Test We dont have implementation of meta in HelpServlet
+    public void testServlet() throws Exception {
+
+        System.out.println("Test get");
+
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+
+        when(request.getRequestURI()).thenReturn("help/");
+        when(request.getQueryString()).thenReturn("?meta");
+
+        ServletOutputStreamToStringWriter out = new ServletOutputStreamToStringWriter();
+        when(response.getOutputStream()).thenReturn(out);
+
+        HelpServlet helpServlet = null;
+        try {
+            helpServlet = new HelpServlet();
+            System.out.println("Server created");
+            createHelpFile("/meta.json", CONTENT);
+
+            helpServlet.doOptions(request, response);
+            System.out.println("Get calling");
+            helpServlet.doGet(request, response);
+            System.out.println("Get called");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        if (helpServlet != null) {
+            helpServlet.close();
+        }
+
+        String result = out.getStringWriter().toString().trim();
+        System.out.println("Result: '" + result + "'");
+        assertEquals(CONTENT, result);
+    }
+
+    @Test
+    public void testServlet2() {
+        this.testGetRequest("test/test.txt");
+        this.testGetRequest("test.css");
+        this.testGetRequest("test.eps");
+        this.testGetRequest("test.pdf");
+    }
+
+    private void testGetRequest(String fn) {
+        HelpServlet helpServlet = new HelpServlet();
+        createHelpFile("/" + fn, CONTENT);
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+
+        when(request.getRequestURI()).thenReturn("help/" + fn);
+        ServletOutputStreamToStringWriter out = new ServletOutputStreamToStringWriter();
+        try {
+            when(response.getOutputStream()).thenReturn(out);
+            helpServlet.doGet(request, response);
+        } catch (ServletException | IOException e) {
+            fail(e.getMessage());
+        }
+        try {
+            out.close();
+        } catch (Exception e) {
+        }
+        try {
+            helpServlet.close();
+        } catch (Exception e) {
+        }
+
+        assertEquals("compare content for " + fn, CONTENT, out.getStringWriter().toString().trim());
+    }
+    
+    public class ServletOutputStreamToStringWriter extends ServletOutputStream {
+
+        // variables
+        private StringWriter out = new StringWriter();
+        // end of variables
+
+        public StringWriter getStringWriter() {
+            return out;
+        }
+
+        @Override
+        public void write(int arg0) throws IOException {
+            out.write(arg0);
+        }
+
+        @Override
+        public String toString() {
+            return out.toString();
+        }
+
+        @Override
+        public boolean isReady() {
+            return false;
+        }
+
+        @Override
+        public void setWriteListener(WriteListener writeListener) {
+        }
+
+
+    }
+
+}
diff --git a/sdnr/wt-odlux/helpserver/provider/src/test/resources/simplelogger.properties b/sdnr/wt-odlux/helpserver/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 0000000..1aa3824
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/src/test/resources/simplelogger.properties
@@ -0,0 +1,58 @@
+#
+# ============LICENSE_START=======================================================
+# ONAP : ccsdk features
+# ================================================================================
+# Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=======================================================
+#
+#
+
+# SLF4J's SimpleLogger configuration file
+# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
+
+# Default logging detail level for all instances of SimpleLogger.
+# Must be one of ("trace", "debug", "info", "warn", or "error").
+# If not specified, defaults to "info".
+org.slf4j.simpleLogger.defaultLogLevel=trace
+
+# Logging detail level for a SimpleLogger instance named "xxx.yyy.zzz".
+# Must be one of ("trace", "debug", "info", "warn", or "error").
+# If not specified, the default logging detail level is used.
+# org.slf4j.simpleLogger.log.xxx.yyy=debug
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager=debug
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.internalTypes.Resources=info
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.netconf.container=trace
+
+# Set to true if you want the current date and time to be included in output messages.
+# Default is false, and will output the number of milliseconds elapsed since startup.
+#org.slf4j.simpleLogger.showDateTime=false
+
+# The date and time format to be used in the output messages.
+# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
+# If the format is not specified or is invalid, the default format is used.
+# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
+#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
+
+# Set to true if you want to output the current thread name.
+# Defaults to true.
+#org.slf4j.simpleLogger.showThreadName=true
+
+# Set to true if you want the Logger instance name to be included in output messages.
+# Defaults to true.
+#org.slf4j.simpleLogger.showLogName=true
+
+# Set to true if you want the last component of the name to be included in output messages.
+# Defaults to false.
+#org.slf4j.simpleLogger.showShortLogName=false
diff --git a/sdnr/wt-odlux/helpserver/provider/test/test.txt b/sdnr/wt-odlux/helpserver/provider/test/test.txt
new file mode 100644
index 0000000..6dc9c45
--- /dev/null
+++ b/sdnr/wt-odlux/helpserver/provider/test/test.txt
@@ -0,0 +1 @@
+abbccdfkamaosie aksdmais
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/.eslintignore b/sdnr/wt-odlux/odlux/.eslintignore
new file mode 100644
index 0000000..23b30b7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/.eslintignore
@@ -0,0 +1,12 @@
+**/dist/**
+**/build/**
+**/node_modules/**
+apps/eventApp/**/*
+apps/faultApp/**/*
+apps/helpApp/**/*
+apps/inventoryApp/**/*
+apps/maintenanceApp/**/*
+apps/mediatorApp/**/*
+apps/performanceHistoryApp/**/*
+#apps/microwaveApp/**/*
+#apps/siteManagerApp/**/*
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/.eslintrc.json b/sdnr/wt-odlux/odlux/.eslintrc.json
new file mode 100644
index 0000000..f98e65b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/.eslintrc.json
@@ -0,0 +1,54 @@
+{
+  "root": true,
+  "parser": "@typescript-eslint/parser",
+  "plugins": [
+    "import",
+    "@typescript-eslint",
+    "react",
+    "react-hooks"
+  ],
+  "extends": [
+    "airbnb-typescript"
+  ],
+  "parserOptions": {
+    "project": [
+      "./tsconfig.json"
+    ],
+    "sourceType": "module"
+  },
+  "settings": {
+    "react": {
+      "version": "detect"
+    }
+  },
+  "rules": { 
+    "no-console": "off",
+    "no-debugger": "off",
+    "import/no-cycle": "off",
+    "quotes": [ "error", "single" ],
+    "import/prefer-default-export": "off",
+    "lines-between-class-members": "off",
+    "no-nested-ternary": "off",
+    "no-unused-vars": "off",
+    "object-curly-newline": "off", //["error", { "multiline": true, "minProperties": 8, "consistent": true }], 
+    "max-len": [ 2, 280, 2, { "ignoreUrls": true } ],
+    "@typescript-eslint/lines-between-class-members": [ "error", "always", { "exceptAfterOverload": true } ],
+    "@typescript-eslint/quotes": [ "error", "single" , { "avoidEscape": true } ],
+    "@typescript-eslint/no-unused-vars": [ "error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_" } ],
+    "@typescript-eslint/naming-convention": [ "error", 
+        { "format": [ "camelCase", "PascalCase", "UPPER_CASE", "snake_case" ], "leadingUnderscore": "allow", "selector": "default", "filter": { "regex": "(^&)|(^\\w+(-\\w+)+)", "match": false } } ],
+    "no-underscore-dangle": [ "error", { "allowAfterThis": true } ],
+    "no-param-reassign": [ "error", { "props": false } ],
+    "react/prop-types": [ "error", { "skipUndeclared": true } ],
+    "@typescript-eslint/member-delimiter-style": ["error"]
+  },
+  "overrides": [
+    { 
+      "files": "**/handlers/*Handler.ts",
+      "rules": {
+        "no-param-reassign": "off",
+        "@typescript-eslint/default-param-last": "off"
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/.gitignore b/sdnr/wt-odlux/odlux/.gitignore
new file mode 100644
index 0000000..1577b0b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/.gitignore
@@ -0,0 +1,7 @@
+package-lock.json
+npm
+yarn-error.log
+node/
+node_modules/
+dist/
+.vscode/
diff --git a/sdnr/wt-odlux/odlux/LICENSE b/sdnr/wt-odlux/odlux/LICENSE
new file mode 100644
index 0000000..c5487c3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/LICENSE
@@ -0,0 +1,15 @@
+============LICENSE_START========================================================================
+ONAP : ccsdk feature sdnr wt
+=================================================================================================
+Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+=================================================================================================
+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.
+============LICENSE_END==========================================================================
diff --git a/sdnr/wt-odlux/odlux/README.md b/sdnr/wt-odlux/odlux/README.md
new file mode 100644
index 0000000..6e5d596
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/README.md
@@ -0,0 +1,111 @@
+# Developing a ODLUX application
+
+## Introduction
+
+ODLUX bundle contains the Browser based Grapical User Interface for SDN-R.
+ODLUX is available as OSGi bundle that is running in Opendaylight Karaf environment, using the configured jetty server of Opendaylight.
+Since ONAP Frankfurt a second WEB Server setup "sdncweb" is available, that extracts the JavaScrip files.
+
+## Prerequisites
+
+Actual version in framework pom.xml in the frontend-maven-plugin definition.
+  * Node
+  * Yarn
+  * Lerna
+
+You can install these globally or let it be installed by maven due "mvn clean install"
+
+* Maven: 3 or higher
+* Java: 8
+
+## Dev-Environment Installation
+
+ * install NodeJS LTS https://nodejs.org/en/ or via packetmanager
+ * sudo npm install -g yarn
+ * sudo yarn global add lerna
+ * get framework from repository: git clone https://gerrit.onap.org/r/ccsdk/features
+ * in features/sdnr/wt/odlux you find a structure like this:
+ ```
+  odlux
+  |-apps
+  |-core
+  |-framework
+
+ ```
+ * go to features/sdnr/wt/odlux/apps and create your app:
+ ```
+ mvn archetype:generate -DarchetypeGroupId=org.onap.ccsdk.features.sdnr.wt \
+  -DarchetypeArtifactId=odlux-app-archetype \
+  -DgroupId=<groupId> \
+  -DartifactId=<artifactId> \
+  -Dversion=<version> \
+  -DappName=<applicationName>
+ ```
+
+ * your start folder for your web application is src/
+ * in src2/main/java are located the Java files and in src2/main/resources/ is the blueprint located
+ * with ```yarn start``` you can run your application due runtime in your application folder
+ * by default this will run on http://localhost:3100/index.html
+ * if you have added new dependencies you have to run ```lerna bootstrap``` in odlux/
+ * build your app for development version you can use ```yarn run build``` or ```yarn run build:dev```
+ * build for karaf with ```mvn clean install```
+
+
+## Including app into karaf environment
+
+ * copy maven repository files to karaf repository e.g.: ```cp ~/.m2/repository/path/of/groupId/artifactId $KARAF_HOME/system/path/of/groupId/```
+ * check if odlux-core is started in karaf console: ```feature:list | grep odlux```
+ * if not install: ```sdnr-wt-odlux-core-feature```
+ * start your app in karaf console: ```bundle:install -s mvn:<groupId>/<artifactId>/<version>```
+
+## Including into ONAP sdnc docker container
+
+ * add maven module to odlux/pom.xml
+ * add dependency to odlux/apps/app-feature/pom.xml and odlux/apps/app-installer/pom.xml
+ * build odlux/pom.xml
+ * this will automatically package your app into the packaged zip file of the installer
+
+## Details
+
+### Default menu positions
+
+ * from 0 for top to 999 for bottom.
+
+```
+0    Connect
+10    Fault
+20    Maintenance
+30    Configuration
+40    Protection
+50    Performance
+60    Security
+70    Inventory
+80    Topology
+90    Mediator
+100    Help
+```
+
+### blueprint.xml
+
+```
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+    <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+    <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+        <property name="loader" ref="loadersvc"/>
+        <property name="bundleName" value="demoApp"/>
+        <property name="index" value="999"/>
+    </bean>
+</blueprint>
+```
+ * bundleName defines the applicationName => default javascript file: <applicationName>.js
+ * index defines the menu position.
+
+### MyOdluxBundle.java
+
+ * is just for getting access to the resources of its bundle (implemented because of OSGi access restrictions)
+
+### pom.xml
+
+ * The pom.xml in the framework subdirectory is the reference for ODLUX creation. [framework pom](framework/pom.xml)
+ * The node and yarn versions are specified
+ * A specific variant of "frontend-maven-plugin" is used to create the environment to compile to javascript. This modified frontend-maven-plugin installs node, yarn and (optionally lerna) to compile the typescript sources to javascript. These will be build into the dist folder.
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/.babelrc b/sdnr/wt-odlux/odlux/apps/apiDemo/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/package.json b/sdnr/wt-odlux/odlux/apps/apiDemo/package.json
new file mode 100644
index 0000000..ff9e3c4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/package.json
@@ -0,0 +1,46 @@
+{
+  "name": "@odlux/api-demo",
+  "version": "0.1.0",
+  "description": "A react based modular UI framework",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@fortawesome/fontawesome-svg-core": "1.2.35",
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@fortawesome/react-fontawesome": "0.1.14",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/pom.xml b/sdnr/wt-odlux/odlux/apps/apiDemo/pom.xml
new file mode 100644
index 0000000..c7088fa
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-apiDemo</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+        <build>
+              <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/src/actions/modulesSuccess.ts b/sdnr/wt-odlux/odlux/apps/apiDemo/src/actions/modulesSuccess.ts
new file mode 100644
index 0000000..12fd3fc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/src/actions/modulesSuccess.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { ModuleResult } from '../models/module';
+export class ModulesRequestSuccess extends Action {
+  constructor(public result: ModuleResult) {
+    super();
+  }
+}
+// error will be handled by the framework
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts b/sdnr/wt-odlux/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
new file mode 100644
index 0000000..128a032
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { moduleHandler, IModules } from './modulesHandler';
+
+export interface IApiDemoStoreState {
+  modules: IModules;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    apiDemo: IApiDemoStoreState;
+  }
+}
+
+const actionHandlers = {
+  modules: moduleHandler,
+};
+
+export const apiDemoRootHandler = combineActionHandler<IApiDemoStoreState>(actionHandlers);
+export default apiDemoRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/src/handlers/modulesHandler.ts b/sdnr/wt-odlux/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
new file mode 100644
index 0000000..1984a2d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { ModulesRequestSuccess } from '../actions/modulesSuccess';
+import { Module } from '../models/module';
+
+export type IModules = Module[];
+
+const modulesInit: IModules = [];
+
+export const moduleHandler: IActionHandler<IModules> = (state = modulesInit, action) => {
+  if (action instanceof ModulesRequestSuccess) {
+    return action.result.modules.module;
+  }
+
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/src/index.html b/sdnr/wt-odlux/odlux/apps/apiDemo/src/index.html
new file mode 100644
index 0000000..c01df6b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/src/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>API Demo App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app","apiDemo"], function (app) {
+      app("./app.tsx")
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/src/models/module.ts b/sdnr/wt-odlux/odlux/apps/apiDemo/src/models/module.ts
new file mode 100644
index 0000000..48772a7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/src/models/module.ts
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type Module = {
+  name: string;
+  revision: string; 
+  namespace: string;
+};
+
+export type ModuleResult = {
+  modules: {
+    module: Module[];
+  };
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/src/plugin.tsx b/sdnr/wt-odlux/odlux/apps/apiDemo/src/plugin.tsx
new file mode 100644
index 0000000..2f70d8e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/src/plugin.tsx
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { faNewspaper } from '@fortawesome/free-solid-svg-icons/faNewspaper';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { connect, Connect } from '../../../framework/src/flux/connect';
+import { ApiAction } from '../../../framework/src/middleware/api'; // for RestConf
+
+import { apiDemoRootHandler } from './handlers/apiDemoRootHandler';
+import { ModulesRequestSuccess } from './actions/modulesSuccess';
+import { Module } from './models/module';
+
+type AppProps = RouteComponentProps & Connect & { modules: Module[]; requestModules: () => void };
+
+const App = (props: AppProps ) => (
+  <>
+    <button color="inherit" onClick={ props.requestModules }>Load Modules</button>
+    <ul>{ props.modules.map((mod, ind) => (<li key={ ind }>{ mod.name }</li>)) }</ul>
+  </>
+);
+
+const FinalApp = withRouter(connect((state) => ({
+  modules: state.apiDemo.modules,
+}), (dispatcher => ({
+  requestModules: () => { dispatcher.dispatch(new ApiAction('restconf/modules', ModulesRequestSuccess, true)); },
+})))(App));
+
+applicationManager.registerApplication({
+  name: 'apiDemo',
+  icon: faNewspaper,
+  rootComponent: FinalApp,
+  rootActionHandler: apiDemoRootHandler,
+  menuEntry: 'API Demo',
+});
+
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/tsconfig.json b/sdnr/wt-odlux/odlux/apps/apiDemo/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/apiDemo/webpack.config.js b/sdnr/wt-odlux/odlux/apps/apiDemo/webpack.config.js
new file mode 100644
index 0000000..6564bef
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/apiDemo/webpack.config.js
@@ -0,0 +1,139 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      apiDemo: ["./plugin.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }]
+    },
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+    plugins: [
+      //  new CopyWebpackPlugin([{
+      //    from: '../../../dist/**.*',
+      //    to: path.resolve(__dirname, "dist")
+      //  }]),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        })
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/restconf/**/*": {
+          target: "https://dlux.just-run.it",
+          secure: false,
+          changeOrigin: true
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/app-installer/pom.xml b/sdnr/wt-odlux/odlux/apps/app-installer/pom.xml
new file mode 100755
index 0000000..978f1e8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/app-installer/pom.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-apps-installer</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <application.name>sdnr-odlux-apps</application.name>
+        <include.transitive.dependencies>false</include.transitive.dependencies>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-apiDemo</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-connectApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-demoApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-faultApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-helpApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-inventoryApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-minimumApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-mediatorApp</artifactId>
+            <version>${project.version}</version>
+        </dependency> -->
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-maintenanceApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-performanceHistoryApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-eventLogApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-odlux-app-configurationApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>maven-repo-zip</id>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                            <attach>true</attach>
+                            <finalName>stage/${application.name}-${project.version}</finalName>
+                            <descriptors>
+                                <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+                            </descriptors>
+                            <appendAssemblyId>true</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-nested-dependencies</id>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <phase>prepare-package</phase>
+                        <configuration>
+                            <transitive>true</transitive>
+                            <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>true</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <useRepositoryLayout>true</useRepositoryLayout>
+                            <addParentPoms>false</addParentPoms>
+                            <copyPom>false</copyPom>
+                            <!--<includeArtifactIds>sdnr-wt-apigateway-provider,${application.name}</includeArtifactIds> -->
+                            <!--<scope>provided</scope> -->
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt-odlux/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 0000000..dfe5060
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,47 @@
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : ccsdk features
+  ~ ================================================================================
+  ~ Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+    <id>repo</id>
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <!--  we want "system" and related files right at the root level
+          as this file is suppose to be unzip on top of a karaf
+          distro. -->
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>target/assembly/</directory>
+            <outputDirectory>.</outputDirectory>
+            <excludes>
+            </excludes>
+        </fileSet>
+    </fileSets>
+
+</assembly>
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/.babelrc b/sdnr/wt-odlux/odlux/apps/configurationApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/package.json b/sdnr/wt-odlux/odlux/apps/configurationApp/package.json
new file mode 100644
index 0000000..b1d7d95
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/package.json
@@ -0,0 +1,47 @@
+{
+  "name": "@odlux/configuration-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI for the configuration app.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*",
+    "@fortawesome/fontawesome-svg-core": "1.2.35",
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@fortawesome/react-fontawesome": "0.1.14",
+    "material-ui-confirm": "3.0.2"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/policies.json b/sdnr/wt-odlux/odlux/apps/configurationApp/policies.json
new file mode 100644
index 0000000..91a0abf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/policies.json
@@ -0,0 +1,12 @@
+[
+  {
+    "path": "/rests/**/node=Sim2230**",
+    "methods": {
+      "get": false,
+      "post": false,
+      "put": false,
+      "delete": false,
+      "patch": false
+    }
+  }
+]
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/pom.xml b/sdnr/wt-odlux/odlux/apps/configurationApp/pom.xml
new file mode 100644
index 0000000..ae60d28
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-configurationApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/actions/deviceActions.ts
new file mode 100644
index 0000000..d8ec4bf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/actions/deviceActions.ts
@@ -0,0 +1,626 @@
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { PushAction, ReplaceAction } from '../../../../framework/src/actions/navigationActions';
+import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
+
+import { DisplayModeType, DisplaySpecification } from '../handlers/viewDescriptionHandler';
+
+import { restService } from '../services/restServices';
+import { YangParser } from '../yang/yangParser';
+import { Module } from '../models/yang';
+import {
+  ViewSpecification,
+  ViewElement,
+  isViewElementReference,
+  isViewElementList,
+  ViewElementString,
+} from '../models/uiModels';
+
+import {
+  checkResponseCode,
+  splitVPath,
+  filterViewElements,
+  flattenViewElements,
+  getReferencedDataList,
+  resolveViewDescription,
+} from '../utilities/viewEngineHelper';
+
+export class EnableValueSelector extends Action {
+  constructor(public listSpecification: ViewSpecification, public listData: any[], public keyProperty: string, public onValueSelected : (value: any) => void ) {
+    super();
+  }
+}
+
+export class SetCollectingSelectionData extends Action {
+  constructor(public busy: boolean) {
+    super();
+  }
+}
+
+export class SetSelectedValue extends Action {
+  constructor(public value: any) {
+    super();
+  }
+}
+
+export class UpdateDeviceDescription extends Action {
+  constructor( public nodeId: string, public modules: { [name:string]: Module }, public views: ViewSpecification[]) {
+    super();
+  }
+}
+
+export class UpdateViewDescription extends Action {
+  constructor(public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay }) {
+    super();
+  }
+}
+
+export class UpdateOutputData extends Action {
+  constructor(public outputData: any) {
+    super();
+  }
+}
+
+export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatch: Dispatch, _getState: () => IApplicationStoreState ) => {
+
+  dispatch(new UpdateDeviceDescription('', {}, []));
+  dispatch(new SetCollectingSelectionData(true));
+  
+  const { availableCapabilities, unavailableCapabilities, importOnlyModules } = await restService.getCapabilitiesByMountId(nodeId);
+  
+  if (!availableCapabilities || availableCapabilities.length <= 0) {
+    dispatch(new SetCollectingSelectionData(false));
+    dispatch(new UpdateDeviceDescription(nodeId, {}, []));
+    dispatch(new UpdateViewDescription('', [], {
+      displayMode: DisplayModeType.displayAsMessage,
+      renderMessage: `NetworkElement : "${nodeId}" has no capabilities.`,
+    }));
+    throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
+  }
+
+  const parser = new YangParser(
+    nodeId,
+    availableCapabilities.reduce((acc, cur) => {
+      acc[cur.capability] = cur.version;
+      return acc;
+    }, {} as { [key: string]: string }),
+    unavailableCapabilities || undefined,
+    importOnlyModules || undefined,
+  );
+
+  for (let i = 0; i < availableCapabilities.length; ++i) {
+    const capRaw = availableCapabilities[i];
+    try {
+      await parser.addCapability(capRaw.capability, capRaw.version);
+    } catch (err) {
+      console.error(`Error in ${capRaw.capability} ${capRaw.version}`, err);
+    }
+  }
+
+  parser.postProcess();
+
+  dispatch(new SetCollectingSelectionData(false));
+
+  if (process.env.NODE_ENV === 'development' ) {
+    console.log(parser, parser.modules, parser.views);
+  }
+
+  return dispatch(new UpdateDeviceDescription(nodeId, parser.modules, parser.views));
+};
+
+export const postProcessDisplaySpecificationActionCreator = (vPath: string, viewData: any, displaySpecification: DisplaySpecification) => async (dispatch: Dispatch, _getState: () => IApplicationStoreState) => {
+  
+  if (displaySpecification.displayMode === DisplayModeType.displayAsObject) {
+    displaySpecification = {
+      ...displaySpecification,
+      viewSpecification: await filterViewElements(vPath, viewData, displaySpecification.viewSpecification),
+    };  
+  }
+
+  dispatch(new UpdateViewDescription(vPath, viewData, displaySpecification));
+};
+
+export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+  const { configuration: { deviceDescription: { nodeId, modules, views } } } = getState();
+  let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
+
+  let inputViewSpecification: ViewSpecification | undefined = undefined;
+  let outputViewSpecification: ViewSpecification | undefined = undefined;
+
+  let viewSpecification: ViewSpecification = views[0];
+  let viewElement: ViewElement;
+
+  let dataMember: string;
+  let extractList: boolean = false;
+
+  let currentNS: string | null = null;
+  let defaultNS: string | null = null;
+
+  dispatch(new SetCollectingSelectionData(true));
+  try {
+    for (let ind = 0; ind < pathParts.length; ++ind) {
+      const [property, key] = pathParts[ind];
+      const namespaceInd = property && property.indexOf(':') || -1;
+      const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+      if (ind === 0) { defaultNS = namespace; }
+
+      viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
+      if (!viewElement) throw Error('Property [' + property + '] does not exist.');
+
+      if (viewElement.isList && !key) {
+        if (pathParts.length - 1 > ind) {
+          dispatch(new SetCollectingSelectionData(false));
+          throw new Error('No key for list [' + property + ']');
+        } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
+
+          // empty key is used for new element
+          if (viewElement && 'viewId' in viewElement) viewSpecification = views[+viewElement.viewId];
+          const data = Object.keys(viewSpecification.elements).reduce<{ [name: string]: any }>((acc, cur) => {
+            const elm = viewSpecification.elements[cur];
+            if (elm.default) {
+              acc[elm.id] = elm.default || '';
+            }
+            return acc;
+          }, {});
+
+          // create display specification
+          const ds: DisplaySpecification = {
+            displayMode: DisplayModeType.displayAsObject,
+            viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+            keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
+          };
+
+          // update display specification
+          return dispatch(postProcessDisplaySpecificationActionCreator(vPath, data, ds));
+        }
+        if (viewElement && isViewElementList(viewElement) && viewSpecification.parentView === '0') {
+          // check if there is a reference as key
+          const listSpecification = views[+viewElement.viewId];
+          const keyElement = viewElement.key && listSpecification.elements[viewElement.key];
+          if (keyElement && isViewElementReference(keyElement)) {
+            const refList = await getReferencedDataList(keyElement.referencePath, dataPath, modules, views);
+            if (!refList) {
+              throw new Error(`Could not find refList for [${keyElement.referencePath}].`);
+            }
+            if (!refList.key) {
+              throw new Error(`Key property not found for [${keyElement.referencePath}].`);
+            }
+            dispatch(new EnableValueSelector(refList.view, refList.data, refList.key, (refKey) => {
+              window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, '%2F')}]`)));
+            }));
+          } else {
+            // Found a list at root level of a module w/o a reference key.
+            dataPath += `?&fields=${encodeURIComponent(viewElement.id)}(${encodeURIComponent(viewElement.key || '')})`; 
+            const restResult = (await restService.getConfigData(dataPath));
+            if (restResult && restResult.status === 200 && restResult.data && restResult.data[viewElement.id] ) {
+              // spoof the not existing view here
+              const refData = restResult.data[viewElement.id];
+              if (!Array.isArray(refData) || !refData.length) {
+                throw new Error('Found a list at root level of a module containing no keys.');
+              }
+              if (refData.length > 1) {
+                const refView : ViewSpecification  = {
+                  id: '-1',
+                  canEdit: false,
+                  config: false,
+                  language: 'en-US',
+                  elements: {
+                    [viewElement.key!] : { 
+                      uiType: 'string',
+                      config: false,
+                      id: viewElement.key,
+                      label: viewElement.key,
+                      isList: true,
+                    } as ViewElementString,
+                  },
+                };
+                dispatch(new EnableValueSelector(refView, refData, viewElement.key!, (refKey) => {
+                  window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, '%2F')}]`))); 
+                }));
+              } else {
+                window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refData[0]?.id.replace(/\//ig, '%2F')}]`))); 
+              }
+            } else {
+              throw new Error('Found a list at root level of a module and could not determine the keys.');
+            }
+            dispatch(new SetCollectingSelectionData(false));
+          }
+          return;
+        }
+        extractList = true;
+      } else {
+        // normal case & replaces unicode %2C if present
+        dataPath += `/${property}${key ? `=${key.replace(/\%2C/g, ',').replace(/\//ig, '%2F')}` : ''}`;
+
+        // in case of the root element the required namespace will be added later,
+        // while extracting the data
+        dataMember = namespace === defaultNS
+          ? viewElement.label
+          : `${namespace}:${viewElement.label}`;
+        extractList = false;
+      }
+
+      if (viewElement && 'viewId' in viewElement) {
+        viewSpecification = views[+viewElement.viewId];
+      } else if (viewElement.uiType === 'rpc') {
+        viewSpecification = views[+(viewElement.inputViewId || 0)];
+
+        // create new instance & flaten
+        inputViewSpecification = viewElement.inputViewId != null && {
+          ...views[+(viewElement.inputViewId || 0)],
+          elements: flattenViewElements(defaultNS, '', views[+(viewElement.inputViewId || 0)].elements, views, viewElement.label),
+        } || undefined;
+        outputViewSpecification = viewElement.outputViewId != null && {
+          ...views[+(viewElement.outputViewId || 0)],
+          elements: flattenViewElements(defaultNS, '', views[+(viewElement.outputViewId || 0)].elements, views, viewElement.label),
+        } || undefined;
+
+      }
+    }
+
+    let data: any = {};
+    // do not get any data from netconf if there is no view specified || this is the root element [0] || this is an rpc
+    if (viewSpecification && !(viewSpecification.id === '0' || viewElement!.uiType === 'rpc')) {
+      const restResult = (await restService.getConfigData(dataPath));
+      if (!restResult.data) {
+        // special case: if this is a list without any response
+        if (extractList && restResult.status === 404) {
+          if (!isViewElementList(viewElement!)) {
+            throw new Error(`vPath: [${vPath}]. ViewElement has no key.`);
+          }
+          // create display specification
+          const ds: DisplaySpecification = {
+            displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
+            viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+            keyProperty: viewElement.key,
+          };
+
+          // update display specification
+          return dispatch(postProcessDisplaySpecificationActionCreator(vPath, [], ds));
+        }
+        throw new Error(`Did not get response from Server. Status: [${restResult.status}]`);
+      } else if (checkResponseCode(restResult)) {
+        const message = restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
+        throw new Error(`Server Error. Status: [${restResult.status}]\n${message}`);
+      } else {
+        // https://tools.ietf.org/html/rfc7951#section-4 the root element may contain a namespace or not !  
+        data = restResult.data[`${defaultNS}:${dataMember!}`];
+        if (data === undefined) {
+          data = restResult.data[dataMember!]; // extract dataMember w/o namespace
+        }
+      }
+
+      // extract the first element list[key]
+      data = data instanceof Array
+        ? data[0]
+        : data;
+
+      // extract the list -> key: list
+      data = extractList
+        ? data[viewElement!.id] || data[viewElement!.label] || [] // if the list is empty, it does not exist
+        : data;
+
+    } else if (viewElement! && viewElement!.uiType === 'rpc') {
+      // set data to defaults
+      data = {};
+      if (inputViewSpecification) {
+        Object.keys(inputViewSpecification.elements).forEach(key => {
+          const elm = inputViewSpecification && inputViewSpecification.elements[key];
+          if (elm && elm.default != undefined) {
+            data[elm.id] = elm.default;
+          }
+        });
+      }
+    }
+    
+    // create display specification
+    const ds: DisplaySpecification = viewElement! && viewElement!.uiType === 'rpc'
+      ? {
+        dataPath,
+        displayMode: DisplayModeType.displayAsRPC,
+        inputViewSpecification: inputViewSpecification && resolveViewDescription(defaultNS, vPath, inputViewSpecification),
+        outputViewSpecification: outputViewSpecification && resolveViewDescription(defaultNS, vPath, outputViewSpecification),
+      }
+      : {
+        dataPath,
+        displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
+        viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+        keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
+        
+        // eslint-disable-next-line max-len
+        apidocPath:  isViewElementList(viewElement!) &&  `/apidoc/explorer/index.html?urls.primaryName=$$$standard$$$#/mounted%20${nodeId}%20${viewElement!.module || 'MODULE_NOT_DEFINED'}/$$$action$$$_${dataPath.replace(/^\//, '').replace(/[\/=\-\:]/g, '_')}_${viewElement! != null ? `${viewElement.id.replace(/[\/=\-\:]/g, '_')}_` : '' }` || undefined,
+      };
+
+    // update display specification
+    return dispatch(postProcessDisplaySpecificationActionCreator(vPath, data, ds));
+    // https://server.com/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]
+    // https://server.com/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]/lp
+  } catch (error) {
+    history.back();
+    dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not process ${dataPath}` }));
+    dispatch(new SetCollectingSelectionData(false));
+  } finally {
+    return;
+  }
+};
+
+export const updateDataActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+  const { configuration: { deviceDescription: { nodeId, views } } } = getState();
+  let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
+  let viewSpecification: ViewSpecification = views[0];
+  let viewElement: ViewElement;
+  let dataMember: string;
+  let embedList: boolean = false;
+  let isNew: string | false = false;
+
+  let currentNS: string | null = null;
+  let defaultNS: string | null = null;
+
+  dispatch(new SetCollectingSelectionData(true));
+  try {
+    for (let ind = 0; ind < pathParts.length; ++ind) {
+      let [property, key] = pathParts[ind];
+      const namespaceInd = property && property.indexOf(':') || -1;
+      const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+      if (ind === 0) { defaultNS = namespace; }
+      viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
+      if (!viewElement) throw Error('Property [' + property + '] does not exist.');
+
+      if (isViewElementList(viewElement) && !key) {
+        embedList = true;
+        if (viewElement && viewElement.isList && viewSpecification.parentView === '0') {
+          throw new Error('Found a list at root level of a module w/o a refenrece key.');
+        }
+        if (pathParts.length - 1 > ind) {
+          dispatch(new SetCollectingSelectionData(false));
+          throw new Error('No key for list [' + property + ']');
+        } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
+          // handle new element with any number of arguments
+          let keyList = viewElement.key?.split(' ');
+          let dataPathParam = keyList?.map(id => data[id]).join(',');
+          key = viewElement.key && String(dataPathParam) || '';
+          isNew = key;
+          if (!key) {
+            dispatch(new SetCollectingSelectionData(false));
+            throw new Error('No value for key [' + viewElement.key + '] in list [' + property + ']');
+          }
+        }
+      }
+
+      dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
+      dataMember = viewElement.label;
+      embedList = false;
+
+      if (viewElement && 'viewId' in viewElement) {
+        viewSpecification = views[+viewElement.viewId];
+      }
+    }
+
+    // remove read-only elements
+    const removeReadOnlyElements = (pViewSpecification: ViewSpecification, isList: boolean, pData: any) => {
+      if (isList) {
+        return pData.map((elm : any) => removeReadOnlyElements(pViewSpecification, false, elm));
+      } else {
+        return Object.keys(pData).reduce<{ [key: string]: any }>((acc, cur)=>{
+          const [nsOrName, name] = cur.split(':', 1);
+          const element = pViewSpecification.elements[cur] || pViewSpecification.elements[nsOrName] || pViewSpecification.elements[name];
+          if (!element && process.env.NODE_ENV === 'development' ) {
+            throw new Error('removeReadOnlyElements: Could not determine elment for data.');
+          }
+          if (element && element.config) {
+            if (element.uiType === 'object') {
+              const view = views[+element.viewId];
+              if (!view) {
+                throw new Error('removeReadOnlyElements: Internal Error could not determine viewId: ' + element.viewId);
+              }
+              acc[cur] = removeReadOnlyElements(view, element.isList != null && element.isList, pData[cur]);
+            } else {
+              acc[cur] = pData[cur];
+            }
+          }
+          return acc;
+        }, {});
+      }
+    };
+    data = removeReadOnlyElements(viewSpecification, embedList, data);
+
+
+    // embed the list -> key: list
+    data = embedList
+      ? { [viewElement!.label]: data }
+      : data;
+
+    // embed the first element list[key]
+    data = isNew
+      ? [data]
+      : data;
+
+    // do not extract root member (0)
+    if (viewSpecification && viewSpecification.id !== '0') {
+      const updateResult = await restService.setConfigData(dataPath, { [`${currentNS}:${dataMember!}`]: data }); // addDataMember using currentNS
+      if (checkResponseCode(updateResult)) {
+        const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
+        throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
+      }
+    }
+
+    if (isNew) {
+      return dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i, `[${isNew}]`)}`)); // navigate to new element
+    }
+
+    // create display specification
+    const ds: DisplaySpecification = {
+      displayMode: embedList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
+      viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+      keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
+    };
+
+    // update display specification
+    return dispatch(new UpdateViewDescription(vPath, data, ds));
+  } catch (error) {
+    history.back();
+    dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not change ${dataPath}` }));
+
+  } finally {
+    dispatch(new SetCollectingSelectionData(false));
+    return;
+  }
+};
+
+export const removeElementActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+  const { configuration: { deviceDescription: { nodeId, views } } } = getState();
+  let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
+  let viewSpecification: ViewSpecification = views[0];
+  let viewElement: ViewElement;
+
+  let currentNS: string | null = null;
+  
+  dispatch(new SetCollectingSelectionData(true));
+  try {
+    for (let ind = 0; ind < pathParts.length; ++ind) {
+      let [property, key] = pathParts[ind];
+      const namespaceInd = property && property.indexOf(':') || -1;
+      const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+      viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
+      if (!viewElement) throw Error('Property [' + property + '] does not exist.');
+
+      if (isViewElementList(viewElement) && !key) {
+        if (viewElement && viewElement.isList && viewSpecification.parentView === '0') {
+          throw new Error('Found a list at root level of a module w/o a reference key.');
+        }
+        if (pathParts.length - 1 > ind) {
+          dispatch(new SetCollectingSelectionData(false));
+          throw new Error('No key for list [' + property + ']');
+        } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
+          // remove the whole table
+        }
+      }
+
+      dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
+
+      if (viewElement && 'viewId' in viewElement) {
+        viewSpecification = views[+viewElement.viewId];
+      } else if (viewElement.uiType === 'rpc') {
+        viewSpecification = views[+(viewElement.inputViewId || 0)];
+      }
+    }
+
+    const updateResult = await restService.removeConfigElement(dataPath);
+    if (checkResponseCode(updateResult)) {
+      const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
+      throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
+    }
+  } catch (error) {
+    dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not remove ${dataPath}` }));
+  } finally {
+    dispatch(new SetCollectingSelectionData(false));
+  }
+};
+
+export const executeRpcActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+  const { configuration: { deviceDescription: { nodeId, views } } } = getState();
+  let dataPath = `/rests/operations/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
+  let viewSpecification: ViewSpecification = views[0];
+  let viewElement: ViewElement;
+  let dataMember: string;
+  let embedList: boolean = false;
+  let isNew: string | false = false;
+
+  let currentNS: string | null = null;
+  let defaultNS: string | null = null;
+
+  dispatch(new SetCollectingSelectionData(true));
+  try {
+    for (let ind = 0; ind < pathParts.length; ++ind) {
+      let [property, key] = pathParts[ind];
+      const namespaceInd = property && property.indexOf(':') || -1;
+      const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+      if (ind === 0) { defaultNS = namespace; }
+      viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
+      if (!viewElement) throw Error('Property [' + property + '] does not exist.');
+
+      if (isViewElementList(viewElement) && !key) {
+        embedList = true;
+      //   if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
+      //     throw new Error("Found a list at root level of a module w/o a reference key.");
+      //   }
+      //   if (pathParts.length - 1 > ind) {
+      //     dispatch(new SetCollectingSelectionData(false));
+      //     throw new Error("No key for list [" + property + "]");
+      //   } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+      //     // handle new element
+      //     key = viewElement.key && String(data[viewElement.key]) || "";
+      //     isNew = key;
+      //     if (!key) {
+      //       dispatch(new SetCollectingSelectionData(false));
+      //       throw new Error("No value for key [" + viewElement.key + "] in list [" + property + "]");
+      //     }
+      //   }
+      }
+
+      dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
+      dataMember = viewElement.label;
+      embedList = false;
+
+      if (viewElement && 'viewId' in viewElement) {
+        viewSpecification = views[+viewElement.viewId];
+      } else if (viewElement.uiType === 'rpc') {
+        viewSpecification = views[+(viewElement.inputViewId || 0)];
+      }
+    }
+
+    // re-inflate formerly flatten rpc data
+    data = data && Object.keys(data).reduce < { [name: string ]: any }>((acc, cur) => {
+      const innerPathParts = cur.split('.');
+      let pos = 0;
+      const updatePath = (obj: any, key: string) => {
+        obj[key] = (pos >= innerPathParts.length)
+          ? data[cur]
+          : updatePath(obj[key] || {}, innerPathParts[pos++]);
+        return obj;
+      };
+      updatePath(acc, innerPathParts[pos++]);
+      return acc;
+    }, {}) || null;
+
+    // embed the list -> key: list
+    data = embedList
+      ? { [viewElement!.label]: data }
+      : data;
+
+    // embed the first element list[key]
+    data = isNew
+      ? [data]
+      : data;
+
+    // do not post root member (0)
+    if ((viewSpecification && viewSpecification.id !== '0') || (dataMember! && !data)) {
+      const updateResult = await restService.executeRpc(dataPath, { [`${defaultNS}:input`]: data || {} });
+      if (checkResponseCode(updateResult)) {
+        const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
+        throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
+      }
+      dispatch(new UpdateOutputData(updateResult.data));
+    } else {
+      throw new Error('There is NO RPC specified.');
+    }
+
+
+    // // update display specification
+    // return
+  } catch (error) {
+    dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not change ${dataPath}` }));
+
+  } finally {
+    dispatch(new SetCollectingSelectionData(false));
+  }
+};
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/assets/icons/configurationAppIcon.svg b/sdnr/wt-odlux/odlux/apps/configurationApp/src/assets/icons/configurationAppIcon.svg
new file mode 100644
index 0000000..1b74cc4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/assets/icons/configurationAppIcon.svg
@@ -0,0 +1,20 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+

+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 142 140" >

+<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="scale(10,10)">

+

+

+	<path fill="#565656" d="M7.887,9.025 C7.799,8.449 7.569,7.92 7.229,7.475 L7.995,6.71 L7.307,6.023 L6.536,6.794 C6.093,6.467 5.566,6.245 4.994,6.161 L4.994,5.066 L4.021,5.066 L4.021,6.155 C3.444,6.232 2.913,6.452 2.461,6.777 L1.709,6.024 L1.021,6.712 L1.761,7.452 C1.411,7.901 1.175,8.437 1.087,9.024 L0.062,9.024 L0.062,9.025 L0.062,9.998 L1.08,9.998 C1.162,10.589 1.396,11.132 1.744,11.587 L1.02,12.31 L1.708,12.997 L2.437,12.268 C2.892,12.604 3.432,12.83 4.02,12.91 L4.02,13.958 L4.993,13.958 L4.993,12.904 C5.576,12.818 6.11,12.589 6.56,12.252 L7.306,12.999 L7.994,12.311 L7.248,11.564 C7.586,11.115 7.812,10.581 7.893,10 L8.952,10 L8.952,9.998 L8.952,9.026 L7.887,9.026 L7.887,9.025 Z M4.496,11.295 C3.512,11.295 2.715,10.497 2.715,9.512 C2.715,8.528 3.512,7.73 4.496,7.73 C5.481,7.73 6.28,8.528 6.28,9.512 C6.28,10.497 5.481,11.295 4.496,11.295 L4.496,11.295 Z" ></path>

+

+	<path fill="#C8D400" d="m 12.231 4.17 l 1.09 -0.281 l -0.252 -0.979 l -1.091 0.282 c -0.118 -0.24 -0.265 -0.47 -0.461 -0.672 c -0.192 -0.196 -0.415 -0.344 -0.647 -0.464 l 0.301 -1.079 l -0.973 -0.271 l -0.299 1.072 c -0.541 -0.043 -1.091 0.078 -1.566 0.382 l -0.76 -0.776 l -0.721 0.707 l 0.756 0.77 c -0.326 0.47 -0.469 1.024 -0.441 1.575 l -1.04 0.268 l 0.252 0.977 l 1.038 -0.268 c 0.117 0.243 0.266 0.475 0.465 0.678 c 0.203 0.208 0.439 0.362 0.686 0.485 l -0.289 1.039 l 0.971 0.271 l 0.293 -1.048 c 0.542 0.033 1.092 -0.1 1.563 -0.415 l 0.771 0.786 l 0.72 -0.707 l -0.776 -0.791 c 0.307 -0.465 0.439 -1.006 0.41 -1.541 l 0 0 z m -2.517 1.617 c -0.823 0 -1.491 -0.669 -1.491 -1.493 c 0 -0.822 0.668 -1.489 1.491 -1.489 c 0.822 0 1.49 0.667 1.49 1.489 c 0 0.824 -0.668 1.493 -1.49 1.493 l 0 0 z" ></path>

+

+</g>

+</svg> 
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/baseProps.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/baseProps.ts
new file mode 100644
index 0000000..7187c0a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/baseProps.ts
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ViewElement } from '../models/uiModels';
+
+export type BaseProps<TValue = string> = { 
+  value: ViewElement; 
+  inputValue: TValue; 
+  readOnly: boolean; 
+  disabled: boolean; 
+  onChange(newValue: TValue): void;
+  isKey?: boolean; 
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
new file mode 100644
index 0000000..b176e5d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
@@ -0,0 +1,101 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import InputAdornment from '@mui/material/InputAdornment';
+import Input, { InputProps } from '@mui/material/Input';
+import Tooltip from '@mui/material/Tooltip';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+import FormHelperText from '@mui/material/FormHelperText';
+
+import makeStyles from '@mui/styles/makeStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import { faAdjust } from '@fortawesome/free-solid-svg-icons/faAdjust';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import { ViewElementBase } from '../models/uiModels';
+
+const useStyles = makeStyles(() =>
+  createStyles({
+    iconDark: {
+      color: '#ff8800',
+    },
+    iconLight: {
+      color: 'orange',
+    },
+    padding: {
+      paddingLeft: 10,
+      paddingRight: 10,
+    },
+  }),
+);
+
+type IfWhenProps = InputProps & {
+  label: string;
+  element: ViewElementBase;
+  helperText: string;
+  error: boolean;
+  onChangeTooltipVisibility(value: boolean): void;
+};
+
+export const IfWhenTextInput = (props: IfWhenProps) => {
+
+  const { element, id, label, helperText: errorText, error, style, ...otherProps } = props;
+  const classes = useStyles();
+
+  const ifFeature = element.ifFeature
+    ? (
+      <Tooltip
+        title={element.ifFeature}
+        disableInteractive
+        onMouseMove={() => props.onChangeTooltipVisibility(false)}
+        onMouseOut={() => props.onChangeTooltipVisibility(true)}
+      >
+          <InputAdornment position="start">
+            <FontAwesomeIcon icon={faAdjust} className={classes.iconDark} />
+          </InputAdornment>
+        </Tooltip>
+    )
+    : null;
+
+  const whenFeature = element.when
+    ? (
+      <Tooltip
+        title={element.when}
+        disableInteractive
+        className={classes.padding}
+        onMouseMove={() => props.onChangeTooltipVisibility(false)}
+        onMouseOut={() => props.onChangeTooltipVisibility(true)}
+      >
+          <InputAdornment className={classes.padding} position="end">
+            <FontAwesomeIcon icon={faAdjust} className={classes.iconLight}/>
+          </InputAdornment>
+        </Tooltip>
+    ) 
+    : null;
+
+  return (
+    <FormControl variant="standard" error={error} style={style}>
+      <InputLabel htmlFor={id} >{label}</InputLabel>
+      <Input id={id} inputProps={{ 'aria-label': label + '-input' }} endAdornment={<div>{ifFeature}{whenFeature}</div>} {...otherProps}  />
+      <FormHelperText>{errorText}</FormHelperText>
+    </FormControl>
+  );
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
new file mode 100644
index 0000000..56fb93c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
@@ -0,0 +1,63 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+
+import MenuItem from '@mui/material/MenuItem';
+import FormHelperText from '@mui/material/FormHelperText';
+import Select from '@mui/material/Select';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+
+import { ViewElementBoolean } from '../models/uiModels';
+import { BaseProps } from './baseProps';
+
+type BooleanInputProps = BaseProps<boolean>;
+
+export const UiElementBoolean = (props: BooleanInputProps) => {
+
+  const element = props.value as ViewElementBoolean;
+
+  const value = String(props.inputValue).toLowerCase();
+  const mandatoryError = element.mandatory && value !== 'true' && value !== 'false';
+    
+  return (!props.readOnly || element.id != null
+    ? (<FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+            <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
+            <Select variant="standard"
+                aria-label={element.label + '-selection'}
+                required={!!element.mandatory}
+                error={mandatoryError}
+                onChange={(e) => { props.onChange(e.target.value === 'true'); }}
+                readOnly={props.readOnly}
+                disabled={props.disabled}
+                value={value}
+                inputProps={{
+                  name: element.id,
+                  id: `select-${element.id}`,
+                }}
+            >
+                <MenuItem value={'true'} aria-label="true">{element.trueValue || 'True'}</MenuItem>
+                <MenuItem value={'false'} aria-label="false">{element.falseValue || 'False'}</MenuItem>
+
+            </Select>
+            <FormHelperText>{mandatoryError ? 'Value is mandatory' : ''}</FormHelperText>
+        </FormControl>)
+    : null
+  );
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx
new file mode 100644
index 0000000..669ddff
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx
@@ -0,0 +1,209 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+import Chip from '@mui/material/Chip';
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import DialogActions from '@mui/material/DialogActions';
+import Button from '@mui/material/Button';
+
+import makeStyles from '@mui/styles/makeStyles';
+import AddIcon from '@mui/icons-material/Add';
+
+import { Theme } from '@mui/material/styles';
+import { ViewElement } from '../models/uiModels';
+
+import { BaseProps } from './baseProps';
+
+const useStyles = makeStyles((theme: Theme) => {
+  const light = theme.palette.mode === 'light';
+  const bottomLineColor = light ? 'rgba(0, 0, 0, 0.42)' : 'rgba(255, 255, 255, 0.7)';
+
+  return ({
+    root: {
+      display: 'flex',
+      justifyContent: 'left',
+      verticalAlign: 'bottom',
+      flexWrap: 'wrap',
+      listStyle: 'none',
+      margin: 0,
+      padding: 0,
+      paddingTop: theme.spacing(0.5),
+      marginTop: theme.spacing(1),
+    },
+    chip: {
+      margin: theme.spacing(0.5),
+    },
+    underline: {
+      '&:after': {
+        borderBottom: `2px solid ${theme.palette.primary.main}`,
+        left: 0,
+        bottom: 0,
+        // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
+        content: '""',
+        position: 'absolute',
+        right: 0,
+        transform: 'scaleX(0)',
+        transition: theme.transitions.create('transform', {
+          duration: theme.transitions.duration.shorter,
+          easing: theme.transitions.easing.easeOut,
+        }),
+        pointerEvents: 'none', // Transparent to the hover style.
+      },
+      '&.Mui-focused:after': {
+        transform: 'scaleX(1)',
+      },
+      '&.Mui-error:after': {
+        borderBottomColor: theme.palette.error.main,
+        transform: 'scaleX(1)', // error is always underlined in red
+      },
+      '&:before': {
+        borderBottom: `1px solid ${bottomLineColor}`,
+        left: 0,
+        bottom: 0,
+        // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
+        content: '"\\00a0"',
+        position: 'absolute',
+        right: 0,
+        transition: theme.transitions.create('border-bottom-color', {
+          duration: theme.transitions.duration.shorter,
+        }),
+        pointerEvents: 'none', // Transparent to the hover style.
+      },
+      '&:hover:not($disabled):before': {
+        borderBottom: `2px solid ${theme.palette.text.primary}`,
+        // Reset on touch devices, it doesn't add specificity
+        // eslint-disable-next-line @typescript-eslint/naming-convention
+        '@media (hover: none)': {
+          borderBottom: `1px solid ${bottomLineColor}`,
+        },
+      },
+      '&.Mui-disabled:before': {
+        borderBottomStyle: 'dotted',
+      },
+    },
+  });
+});
+
+type LeafListProps = BaseProps<any []> & {
+  getEditorForViewElement:  (uiElement: ViewElement) => (null | React.ComponentType<BaseProps<any>>);  
+};
+
+export const UiElementLeafList = (props: LeafListProps) => {
+  const { value: element, inputValue, onChange } = props;
+
+  const classes = useStyles();
+
+  const [open, setOpen] = React.useState(false);
+  const [editorValue, setEditorValue] = React.useState('');
+  const [editorValueIndex, setEditorValueIndex] = React.useState(-1);
+  
+  const handleClose = () => {
+    setOpen(false);
+  };
+
+  const onApplyButton = () => { 
+    if (editorValue != null && editorValue != '' && editorValueIndex < 0) {
+      props.onChange([
+        ...inputValue,
+        editorValue,
+      ]);
+    } else if (editorValue != null && editorValue != '') {
+      props.onChange([
+        ...inputValue.slice(0, editorValueIndex),
+        editorValue,
+        ...inputValue.slice(editorValueIndex + 1),
+      ]);
+    }
+    setOpen(false);
+  };
+
+  const onDelete = (index : number) => {
+    const newValue : any[] = [
+      ...inputValue.slice(0, index),
+      ...inputValue.slice(index + 1),
+    ];
+    onChange(newValue);
+  };
+
+  const ValueEditor = props.getEditorForViewElement(props.value); 
+
+  return (
+    <>
+      <FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+        <InputLabel htmlFor={`list-${element.id}`} shrink={!props.readOnly || !!(inputValue && inputValue.length)} >{element.label}</InputLabel>
+        <ul className={`${classes.root} ${classes.underline}`} id={`list-${element.id}`}>
+        { !props.readOnly ? <li>
+          <Chip
+            icon={<AddIcon />}
+            label={'Add'}
+            className={classes.chip}
+            size="small"
+            color="secondary"
+            onClick={ () => { 
+              setOpen(true); 
+              setEditorValue('');
+              setEditorValueIndex(-1);
+            } 
+            }
+          />
+        </li> : null }  
+        { inputValue.map((val, ind) => (
+          <li key={ind}>
+            <Chip
+              className={classes.chip}
+              size="small"
+              variant="outlined"
+              label={String(val)}
+              onDelete={ !props.readOnly ? () => { onDelete(ind); } : undefined }  
+              onClick={ !props.readOnly ? () => { 
+                setOpen(true); 
+                setEditorValue(val);
+                setEditorValueIndex(ind);
+              } : undefined
+              }   
+            />
+            </li>
+        ))
+        }
+        </ul>
+        {/* <FormHelperText>{ "Value is mandetory"}</FormHelperText> */}
+        </FormControl>
+        <Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
+          <DialogTitle id="form-dialog-title">{editorValueIndex < 0 ? 'Add new value' : 'Edit value' } </DialogTitle>
+          <DialogContent>
+            { ValueEditor && <ValueEditor 
+                inputValue={ editorValue }
+                value={{ ...element, isList: false }}
+                disabled={false}
+                readOnly={props.readOnly}
+                onChange={ setEditorValue }
+            /> || null }
+          </DialogContent>
+          <DialogActions>
+            <Button color="inherit" onClick={ handleClose }> Cancel </Button>
+            <Button disabled={editorValue == null || editorValue === '' } onClick={ onApplyButton } color="secondary"> {editorValueIndex < 0 ? 'Add' : 'Apply'} </Button>
+          </DialogActions>
+        </Dialog>
+      </>
+  );
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementNumber.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
new file mode 100644
index 0000000..b034278
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
@@ -0,0 +1,70 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { ViewElementNumber } from "../models/uiModels";
+import { Tooltip, InputAdornment } from "@mui/material";
+import { BaseProps } from "./baseProps";
+import { IfWhenTextInput } from "./ifWhenTextInput";
+import { checkRange } from "../utilities/verifyer";
+
+type numberInputProps = BaseProps<number>;
+
+export const UiElementNumber = (props: numberInputProps) => {
+
+
+  const [error, setError] = React.useState(false);
+  const [helperText, setHelperText] = React.useState("");
+  const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+
+  const element = props.value as ViewElementNumber;
+
+  const verifyValue = (data: string) => {
+    const num = Number(data);
+    if (!isNaN(num)) {
+      const result = checkRange(element, num);
+      if (result.length > 0) {
+        setError(true);
+        setHelperText(result);
+      } else {
+        setError(false);
+        setHelperText("");
+      }
+    } else {
+      setError(true);
+      setHelperText("Input is not a number.");
+    }
+    props.onChange(num);
+  }
+
+  return (
+    <Tooltip disableInteractive title={isTooltipVisible ? element.description || '' : ''}>
+      <IfWhenTextInput element={element} onChangeTooltipVisibility={setTooltipVisibility}
+        spellCheck={false} autoFocus margin="dense"
+        id={element.id} label={element.label} type="text" value={props.inputValue}
+        style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+        onChange={(e) => { verifyValue(e.target.value) }}
+        error={error}
+        readOnly={props.readOnly}
+        disabled={props.disabled}
+        helperText={helperText}
+        startAdornment={element.units != null ? <InputAdornment position="start">{element.units}</InputAdornment> : undefined}
+      />
+    </Tooltip>
+  );
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementReference.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementReference.tsx
new file mode 100644
index 0000000..e3bb8f0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementReference.tsx
@@ -0,0 +1,67 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React, { useState } from 'react';
+import { Tooltip, Button, FormControl } from '@mui/material';
+
+import createStyles from '@mui/styles/createStyles';
+import makeStyles from '@mui/styles/makeStyles';
+
+import { ViewElement } from '../models/uiModels';
+
+const useStyles = makeStyles(() => createStyles({
+  button: {
+    'justifyContent': 'left',
+  },
+}));
+
+type UIElementReferenceProps = {
+  element: ViewElement;
+  disabled: boolean;
+  onOpenReference(element: ViewElement): void;
+};
+
+export const UIElementReference: React.FC<UIElementReferenceProps> = (props) => {
+  const { element } = props;
+  const [disabled, setDisabled] = useState(true);
+  const classes = useStyles();
+  return (
+    <FormControl
+      variant="standard"
+      key={element.id}
+      style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+      onMouseDown={(ev) => {
+        ev.preventDefault();
+        ev.stopPropagation();
+        if (ev.button === 1) {
+          setDisabled(!disabled);
+        }
+      }}>
+      <Tooltip disableInteractive title={element.description || element.path || ''}>
+        <Button
+          className={classes.button}
+          aria-label={element.label + '-button'}
+          color="secondary"
+          disabled={props.disabled && disabled}
+          onClick={() => {
+            props.onOpenReference(element);
+          }}  >{`${element.label}`}</Button>
+      </Tooltip>
+    </FormControl>
+  );
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementSelection.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
new file mode 100644
index 0000000..ebd04da
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
@@ -0,0 +1,69 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { BaseProps } from './baseProps';
+import { ViewElementSelection } from '../models/uiModels';
+import { FormControl, InputLabel, Select, FormHelperText, MenuItem, Tooltip } from '@mui/material';
+
+type selectionProps = BaseProps;
+
+export const UiElementSelection = (props: selectionProps) => {
+
+  const element = props.value as ViewElementSelection;
+
+  let error = '';
+  const value = String(props.inputValue);
+  if (element.mandatory && Boolean(!value)) {
+    error = 'Error';
+  }
+
+  return (props.readOnly || props.inputValue != null
+    ? (<FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+         <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
+            <Select variant="standard"
+                required={!!element.mandatory}
+                error={!!error}
+                onChange={(e) => { props.onChange(e.target.value as string); }}
+                readOnly={props.readOnly}
+                disabled={props.disabled}
+                value={value.toString()}
+                aria-label={element.label + '-selection'}
+                inputProps={{
+                  name: element.id,
+                  id: `select-${element.id}`,
+                }}
+            >
+                {element.options.map(option => (
+                    <MenuItem
+                        key={option.key}
+                        value={option.key}
+                        aria-label={option.key}>
+                        <Tooltip disableInteractive title={option.description || ''}>
+                            <div style={{ width: '100%' }}>
+                                {option.key}
+                            </div>
+                        </Tooltip>
+                    </MenuItem>
+                ))}
+            </Select>
+            <FormHelperText>{error}</FormHelperText>
+        </FormControl>)
+    : null
+  );
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementString.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementString.tsx
new file mode 100644
index 0000000..8381d99
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementString.tsx
@@ -0,0 +1,84 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from "react"
+import { Tooltip, TextField } from "@mui/material";
+import { ViewElementString } from "../models/uiModels";
+import { BaseProps } from "./baseProps";
+import { IfWhenTextInput } from "./ifWhenTextInput";
+import { checkRange, checkPattern } from "../utilities/verifyer";
+
+type stringEntryProps = BaseProps ;
+
+export const UiElementString = (props: stringEntryProps) => {
+
+    const [isError, setError] = React.useState(false);
+    const [helperText, setHelperText] = React.useState("");
+    const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+
+    const element = props.value as ViewElementString;
+
+    const verifyValues = (data: string) => {
+
+        if (data.trim().length > 0) {
+
+            let errorMessage = "";
+            const result = checkRange(element, data.length);
+
+            if (result.length > 0) {
+                errorMessage += result;
+            }
+
+            const patternResult = checkPattern(element.pattern, data)
+
+            if (patternResult.error) {
+                errorMessage += patternResult.error;
+            }
+
+            if (errorMessage.length > 0) {
+                setError(true);
+                setHelperText(errorMessage);
+            } else {
+                setError(false);
+                setHelperText("");
+            }
+        } else {
+            setError(false);
+            setHelperText("");
+        }
+
+
+        props.onChange(data);
+
+    }
+
+    return (
+        <Tooltip disableInteractive title={isTooltipVisible ? element.description || '' : ''}>
+            <IfWhenTextInput element={element} onChangeTooltipVisibility={setTooltipVisibility}
+                spellCheck={false} autoFocus margin="dense"
+                id={element.id} label={props?.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+                style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+                onChange={(e: any) => { verifyValues(e.target.value) }}
+                error={isError}
+                readOnly={props.readOnly}
+                disabled={props.disabled}
+                helperText={helperText}
+            />
+        </Tooltip>
+    );
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementUnion.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
new file mode 100644
index 0000000..8d232f5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
@@ -0,0 +1,91 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react'
+import { BaseProps } from './baseProps';
+import { Tooltip } from '@mui/material';
+import { IfWhenTextInput } from './ifWhenTextInput';
+import { ViewElementUnion, isViewElementString, isViewElementNumber, isViewElementObject, ViewElementNumber } from '../models/uiModels';
+import { checkRange, checkPattern } from '../utilities/verifyer';
+
+type UiElementUnionProps = { isKey: boolean } & BaseProps;
+
+export const UIElementUnion = (props: UiElementUnionProps) => {
+
+  const [isError, setError] = React.useState(false);
+  const [helperText, setHelperText] = React.useState("");
+  const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+
+  const element = props.value as ViewElementUnion;
+
+  const verifyValues = (data: string) => {
+
+    let foundObjectElements = 0;
+    let errorMessage = "";
+    let isPatternCorrect = null;
+
+    for (let i = 0; i < element.elements.length; i++) {
+      const unionElement = element.elements[i];
+
+      if (isViewElementNumber(unionElement)) {
+
+        errorMessage = checkRange(unionElement, Number(data));
+
+      } else if (isViewElementString(unionElement)) {
+        errorMessage += checkRange(unionElement, data.length);
+        isPatternCorrect = checkPattern(unionElement.pattern, data).isValid;
+
+
+      } else if (isViewElementObject(unionElement)) {
+        foundObjectElements++;
+      }
+
+      if (isPatternCorrect || errorMessage.length === 0) {
+        break;
+      }
+    }
+
+    if (errorMessage.length > 0 || isPatternCorrect !== null && !isPatternCorrect) {
+      setError(true);
+      setHelperText("Input is wrong.");
+    } else {
+      setError(false);
+      setHelperText("");
+    }
+
+    if (foundObjectElements > 0 && foundObjectElements != element.elements.length) {
+      throw new Error(`The union element ${element.id} can't be changed.`);
+
+    } else {
+      props.onChange(data);
+    }
+  };
+
+  return <Tooltip disableInteractive title={isTooltipVisible ? element.description || '' : ''}>
+    <IfWhenTextInput element={element} onChangeTooltipVisibility={setTooltipVisibility}
+      spellCheck={false} autoFocus margin="dense"
+      id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+      onChange={(e: any) => { verifyValues(e.target.value) }}
+      error={isError}
+      style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+      readOnly={props.readOnly}
+      disabled={props.disabled}
+      helperText={helperText}
+    />
+  </Tooltip>;
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
new file mode 100644
index 0000000..9cbd916
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IConnectedNetworkElementsState, connectedNetworkElementsActionHandler } from './connectedNetworkElementsHandler';
+import { IDeviceDescriptionState, deviceDescriptionHandler } from './deviceDescriptionHandler';
+import { IViewDescriptionState, viewDescriptionHandler } from './viewDescriptionHandler';
+import { IValueSelectorState, valueSelectorHandler } from './valueSelectorHandler';
+
+interface IConfigurationAppStoreState {
+  connectedNetworkElements: IConnectedNetworkElementsState; // used for ne selection
+  deviceDescription: IDeviceDescriptionState;               // contains ui and device descriptions
+  viewDescription: IViewDescriptionState;                   // contains current ui description
+  valueSelector: IValueSelectorState;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    configuration: IConfigurationAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  connectedNetworkElements: connectedNetworkElementsActionHandler,
+  deviceDescription: deviceDescriptionHandler,
+  viewDescription: viewDescriptionHandler,
+  valueSelector: valueSelectorHandler,
+};
+
+export const configurationAppRootHandler = combineActionHandler<IConfigurationAppStoreState>(actionHandlers);
+export default configurationAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
new file mode 100644
index 0000000..d2863dd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { restService } from '../services/restServices';
+
+export interface IConnectedNetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
+
+// create elastic search material data fetch handler
+const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', false, { status: 'Connected' });
+
+export const {
+  actionHandler: connectedNetworkElementsActionHandler,
+  createActions: createConnectedNetworkElementsActions,
+  createProperties: createConnectedNetworkElementsProperties,
+  reloadAction: connectedNetworkElementsReloadAction,
+
+  // set value action, to change a value
+} = createExternal<NetworkElementConnection>(connectedNetworkElementsSearchHandler, appState => appState.configuration.connectedNetworkElements, 
+  (ne) => {
+    if (!ne || !ne.id) return true;
+    const neUrl = restService.getNetworkElementUri(ne.id);
+    const policy = getAccessPolicyByUrl(neUrl);
+    return !(policy.GET && policy.POST);
+  },
+);
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
new file mode 100644
index 0000000..cd01b09
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Module } from '../models/yang';
+import { ViewSpecification } from '../models/uiModels';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { UpdateDeviceDescription } from '../actions/deviceActions';
+
+export interface IDeviceDescriptionState {
+  nodeId: string;
+  modules: {
+    [name: string]: Module;
+  };
+  views: ViewSpecification[];
+}
+
+const deviceDescriptionStateInit: IDeviceDescriptionState = {
+  nodeId: '',
+  modules: {},
+  views: [],
+};
+
+export const deviceDescriptionHandler: IActionHandler<IDeviceDescriptionState> = (state = deviceDescriptionStateInit, action) => {
+  if (action instanceof UpdateDeviceDescription) {
+    state = {
+      ...state,
+      nodeId: action.nodeId,
+      modules: action.modules,
+      views: action.views,
+    };
+  }
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
new file mode 100644
index 0000000..70d5eb2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { ViewSpecification } from '../models/uiModels';
+import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdateViewDescription, UpdateOutputData } from '../actions/deviceActions';
+
+export interface IValueSelectorState {
+  collectingData: boolean;
+  keyProperty: string | undefined;
+  listSpecification: ViewSpecification | null;
+  listData: any[];
+  onValueSelected: (value: any) => void;
+}
+
+const dummyFunc = () => { };
+const valueSelectorStateInit: IValueSelectorState = {
+  collectingData: false,
+  keyProperty: undefined,
+  listSpecification: null,
+  listData: [],
+  onValueSelected: dummyFunc,
+};
+
+export const valueSelectorHandler: IActionHandler<IValueSelectorState> = (state = valueSelectorStateInit, action) => {
+  if (action instanceof SetCollectingSelectionData) {
+    state = {
+      ...state,
+      collectingData: action.busy,
+    };
+  } else if (action instanceof EnableValueSelector) {
+    state = {
+      ...state,
+      collectingData: false,
+      keyProperty: action.keyProperty,
+      listSpecification: action.listSpecification,
+      onValueSelected: action.onValueSelected,
+      listData: action.listData,
+    };
+  } else if (action instanceof SetSelectedValue) {
+    if (state.keyProperty) {
+      state.onValueSelected(action.value[state.keyProperty]);
+    }
+    state = {
+      ...state,
+      collectingData: false,
+      keyProperty: undefined,
+      listSpecification: null,
+      onValueSelected: dummyFunc,
+      listData: [],
+    };
+  } else if (action instanceof UpdateDeviceDescription || action instanceof UpdateViewDescription || action instanceof UpdateOutputData) {
+    state = {
+      ...state,
+      collectingData: false,
+      keyProperty: undefined,
+      listSpecification: null,
+      onValueSelected: dummyFunc,
+      listData: [],
+    };
+  }
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
new file mode 100644
index 0000000..39b47be
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
@@ -0,0 +1,82 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { UpdateViewDescription, UpdateOutputData } from '../actions/deviceActions';
+import { ViewSpecification } from '../models/uiModels';
+
+export enum DisplayModeType {
+  doNotDisplay = 0,
+  displayAsObject = 1,
+  displayAsList = 2,
+  displayAsRPC = 3,
+  displayAsMessage = 4,
+}
+
+export type DisplaySpecification =  {
+  displayMode: DisplayModeType.doNotDisplay;
+} | {
+  displayMode: DisplayModeType.displayAsObject | DisplayModeType.displayAsList ;
+  viewSpecification: ViewSpecification;
+  keyProperty?: string;
+  apidocPath?: string;
+  dataPath?: string;
+} | {
+  displayMode: DisplayModeType.displayAsRPC;
+  inputViewSpecification?: ViewSpecification;
+  outputViewSpecification?: ViewSpecification;
+  dataPath?: string;
+} | {
+  displayMode: DisplayModeType.displayAsMessage;
+  renderMessage: string;
+};
+
+export interface IViewDescriptionState {
+  vPath: string | null;
+  displaySpecification: DisplaySpecification;
+  viewData: any;
+  outputData?: any;
+}
+
+const viewDescriptionStateInit: IViewDescriptionState = {
+  vPath: null,
+  displaySpecification: {
+    displayMode: DisplayModeType.doNotDisplay,
+  },
+  viewData: null,
+  outputData: undefined,
+};
+
+export const viewDescriptionHandler: IActionHandler<IViewDescriptionState> = (state = viewDescriptionStateInit, action) => {
+  if (action instanceof UpdateViewDescription) {
+    state = {
+      ...state,
+      vPath: action.vPath,
+      viewData: action.viewData,
+      outputData: undefined,
+      displaySpecification: action.displaySpecification,
+    };
+  } else if (action instanceof UpdateOutputData) {
+    state = {
+      ...state,
+      outputData: action.outputData,
+    };
+  }
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/index.html b/sdnr/wt-odlux/odlux/apps/configurationApp/src/index.html
new file mode 100644
index 0000000..4a0496b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/index.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css"> -->
+  <title>Configuration App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+      require(["app", "connectApp", "maintenanceApp", "configurationApp", "faultApp"], function (app, connectApp, maintenanceApp, configurationApp, faultApp) {
+        connectApp.register();
+        configurationApp.register();
+        maintenanceApp.register();
+        faultApp.register();
+       // app("./app.tsx").configureApplication({ authentication:"oauth",  enablePolicy:  true,});
+        app("./app.tsx").configureApplication({ authentication:"basic",  enablePolicy:  false,});
+        app("./app.tsx").runApplication();
+      });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/networkElementConnection.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/networkElementConnection.ts
new file mode 100644
index 0000000..e1ef1ea
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/networkElementConnection.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type NetworkElementConnection = {
+  id?: string;
+  nodeId: string;
+  host: string;
+  port: number;
+  username?: string;
+  password?: string;
+  isRequired?: boolean;
+  status?: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
+  coreModelCapability?: string;
+  deviceType?: string;
+  nodeDetails?: {
+    availableCapabilities: string[];
+    unavailableCapabilities: {
+      failureReason: string;
+      capability: string;
+    }[];
+  };
+};
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts
new file mode 100644
index 0000000..7d9e63c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts
@@ -0,0 +1,241 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import type { WhenAST } from '../yang/whenParser';
+
+export type ViewElementBase = {
+  'id': string;
+  'label': string;
+  'module': string;
+  'path': string;
+  'config': boolean;
+  'ifFeature'?: string;
+  'when'?: WhenAST;
+  'mandatory'?: boolean;
+  'description'?: string;
+  'isList'?: boolean;
+  'default'?: string;
+  'status'?: 'current' | 'deprecated' | 'obsolete';
+  'reference'?: string; // https://tools.ietf.org/html/rfc7950#section-7.21.4
+};
+
+// https://tools.ietf.org/html/rfc7950#section-9.8
+export type ViewElementBinary = ViewElementBase & {
+  'uiType': 'binary';
+  'length'?: Expression<YangRange>;  // number of octets
+};
+
+// https://tools.ietf.org/html/rfc7950#section-9.7.4
+export type ViewElementBits = ViewElementBase & {
+  'uiType': 'bits';
+  'flags': {
+    [name: string]: number | undefined;    // 0 - 4294967295
+  };
+};
+
+// https://tools.ietf.org/html/rfc7950#section-9
+export type ViewElementString = ViewElementBase & {
+  'uiType': 'string';
+  'pattern'?: Expression<RegExp>;
+  'length'?: Expression<YangRange>;
+  'invertMatch'?: true;
+};
+
+// special case derived from 
+export type ViewElementDate = ViewElementBase & {
+  'uiType': 'date';
+  'pattern'?: Expression<RegExp>;
+  'length'?: Expression<YangRange>;
+  'invertMatch'?: true;
+};
+
+// https://tools.ietf.org/html/rfc7950#section-9.3
+export type ViewElementNumber = ViewElementBase & {
+  'uiType': 'number';
+  'min': number;
+  'max': number;
+  'range'?: Expression<YangRange>;
+  'units'?: string;
+  'format'?: string;
+  'fDigits'?: number;
+};
+
+// https://tools.ietf.org/html/rfc7950#section-9.5
+export type ViewElementBoolean = ViewElementBase & {
+  'uiType': 'boolean';
+  'trueValue'?: string;
+  'falseValue'?: string;
+};
+
+// https://tools.ietf.org/html/rfc7950#section-9.6.4
+export type ViewElementSelection = ViewElementBase & {
+  'uiType': 'selection';
+  'multiSelect'?: boolean;
+  'options': {
+    'key': string;
+    'value': string;
+    'description'?: string;
+    'status'?: 'current' | 'deprecated' | 'obsolete';
+    'reference'?: string;
+  }[];
+};
+
+// is a list if isList is true ;-)
+export type ViewElementObject = ViewElementBase & {
+  'uiType': 'object';
+  'isList'?: false;
+  'viewId': string;
+};
+
+// Hint: read only lists do not need a key
+export type ViewElementList = (ViewElementBase & {
+  'uiType': 'object';
+  'isList': true;
+  'viewId': string;
+  'key'?: string;
+});
+
+export type ViewElementReference = ViewElementBase & {
+  'uiType': 'reference';
+  'referencePath': string;
+  'ref': (currentPath: string) => [ViewElement, string] | undefined;
+};
+
+export type ViewElementUnion = ViewElementBase & {
+  'uiType': 'union';
+  'elements': ViewElement[];
+};
+
+export type ViewElementChoiceCase = { id: string; label: string; description?: string; elements: { [name: string]: ViewElement }  };
+
+export type ViewElementChoice = ViewElementBase & {
+  'uiType': 'choice';
+  'cases': {
+    [name: string]: ViewElementChoiceCase;
+  };
+};
+
+// https://tools.ietf.org/html/rfc7950#section-7.14.1
+export type ViewElementRpc = ViewElementBase & {
+  'uiType': 'rpc';
+  'inputViewId'?: string;
+  'outputViewId'?: string;
+};
+
+export type ViewElementEmpty = ViewElementBase & {
+  'uiType': 'empty';
+};
+
+export type ViewElement =
+  | ViewElementEmpty
+  | ViewElementBits
+  | ViewElementBinary
+  | ViewElementString
+  | ViewElementDate
+  | ViewElementNumber
+  | ViewElementBoolean
+  | ViewElementObject
+  | ViewElementList
+  | ViewElementSelection
+  | ViewElementReference
+  | ViewElementUnion
+  | ViewElementChoice
+  | ViewElementRpc;
+
+export const isViewElementString = (viewElement: ViewElement): viewElement is ViewElementString => {
+  return viewElement && (viewElement.uiType === 'string' || viewElement.uiType === 'date');
+};
+
+export const isViewElementDate = (viewElement: ViewElement): viewElement is ViewElementDate => {
+  return viewElement && (viewElement.uiType === 'date');
+};
+
+export const isViewElementNumber = (viewElement: ViewElement): viewElement is ViewElementNumber => {
+  return viewElement && viewElement.uiType === 'number';
+};
+
+export const isViewElementBoolean = (viewElement: ViewElement): viewElement is ViewElementBoolean => {
+  return viewElement && viewElement.uiType === 'boolean';
+};
+
+export const isViewElementObject = (viewElement: ViewElement): viewElement is ViewElementObject => {
+  return viewElement && viewElement.uiType === 'object' && viewElement.isList === false;
+};
+
+export const isViewElementList = (viewElement: ViewElement): viewElement is ViewElementList => {
+  return viewElement && viewElement.uiType === 'object' && viewElement.isList === true;
+};
+
+export const isViewElementObjectOrList = (viewElement: ViewElement): viewElement is ViewElementObject | ViewElementList => {
+  return viewElement && viewElement.uiType === 'object';
+};
+
+export const isViewElementSelection = (viewElement: ViewElement): viewElement is ViewElementSelection => {
+  return viewElement && viewElement.uiType === 'selection';
+};
+
+export const isViewElementReference = (viewElement: ViewElement): viewElement is ViewElementReference => {
+  return viewElement && viewElement.uiType === 'reference';
+};
+
+export const isViewElementUnion = (viewElement: ViewElement): viewElement is ViewElementUnion => {
+  return viewElement && viewElement.uiType === 'union';
+};
+
+export const isViewElementChoice = (viewElement: ViewElement): viewElement is ViewElementChoice => {
+  return viewElement && viewElement.uiType === 'choice';
+};
+
+export const isViewElementRpc = (viewElement: ViewElement): viewElement is ViewElementRpc => {
+  return viewElement && viewElement.uiType === 'rpc';
+};
+
+export const isViewElementEmpty = (viewElement: ViewElement): viewElement is ViewElementRpc => {
+  return viewElement && viewElement.uiType === 'empty';
+};
+
+export const ResolveFunction = Symbol('IsResolved');
+
+export type ViewSpecification = {
+  id: string;
+  ns?: string;
+  name?: string;
+  title?: string;
+  parentView?: string;
+  language: string;
+  ifFeature?: string;
+  when?: WhenAST;
+  uses?: (string[]) & { [ResolveFunction]?: (parent: string) => void };
+  elements: { [name: string]: ViewElement };
+  config: boolean;
+  readonly canEdit: boolean;
+};
+
+export type YangRange = {
+  min: number;
+  max: number;
+};
+
+export type Expression<T> =
+  | T
+  | Operator<T>;
+
+export type Operator<T> = {
+  operation: 'AND' | 'OR';
+  arguments: Expression<T>[];
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/yang.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/yang.ts
new file mode 100644
index 0000000..e4e59fb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/yang.ts
@@ -0,0 +1,71 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ViewElement, ViewSpecification } from './uiModels';
+
+export enum ModuleState {
+  stable,
+  instable,
+  importOnly,
+  unavailable,
+}
+
+export type Token = {
+  name: string;
+  value: string;
+  start: number;
+  end: number;
+};
+
+export type Statement = {
+  key: string;
+  arg?: string;
+  sub?: Statement[];
+};
+
+export type Identity = {
+  id: string;
+  label: string;
+  base?: string;
+  description?: string;
+  reference?: string;
+  children?: Identity[];
+  values?: Identity[];
+};
+
+export type Revision = {
+  description?: string;
+  reference?: string;
+};
+
+export type Module = {
+  name: string;
+  namespace?: string;
+  prefix?: string;
+  state: ModuleState;
+  identities: { [name: string]: Identity };
+  revisions: { [version: string]: Revision };
+  imports: { [prefix: string]: string };
+  features: { [feature: string]: { description?: string } };
+  typedefs: { [type: string]: ViewElement };
+  augments: { [path: string]: ViewSpecification[] };
+  groupings: { [group: string]: ViewSpecification };
+  views: { [view: string]: ViewSpecification };
+  elements: { [view: string]: ViewElement };
+  executionOrder?: number;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/pluginConfiguration.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/pluginConfiguration.tsx
new file mode 100644
index 0000000..7dd2d6a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/pluginConfiguration.tsx
@@ -0,0 +1,145 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { configurationAppRootHandler } from './handlers/configurationAppRootHandler';
+import { NetworkElementSelector } from './views/networkElementSelector';
+
+import ConfigurationApplication from './views/configurationApplication';
+import { updateNodeIdAsyncActionCreator, updateViewActionAsyncCreator } from './actions/deviceActions';
+import { DisplayModeType } from './handlers/viewDescriptionHandler';
+import { ViewSpecification } from './models/uiModels';
+
+const appIcon = require('./assets/icons/configurationAppIcon.svg');  // select app icon
+
+let currentNodeId: string | null | undefined = undefined;
+let currentVirtualPath: string | null | undefined = undefined;
+let lastUrl: string | undefined = undefined;
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  updateNodeId: (nodeId: string) => dispatcher.dispatch(updateNodeIdAsyncActionCreator(nodeId)),
+  updateView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
+});
+
+// eslint-disable-next-line @typescript-eslint/naming-convention
+const ConfigurationApplicationRouteAdapter = connect(undefined, mapDispatch)((props: RouteComponentProps<{ nodeId?: string; 0: string }> & Connect<undefined, typeof mapDispatch>) => {
+  React.useEffect(() => {
+    return () => {
+      lastUrl = undefined;
+      currentNodeId = undefined;
+      currentVirtualPath = undefined;
+    };
+  }, []);
+  if (props.location.pathname !== lastUrl) {
+    // ensure the asynchronous update will only be called once per path
+    lastUrl = props.location.pathname;
+    window.setTimeout(async () => {
+
+      // check if the nodeId has changed
+      let enableDump = false;
+      if (currentNodeId !== props.match.params.nodeId) {
+        currentNodeId = props.match.params.nodeId || undefined;
+        if (currentNodeId && currentNodeId.endsWith('|dump')) {
+          enableDump = true;
+          currentNodeId = currentNodeId.replace(/\|dump$/i, '');
+        }
+        currentVirtualPath = null;
+        if (currentNodeId) {
+          await props.updateNodeId(currentNodeId);
+        }
+      }
+
+      if (currentVirtualPath !== props.match.params[0]) {
+        currentVirtualPath = props.match.params[0];
+        if (currentVirtualPath && currentVirtualPath.endsWith('|dump')) {
+          enableDump = true;
+          currentVirtualPath = currentVirtualPath.replace(/\|dump$/i, '');
+        }
+        await props.updateView(currentVirtualPath);
+      }
+
+      if (enableDump) {
+        const device = props.state.configuration.deviceDescription;
+        const ds = props.state.configuration.viewDescription.displaySpecification;
+
+        const createDump = (view: ViewSpecification | null, level: number = 0) => {
+          if (view === null) return 'Empty';
+          const indention = Array(level * 4).fill(' ').join('');
+          let result = '';
+
+          if (!view) debugger;
+          // result += `${indention}  [${view.canEdit ? 'rw' : 'ro'}] ${view.ns}:${view.name} ${ds.displayMode === DisplayModeType.displayAsList ? '[LIST]' : ''}\r\n`;
+          result += Object.keys(view.elements).reduce((acc, cur) => {
+            const elm = view.elements[cur];
+            acc += `${indention}  [${elm.uiType === 'rpc' ? 'x' : elm.config ? 'rw' : 'ro'}:${elm.id}] (${elm.module}:${elm.label}) {${elm.uiType}} ${elm.uiType === 'object' && elm.isList ? `as LIST with KEY [${elm.key}]` : ''}\r\n`;
+            // acc += `${indention}    +${elm.mandatory ? "mandatory" : "none"} - ${elm.path} \r\n`;
+            
+            switch (elm.uiType) {
+              case 'object':
+                acc += createDump(device.views[(elm as any).viewId], level + 1);
+                break;
+              default:
+            }
+            return acc;
+          }, '');
+          return `${result}`;
+        };
+
+        const dump = createDump(ds.displayMode === DisplayModeType.displayAsObject || ds.displayMode === DisplayModeType.displayAsList ? ds.viewSpecification : null, 0);
+        const element = document.createElement('a');
+        element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(dump));
+        element.setAttribute('download', currentNodeId + '.txt');
+
+        element.style.display = 'none';
+        document.body.appendChild(element);
+
+        element.click();
+
+        document.body.removeChild(element);
+      }
+
+    });
+  }
+  return (
+    <ConfigurationApplication />
+  );
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+  <Switch>
+    <Route path={`${props.match.url}/:nodeId/*`} component={ConfigurationApplicationRouteAdapter} />
+    <Route path={`${props.match.url}/:nodeId`} component={ConfigurationApplicationRouteAdapter} />
+    <Route path={`${props.match.url}`} component={NetworkElementSelector} />
+    <Redirect to={`${props.match.url}`} />
+  </Switch>
+));
+
+export function register() {
+  applicationManager.registerApplication({
+    name: 'configuration',
+    icon: appIcon,
+    rootComponent: App,
+    rootActionHandler: configurationAppRootHandler,
+    menuEntry: 'Configuration',
+  });
+}
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/services/restServices.ts
new file mode 100644
index 0000000..07e2635
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/services/restServices.ts
@@ -0,0 +1,164 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { requestRest, requestRestExt } from '../../../../framework/src/services/restService';
+import { convertPropertyNames, replaceHyphen } from '../../../../framework/src/utilities/yangHelper';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+
+type ImportOnlyResponse = {
+  'ietf-yang-library:yang-library': {
+    'module-set': {
+      'import-only-module': {
+        'name': string;
+        'revision': string;
+      }[];
+    }[];
+  };
+};
+
+
+type CapabilityResponse = {
+  'network-topology:node': {
+    'node-id': string;
+    'netconf-node-topology:available-capabilities': {
+      'available-capability': {
+        'capability-origin': string;
+        'capability': string;
+      }[];
+    };
+    'netconf-node-topology:unavailable-capabilities': {
+      'unavailable-capability': {
+        'capability': string;
+        'failure-reason': string;
+      }[];
+    };
+  }[];
+};
+
+type CapabilityAnswer = {
+  availableCapabilities: {
+    capabilityOrigin: string;
+    capability: string;
+    version: string;
+  }[] | null;
+  unavailableCapabilities: {
+    failureReason: string;
+    capability: string;
+    version: string;
+  }[] | null;
+  importOnlyModules: {
+    name: string;
+    revision: string;
+  }[] | null;
+};
+
+const capParser = /^\(.*\?revision=(\d{4}-\d{2}-\d{2})\)(\S+)$/i;
+
+class RestService {
+  public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
+
+  public async getImportOnlyModules(nodeId: string): Promise<{ name: string; revision: string }[]> {
+    const path = `${this.getNetworkElementUri(nodeId)}/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig&fields=module-set(import-only-module(name;revision))`;
+    const importOnlyResult = await requestRest<ImportOnlyResponse>(path, { method: 'GET' });
+    const importOnlyModules = importOnlyResult
+      ? importOnlyResult['ietf-yang-library:yang-library']['module-set'][0]['import-only-module']
+      : [];
+    return importOnlyModules;
+  }
+
+  public async getCapabilitiesByMountId(nodeId: string): Promise<CapabilityAnswer> {
+    const path = this.getNetworkElementUri(nodeId);
+    const capabilitiesResult = await requestRest<CapabilityResponse>(path, { method: 'GET' });
+    const availableCapabilities = capabilitiesResult && capabilitiesResult['network-topology:node'] && capabilitiesResult['network-topology:node'].length > 0 &&
+      (capabilitiesResult['network-topology:node'][0]['netconf-node-topology:available-capabilities'] &&
+        capabilitiesResult['network-topology:node'][0]['netconf-node-topology:available-capabilities']['available-capability'] &&
+        capabilitiesResult['network-topology:node'][0]['netconf-node-topology:available-capabilities']['available-capability'].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [])
+        .map(cap => {
+          const capMatch = cap && capParser.exec(cap.capability);
+          return capMatch ? {
+            capabilityOrigin: cap.capabilityOrigin,
+            capability: capMatch && capMatch[2] || '',
+            version: capMatch && capMatch[1] || '',
+          } : null ;
+        }).filter((cap) => cap != null) || [] as any;
+
+    const unavailableCapabilities = capabilitiesResult && capabilitiesResult['network-topology:node'] && capabilitiesResult['network-topology:node'].length > 0 &&
+      (capabilitiesResult['network-topology:node'][0]['netconf-node-topology:unavailable-capabilities'] &&
+      capabilitiesResult['network-topology:node'][0]['netconf-node-topology:unavailable-capabilities']['unavailable-capability'] &&
+      capabilitiesResult['network-topology:node'][0]['netconf-node-topology:unavailable-capabilities']['unavailable-capability'].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [])
+        .map(cap => {
+          const capMatch = cap && capParser.exec(cap.capability);
+          return capMatch ? {
+            failureReason: cap.failureReason,
+            capability: capMatch && capMatch[2] || '',
+            version: capMatch && capMatch[1] || '',
+          } : null ;
+        }).filter((cap) => cap != null) || [] as any;
+
+    const importOnlyModules = availableCapabilities && availableCapabilities.findIndex((ac: { capability: string }) => ac.capability && ac.capability.toLowerCase() === 'ietf-yang-library') > -1
+      ? await this.getImportOnlyModules(nodeId)
+      : null;
+
+    return { availableCapabilities, unavailableCapabilities, importOnlyModules };
+  }
+
+  public async getMountedNetworkElementByMountId(nodeId: string): Promise<NetworkElementConnection | null> {
+    // const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId;
+    // const connectedNetworkElement = await requestRest<NetworkElementConnection>(path, { method: "GET" });
+    // return connectedNetworkElement || null;
+
+    const path = '/rests/operations/data-provider:read-network-element-connection-list';
+    const body = { 'data-provider:input': { 'filter': [{ 'property': 'node-id', 'filtervalue': nodeId }], 'sortorder': [], 'pagination': { 'size': 1, 'page': 1 } } };
+    const networkElementResult = await requestRest<{ 'data-provider:output': { data: NetworkElementConnection[] } }>(path, { method: 'POST', body: JSON.stringify(body) });
+    return networkElementResult && networkElementResult['data-provider:output'] && networkElementResult['data-provider:output'].data &&
+      networkElementResult['data-provider:output'].data.map(obj => convertPropertyNames(obj, replaceHyphen))[0] || null;
+  }
+
+  /** Reads the config data by restconf path.
+  * @param path The restconf path to be used for read.
+  * @returns The data.
+  */
+  public getConfigData(path: string) {
+    return requestRestExt<{ [key: string]: any }>(path, { method: 'GET' });
+  }
+
+  /** Updates or creates the config data by restconf path using data.
+   * @param path The restconf path to identify the note to update.
+   * @param data The data to be updated.
+   * @returns The written data.
+   */
+  public setConfigData(path: string, data: any) {
+    return requestRestExt<{ [key: string]: any }>(path, { method: 'PUT', body: JSON.stringify(data) });
+  }
+
+  public executeRpc(path: string, data: any) {
+    return requestRestExt<{ [key: string]: any }>(path, { method: 'POST', body: JSON.stringify(data) });
+  }
+
+  /** Removes the element by restconf path.
+  * @param path The restconf path to identify the note to update.
+  * @returns The restconf result.
+  */
+  public removeConfigElement(path: string) {
+    return requestRestExt<{ [key: string]: any }>(path, { method: 'DELETE' });
+  }
+}
+
+export const restService = new RestService();
+export default restService;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/services/yangService.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/services/yangService.ts
new file mode 100644
index 0000000..bbd051a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/services/yangService.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+const cache: { [path: string]: string } = { };
+const getCapability = async (capability: string, nodeId: string, version?: string) => {
+  const url = `/yang-schema/${capability}${version ? `/${version}` : ''}?node=${nodeId}`;
+
+  const cacheHit = cache[url];
+  if (cacheHit) return cacheHit;
+
+  const res = await fetch(url);
+  const yangFile = res.ok && (await res.text());
+  if (yangFile !== false && yangFile !== null) {
+    cache[url] = yangFile;
+  }
+  return yangFile;
+};
+
+export const yangService = {
+  getCapability,
+};
+export default yangService;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/utilities/verifyer.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/utilities/verifyer.ts
new file mode 100644
index 0000000..9dd1203
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/utilities/verifyer.ts
@@ -0,0 +1,261 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { YangRange, Operator, ViewElementNumber, ViewElementString, isViewElementNumber, isViewElementString } from '../models/uiModels';
+
+export type validated = { isValid: boolean; error?: string };
+
+export type validatedRange = { isValid: boolean; error?: string };
+
+const rangeErrorStartNumber = 'The entered number must be';
+const rangeErrorInnerMinTextNumber = 'greater or equals than';
+const rangeErrorInnerMaxTextNumber = 'less or equals than';
+const rangeErrorEndTextNumber = '.';
+
+const rangeErrorStartString = 'The entered text must have';
+const rangeErrorInnerMinTextString = 'no more than';
+const rangeErrorInnerMaxTextString = 'less than';
+const rangeErrorEndTextString = ' characters.';
+
+let errorMessageStart = '';
+let errorMessageMiddleMinPart = '';
+let errorMessageMiddleMaxPart = '';
+let errorMessageEnd = '';
+
+const isYangRange = (val: YangRange | Operator<YangRange>): val is YangRange => (val as YangRange).min !== undefined;
+  
+const isYangOperator = (val: YangRange | Operator<YangRange>): val is Operator<YangRange> => (val as Operator<YangRange>).operation !== undefined;
+
+const isRegExp = (val: RegExp | Operator<RegExp>): val is RegExp => (val as RegExp).source !== undefined;
+
+const isRegExpOperator = (val: RegExp | Operator<RegExp>): val is Operator<RegExp> => (val as Operator<RegExp>).operation !== undefined;
+
+const getRangeErrorMessagesRecursively = (value: Operator<YangRange>, data: number): string[] => {
+  let currentIteration: string[] = [];
+  
+  // iterate over all elements
+  for (let i = 0; i < value.arguments.length; i++) {
+    const element = value.arguments[i];
+  
+    let min = undefined;
+    let max = undefined;
+  
+    let isNumberCorrect = false;
+  
+    if (isYangRange(element)) {
+  
+      //check found min values
+      if (!isNaN(element.min)) {
+        if (data < element.min) {
+          min = element.min;
+        } else {
+          isNumberCorrect = true;
+        }
+      }
+  
+      // check found max values
+      if (!isNaN(element.max)) {
+        if (data > element.max) {
+          max = element.max;
+        } else {
+          isNumberCorrect = true;
+        }
+      }
+  
+      // construct error messages
+      if (min != undefined) {
+        currentIteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMinPart} ${min}`);
+      } else if (max != undefined) {
+        currentIteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMaxPart} ${max}`);
+  
+      }
+  
+    } else if (isYangOperator(element)) {
+  
+      //get error_message from expression
+      const result = getRangeErrorMessagesRecursively(element, data);
+      if (result.length === 0) {
+        isNumberCorrect = true;
+      }
+      currentIteration = currentIteration.concat(result);
+    }
+  
+    // if its an OR operation, the number has been checked and min/max are empty (thus not violated)
+    // delete everything found (because at least one found is correct, therefore all are correct) and break from loop
+    if (min === undefined && max === undefined && isNumberCorrect && value.operation === 'OR') {
+  
+      currentIteration.splice(0, currentIteration.length);
+      break;
+    }
+  }
+  
+  return currentIteration;
+};
+
+const createStartMessage = (element: string) => {
+  //remove leading or or and from text
+  if (element.startsWith('and')) {
+    element = element.replace('and', '');
+  } else if (element.startsWith('or')) {
+    element = element.replace('or', '');
+  }
+  return `${errorMessageStart} ${element}`;
+};
+  
+const getRangeErrorMessages = (value: Operator<YangRange>, data: number): string => {
+
+  const currentIteration = getRangeErrorMessagesRecursively(value, data);
+  
+  // build complete error message from found parts
+  let errorMessage = '';
+  if (currentIteration.length > 1) {
+  
+    currentIteration.forEach((element, index) => {
+      if (index === 0) {
+        errorMessage = createStartMessage(element);
+      } else if (index === currentIteration.length - 1) {
+        errorMessage += ` ${element}${errorMessageEnd}`;
+      } else {
+        errorMessage += `, ${element}`;
+      }
+    });
+  } else if (currentIteration.length == 1) {
+    errorMessage = `${createStartMessage(currentIteration[0])}${errorMessageEnd}`;
+  }
+  
+  return errorMessage;
+};
+
+export const checkRange = (element: ViewElementNumber | ViewElementString, data: number): string => {
+  const number = data;
+
+  let expression = undefined;
+
+  if (isViewElementString(element)) {
+    expression = element.length;
+
+    errorMessageStart = rangeErrorStartString;
+    errorMessageMiddleMaxPart = rangeErrorInnerMaxTextString;
+    errorMessageMiddleMinPart = rangeErrorInnerMinTextString;
+    errorMessageEnd = rangeErrorEndTextString;
+
+  } else if (isViewElementNumber(element)) {
+    expression = element.range;
+
+    errorMessageStart = rangeErrorStartNumber;
+    errorMessageMiddleMaxPart = rangeErrorInnerMaxTextNumber;
+    errorMessageMiddleMinPart = rangeErrorInnerMinTextNumber;
+    errorMessageEnd = rangeErrorEndTextNumber;
+  }
+
+  if (expression) {
+    if (isYangOperator(expression)) {
+
+      const errorMessage = getRangeErrorMessages(expression, data);
+      return errorMessage;
+
+    } else
+    if (isYangRange(expression)) {
+
+      if (!isNaN(expression.min)) {
+        if (number < expression.min) {
+          return `${errorMessageStart} ${errorMessageMiddleMinPart} ${expression.min}${errorMessageEnd}`;
+        }
+      }
+
+      if (!isNaN(expression.max)) {
+        if (number > expression.max) {
+          return `${errorMessageStart} ${errorMessageMiddleMaxPart} ${expression.max}${errorMessageEnd}`;
+        }
+      }
+    }
+  }
+
+  return '';
+};
+
+const getRegexRecursively = (value: Operator<RegExp>, data: string): boolean[] => {
+  let currentItteration: boolean[] = [];
+  for (let i = 0; i < value.arguments.length; i++) {
+    const element = value.arguments[i];
+    if (isRegExp(element)) {
+      // if regex is found, add it to list
+      currentItteration.push(element.test(data));
+    } else if (isRegExpOperator(element)) {
+      //if RegexExpression is found, try to get regex from it
+      currentItteration = currentItteration.concat(getRegexRecursively(element, data));
+    }
+  }
+  
+  if (value.operation === 'OR') {
+    // if one is true, all are true, all found items can be discarded
+    let result = currentItteration.find(element => element);
+    if (result) {
+      return [];
+    }
+  }
+  return currentItteration;
+};
+  
+const isPatternValid = (value: Operator<RegExp>, data: string): boolean => {
+  // get all regex
+  const result = getRegexRecursively(value, data);
+  
+  if (value.operation === 'AND') {
+    // if AND operation is executed...
+    // no element can be false
+    const check = result.find(element => element !== true);
+    if (check)
+      return false;
+    else
+      return true;
+  } else {
+    // if OR operation is executed...
+    // ... just one element must be true
+    const check = result.find(element => element === true);
+    if (check)
+      return true;
+    else
+      return false;
+  
+  }
+};
+
+export const checkPattern = (expression: RegExp | Operator<RegExp> | undefined, data: string): validated => {
+
+  if (expression) {
+    if (isRegExp(expression)) {
+      const isValid = expression.test(data);
+      if (!isValid)
+        return { isValid: isValid, error: 'The input is in a wrong format.' };
+
+    } else if (isRegExpOperator(expression)) {
+      const result = isPatternValid(expression, data);
+
+      if (!result) {
+        return { isValid: false, error: 'The input is in a wrong format.' };
+      }
+    }
+  }
+
+  return { isValid: true };
+};
+
+
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/utilities/viewEngineHelper.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/utilities/viewEngineHelper.ts
new file mode 100644
index 0000000..ad34c83
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/utilities/viewEngineHelper.ts
@@ -0,0 +1,324 @@
+import { storeService } from '../../../../framework/src/services/storeService';
+import { WhenAST, WhenTokenType } from '../yang/whenParser';
+
+import {
+  ViewSpecification,
+  ViewElement,
+  isViewElementReference,
+  isViewElementList,
+  isViewElementObjectOrList,
+  isViewElementRpc,
+  isViewElementChoice,
+  ViewElementChoiceCase,
+} from '../models/uiModels';
+
+import { Module } from '../models/yang';
+
+import { restService } from '../services/restServices';
+
+export type HttpResult = {
+  status: number;
+  message?: string | undefined;
+  data: {
+    [key: string]: any;
+  } | null | undefined;
+};
+
+export const checkResponseCode = (restResult: HttpResult) =>{
+  //403 gets handled by the framework from now on
+  return restResult.status !== 403 && ( restResult.status < 200 || restResult.status > 299);
+};
+
+export const resolveVPath = (current: string, vPath: string): string => {
+  if (vPath.startsWith('/')) {
+    return vPath;
+  }
+  const parts = current.split('/');
+  const vPathParts = vPath.split('/');
+  for (const part of vPathParts) {
+    if (part === '.') {
+      continue;
+    } else if (part === '..') {
+      parts.pop();
+    } else {
+      parts.push(part);
+    }
+  }
+  return parts.join('/');
+};
+
+export const splitVPath = (vPath: string, vPathParser : RegExp): [string, string?][] => {
+  const pathParts: [string, string?][] = [];
+  let partMatch: RegExpExecArray | null;
+  if (vPath) do {
+    partMatch = vPathParser.exec(vPath);
+    if (partMatch) {
+      pathParts.push([partMatch[1], partMatch[2] || undefined]);
+    }
+  } while (partMatch);
+  return pathParts;
+};
+
+const derivedFrom = (vPath: string, when: WhenAST, viewData: any, includeSelf = false) => {
+  if (when.args?.length !== 2) {
+    throw new Error('derived-from or derived-from-or-self requires 2 arguments.');
+  }
+  const [arg1, arg2] = when.args;
+  if (arg1.type !== WhenTokenType.IDENTIFIER || arg2.type !== WhenTokenType.STRING) {
+    throw new Error('derived-from or derived-from-or-self requires first argument IDENTIFIER and second argument STRING.');
+  }
+
+  if (!storeService.applicationStore) {
+    throw new Error('storeService.applicationStore is not defined.');
+  }
+
+  const pathParts = splitVPath(arg1.value as string || '', /(?:(?:([^\/\:]+):)?([^\/]+))/g); 
+  const referenceValueParts = /(?:(?:([^\/\:]+):)?([^\/]+))/g.exec(arg2.value as string || ''); 
+
+  if (!pathParts || !referenceValueParts || pathParts.length === 0 || referenceValueParts.length === 0) {
+    throw new Error('derived-from or derived-from-or-self requires first argument PATH and second argument IDENTITY.');
+  }
+
+  if (pathParts[0][1]?.startsWith('..') || pathParts[0][1]?.startsWith('/')) {
+    throw new Error('derived-from or derived-from-or-self currently only supports relative paths.');
+  }
+
+  const { configuration: { deviceDescription: { modules } } } = storeService.applicationStore.state;
+  const dataValue = pathParts.reduce((acc, [ns, prop]) => {
+    if (prop === '.') {
+      return acc;
+    } 
+    if (acc && prop) {
+      const moduleName = ns && (Object.values(modules).find((m: Module) => m.prefix === ns) || Object.values(modules).find((m: Module) => m.name === ns))?.name;
+      return (moduleName) ? acc[`${moduleName}:${prop}`] ||  acc[prop] : acc[prop];
+    }
+    return undefined;
+  }, viewData);
+
+  let dataValueParts = dataValue && /(?:(?:([^\/\:]+):)?([^\/]+))/g.exec(dataValue);
+  if (!dataValueParts || dataValueParts.length < 2) {
+    throw new Error(`derived-from or derived-from-or-self value referenced by first argument [${arg1.value}] not found.`);
+  }
+  let [, dataValueNs, dataValueProp] = dataValueParts;
+  let dataValueModule: Module = dataValueNs && (Object.values(modules).find((m: Module) => m.name === dataValueNs));
+  let dataValueIdentity = dataValueModule && dataValueModule.identities && (Object.values(dataValueModule.identities).find((i) => i.label === dataValueProp));
+
+  if (!dataValueIdentity) {
+    throw new Error(`derived-from or derived-from-or-self identity [${dataValue}] referenced by first argument [${arg1.value}] not found.`);
+  }
+
+  const [, referenceValueNs, referenceValueProp] = referenceValueParts;
+  const referenceValueModule = referenceValueNs && (Object.values(modules).find((m: Module) => m.prefix === referenceValueNs));
+  const referenceValueIdentity = referenceValueModule && referenceValueModule.identities && (Object.values(referenceValueModule.identities).find((i) => i.label === referenceValueProp));
+
+  if (!referenceValueIdentity) {
+    throw new Error(`derived-from or derived-from-or-self identity [${arg2.value}] referenced by second argument not found.`);
+  }
+
+  let result = includeSelf && (referenceValueIdentity === dataValueIdentity);
+  while (dataValueIdentity && dataValueIdentity.base && !result) {
+    dataValueParts = dataValue && /(?:(?:([^\/\:]+):)?([^\/]+))/g.exec(dataValueIdentity.base);
+    const [, innerDataValueNs, innerDataValueProp] = dataValueParts;
+    dataValueModule = innerDataValueNs && (Object.values(modules).find((m: Module) => m.prefix === innerDataValueNs)) || dataValueModule;
+    dataValueIdentity = dataValueModule && dataValueModule.identities && (Object.values(dataValueModule.identities).find((i) => i.label === innerDataValueProp)) ;
+    result = (referenceValueIdentity === dataValueIdentity);
+  }
+
+  return result;
+};
+
+const evaluateWhen = async (vPath: string, when: WhenAST, viewData: any): Promise<boolean> => {
+  switch (when.type) {
+    case WhenTokenType.FUNCTION:
+      switch (when.name) {
+        case 'derived-from-or-self':
+          return derivedFrom(vPath, when, viewData, true);
+        case 'derived-from':
+          return derivedFrom(vPath, when, viewData, false);
+        default:
+          throw new Error(`Unknown function ${when.name}`);
+      }
+    case WhenTokenType.AND:
+      return !when.left || !when.right || (await evaluateWhen(vPath, when.left, viewData) && await evaluateWhen(vPath, when.right, viewData));
+    case WhenTokenType.OR:
+      return !when.left || !when.right || (await evaluateWhen(vPath, when.left, viewData) || await evaluateWhen(vPath, when.right, viewData));
+    case WhenTokenType.NOT:
+      return !when.right || ! await evaluateWhen(vPath, when.right, viewData);
+    case WhenTokenType.EXPRESSION:
+      return !(when.value && typeof when.value !== 'string') || await evaluateWhen(vPath, when.value, viewData);
+  }   
+  return true;
+};
+
+export const getReferencedDataList = async (refPath: string, dataPath: string, modules: { [name: string]: Module }, views: ViewSpecification[]) => {
+  const pathParts = splitVPath(refPath, /(?:(?:([^\/\:]+):)?([^\/]+))/g);  // 1 = opt: namespace / 2 = property
+  const defaultNS = pathParts[0][0];
+  let referencedModule = modules[defaultNS];
+
+  let dataMember: string;
+  let view: ViewSpecification;
+  let currentNS: string | null = null;
+  let dataUrls = [dataPath];
+  let data: any;
+
+  for (let i = 0; i < pathParts.length; ++i) {
+    const [pathPartNS, pathPart] = pathParts[i];
+    const namespace = pathPartNS != null ? (currentNS = pathPartNS) : currentNS;
+
+    const viewElement = i === 0
+      ? views[0].elements[`${referencedModule.name}:${pathPart}`]
+      : view!.elements[`${pathPart}`] || view!.elements[`${namespace}:${pathPart}`];
+
+    if (!viewElement) throw new Error(`Could not find ${pathPart} in ${refPath}`);
+    if (i < pathParts.length - 1) {
+      if (!isViewElementObjectOrList(viewElement)) {
+        throw Error(`Module: [${referencedModule.name}].[${viewElement.label}]. View element is not list or object.`);
+      }
+      view = views[+viewElement.viewId];
+      const resultingDataUrls : string[] = [];
+      if (isViewElementList(viewElement)) {
+        for (let j = 0; j < dataUrls.length; ++j) {
+          const dataUrl = dataUrls[j];
+          const restResult = (await restService.getConfigData(dataUrl));
+          if (restResult.data == null || checkResponseCode(restResult)) {
+            const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
+            throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
+          }
+
+          let dataRaw = restResult.data[`${defaultNS}:${dataMember!}`];
+          if (dataRaw === undefined) {
+            dataRaw = restResult.data[dataMember!];
+          }
+          dataRaw = dataRaw instanceof Array
+            ? dataRaw[0]
+            : dataRaw;
+
+          data = dataRaw && dataRaw[viewElement.label] || [];
+          const keys: string[] = data.map((entry: { [key: string]: any } )=> entry[viewElement.key!]);
+          resultingDataUrls.push(...keys.map(key => `${dataUrl}/${viewElement.label.replace(/\//ig, '%2F')}=${key.replace(/\//ig, '%2F')}`));
+        }
+        dataMember = viewElement.label;
+      } else {
+        // just a member, not a list
+        const pathSegment = (i === 0
+          ? `/${referencedModule.name}:${viewElement.label.replace(/\//ig, '%2F')}`
+          : `/${viewElement.label.replace(/\//ig, '%2F')}`);
+        resultingDataUrls.push(...dataUrls.map(dataUrl => dataUrl + pathSegment));
+        dataMember = viewElement.label;
+      }
+      dataUrls = resultingDataUrls;
+    } else {
+      data = [];
+      for (let j = 0; j < dataUrls.length; ++j) {
+        const dataUrl = dataUrls[j];
+        const restResult = (await restService.getConfigData(dataUrl));
+        if (restResult.data == null || checkResponseCode(restResult)) {
+          const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
+          throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
+        }
+        let dataRaw = restResult.data[`${defaultNS}:${dataMember!}`];
+        if (dataRaw === undefined) {
+          dataRaw = restResult.data[dataMember!];
+        }
+        dataRaw = dataRaw instanceof Array
+          ? dataRaw[0]
+          : dataRaw;
+        data.push(dataRaw);
+      }
+      // BUG UUID ist nicht in den elements enthalten !!!!!!
+      const key = viewElement && viewElement.label || pathPart;
+      return {
+        view: view!,
+        data: data,
+        key: key,
+      };
+    }
+  }
+  return null;
+};
+
+export const resolveViewDescription = (defaultNS: string | null, vPath: string, view: ViewSpecification): ViewSpecification =>{
+
+  // resolve all references.
+  view = { ...view };
+  view.elements = Object.keys(view.elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+    const resolveHistory : ViewElement[] = [];  
+    let elm = view.elements[cur];
+    const key = defaultNS && cur.replace(new RegExp(`^${defaultNS}:`, 'i'), '') || cur;
+    while (isViewElementReference(elm)) {
+      const result = (elm.ref(vPath));  
+      if (result) {
+        const [referencedElement, referencedPath] = result;
+        if (resolveHistory.some(hist => hist === referencedElement)) {
+          console.error(`Circle reference found at: ${vPath}`, resolveHistory);
+          break;
+        }
+        elm = referencedElement;
+        vPath = referencedPath;
+        resolveHistory.push(elm);
+      }
+    } 
+    
+    acc[key] = { ...elm, id: key };
+    
+    return acc;
+  }, {});
+  return view;
+};
+
+export const flattenViewElements = (defaultNS: string | null, parentPath: string, elements: { [name: string]: ViewElement }, views: ViewSpecification[], currentPath: string ): { [name: string]: ViewElement } => {
+  if (!elements) return {};
+  return Object.keys(elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+    const elm = elements[cur];
+
+    // remove the default namespace, and only the default namespace, sine it seems that this is also not in the restconf response
+    const elmKey = defaultNS && elm.id.replace(new RegExp(`^${defaultNS}:`, 'i'), '') || elm.id;
+    const key = parentPath ? `${parentPath}.${elmKey}` : elmKey;
+
+    if (isViewElementRpc(elm)) {
+      console.warn(`Flatten of RFC not supported ! [${currentPath}][${elm.label}]`);
+      return acc;
+    } else if (isViewElementObjectOrList(elm)) {
+      const view = views[+elm.viewId];
+      const inner = view && flattenViewElements(defaultNS, key, view.elements, views, `${currentPath}/${view.name}`);
+      if (inner) {
+        Object.keys(inner).forEach(k => (acc[k] = inner[k]));
+      }
+    } else if (isViewElementChoice(elm)) {
+      acc[key] = {
+        ...elm,
+        id: key,
+        cases: Object.keys(elm.cases).reduce<{ [name: string]: ViewElementChoiceCase }>((accCases, curCases) => {
+          const caseElement = elm.cases[curCases];
+          accCases[curCases] = {
+            ...caseElement,
+            // Hint: do not use key it contains elmKey, which shell be omitted for cases.
+            elements: flattenViewElements(defaultNS, /*key*/ parentPath, caseElement.elements, views, `${currentPath}/${elm.label}`),
+          };
+          return accCases;
+        }, {}),
+      };
+    } else {
+      acc[key] = {
+        ...elm,
+        id: key,
+      };
+    }
+    return acc;
+  }, {});
+};
+
+export const filterViewElements = async (vPath: string, viewData: any, viewSpecification: ViewSpecification) => {
+  // filter elements of viewSpecification by evaluating when property
+  return Object.keys(viewSpecification.elements).reduce(async (accPromise, cur) => {
+    const acc = await accPromise;
+    const elm = viewSpecification.elements[cur];
+    if (!elm.when || await evaluateWhen(vPath || '', elm.when, viewData).catch((ex) => {
+      console.warn(`Error evaluating when clause at: ${viewSpecification.name} for element: ${cur}`, ex);
+      return true;
+    })) {
+      acc.elements[cur] = elm;
+    }
+    return acc;
+  }, Promise.resolve({ ...viewSpecification, elements: {} as { [key: string]: ViewElement } }));
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx
new file mode 100644
index 0000000..0f143d8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -0,0 +1,931 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React, { useState } from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import { useConfirm } from 'material-ui-confirm';
+
+import { connect, IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { Loader } from '../../../../framework/src/components/material-ui/loader';
+import { renderObject } from '../../../../framework/src/components/objectDump';
+
+import { DisplayModeType } from '../handlers/viewDescriptionHandler';
+import {
+  SetSelectedValue,
+  updateDataActionAsyncCreator,
+  updateViewActionAsyncCreator,
+  removeElementActionAsyncCreator,
+  executeRpcActionAsyncCreator,
+} from '../actions/deviceActions';
+
+import {
+  ViewElement,
+  ViewSpecification,
+  ViewElementChoice,
+  ViewElementRpc,
+  isViewElementString,
+  isViewElementNumber,
+  isViewElementBoolean,
+  isViewElementObjectOrList,
+  isViewElementSelection,
+  isViewElementChoice,
+  isViewElementUnion,
+  isViewElementRpc,
+  isViewElementEmpty,
+  isViewElementDate,
+} from '../models/uiModels';
+
+import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+
+import Fab from '@mui/material/Fab';
+import AddIcon from '@mui/icons-material/Add';
+import PostAdd from '@mui/icons-material/PostAdd';
+import ArrowBack from '@mui/icons-material/ArrowBack';
+import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
+import SaveIcon from '@mui/icons-material/Save';
+import EditIcon from '@mui/icons-material/Edit';
+import Tooltip from '@mui/material/Tooltip';
+import FormControl from '@mui/material/FormControl';
+import IconButton from '@mui/material/IconButton';
+
+import InputLabel from '@mui/material/InputLabel';
+import Select from '@mui/material/Select';
+import MenuItem from '@mui/material/MenuItem';
+import Breadcrumbs from '@mui/material/Breadcrumbs';
+import Button from '@mui/material/Button';
+import Link from '@mui/material/Link';
+import Accordion from '@mui/material/Accordion';
+import AccordionSummary from '@mui/material/AccordionSummary';
+import AccordionDetails from '@mui/material/AccordionDetails';
+import Typography from '@mui/material/Typography';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+
+import { BaseProps } from '../components/baseProps';
+import { UIElementReference } from '../components/uiElementReference';
+import { UiElementNumber } from '../components/uiElementNumber';
+import { UiElementString } from '../components/uiElementString';
+import { UiElementBoolean } from '../components/uiElementBoolean';
+import { UiElementSelection } from '../components/uiElementSelection';
+import { UIElementUnion } from '../components/uiElementUnion';
+import { UiElementLeafList } from '../components/uiElementLeafList';
+
+import { splitVPath } from '../utilities/viewEngineHelper';
+
+const styles = (theme: Theme) => createStyles({
+  header: {
+    'display': 'flex',
+    'justifyContent': 'space-between',
+  },
+  leftButton: {
+    'justifyContent': 'left',
+  },
+  outer: {
+    'flex': '1',
+    'height': '100%',
+    'display': 'flex',
+    'alignItems': 'center',
+    'justifyContent': 'center',
+  },
+  inner: {
+
+  },
+  container: {
+    'height': '100%',
+    'display': 'flex',
+    'flexDirection': 'column',
+  },
+  'icon': {
+    'marginRight': theme.spacing(0.5),
+    'width': 20,
+    'height': 20,
+  },
+  'fab': {
+    'margin': theme.spacing(1),
+  },
+  button: {
+    margin: 0,
+    padding: '6px 6px',
+    minWidth: 'unset',
+  },
+  readOnly: {
+    '& label.Mui-focused': {
+      color: 'green',
+    },
+    '& .MuiInput-underline:after': {
+      borderBottomColor: 'green',
+    },
+    '& .MuiOutlinedInput-root': {
+      '& fieldset': {
+        borderColor: 'red',
+      },
+      '&:hover fieldset': {
+        borderColor: 'yellow',
+      },
+      '&.Mui-focused fieldset': {
+        borderColor: 'green',
+      },
+    },
+  },
+  uiView: {
+    overflowY: 'auto',
+  },
+  section: {
+    padding: '15px',
+    borderBottom: `2px solid ${theme.palette.divider}`,
+  },
+  viewElements: {
+    width: 485, marginLeft: 20, marginRight: 20,
+  },
+  verificationElements: {
+    width: 485, marginLeft: 20, marginRight: 20,
+  },
+  heading: {
+    fontSize: theme.typography.pxToRem(15),
+    fontWeight: theme.typography.fontWeightRegular,
+  },
+  moduleCollection: {
+    marginTop: '16px',
+    overflow: 'auto',
+  },
+  objectReult: {
+    overflow: 'auto',
+  },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  collectingData: state.configuration.valueSelector.collectingData,
+  listKeyProperty: state.configuration.valueSelector.keyProperty,
+  listSpecification: state.configuration.valueSelector.listSpecification,
+  listData: state.configuration.valueSelector.listData,
+  vPath: state.configuration.viewDescription.vPath,
+  nodeId: state.configuration.deviceDescription.nodeId,
+  viewData: state.configuration.viewDescription.viewData,
+  outputData: state.configuration.viewDescription.outputData,
+  displaySpecification: state.configuration.viewDescription.displaySpecification,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  onValueSelected: (value: any) => dispatcher.dispatch(new SetSelectedValue(value)),
+  onUpdateData: (vPath: string, data: any) => dispatcher.dispatch(updateDataActionAsyncCreator(vPath, data)),
+  reloadView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
+  removeElement: (vPath: string) => dispatcher.dispatch(removeElementActionAsyncCreator(vPath)),
+  executeRpc: (vPath: string, data: any) => dispatcher.dispatch(executeRpcActionAsyncCreator(vPath, data)),
+});
+
+const SelectElementTable = MaterialTable as MaterialTableCtorType<{ [key: string]: any }>;
+
+type ConfigurationApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type ConfigurationApplicationComponentState = {
+  isNew: boolean;
+  editMode: boolean;
+  canEdit: boolean;
+  viewData: { [key: string]: any } | null;
+  choices: { [path: string]: { selectedCase: string; data: { [property: string]: any } } };
+};
+
+type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any;
+const AccordionSummaryExt: React.FC<GetStatelessComponentProps<typeof AccordionSummary>> = (props) => {
+  const [disabled, setDisabled] = useState(true);
+  const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
+    if (ev.button === 1) {
+      setDisabled(!disabled);
+      ev.preventDefault();
+    }
+  };
+  return (
+    <div onMouseDown={onMouseDown} >
+      <AccordionSummary {...{ ...props, disabled: props.disabled && disabled }} />
+    </div>
+  );
+};
+
+const OldProps = Symbol('OldProps');
+class ConfigurationApplicationComponent extends React.Component<ConfigurationApplicationComponentProps, ConfigurationApplicationComponentState> {
+
+  /**
+   *
+   */
+  constructor(props: ConfigurationApplicationComponentProps) {
+    super(props);
+
+    this.state = {
+      isNew: false,
+      canEdit: false,
+      editMode: false,
+      viewData: null,
+      choices: {},
+    };
+  }
+
+  private static getChoicesFromElements = (elements: { [name: string]: ViewElement }, viewData: any) => {
+    return Object.keys(elements).reduce((acc, cur) => {
+      const elm = elements[cur];
+      if (isViewElementChoice(elm)) {
+        const caseKeys = Object.keys(elm.cases);
+
+        // find the right case for this choice, use the first one with data, at least use index 0
+        const selectedCase = caseKeys.find(key => {
+          const caseElm = elm.cases[key];
+          return Object.keys(caseElm.elements).some(caseElmKey => {
+            const caseElmElm = caseElm.elements[caseElmKey];
+            return viewData[caseElmElm.label] !== undefined || viewData[caseElmElm.id] != undefined;
+          });
+        }) || caseKeys[0];
+
+        // extract all data of the active case
+        const caseElements = elm.cases[selectedCase].elements;
+        const data = Object.keys(caseElements).reduce((dataAcc, dataCur) => {
+          const dataElm = caseElements[dataCur];
+          if (isViewElementEmpty(dataElm)) {
+            dataAcc[dataElm.label] = null;
+          } else if (viewData[dataElm.label] !== undefined) {
+            dataAcc[dataElm.label] = viewData[dataElm.label];
+          } else if (viewData[dataElm.id] !== undefined) {
+            dataAcc[dataElm.id] = viewData[dataElm.id];
+          }
+          return dataAcc;
+        }, {} as { [name: string]: any });
+
+        acc[elm.id] = {
+          selectedCase,
+          data,
+        };
+      }
+      return acc;
+    }, {} as { [path: string]: { selectedCase: string; data: { [property: string]: any } } }) || {};
+  };
+
+  static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
+
+    if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
+      const isNew: boolean = nextProps.vPath?.endsWith('[]') || false;
+      const state = {
+        ...prevState,
+        isNew: isNew,
+        editMode: isNew,
+        viewData: nextProps.viewData || null,
+        [OldProps]: nextProps,
+        choices: nextProps.displaySpecification.displayMode === DisplayModeType.doNotDisplay
+          || nextProps.displaySpecification.displayMode === DisplayModeType.displayAsMessage
+          ? null
+          : nextProps.displaySpecification.displayMode === DisplayModeType.displayAsRPC
+            ? nextProps.displaySpecification.inputViewSpecification && ConfigurationApplicationComponent.getChoicesFromElements(nextProps.displaySpecification.inputViewSpecification.elements, nextProps.viewData) || []
+            : ConfigurationApplicationComponent.getChoicesFromElements(nextProps.displaySpecification.viewSpecification.elements, nextProps.viewData),
+      };
+      return state;
+    }
+    return null;
+  }
+
+  private navigate = (path: string) => {
+    this.props.history.push(`${this.props.match.url}${path}`);
+  };
+
+  private changeValueFor = (property: string, value: any) => {
+    this.setState({
+      viewData: {
+        ...this.state.viewData,
+        [property]: value,
+      },
+    });
+  };
+
+  private collectData = (elements: { [name: string]: ViewElement }) => {
+    // ensure only active choices will be contained
+    const viewData: { [key: string]: any } = { ...this.state.viewData };
+    const choiceKeys = Object.keys(elements).filter(elmKey => isViewElementChoice(elements[elmKey]));
+    const elementsToRemove = choiceKeys.reduce((acc, curChoiceKey) => {
+      const currentChoice = elements[curChoiceKey] as ViewElementChoice;
+      const selectedCase = this.state.choices[curChoiceKey].selectedCase;
+      Object.keys(currentChoice.cases).forEach(caseKey => {
+        const caseElements = currentChoice.cases[caseKey].elements;
+        if (caseKey === selectedCase) {
+          Object.keys(caseElements).forEach(caseElementKey => {
+            const elm = caseElements[caseElementKey];
+            if (isViewElementEmpty(elm)) {
+              // insert null for all empty elements
+              viewData[elm.id] = null;
+            }
+          });
+          return;
+        }
+        Object.keys(caseElements).forEach(caseElementKey => {
+          acc.push(caseElements[caseElementKey]);
+        });
+      });
+      return acc;
+    }, [] as ViewElement[]);
+
+    return viewData && Object.keys(viewData).reduce((acc, cur) => {
+      if (!elementsToRemove.some(elm => elm.label === cur || elm.id === cur)) {
+        acc[cur] = viewData[cur];
+      }
+      return acc;
+    }, {} as { [key: string]: any });
+  };
+
+  private isPolicyViewElementForbidden = (element: ViewElement, dataPath: string): boolean => {
+    const policy = getAccessPolicyByUrl(`${dataPath}/${element.id}`);
+    return !(policy.GET && policy.POST);
+  };
+
+  private isPolicyModuleForbidden = (moduleName: string, dataPath: string): boolean => {
+    const policy = getAccessPolicyByUrl(`${dataPath}/${moduleName}`);
+    return !(policy.GET && policy.POST);
+  };
+
+  private getEditorForViewElement = (uiElement: ViewElement): (null | React.ComponentType<BaseProps<any>>) => {
+    if (isViewElementEmpty(uiElement)) {
+      return null;
+    } else if (isViewElementSelection(uiElement)) {
+      return UiElementSelection;
+    } else if (isViewElementBoolean(uiElement)) {
+      return UiElementBoolean;
+    } else if (isViewElementString(uiElement)) {
+      return UiElementString;
+    } else if (isViewElementDate(uiElement)) {
+      return UiElementString;
+    } else if (isViewElementNumber(uiElement)) {
+      return UiElementNumber;
+    } else if (isViewElementUnion(uiElement)) {
+      return UIElementUnion;
+    } else {
+      if (process.env.NODE_ENV !== 'production') {
+        console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`);
+      }
+      return null;
+    }
+  };
+
+  private renderUIElement = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+    const isKey = (uiElement.label === keyProperty);
+    const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+
+    // do not show elements w/o any value from the backend
+    if (viewData[uiElement.id] == null && !editMode) {
+      return null;
+    } else if (isViewElementEmpty(uiElement)) {
+      return null;
+    } else if (uiElement.isList) {
+      /* element is a leaf-list */
+      return <UiElementLeafList
+        key={uiElement.id}
+        inputValue={viewData[uiElement.id] == null ? [] : viewData[uiElement.id]}
+        value={uiElement}
+        readOnly={!canEdit}
+        disabled={editMode && !canEdit}
+        onChange={(e) => { this.changeValueFor(uiElement.id, e); }}
+        getEditorForViewElement={this.getEditorForViewElement}
+      />;
+    } else {
+      const Element = this.getEditorForViewElement(uiElement);
+      return Element != null
+        ? (
+          <Element
+            key={uiElement.id}
+            isKey={isKey}
+            inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
+            value={uiElement}
+            readOnly={!canEdit}
+            disabled={editMode && !canEdit}
+            onChange={(e) => { this.changeValueFor(uiElement.id, e); }}
+          />)
+        : null;
+    }
+  };
+
+  // private renderUIReference = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+  //   const isKey = (uiElement.label === keyProperty);
+  //   const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+  //   if (isViewElementObjectOrList(uiElement)) {
+  //     return (
+  //       <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+  //         <Tooltip title={uiElement.description || ''}>
+  //           <Button className={this.props.classes.leftButton} color="secondary" disabled={this.state.editMode} onClick={() => {
+  //             this.navigate(`/${uiElement.id}`);
+  //           }}>{uiElement.label}</Button>
+  //         </Tooltip>
+  //       </FormControl>
+  //     );
+  //   } else {
+  //     if (process.env.NODE_ENV !== "production") {
+  //       console.error(`Unknown reference type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+  //     }
+  //     return null;
+  //   }
+  // };
+
+  private renderUIChoice = (uiElement: ViewElementChoice, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+    const isKey = (uiElement.label === keyProperty);
+
+    const currentChoice = this.state.choices[uiElement.id];
+    const currentCase = currentChoice && uiElement.cases[currentChoice.selectedCase];
+
+    const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+    if (isViewElementChoice(uiElement)) {
+      const subElements = currentCase?.elements;
+      return (
+        <>
+          <FormControl variant="standard" key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+            <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
+            <Select variant="standard"
+              aria-label={uiElement.label + '-selection'}
+              required={!!uiElement.mandatory}
+              onChange={(e) => {
+                if (currentChoice.selectedCase === e.target.value) {
+                  return; // nothing changed
+                }
+                this.setState({ choices: { ...this.state.choices, [uiElement.id]: { ...this.state.choices[uiElement.id], selectedCase: e.target.value as string } } });
+              }}
+              readOnly={!canEdit}
+              disabled={editMode && !canEdit}
+              value={this.state.choices[uiElement.id].selectedCase}
+              inputProps={{
+                name: uiElement.id,
+                id: `select-${uiElement.id}`,
+              }}
+            >
+              {
+                Object.keys(uiElement.cases).map(caseKey => {
+                  const caseElm = uiElement.cases[caseKey];
+                  return (
+                    <MenuItem key={caseElm.id} value={caseKey} aria-label={caseKey}><Tooltip title={caseElm.description || ''}><div style={{ width: '100%' }}>{caseElm.label}</div></Tooltip></MenuItem>
+                  );
+                })
+              }
+            </Select>
+          </FormControl>
+          {subElements
+            ? Object.keys(subElements).map(elmKey => {
+              const elm = subElements[elmKey];
+              return this.renderUIElement(elm, viewData, keyProperty, editMode, isNew);
+            })
+            : <h3>Invalid Choice</h3>
+          }
+        </>
+      );
+    } else {
+      if (process.env.NODE_ENV !== 'production') {
+        console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`);
+      }
+      return null;
+    }
+  };
+
+  private renderUIView = (viewSpecification: ViewSpecification, dataPath: string, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+    const { classes } = this.props;
+
+    const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
+      if (keyProperty) {
+        // if (vsA.label === vsB.label) return 0;
+        if (vsA.label === keyProperty) return -1;
+        if (vsB.label === keyProperty) return +1;
+      }
+
+      // if (vsA.uiType === vsB.uiType) return 0;
+      // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+      // if (vsA.uiType === "object") return +1;
+      return -1;
+    };
+
+    const sections = Object.keys(viewSpecification.elements).reduce((acc, cur) => {
+      const elm = viewSpecification.elements[cur];
+      if (isViewElementObjectOrList(elm)) {
+        acc.references.push(elm);
+      } else if (isViewElementChoice(elm)) {
+        acc.choices.push(elm);
+      } else if (isViewElementRpc(elm)) {
+        acc.rpcs.push(elm);
+      } else {
+        acc.elements.push(elm);
+      }
+      return acc;
+    }, { elements: [] as ViewElement[], references: [] as ViewElement[], choices: [] as ViewElementChoice[], rpcs: [] as ViewElementRpc[] });
+
+    sections.elements = sections.elements.sort(orderFunc);
+
+    return (
+      <div className={classes.uiView}>
+        <div className={classes.section} />
+        {sections.elements.length > 0
+          ? (
+            <div className={classes.section}>
+              {sections.elements.map(element => this.renderUIElement(element, viewData, keyProperty, editMode, isNew))}
+            </div>
+          ) : null
+        }
+        {sections.references.length > 0
+          ? (
+            <div className={classes.section}>
+              {sections.references.map(element => (
+                <UIElementReference key={element.id} element={element} disabled={editMode || this.isPolicyViewElementForbidden(element, dataPath)} onOpenReference={(elm) => { this.navigate(`/${elm.id}`); }} />
+              ))}
+            </div>
+          ) : null
+        }
+        {sections.choices.length > 0
+          ? (
+            <div className={classes.section}>
+              {sections.choices.map(element => this.renderUIChoice(element, viewData, keyProperty, editMode, isNew))}
+            </div>
+          ) : null
+        }
+        {sections.rpcs.length > 0
+          ? (
+            <div className={classes.section}>
+              {sections.rpcs.map(element => (
+                <UIElementReference key={element.id} element={element} disabled={editMode || this.isPolicyViewElementForbidden(element, dataPath)} onOpenReference={(elm) => { this.navigate(`/${elm.id}`); }} />
+              ))}
+            </div>
+          ) : null
+        }
+      </div>
+    );
+  };
+
+  private renderUIViewSelector = (viewSpecification: ViewSpecification, dataPath: string, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+    const { classes } = this.props;
+    
+    // group by module name
+    const modules = Object.keys(viewSpecification.elements).reduce<{ [key: string]: ViewSpecification }>((acc, cur) => {
+      const elm = viewSpecification.elements[cur];
+      const moduleView = (acc[elm.module] = acc[elm.module] || { ...viewSpecification, elements: {} });
+      moduleView.elements[cur] = elm;
+      return acc;
+    }, {});
+
+    const moduleKeys = Object.keys(modules).sort();
+
+    return (
+      <div className={classes.moduleCollection}>
+        {
+          moduleKeys.map(key => {
+            const moduleView = modules[key];
+            
+            return (
+              <Accordion key={key} defaultExpanded={moduleKeys.length < 4} aria-label={key + '-panel'} >
+                <AccordionSummaryExt expandIcon={<ExpandMoreIcon />} aria-controls={`content-${key}`} id={`header-${key}`} disabled={this.isPolicyModuleForbidden(`${key}:`, dataPath)} >
+                  <Typography className={classes.heading}>{key}</Typography>
+                </AccordionSummaryExt>
+                <AccordionDetails>
+                  {this.renderUIView(moduleView, dataPath, viewData, keyProperty, editMode, isNew)}
+                </AccordionDetails>
+              </Accordion>
+            );
+          })
+        }
+      </div>
+    );
+  };
+
+  private renderUIViewList(listSpecification: ViewSpecification, dataPath: string, listKeyProperty: string, apiDocPath: string, listData: { [key: string]: any }[]) {
+    const listElements = listSpecification.elements;
+    const apiDocPathCreate = apiDocPath  ? `${location.origin}${apiDocPath
+      .replace('$$$standard$$$', 'topology-netconfnode%20resources%20-%20RestConf%20RFC%208040')
+      .replace('$$$action$$$', 'put')}${listKeyProperty ? `_${listKeyProperty.replace(/[\/=\-\:]/g, '_')}_` : '' }` : undefined;
+
+    const config = listSpecification.config && listKeyProperty; // We can not configure a list with no key.
+
+    const navigate = (path: string) => {
+      this.props.history.push(`${this.props.match.url}${path}`);
+    };
+
+    const addNewElementAction = {
+      icon: AddIcon, 
+      tooltip: 'Add',
+      ariaLabel:'add-element',
+      onClick: () => {
+        navigate('[]'); // empty key means new element
+      },
+      disabled: !config,
+    };
+
+    const addWithApiDocElementAction = {
+      icon: PostAdd, 
+      tooltip: 'Add',
+      ariaLabel:'add-element-via-api-doc',
+      onClick: () => {
+        window.open(apiDocPathCreate, '_blank');
+      },
+      disabled: !config,
+    };
+
+    const { classes, removeElement } = this.props;
+
+    const DeleteIconWithConfirmation: React.FC<{ disabled?: boolean; rowData: { [key: string]: any }; onReload: () => void }> = (props) => {
+      const confirm = useConfirm();
+
+      return (
+        <Tooltip disableInteractive title={'Remove'} >
+          <IconButton
+            disabled={props.disabled}
+            className={classes.button}
+            aria-label="remove-element-button"
+            onClick={async (e) => {
+              e.stopPropagation();
+              e.preventDefault();
+              confirm({ title: 'Do you really want to delete this element ?', description: 'This action is permanent!', confirmationButtonProps: { color: 'secondary' }, cancellationButtonProps: { color:'inherit' } })
+                .then(() => {
+                  let keyId = '';
+                  if (listKeyProperty && listKeyProperty.split(' ').length > 1) {
+                    keyId += listKeyProperty.split(' ').map(id => props.rowData[id]).join(',');
+                  } else {
+                    keyId = props.rowData[listKeyProperty];
+                  }
+                  return removeElement(`${this.props.vPath}[${keyId}]`);
+                }).then(props.onReload);
+            }}
+            size="large">
+            <RemoveIcon />
+          </IconButton>
+        </Tooltip>
+      );
+    };
+
+    return (
+      <SelectElementTable stickyHeader idProperty={listKeyProperty} tableId={null} rows={listData} customActionButtons={apiDocPathCreate ? [addNewElementAction, addWithApiDocElementAction] : [addNewElementAction]} columns={
+        Object.keys(listElements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
+          const elm = listElements[cur];
+          if (elm.uiType !== 'object' && listData.every(entry => entry[elm.label] != null)) {
+            if (elm.label !== listKeyProperty) {
+              acc.push(elm.uiType === 'boolean'
+                ? { property: elm.label, type: ColumnType.boolean }
+                : elm.uiType === 'date'
+                  ? { property: elm.label, type: ColumnType.date }
+                  : { property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
+            } else {
+              acc.unshift(elm.uiType === 'boolean'
+                ? { property: elm.label, type: ColumnType.boolean }
+                : elm.uiType === 'date'
+                  ? { property: elm.label, type: ColumnType.date }
+                  : { property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
+            }
+          }
+          return acc;
+        }, []).concat([{
+          property: 'Actions', disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (({ rowData }) => {
+            return (
+              <DeleteIconWithConfirmation disabled={!config} rowData={rowData} onReload={() => this.props.vPath && this.props.reloadView(this.props.vPath)} />
+            );
+          }),
+        }])
+      } onHandleClick={(ev, row) => {
+        ev.preventDefault();
+        let keyId = '';
+        if (listKeyProperty && listKeyProperty.split(' ').length > 1) {
+          keyId += listKeyProperty.split(' ').map(id => row[id]).join(',');
+        } else {
+          keyId = row[listKeyProperty];
+        }
+        if (listKeyProperty) {
+          navigate(`[${encodeURIComponent(keyId)}]`); // Do not navigate without key.
+        }
+      }} ></SelectElementTable>
+    );
+  }
+
+  private renderUIViewRPC(inputViewSpecification: ViewSpecification | undefined, dataPath: string, inputViewData: { [key: string]: any }, outputViewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) {
+    const { classes } = this.props;
+
+    const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
+      if (keyProperty) {
+        // if (vsA.label === vsB.label) return 0;
+        if (vsA.label === keyProperty) return -1;
+        if (vsB.label === keyProperty) return +1;
+      }
+
+      // if (vsA.uiType === vsB.uiType) return 0;
+      // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+      // if (vsA.uiType === "object") return +1;
+      return -1;
+    };
+
+    const sections = inputViewSpecification && Object.keys(inputViewSpecification.elements).reduce((acc, cur) => {
+      const elm = inputViewSpecification.elements[cur];
+      if (isViewElementObjectOrList(elm)) {
+        console.error('Object should not appear in RPC view !');
+      } else if (isViewElementChoice(elm)) {
+        acc.choices.push(elm);
+      } else if (isViewElementRpc(elm)) {
+        console.error('RPC should not appear in RPC view !');
+      } else {
+        acc.elements.push(elm);
+      }
+      return acc;
+    }, { elements: [] as ViewElement[], references: [] as ViewElement[], choices: [] as ViewElementChoice[], rpcs: [] as ViewElementRpc[] })
+      || { elements: [] as ViewElement[], references: [] as ViewElement[], choices: [] as ViewElementChoice[], rpcs: [] as ViewElementRpc[] };
+
+    sections.elements = sections.elements.sort(orderFunc);
+
+    return (
+      <>
+        <div className={classes.section} />
+        { sections.elements.length > 0
+          ? (
+            <div className={classes.section}>
+              {sections.elements.map(element => this.renderUIElement(element, inputViewData, keyProperty, editMode, isNew))}
+            </div>
+          ) : null
+        }
+        { sections.choices.length > 0
+          ? (
+            <div className={classes.section}>
+              {sections.choices.map(element => this.renderUIChoice(element, inputViewData, keyProperty, editMode, isNew))}
+            </div>
+          ) : null
+        }
+        <Button color="inherit" onClick={() => {
+          const resultingViewData = inputViewSpecification && this.collectData(inputViewSpecification.elements);
+          this.props.executeRpc(this.props.vPath!, resultingViewData);
+        }} >Exec</Button>
+        <div className={classes.objectReult}>
+          {outputViewData !== undefined
+            ? renderObject(outputViewData)
+            : null
+          }
+        </div>
+      </>
+    );
+  }
+
+  private renderBreadCrumps() {
+    const { editMode } = this.state;
+    const { displaySpecification, vPath, nodeId } = this.props;
+    const pathParts = splitVPath(vPath!, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+    let lastPath = '/configuration';
+    let basePath = `/configuration/${nodeId}`;
+    return (
+      <div className={this.props.classes.header}>
+        <div>
+          <Breadcrumbs aria-label="breadcrumbs">
+            <Link underline="hover" color="inherit" href="#" aria-label="back-breadcrumb"
+              onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                ev.preventDefault();
+                this.props.history.push(lastPath);
+              }}>Back</Link>
+            <Link underline="hover" color="inherit" href="#"
+              aria-label={nodeId + '-breadcrumb'}
+              onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                ev.preventDefault();
+                this.props.history.push(`/configuration/${nodeId}`);
+              }}><span>{nodeId}</span></Link>
+            {
+              pathParts.map(([prop, key], ind) => {
+                const path = `${basePath}/${prop}`;
+                const keyPath = key && `${basePath}/${prop}[${key}]`;
+                const propTitle = prop.replace(/^[^:]+:/, '');
+                const ret = (
+                  <span key={ind}>
+                    <Link underline="hover" color="inherit" href="#"
+                      aria-label={propTitle + '-breadcrumb'}
+                      onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                        ev.preventDefault();
+                        this.props.history.push(path);
+                      }}><span>{propTitle}</span></Link>
+                    {
+                      keyPath && <Link underline="hover" color="inherit" href="#"
+                        aria-label={key + '-breadcrumb'}
+                        onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                          ev.preventDefault();
+                          this.props.history.push(keyPath);
+                        }}>{`[${key && key.replace(/\%2C/g, ',')}]`}</Link> || null
+                      }
+                  </span>
+                );
+                lastPath = basePath;
+                basePath = keyPath || path;
+                return ret;
+              })
+            }
+          </Breadcrumbs>
+        </div>
+        {this.state.editMode && (
+          <Fab color="secondary" aria-label="back-button" className={this.props.classes.fab} onClick={async () => {
+            if (this.props.vPath) {
+              await this.props.reloadView(this.props.vPath);
+            }
+            this.setState({ editMode: false });
+          }} ><ArrowBack /></Fab>
+        ) || null}
+        { /* do not show edit if this is a list or it can't be edited */
+          displaySpecification.displayMode === DisplayModeType.displayAsObject && displaySpecification.viewSpecification.canEdit && (<div>
+            <Fab color="secondary" aria-label={editMode ? 'save-button' : 'edit-button'} className={this.props.classes.fab} onClick={() => {
+              if (this.state.editMode) {
+                // ensure only active choices will be contained
+                const resultingViewData = this.collectData(displaySpecification.viewSpecification.elements);
+                this.props.onUpdateData(this.props.vPath!, resultingViewData);
+              }
+              this.setState({ editMode: !editMode });
+            }}>
+              {editMode
+                ? <SaveIcon />
+                : <EditIcon />
+              }
+            </Fab>
+          </div> || null)
+        }
+      </div>
+    );
+  }
+
+  private renderValueSelector() {
+    const { listKeyProperty, listSpecification, listData, onValueSelected } = this.props;
+    if (!listKeyProperty || !listSpecification) {
+      throw new Error('ListKex ot view not specified.');
+    }
+
+    return (
+      <div className={this.props.classes.container}>
+        <SelectElementTable stickyHeader idProperty={listKeyProperty} tableId={null} rows={listData} columns={
+          Object.keys(listSpecification.elements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
+            const elm = listSpecification.elements[cur];
+            if (elm.uiType !== 'object' && listData.every(entry => entry[elm.label] != null)) {
+              if (elm.label !== listKeyProperty) {
+                acc.push({ property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
+              } else {
+                acc.unshift({ property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
+              }
+            }
+            return acc;
+          }, [])
+        } onHandleClick={(ev, row) => { ev.preventDefault(); onValueSelected(row); }} ></SelectElementTable>
+      </div>
+    );
+  }
+
+  private renderValueEditor() {
+    const { displaySpecification: ds, outputData } = this.props;
+    const { viewData, editMode, isNew } = this.state;
+
+    return (
+      <div className={this.props.classes.container}>
+        {this.renderBreadCrumps()}
+        {ds.displayMode === DisplayModeType.doNotDisplay
+          ? null
+          : ds.displayMode === DisplayModeType.displayAsList && viewData instanceof Array
+            ? this.renderUIViewList(ds.viewSpecification, ds.dataPath!, ds.keyProperty!, ds.apidocPath!, viewData)
+            : ds.displayMode === DisplayModeType.displayAsRPC
+              ? this.renderUIViewRPC(ds.inputViewSpecification, ds.dataPath!, viewData!, outputData, undefined, true, false)
+              : ds.displayMode === DisplayModeType.displayAsMessage
+                ? this.renderMessage(ds.renderMessage)
+                : this.renderUIViewSelector(ds.viewSpecification, ds.dataPath!, viewData!, ds.keyProperty, editMode, isNew)
+        }
+      </div >
+    );
+  }
+
+  private renderMessage(renderMessage: string) {
+    return (
+      <div className={this.props.classes.container}>
+        <h4>{renderMessage}</h4>
+      </div>
+    );
+  }
+
+  private renderCollectingData() {
+    return (
+      <div className={this.props.classes.outer}>
+        <div className={this.props.classes.inner}>
+          <Loader />
+          <h3>Processing ...</h3>
+        </div>
+      </div>
+    );
+  }
+
+  render() {
+    return this.props.collectingData || !this.state.viewData
+      ? this.renderCollectingData()
+      : this.props.listSpecification
+        ? this.renderValueSelector()
+        : this.renderValueEditor();
+  }
+}
+
+export const ConfigurationApplication = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(ConfigurationApplicationComponent)));
+export default ConfigurationApplication;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
new file mode 100644
index 0000000..e96f40d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { connect, IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { MaterialTable, MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from '../../../configurationApp/src/handlers/connectedNetworkElementsHandler';
+
+
+const mapProps = (state: IApplicationStoreState) => ({
+  connectedNetworkElementsProperties: createConnectedNetworkElementsProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  connectedNetworkElementsActions: createConnectedNetworkElementsActions(dispatcher.dispatch),
+});
+
+const ConnectedElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
+
+type NetworkElementSelectorComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch>;
+
+let initialSorted = false;
+
+class NetworkElementSelectorComponent extends React.Component<NetworkElementSelectorComponentProps> {
+
+  componentDidMount() {
+
+    if (!initialSorted) {
+      initialSorted = true;
+      this.props.connectedNetworkElementsActions.onHandleRequestSort('node-id');
+    } else
+      this.props.connectedNetworkElementsActions.onRefresh();
+  }
+
+  render() {
+    return (
+      <ConnectedElementTable stickyHeader tableId="configurable-elements-table" onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`); }} columns={[
+        { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
+        { property: 'isRequired', title: 'Required', type: ColumnType.boolean },
+        { property: 'host', title: 'Host', type: ColumnType.text },
+        { property: 'port', title: 'Port', type: ColumnType.numeric },
+        { property: 'coreModelCapability', title: 'Core Model', type: ColumnType.text },
+        { property: 'deviceType', title: 'Type', type: ColumnType.text },
+      ]} idProperty="id" {...this.props.connectedNetworkElementsActions} {...this.props.connectedNetworkElementsProperties} asynchronus >
+      </ConnectedElementTable>
+    );
+  }
+}
+
+export const NetworkElementSelector = withRouter(connect(mapProps, mapDispatch)(NetworkElementSelectorComponent));
+export default NetworkElementSelector;
+
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/whenParser.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/whenParser.ts
new file mode 100644
index 0000000..fa2968c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/whenParser.ts
@@ -0,0 +1,235 @@
+enum WhenTokenType {
+  AND = 'AND',
+  OR = 'OR',
+  NOT = 'NOT',
+  EQUALS = 'EQUALS',
+  COMMA = 'COMMA',
+  STRING = 'STRING',
+  FUNCTION = 'FUNCTION',
+  IDENTIFIER = 'IDENTIFIER',
+  OPEN_PAREN = 'OPEN_PAREN',
+  CLOSE_PAREN = 'CLOSE_PAREN',
+  EXPRESSION = 'EXPRESSION',
+}
+
+type Token = {
+  type: WhenTokenType;
+  value: string;
+};
+
+const isAlpha = (char: string) => /[a-z]/i.test(char);
+
+const isAlphaNumeric = (char: string) => /[A-Za-z0-9_\-/:\.]/i.test(char);
+
+const lex = (input: string) : Token[] => {
+  let tokens = [] as any[];
+  let current = 0;
+
+  while (current < input.length) {
+    let char = input[current];
+
+    if (char === ' ') {
+      current++;
+      continue;
+    }
+
+    if (char === '(') {
+      tokens.push({ type: WhenTokenType.OPEN_PAREN, value: char });
+      current++;
+      continue;
+    }
+
+    if (char === ')') {
+      tokens.push({ type: WhenTokenType.CLOSE_PAREN, value: char });
+      current++;
+      continue;
+    }
+
+    if (char === '=') {
+      tokens.push({ type: WhenTokenType.EQUALS, value: char });
+      current++;
+      continue;
+    }
+
+    if (char === ',') {
+      tokens.push({ type: WhenTokenType.COMMA, value: char });
+      current++;
+      continue;
+    }
+
+    if (char === '\"' || char === '\'') {
+      let value = '';
+      let start = current;
+      current++;
+
+      while (current < input.length) {
+        let innerChar = input[current];
+        if (innerChar === '\\') {
+          value += input[current] + input[current + 1];
+          current += 2;
+        } else if (innerChar === input[start]) {
+          current++;
+          break;
+        } else {
+          value += innerChar;
+          current++;
+        }
+      }
+
+      tokens.push({ type: WhenTokenType.STRING, value });
+      continue;
+    }
+
+    if (isAlpha(char)) {
+      let value = '';
+      while (isAlpha(char)) {
+        value += char;
+        char = input[++current];
+      }
+
+      switch (value) {
+        case 'and':
+          tokens.push({ type: WhenTokenType.AND });
+          break;
+        case 'or':
+          tokens.push({ type: WhenTokenType.OR });
+          break;
+        case 'not':
+          tokens.push({ type: WhenTokenType.NOT });
+          break;
+        case 'eq':
+          tokens.push({ type: WhenTokenType.EQUALS });
+          break;
+        default:
+          while (isAlphaNumeric(char)) {
+            value += char;
+            char = input[++current];
+          }
+          tokens.push({ type: WhenTokenType.IDENTIFIER, value });
+      }
+
+      continue;
+    }
+    if (isAlphaNumeric(char)) {
+      let value = '';
+      while (isAlphaNumeric(char)) {
+        value += char;
+        char = input[++current];
+      }
+
+      tokens.push({ type: WhenTokenType.IDENTIFIER, value });
+      continue;
+    }
+    throw new TypeError(`I don't know what this character is: ${char}`);
+  }
+  return tokens;
+};
+
+type WhenAST = {
+  type: WhenTokenType;
+  left?: WhenAST;
+  right?: WhenAST;
+  value?: string | WhenAST;
+  name?: string;
+  args?: WhenAST[];
+};
+
+const precedence : { [index: string] : number } = {
+  'EQUALS': 4,
+  'NOT': 3,
+  'AND': 2,
+  'OR': 1,
+};
+
+const parseWhen = (whenExpression: string) => {
+  const tokens = lex(whenExpression);
+  let current = 0;
+
+  const walk = (precedenceLevel = 0) : WhenAST => {
+    let token = tokens[current];
+    let node: WhenAST | null = null;
+
+    if (token.type === WhenTokenType.OPEN_PAREN) {
+      token = tokens[++current];
+      let innerNode: WhenAST = { type: WhenTokenType.EXPRESSION, value: walk() };
+      token = tokens[current];
+
+      while (token.type !== WhenTokenType.CLOSE_PAREN) {
+        innerNode = {
+          type: token.type,
+          value: token.value,
+          left: innerNode,
+          right: walk(),
+        };
+        token = tokens[current];
+      }
+      current++;
+      return innerNode;
+    }
+
+    if (token.type === WhenTokenType.STRING ) {
+      current++;
+      node = { type: token.type, value: token.value };
+    }
+
+    if (token.type === WhenTokenType.NOT) {
+      token = tokens[++current];
+      node = { type: WhenTokenType.NOT, value: token.value, right: walk() };
+    }
+
+    if (token.type === WhenTokenType.IDENTIFIER) {
+      const nextToken = tokens[current + 1];
+      if (nextToken.type === WhenTokenType.OPEN_PAREN) {
+        let name = token.value;
+        token = tokens[++current];
+
+        let args = [];
+        token = tokens[++current];
+
+        while (token.type !== WhenTokenType.CLOSE_PAREN) {
+          if (token.type === WhenTokenType.COMMA) {
+            current++;
+          } else {
+            args.push(walk());
+          }
+          token = tokens[current];
+        }
+
+        current++;
+        node = { type: WhenTokenType.FUNCTION, name, args };
+      } else {
+        current++;
+        node = { type: WhenTokenType.IDENTIFIER, value: token.value };
+      }
+    }   
+
+    if (!node) throw new TypeError('Unexpected token: ' + token.type);
+
+    token = tokens[current];
+    while (current < tokens.length && precedence[token.type] >= precedenceLevel) {
+      console.log(current, tokens[current], tokens[current].type, precedenceLevel, precedence[token.type]);
+      token = tokens[current];
+      if (token.type === WhenTokenType.EQUALS || token.type === WhenTokenType.AND || token.type === WhenTokenType.OR) {
+        current++;
+        node = {
+          type: token.type,
+          left: node,
+          right: walk(precedence[token.type]),
+        };
+      } else {
+        break;
+      }
+    }
+
+    return node;
+   
+  };
+
+  return walk();
+};
+
+export {
+  parseWhen,
+  WhenAST,
+  WhenTokenType,
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts
new file mode 100644
index 0000000..2dbbae2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -0,0 +1,1625 @@
+/* eslint-disable @typescript-eslint/no-loss-of-precision */
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+/* eslint-disable @typescript-eslint/naming-convention */
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Token, Statement, Module, Identity, ModuleState } from '../models/yang';
+import {
+  Expression,
+  ViewElement,
+  ViewElementBase,
+  ViewSpecification,
+  ViewElementNumber,
+  ViewElementString,
+  ViewElementChoice,
+  ViewElementUnion,
+  ViewElementRpc,
+  isViewElementObjectOrList,
+  isViewElementNumber,
+  isViewElementString,
+  isViewElementRpc,
+  ResolveFunction,
+  YangRange,
+} from '../models/uiModels';
+import { yangService } from '../services/yangService';
+
+const LOGLEVEL = +(localStorage.getItem('log.odlux.app.configuration.yang.yangParser') || 0);
+
+import { LogLevel } from '../../../../framework/src/utilities/logLevel';
+import { parseWhen, WhenAST, WhenTokenType } from './whenParser';
+
+export const splitVPath = (vPath: string, vPathParser: RegExp): RegExpMatchArray[] => {
+  const pathParts: RegExpMatchArray[] = [];
+  let partMatch: RegExpExecArray | null;
+  if (vPath) do {
+    partMatch = vPathParser.exec(vPath);
+    if (partMatch) {
+      pathParts.push(partMatch);
+    }
+  } while (partMatch);
+  return pathParts;
+};
+
+class YangLexer {
+
+  private pos: number = 0;
+
+  private buf: string = '';
+
+  constructor(input: string) {
+    this.pos = 0;
+    this.buf = input;
+  }
+
+  private _opTable: { [key: string]: string } = {
+    ';': 'SEMI',
+    '{': 'L_BRACE',
+    '}': 'R_BRACE',
+  };
+
+  private _isNewline(char: string): boolean {
+    return char === '\r' || char === '\n';
+  }
+
+  private _isWhitespace(char: string): boolean {
+    return char === ' ' || char === '\t' || this._isNewline(char);
+  }
+
+  private _isDigit(char: string): boolean {
+    return char >= '0' && char <= '9';
+  }
+
+  private _isAlpha(char: string): boolean {
+    return (char >= 'a' && char <= 'z') ||
+      (char >= 'A' && char <= 'Z');
+  }
+
+  private _isAlphanum(char: string): boolean {
+    return this._isAlpha(char) || this._isDigit(char) ||
+      char === '_' || char === '-' || char === '.';
+  }
+
+  private _skipNonTokens() {
+    while (this.pos < this.buf.length) {
+      const char = this.buf.charAt(this.pos);
+      if (this._isWhitespace(char)) {
+        this.pos++;
+      } else {
+        break;
+      }
+    }
+  }
+
+  private _processString(terminator: string | null): Token {
+    // this.pos points at the opening quote. Find the ending quote.
+    let end_index = this.pos + 1;
+    while (end_index < this.buf.length) {
+      const char = this.buf.charAt(end_index);
+      if (char === '\\') {
+        end_index += 2;
+        continue;
+      }
+      if (terminator === null && (this._isWhitespace(char) || this._opTable[char] !== undefined) || char === terminator) {
+        break;
+      }
+      end_index++;
+    }
+
+    if (end_index >= this.buf.length) {
+      throw Error('Unterminated quote at ' + this.pos);
+    } else {
+      const start = this.pos + (terminator ? 1 : 0);
+      const end = end_index;
+      const tok = {
+        name: 'STRING',
+        value: this.buf.substring(start, end),
+        start,
+        end,
+      };
+      this.pos = terminator ? end + 1 : end;
+      return tok;
+    }
+  }
+
+  private _processIdentifier(): Token {
+    let endpos = this.pos + 1;
+    while (endpos < this.buf.length && this._isAlphanum(this.buf.charAt(endpos))) {
+      ++endpos;
+    }
+
+    let name = 'IDENTIFIER';
+    if (this.buf.charAt(endpos) === ':') {
+      name = 'IDENTIFIERREF';
+      ++endpos;
+      while (endpos < this.buf.length && this._isAlphanum(this.buf.charAt(endpos))) {
+        ++endpos;
+      }
+    }
+
+    const tok = {
+      name: name,
+      value: this.buf.substring(this.pos, endpos),
+      start: this.pos,
+      end: endpos,
+    };
+
+    this.pos = endpos;
+    return tok;
+  }
+
+  private _processNumber(): Token {
+    let endpos = this.pos + 1;
+    while (endpos < this.buf.length &&
+      this._isDigit(this.buf.charAt(endpos))) {
+      endpos++;
+    }
+
+    const tok = {
+      name: 'NUMBER',
+      value: this.buf.substring(this.pos, endpos),
+      start: this.pos,
+      end: endpos,
+    };
+    this.pos = endpos;
+    return tok;
+  }
+
+  private _processLineComment() {
+    var endpos = this.pos + 2;
+    // Skip until the end of the line
+    while (endpos < this.buf.length && !this._isNewline(this.buf.charAt(endpos))) {
+      endpos++;
+    }
+    this.pos = endpos + 1;
+  }
+
+  private _processBlockComment() {
+    var endpos = this.pos + 2;
+    // Skip until the end of the line
+    while (endpos < this.buf.length && !((this.buf.charAt(endpos) === '/' && this.buf.charAt(endpos - 1) === '*'))) {
+      endpos++;
+    }
+    this.pos = endpos + 1;
+  }
+
+  public tokenize(): Token[] {
+    const result: Token[] = [];
+    this._skipNonTokens();
+    while (this.pos < this.buf.length) {
+
+      const char = this.buf.charAt(this.pos);
+      const op = this._opTable[char];
+
+      if (op !== undefined) {
+        result.push({ name: op, value: char, start: this.pos, end: ++this.pos });
+      } else if (this._isAlpha(char)) {
+        result.push(this._processIdentifier());
+        this._skipNonTokens();
+        const peekChar = this.buf.charAt(this.pos);
+        if (this._opTable[peekChar] === undefined) {
+          result.push((peekChar !== '\'' && peekChar !== '"')
+            ? this._processString(null)
+            : this._processString(peekChar));
+        }
+      } else if (char === '/' && this.buf.charAt(this.pos + 1) === '/') {
+        this._processLineComment();
+      } else if (char === '/' && this.buf.charAt(this.pos + 1) === '*') {
+        this._processBlockComment();
+      } else {
+        throw Error('Token error at ' + this.pos + ' ' + this.buf[this.pos]);
+      }
+      this._skipNonTokens();
+    }
+    return result;
+  }
+
+  public tokenize2(): Statement {
+    let stack: Statement[] = [{ key: 'ROOT', sub: [] }];
+    let current: Statement | null = null;
+
+    this._skipNonTokens();
+    while (this.pos < this.buf.length) {
+
+      const char = this.buf.charAt(this.pos);
+      const op = this._opTable[char];
+
+      if (op !== undefined) {
+        if (op === 'L_BRACE') {
+          current && stack.unshift(current);
+          current = null;
+        } else if (op === 'R_BRACE') {
+          current = stack.shift() || null;
+        }
+        this.pos++;
+      } else if (this._isAlpha(char) || char === '_') {
+        const key = this._processIdentifier().value;
+        this._skipNonTokens();
+        let peekChar = this.buf.charAt(this.pos);
+        let arg = undefined;
+        if (this._opTable[peekChar] === undefined) {
+          arg = (peekChar === '"' || peekChar === '\'')
+            ? this._processString(peekChar).value
+            : this._processString(null).value;
+        }
+        do {
+          this._skipNonTokens();
+          peekChar = this.buf.charAt(this.pos);
+          if (peekChar !== '+') break;
+          this.pos++;
+          this._skipNonTokens();
+          peekChar = this.buf.charAt(this.pos);
+          arg += (peekChar === '"' || peekChar === '\'')
+            ? this._processString(peekChar).value
+            : this._processString(null).value;
+        } while (true);
+        current = { key, arg, sub: [] };
+        stack[0].sub!.push(current);
+      } else if (char === '/' && this.buf.charAt(this.pos + 1) === '/') {
+        this._processLineComment();
+      } else if (char === '/' && this.buf.charAt(this.pos + 1) === '*') {
+        this._processBlockComment();
+      } else {
+        throw Error('Token error at ' + this.pos + ' ' + this.buf.slice(this.pos - 10, this.pos + 10));
+      }
+      this._skipNonTokens();
+    }
+    if (stack[0].key !== 'ROOT' || !stack[0].sub![0]) {
+      throw new Error('Internal Perser Error');
+    }
+    return stack[0].sub![0];
+  }
+}
+
+export class YangParser {
+  private _groupingsToResolve: ViewSpecification[] = [];
+
+  private _typeRefToResolve: (() => void)[] = [];
+
+  private _identityToResolve: (() => void)[] = [];
+
+  private _unionsToResolve: (() => void)[] = [];
+
+  private _modulesToResolve: (() => void)[] = [];
+
+  private _modules: { [name: string]: Module } = {};
+
+  private _views: ViewSpecification[] = [{
+    id: '0',
+    name: 'root',
+    language: 'en-US',
+    canEdit: false,
+    config: true,
+    parentView: '0',
+    title: 'root',
+    elements: {},
+  }];
+
+  public static ResolveStack = Symbol('ResolveStack');
+
+  constructor(
+    private nodeId: string,
+    private _capabilityRevisionMap: { [capability: string]: string } = {},
+    private _unavailableCapabilities: { failureReason: string; capability: string }[] = [],
+    private _importOnlyModules: { name: string; revision: string }[] = [],
+  ) {
+
+  }
+
+  public get modules() {
+    return this._modules;
+  }
+
+  public get views() {
+    return this._views;
+  }
+
+  public async addCapability(capability: string, version?: string, parentImportOnlyModule?: boolean) {
+    // do not add twice
+    const existingCapability = this._modules[capability];
+    const latestVersionExisting = existingCapability && Object.keys(existingCapability.revisions).sort().reverse()[0];
+    if ((latestVersionExisting && version) && (version <= latestVersionExisting)) {
+      if (LOGLEVEL == LogLevel.Warning) {
+        console.warn(`Skipped capability: ${capability}:${version || ''} since already contained.`);
+      }
+      return;
+    }
+
+    // // do not add unavailable capabilities
+    // if (this._unavailableCapabilities.some(c => c.capability === capability)) {
+    //   // console.warn(`Skipped capability: ${capability} since it is marked as unavailable.` );
+    //   return;
+    // }
+
+    const data = await yangService.getCapability(capability, this.nodeId, version);
+    if (!data) {
+      throw new Error(`Could not load yang file for ${capability}:${version || ''}.`);
+    }
+
+    const rootStatement = new YangLexer(data).tokenize2();
+
+    if (rootStatement.key !== 'module') {
+      throw new Error(`Root element of ${capability} is not a module.`);
+    }
+    if (rootStatement.arg !== capability) {
+      throw new Error(`Root element capability ${rootStatement.arg} does not requested ${capability}.`);
+    }
+
+    const isUnavailable = this._unavailableCapabilities.some(c => c.capability === capability);
+    const isImportOnly = parentImportOnlyModule === true || this._importOnlyModules.some(c => c.name === capability);
+
+    // extract revisions
+    const revisions = this.extractNodes(rootStatement, 'revision').reduce<{ [version: string]: {} }>((acc, revision) => {
+      if (!revision.arg) {
+        throw new Error(`Module [${rootStatement.arg}] has a version w/o version number.`);
+      }
+      const description = this.extractValue(revision, 'description');
+      const reference = this.extractValue(revision, 'reference');
+      acc[revision.arg] = {
+        description,
+        reference,
+      };
+      return acc;
+    }, {});
+
+    const latestVersionLoaded = Object.keys(revisions).sort().reverse()[0];
+    if (existingCapability && latestVersionExisting >= latestVersionLoaded) {
+      if (LOGLEVEL == LogLevel.Warning) {
+        console.warn(`Skipped capability: ${capability}:${latestVersionLoaded} since ${capability}:${latestVersionExisting} already contained.`);
+      }
+      return;
+    }
+    
+    const module = this._modules[capability] = {
+      name: rootStatement.arg,
+      revisions,
+      imports: {},
+      features: {},
+      identities: {},
+      augments: {},
+      groupings: {},
+      typedefs: {},
+      views: {},
+      elements: {},
+      state: isUnavailable
+        ? ModuleState.unavailable
+        : isImportOnly
+          ? ModuleState.importOnly
+          : ModuleState.stable,
+    };
+
+    await this.handleModule(module, rootStatement, capability);
+  }
+
+  private async handleModule(module: Module, rootStatement: Statement, capability: string) {
+
+    // extract namespace && prefix
+    module.namespace = this.extractValue(rootStatement, 'namespace');
+    module.prefix = this.extractValue(rootStatement, 'prefix');
+    if (module.prefix) {
+      module.imports[module.prefix] = capability;
+    }
+
+    // extract features
+    const features = this.extractNodes(rootStatement, 'feature');
+    module.features = {
+      ...module.features,
+      ...features.reduce<{ [version: string]: {} }>((acc, feature) => {
+        if (!feature.arg) {
+          throw new Error(`Module [${module.name}] has a feature w/o name.`);
+        }
+        const description = this.extractValue(feature, 'description');
+        acc[feature.arg] = {
+          description,
+        };
+        return acc;
+      }, {}),
+    };
+
+    // extract imports
+    const imports = this.extractNodes(rootStatement, 'import');
+    module.imports = {
+      ...module.imports,
+      ...imports.reduce<{ [key: string]: string }>((acc, imp) => {
+        const prefix = imp.sub && imp.sub.filter(s => s.key === 'prefix');
+        if (!imp.arg) {
+          throw new Error(`Module [${module.name}] has an import with neither name nor prefix.`);
+        }
+        acc[prefix && prefix.length === 1 && prefix[0].arg || imp.arg] = imp.arg;
+        return acc;
+      }, {}),
+    };
+
+    // import all required files and set module state 
+    if (imports) for (let ind = 0; ind < imports.length; ++ind) {
+      const moduleName = imports[ind].arg!;
+
+      const revision = this._capabilityRevisionMap[moduleName] || undefined;
+      await this.addCapability(moduleName, revision, module.state === ModuleState.importOnly);
+      const importedModule = this._modules[imports[ind].arg!];
+      if (importedModule && importedModule.state > ModuleState.stable) {
+        module.state = Math.max(module.state, ModuleState.instable);
+      }
+    }
+
+    this.extractTypeDefinitions(rootStatement, module, '');
+
+    this.extractIdentities(rootStatement, 0, module, '');
+
+    const groupings = this.extractGroupings(rootStatement, 0, module, '');
+    this._views.push(...groupings);
+
+    const augments = this.extractAugments(rootStatement, 0, module, '');
+    this._views.push(...augments);
+
+    // the default for config on module level is config = true;
+    const [currentView, subViews] = this.extractSubViews(rootStatement, 0, module, '');
+    this._views.push(currentView, ...subViews);
+
+    // create the root elements for this module
+    module.elements = currentView.elements;
+    this._modulesToResolve.push(() => {
+      Object.keys(module.elements).forEach(key => {
+        const viewElement = module.elements[key];
+        if (!(isViewElementObjectOrList(viewElement) || isViewElementRpc(viewElement))) {
+          console.error(new Error(`Module: [${module}]. Only Object, List or RPC are allowed on root level.`));
+        }
+        if (isViewElementObjectOrList(viewElement)) {
+          const viewIdIndex = Number(viewElement.viewId);
+          module.views[key] = this._views[viewIdIndex];
+        }
+
+        // add only the UI View if the module is available
+        if (module.state === ModuleState.stable || module.state === ModuleState.instable) this._views[0].elements[key] = module.elements[key];
+      });
+    });
+    return module;
+  }
+
+  public postProcess() {
+
+    // execute all post processes like resolving in proper order
+    this._unionsToResolve.forEach(cb => {
+      try { cb(); } catch (error) {
+        console.warn(error.message);
+      }
+    });
+
+    // process all groupings
+    this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => {
+      try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!('|'); } catch (error) {
+        console.warn(`Error resolving: [${vs.name}] [${error.message}]`);
+      }
+    });
+
+    /**
+     * This is to fix the issue for sequential execution of modules based on their child and parent relationship
+     * We are sorting the module object based on their augment status
+     */
+    Object.keys(this.modules)
+      .map(elem => {
+        if (this.modules[elem].augments && Object.keys(this.modules[elem].augments).length > 0) {
+          const { augments, ..._rest } = this.modules[elem];
+          const partsOfKeys = Object.keys(augments).map((key) => (key.split('/').length - 1));
+          this.modules[elem].executionOrder = Math.max(...partsOfKeys);
+        } else {
+          this.modules[elem].executionOrder = 0;
+        }
+      });
+
+    // process all augmentations / sort by namespace changes to ensure proper order 
+    Object.keys(this.modules).sort((a, b) => this.modules[a].executionOrder! - this.modules[b].executionOrder!).forEach(modKey => {
+      const module = this.modules[modKey];
+      const augmentKeysWithCounter = Object.keys(module.augments).map((key) => {
+        const pathParts = splitVPath(key, /(?:(?:([^\/\:]+):)?([^\/]+))/g);  // 1 = opt: namespace / 2 = property 
+        let nameSpaceChangeCounter = 0;
+        let currentNS = module.name; // init namespace
+        pathParts.forEach(([ns, _]) => {
+          if (ns === currentNS) {
+            currentNS = ns;
+            nameSpaceChangeCounter++;
+          }
+        });
+        return {
+          key,
+          nameSpaceChangeCounter,
+        };
+      });
+
+      const augmentKeys = augmentKeysWithCounter
+        .sort((a, b) => a.nameSpaceChangeCounter > b.nameSpaceChangeCounter ? 1 : a.nameSpaceChangeCounter === b.nameSpaceChangeCounter ? 0 : -1)
+        .map((a) => a.key);
+
+      augmentKeys.forEach(augKey => {
+        const augments = module.augments[augKey];
+        const viewSpec = this.resolveView(augKey);
+        if (!viewSpec) console.warn(`Could not find view to augment [${augKey}] in [${module.name}].`);
+        if (augments && viewSpec) {
+          augments.forEach(augment => Object.keys(augment.elements).forEach(key => {
+            const elm = augment.elements[key];
+            
+            const when = elm.when && augment.when
+              ? {
+                type: WhenTokenType.AND,
+                left: elm.when,
+                right: augment.when,
+              }
+              : elm.when || augment.when;
+            
+            const ifFeature = elm.ifFeature
+              ? `(${augment.ifFeature}) and (${elm.ifFeature})`
+              : augment.ifFeature;
+            
+            viewSpec.elements[key] = {
+              ...augment.elements[key],
+              when,
+              ifFeature,
+            };
+          }));
+        }
+      });
+    });
+
+    // process Identities
+    const traverseIdentity = (identities: Identity[]) => {
+      const result: Identity[] = [];
+      for (let identity of identities) {
+        if (identity.children && identity.children.length > 0) {
+          result.push(...traverseIdentity(identity.children));
+        } else {
+          result.push(identity);
+        }
+      }
+      return result;
+    };
+
+    const baseIdentities: Identity[] = [];
+    Object.keys(this.modules).forEach(modKey => {
+      const module = this.modules[modKey];
+      Object.keys(module.identities).forEach(idKey => {
+        const identity = module.identities[idKey];
+        if (identity.base != null) {
+          const base = this.resolveIdentity(identity.base, module);
+          base.children?.push(identity);
+        } else {
+          baseIdentities.push(identity);
+        }
+      });
+    });
+    baseIdentities.forEach(identity => {
+      identity.values = identity.children && traverseIdentity(identity.children) || [];
+    });
+
+    this._identityToResolve.forEach(cb => {
+      try { cb(); } catch (error) {
+        console.warn(error.message);
+      }
+    });
+
+    this._typeRefToResolve.forEach(cb => {
+      try { cb(); } catch (error) {
+        console.warn(error.message);
+      }
+    });
+
+    this._modulesToResolve.forEach(cb => {
+      try { cb(); } catch (error) {
+        console.warn(error.message);
+      }
+    });
+
+    // resolve readOnly
+    const resolveReadOnly = (view: ViewSpecification, parentConfig: boolean) => {
+
+      // update view config
+      view.config = view.config && parentConfig;
+
+      Object.keys(view.elements).forEach((key) => {
+        const elm = view.elements[key];
+
+        // update element config
+        elm.config = elm.config && view.config;
+
+        // update all sub-elements of objects
+        if (elm.uiType === 'object') {
+          resolveReadOnly(this.views[+elm.viewId], elm.config);
+        }
+
+      });
+    };
+
+    const dump = resolveReadOnly(this.views[0], true);
+    if (LOGLEVEL > 2) {
+      console.log('Resolved views:', dump);
+    }
+  }
+
+  private _nextId = 1;
+
+  private get nextId() {
+    return this._nextId++;
+  }
+
+  private extractNodes(statement: Statement, key: string): Statement[] {
+    return statement.sub && statement.sub.filter(s => s.key === key) || [];
+  }
+
+  private extractValue(statement: Statement, key: string): string | undefined;
+  private extractValue(statement: Statement, key: string, parser: RegExp): RegExpExecArray | undefined;
+  private extractValue(statement: Statement, key: string, parser?: RegExp): string | RegExpExecArray | undefined {
+    const typeNodes = this.extractNodes(statement, key);
+    const rawValue = typeNodes.length > 0 && typeNodes[0].arg || undefined;
+    return parser
+      ? rawValue && parser.exec(rawValue) || undefined
+      : rawValue;
+  }
+
+  private extractTypeDefinitions(statement: Statement, module: Module, currentPath: string): void {
+    const typedefs = this.extractNodes(statement, 'typedef');
+    typedefs && typedefs.forEach(def => {
+      if (!def.arg) {
+        throw new Error(`Module: [${module.name}]. Found typedef without name.`);
+      }
+      module.typedefs[def.arg] = this.getViewElement(def, module, 0, currentPath, false);
+    });
+  }
+
+  /** Handles groupings like named Container */
+  private extractGroupings(statement: Statement, parentId: number, module: Module, currentPath: string): ViewSpecification[] {
+    const subViews: ViewSpecification[] = [];
+    const groupings = this.extractNodes(statement, 'grouping');
+    if (groupings && groupings.length > 0) {
+      subViews.push(...groupings.reduce<ViewSpecification[]>((acc, cur) => {
+        if (!cur.arg) {
+          throw new Error(`Module: [${module.name}][${currentPath}]. Found grouping without name.`);
+        }
+        const grouping = cur.arg;
+
+        // the default for config on module level is config = true;
+        const [currentView, currentSubViews] = this.extractSubViews(cur, /* parentId */ -1, module, currentPath);
+        grouping && (module.groupings[grouping] = currentView);
+        acc.push(currentView, ...currentSubViews);
+        return acc;
+      }, []));
+    }
+
+    return subViews;
+  }
+
+  /** Handles augments also like named container */
+  private extractAugments(statement: Statement, parentId: number, module: Module, currentPath: string): ViewSpecification[] {
+    const subViews: ViewSpecification[] = [];
+    const augments = this.extractNodes(statement, 'augment');
+    if (augments && augments.length > 0) {
+      subViews.push(...augments.reduce<ViewSpecification[]>((acc, cur) => {
+        if (!cur.arg) {
+          throw new Error(`Module: [${module.name}][${currentPath}]. Found augment without path.`);
+        }
+        const augment = this.resolveReferencePath(cur.arg, module);
+
+        // the default for config on module level is config = true;
+        const [currentView, currentSubViews] = this.extractSubViews(cur, parentId, module, currentPath);
+        if (augment) {
+          module.augments[augment] = module.augments[augment] || [];
+          module.augments[augment].push(currentView);
+        }
+        acc.push(currentView, ...currentSubViews);
+        return acc;
+      }, []));
+    }
+
+    return subViews;
+  }
+
+  /** Handles identities  */
+  private extractIdentities(statement: Statement, parentId: number, module: Module, currentPath: string) {
+    const identities = this.extractNodes(statement, 'identity');
+    module.identities = identities.reduce<{ [name: string]: Identity }>((acc, cur) => {
+      if (!cur.arg) {
+        throw new Error(`Module: [${module.name}][${currentPath}]. Found identity without name.`);
+      }
+      acc[cur.arg] = {
+        id: `${module.name}:${cur.arg}`,
+        label: cur.arg,
+        base: this.extractValue(cur, 'base'),
+        description: this.extractValue(cur, 'description'),
+        reference: this.extractValue(cur, 'reference'),
+        children: [],
+      };
+      return acc;
+    }, {});
+  }
+
+  // Hint: use 0 as parentId for rootElements and -1 for rootGroupings.
+  private extractSubViews(statement: Statement, parentId: number, module: Module, currentPath: string): [ViewSpecification, ViewSpecification[]] {
+    // used for scoped definitions
+    const context: Module = {
+      ...module,
+      typedefs: {
+        ...module.typedefs,
+      },
+    };
+
+    const currentId = this.nextId;
+    const subViews: ViewSpecification[] = [];
+    let elements: ViewElement[] = [];
+
+    const configValue = this.extractValue(statement, 'config');
+    const config = configValue == null ? true : configValue.toLocaleLowerCase() !== 'false';
+
+    // extract conditions
+    const ifFeature = this.extractValue(statement, 'if-feature');
+    const whenCondition = this.extractValue(statement, 'when');
+    if (whenCondition) console.warn('Found in [' + context.name + ']' + currentPath + ' when: ' + whenCondition);
+
+    // extract all scoped typedefs
+    this.extractTypeDefinitions(statement, context, currentPath);
+
+    // extract all scoped groupings
+    subViews.push(
+      ...this.extractGroupings(statement, parentId, context, currentPath),
+    );
+
+    // extract all container
+    const container = this.extractNodes(statement, 'container');
+    if (container && container.length > 0) {
+      subViews.push(...container.reduce<ViewSpecification[]>((acc, cur) => {
+        if (!cur.arg) {
+          throw new Error(`Module: [${context.name}]${currentPath}. Found container without name.`);
+        }
+        const [currentView, currentSubViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
+        elements.push({
+          id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
+          label: cur.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
+          uiType: 'object',
+          viewId: currentView.id,
+          config: currentView.config,
+        });
+        acc.push(currentView, ...currentSubViews);
+        return acc;
+      }, []));
+    }
+
+    // process all lists
+    // a list is a list of containers with the leafs contained in the list
+    const lists = this.extractNodes(statement, 'list');
+    if (lists && lists.length > 0) {
+      subViews.push(...lists.reduce<ViewSpecification[]>((acc, cur) => {
+        let elmConfig = config;
+        if (!cur.arg) {
+          throw new Error(`Module: [${context.name}]${currentPath}. Found list without name.`);
+        }
+        const key = this.extractValue(cur, 'key') || undefined;
+        if (elmConfig && !key) {
+          console.warn(`Module: [${context.name}]${currentPath}. Found configurable list without key. Assume config shell be false.`);
+          elmConfig = false;
+        }
+        const [currentView, currentSubViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
+        elements.push({
+          id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
+          label: cur.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
+          isList: true,
+          uiType: 'object',
+          viewId: currentView.id,
+          key: key,
+          config: elmConfig && currentView.config,
+        });
+        acc.push(currentView, ...currentSubViews);
+        return acc;
+      }, []));
+    }
+
+    // process all leaf-lists
+    // a leaf-list is a list of some type
+    const leafLists = this.extractNodes(statement, 'leaf-list');
+    if (leafLists && leafLists.length > 0) {
+      elements.push(...leafLists.reduce<ViewElement[]>((acc, cur) => {
+        const element = this.getViewElement(cur, context, parentId, currentPath, true);
+        element && acc.push(element);
+        return acc;
+      }, []));
+    }
+
+    // process all leafs
+    // a leaf is mainly a property of an object
+    const leafs = this.extractNodes(statement, 'leaf');
+    if (leafs && leafs.length > 0) {
+      elements.push(...leafs.reduce<ViewElement[]>((acc, cur) => {
+        const element = this.getViewElement(cur, context, parentId, currentPath, false);
+        element && acc.push(element);
+        return acc;
+      }, []));
+    }
+
+
+    const choiceStms = this.extractNodes(statement, 'choice');
+    if (choiceStms && choiceStms.length > 0) {
+      elements.push(...choiceStms.reduce<ViewElementChoice[]>((accChoice, curChoice) => {
+        if (!curChoice.arg) {
+          throw new Error(`Module: [${context.name}]${currentPath}. Found choise without name.`);
+        }
+        // extract all cases like containers
+        const cases: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } }[] = [];
+        const caseStms = this.extractNodes(curChoice, 'case');
+        if (caseStms && caseStms.length > 0) {
+          cases.push(...caseStms.reduce((accCase, curCase) => {
+            if (!curCase.arg) {
+              throw new Error(`Module: [${context.name}]${currentPath}/${curChoice.arg}. Found case without name.`);
+            }
+            const description = this.extractValue(curCase, 'description') || undefined;
+            const [caseView, caseSubViews] = this.extractSubViews(curCase, parentId, context, `${currentPath}/${context.name}:${curChoice.arg}`);
+            subViews.push(caseView, ...caseSubViews);
+
+            const caseDef: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } } = {
+              id: parentId === 0 ? `${context.name}:${curCase.arg}` : curCase.arg,
+              label: curCase.arg,
+              description: description,
+              elements: caseView.elements,
+            };
+            accCase.push(caseDef);
+            return accCase;
+          }, [] as { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } }[]));
+        }
+
+        // extract all simple cases (one case per leaf, container, etc.)
+        const [choiceView, choiceSubViews] = this.extractSubViews(curChoice, parentId, context, `${currentPath}/${context.name}:${curChoice.arg}`);
+        subViews.push(choiceView, ...choiceSubViews);
+        cases.push(...Object.keys(choiceView.elements).reduce((accElm, curElm) => {
+          const elm = choiceView.elements[curElm];
+          const caseDef: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } } = {
+            id: elm.id,
+            label: elm.label,
+            description: elm.description,
+            elements: { [elm.id]: elm },
+          };
+          accElm.push(caseDef);
+          return accElm;
+        }, [] as { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } }[]));
+
+        const choiceDescription = this.extractValue(curChoice, 'description') || undefined;
+        const choiceConfigValue = this.extractValue(curChoice, 'config');
+        const choiceConfig = choiceConfigValue == null ? true : choiceConfigValue.toLocaleLowerCase() !== 'false';
+
+        const mandatory = this.extractValue(curChoice, 'mandatory') === 'true' || false;
+
+        const element: ViewElementChoice = {
+          uiType: 'choice',
+          id: parentId === 0 ? `${context.name}:${curChoice.arg}` : curChoice.arg,
+          label: curChoice.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
+          config: choiceConfig,
+          mandatory: mandatory,
+          description: choiceDescription,
+          cases: cases.reduce((acc, cur) => {
+            acc[cur.id] = cur;
+            return acc;
+          }, {} as { [name: string]: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } } }),
+        };
+
+        accChoice.push(element);
+        return accChoice;
+      }, []));
+    }
+
+    const rpcStms = this.extractNodes(statement, 'rpc');
+    if (rpcStms && rpcStms.length > 0) {
+      elements.push(...rpcStms.reduce<ViewElementRpc[]>((accRpc, curRpc) => {
+        if (!curRpc.arg) {
+          throw new Error(`Module: [${context.name}]${currentPath}. Found rpc without name.`);
+        }
+
+        const rpcDescription = this.extractValue(curRpc, 'description') || undefined;
+        const rpcConfigValue = this.extractValue(curRpc, 'config');
+        const rpcConfig = rpcConfigValue == null ? true : rpcConfigValue.toLocaleLowerCase() !== 'false';
+
+        let inputViewId: string | undefined = undefined;
+        let outputViewId: string | undefined = undefined;
+
+        const input = this.extractNodes(curRpc, 'input') || undefined;
+        const output = this.extractNodes(curRpc, 'output') || undefined;
+
+        if (input && input.length > 0) {
+          const [inputView, inputSubViews] = this.extractSubViews(input[0], parentId, context, `${currentPath}/${context.name}:${curRpc.arg}`);
+          subViews.push(inputView, ...inputSubViews);
+          inputViewId = inputView.id;
+        }
+
+        if (output && output.length > 0) {
+          const [outputView, outputSubViews] = this.extractSubViews(output[0], parentId, context, `${currentPath}/${context.name}:${curRpc.arg}`);
+          subViews.push(outputView, ...outputSubViews);
+          outputViewId = outputView.id;
+        }
+
+        const element: ViewElementRpc = {
+          uiType: 'rpc',
+          id: parentId === 0 ? `${context.name}:${curRpc.arg}` : curRpc.arg,
+          label: curRpc.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
+          config: rpcConfig,
+          description: rpcDescription,
+          inputViewId: inputViewId,
+          outputViewId: outputViewId,
+        };
+
+        accRpc.push(element);
+
+        return accRpc;
+      }, []));
+    }
+
+    if (!statement.arg) {
+      console.error(new Error(`Module: [${context.name}]. Found statement without name.`));
+    }
+
+    let whenParsed: WhenAST | undefined = undefined;
+    try {
+      whenParsed = whenCondition && parseWhen(whenCondition) || undefined;
+    } catch (e) {
+      console.error(new Error(`Module: [${context.name}]. Found invalid when condition: ${whenCondition}`));
+    }
+
+    const viewSpec: ViewSpecification = {
+      id: String(currentId),
+      parentView: String(parentId),
+      ns: context.name,
+      name: statement.arg != null ? statement.arg : undefined,
+      title: statement.arg != null ? statement.arg : undefined,
+      language: 'en-us',
+      canEdit: false,
+      config: config,
+      ifFeature: ifFeature,
+      when: whenParsed,
+      elements: elements.reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+        acc[cur.id] = cur;
+        return acc;
+      }, {}),
+    };
+
+    // evaluate canEdit depending on all conditions
+    Object.defineProperty(viewSpec, 'canEdit', {
+      get: () => {
+        return Object.keys(viewSpec.elements).some(key => {
+          const elm = viewSpec.elements[key];
+          return (!isViewElementObjectOrList(elm) && elm.config);
+        });
+      },
+    });
+
+    // merge in all uses references and resolve groupings
+    const usesRefs = this.extractNodes(statement, 'uses');
+    if (usesRefs && usesRefs.length > 0) {
+
+      viewSpec.uses = (viewSpec.uses || []);
+      const resolveFunctions: ((parentElementPath: string) => void)[] = [];
+
+      for (let i = 0; i < usesRefs.length; ++i) {
+        const groupingName = usesRefs[i].arg;
+        if (!groupingName) {
+          throw new Error(`Module: [${context.name}]. Found an uses statement without a grouping name.`);
+        }
+
+        viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
+
+        resolveFunctions.push((parentElementPath: string) => {
+          const groupingViewSpec = this.resolveGrouping(groupingName, context);
+          if (groupingViewSpec) {
+
+            // resolve recursive
+            const resolveFunc = groupingViewSpec.uses && groupingViewSpec.uses[ResolveFunction];
+            resolveFunc && resolveFunc(parentElementPath);
+
+            Object.keys(groupingViewSpec.elements).forEach(key => {
+              const elm = groupingViewSpec.elements[key];
+              // a useRef on root level need a namespace
+              const resolvedWhen = elm.when && groupingViewSpec.when
+                ? {
+                  type: WhenTokenType.AND,
+                  left: elm.when,
+                  right: groupingViewSpec.when,
+                }
+                : elm.when || groupingViewSpec.when;  
+              
+              const resolvedIfFeature = elm.ifFeature
+                ? `(${groupingViewSpec.ifFeature}) and (${elm.ifFeature})`
+                : groupingViewSpec.ifFeature;
+
+              viewSpec.elements[parentId === 0 ? `${module.name}:${key}` : key] = {
+                ...elm,
+                when: resolvedWhen,
+                ifFeature: resolvedIfFeature,
+              };
+            });
+          }
+        });
+      }
+
+      viewSpec.uses[ResolveFunction] = (parentElementPath: string) => {
+        const currentElementPath = `${parentElementPath} -> ${viewSpec.ns}:${viewSpec.name}`;
+        resolveFunctions.forEach(resolve => {
+          try {
+            resolve(currentElementPath);
+          } catch (error) {
+            console.error(error);
+          }
+        });
+        // console.log("Resolved "+currentElementPath, viewSpec);
+        if (viewSpec?.uses) {
+          viewSpec.uses[ResolveFunction] = undefined;
+        }
+      };
+
+      this._groupingsToResolve.push(viewSpec);
+    }
+
+    return [viewSpec, subViews];
+  }
+
+  // https://tools.ietf.org/html/rfc7950#section-9.3.4
+  private static decimalRange = [
+    { min: -9223372036854775808, max: 9223372036854775807 },
+    { min: -922337203685477580.8, max: 922337203685477580.7 },
+    { min: -92233720368547758.08, max: 92233720368547758.07 },
+    { min: -9223372036854775.808, max: 9223372036854775.807 },
+    { min: -922337203685477.5808, max: 922337203685477.5807 },
+    { min: -92233720368547.75808, max: 92233720368547.75807 },
+    { min: -9223372036854.775808, max: 9223372036854.775807 },
+    { min: -922337203685.4775808, max: 922337203685.4775807 },
+    { min: -92233720368.54775808, max: 92233720368.54775807 },
+    { min: -9223372036.854775808, max: 9223372036.854775807 },
+    { min: -922337203.6854775808, max: 922337203.6854775807 },
+    { min: -92233720.36854775808, max: 92233720.36854775807 },
+    { min: -9223372.036854775808, max: 9223372.036854775807 },
+    { min: -922337.2036854775808, max: 922337.2036854775807 },
+    { min: -92233.72036854775808, max: 92233.72036854775807 },
+    { min: -9223.372036854775808, max: 9223.372036854775807 },
+    { min: -922.3372036854775808, max: 922.3372036854775807 },
+    { min: -92.23372036854775808, max: 92.23372036854775807 },
+    { min: -9.223372036854775808, max: 9.223372036854775807 },
+  ];
+
+  /** Extracts the UI View from the type in the cur statement. */
+  private getViewElement(cur: Statement, module: Module, parentId: number, currentPath: string, isList: boolean): ViewElement {
+
+    const type = this.extractValue(cur, 'type');
+    const defaultVal = this.extractValue(cur, 'default') || undefined;
+    const description = this.extractValue(cur, 'description') || undefined;
+
+    const configValue = this.extractValue(cur, 'config');
+    const config = configValue == null ? true : configValue.toLocaleLowerCase() !== 'false';
+
+    const extractRange = (min: number, max: number, property: string = 'range'): { expression: Expression<YangRange> | undefined; min: number; max: number } => {
+      const ranges = this.extractValue(this.extractNodes(cur, 'type')[0]!, property) || undefined;
+      const range = ranges?.replace(/min/i, String(min)).replace(/max/i, String(max)).split('|').map(r => {
+        let minValue: number;
+        let maxValue: number;
+
+        if (r.indexOf('..') > -1) {
+          const [minStr, maxStr] = r.split('..');
+          minValue = Number(minStr);
+          maxValue = Number(maxStr);
+        } else if (!isNaN(maxValue = Number(r && r.trim()))) {
+          minValue = maxValue;
+        } else {
+          minValue = min,
+          maxValue = max;
+        }
+
+        if (minValue > min) min = minValue;
+        if (maxValue < max) max = maxValue;
+
+        return {
+          min: minValue,
+          max: maxValue,
+        };
+      });
+      return {
+        min: min,
+        max: max,
+        expression: range && range.length === 1
+          ? range[0]
+          : range && range.length > 1
+            ? { operation: 'OR', arguments: range }
+            : undefined,
+      };
+    };
+
+    const extractPattern = (): Expression<RegExp> | undefined => {
+    // 2023.01.26 decision MF & SKO: we will no longer remove the backslashes from the pattern, seems to be a bug in the original code
+      const pattern = this.extractNodes(this.extractNodes(cur, 'type')[0]!, 'pattern').map(p => p.arg!).filter(p => !!p).map(p => `^${p/*.replace(/(?:\\(.))/g, '$1')*/}$`);
+      return pattern && pattern.length == 1
+        ? new RegExp(pattern[0])
+        : pattern && pattern.length > 1
+          ? { operation: 'AND', arguments: pattern.map(p => new RegExp(p)) }
+          : undefined;
+    };
+
+    const mandatory = this.extractValue(cur, 'mandatory') === 'true' || false;
+
+    if (!cur.arg) {
+      throw new Error(`Module: [${module.name}]. Found element without name.`);
+    }
+
+    if (!type) {
+      throw new Error(`Module: [${module.name}].[${cur.arg}]. Found element without type.`);
+    }
+
+    const element: ViewElementBase = {
+      id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
+      label: cur.arg,
+      path: currentPath,
+      module: module.name || '',
+      config: config,
+      mandatory: mandatory,
+      isList: isList,
+      default: defaultVal,
+      description: description,
+    };
+
+    if (type === 'string') {
+      const length = extractRange(0, +18446744073709551615, 'length');
+      return ({
+        ...element,
+        uiType: 'string',
+        length: length.expression,
+        pattern: extractPattern(),
+      });
+    } else if (type === 'boolean') {
+      return ({
+        ...element,
+        uiType: 'boolean',
+      });
+    } else if (type === 'uint8') {
+      const range = extractRange(0, +255);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'uint16') {
+      const range = extractRange(0, +65535);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'uint32') {
+      const range = extractRange(0, +4294967295);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'uint64') {
+      const range = extractRange(0, +18446744073709551615);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'int8') {
+      const range = extractRange(-128, +127);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'int16') {
+      const range = extractRange(-32768, +32767);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'int32') {
+      const range = extractRange(-2147483648, +2147483647);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'int64') {
+      const range = extractRange(-9223372036854775808, +9223372036854775807);
+      return ({
+        ...element,
+        uiType: 'number',
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'decimal64') {
+      // decimalRange
+      const fDigits = Number(this.extractValue(this.extractNodes(cur, 'type')[0]!, 'fraction-digits')) || -1;
+      if (fDigits === -1) {
+        throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found decimal64 with invalid fraction-digits.`);
+      }
+      const range = extractRange(YangParser.decimalRange[fDigits].min, YangParser.decimalRange[fDigits].max);
+      return ({
+        ...element,
+        uiType: 'number',
+        fDigits: fDigits,
+        range: range.expression,
+        min: range.min,
+        max: range.max,
+        units: this.extractValue(cur, 'units') || undefined,
+        format: this.extractValue(cur, 'format') || undefined,
+      });
+    } else if (type === 'enumeration') {
+      const typeNode = this.extractNodes(cur, 'type')[0]!;
+      const enumNodes = this.extractNodes(typeNode, 'enum');
+      return ({
+        ...element,
+        uiType: 'selection',
+        options: enumNodes.reduce<{ key: string; value: string; description?: string }[]>((acc, enumNode) => {
+          if (!enumNode.arg) {
+            throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found option without name.`);
+          }
+          // const ifClause = this.extractValue(enumNode, 'if-feature');
+          const value = this.extractValue(enumNode, 'value');
+          const enumOption = {
+            key: enumNode.arg,
+            value: value != null ? value : enumNode.arg,
+            description: this.extractValue(enumNode, 'description') || undefined,
+          };
+          // todo: ❗ handle the if clause ⚡
+          acc.push(enumOption);
+          return acc;
+        }, []),
+      });
+    } else if (type === 'leafref') {
+      const typeNode = this.extractNodes(cur, 'type')[0]!;
+      const vPath = this.extractValue(typeNode, 'path');
+      if (!vPath) {
+        throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found leafref without path.`);
+      }
+      const refPath = this.resolveReferencePath(vPath, module);
+      const resolve = this.resolveReference.bind(this);
+      const res: ViewElement = {
+        ...element,
+        uiType: 'reference',
+        referencePath: refPath,
+        ref(this: ViewElement, basePath: string) {
+          const elementPath = `${basePath}/${cur.arg}`;
+
+          const result = resolve(refPath, elementPath);
+          if (!result) return undefined;
+
+          const [resolvedElement, resolvedPath] = result;
+          return resolvedElement && [{
+            ...resolvedElement,
+            id: this.id,
+            label: this.label,
+            config: this.config,
+            mandatory: this.mandatory,
+            isList: this.isList,
+            default: this.default,
+            description: this.description,
+          } as ViewElement, resolvedPath] || undefined;
+        },
+      };
+      return res;
+    } else if (type === 'identityref') {
+      const typeNode = this.extractNodes(cur, 'type')[0]!;
+      const base = this.extractValue(typeNode, 'base');
+      if (!base) {
+        throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found identityref without base.`);
+      }
+      const res: ViewElement = {
+        ...element,
+        uiType: 'selection',
+        options: [],
+      };
+      this._identityToResolve.push(() => {
+        const identity: Identity = this.resolveIdentity(base, module);
+        if (!identity) {
+          throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Could not resolve identity [${base}].`);
+        }
+        if (!identity.values || identity.values.length === 0) {
+          throw new Error(`Identity: [${base}] has no values.`);
+        }
+        res.options = identity.values.map(val => ({
+          key: val.id,
+          value: val.id,
+          description: val.description,
+        }));
+      });
+      return res;
+    } else if (type === 'empty') {
+      // todo: ❗ handle empty ⚡
+      /*  9.11.  The empty Built-In Type
+          The empty built-in type represents a leaf that does not have any
+          value, it conveys information by its presence or absence. */
+      return {
+        ...element,
+        uiType: 'empty',
+      };
+    } else if (type === 'union') {
+      // todo: ❗ handle union ⚡
+      /* 9.12.  The union Built-In Type */
+      const typeNode = this.extractNodes(cur, 'type')[0]!;
+      const typeNodes = this.extractNodes(typeNode, 'type');
+
+      const resultingElement = {
+        ...element,
+        uiType: 'union',
+        elements: [],
+      } as ViewElementUnion;
+
+      const resolveUnion = () => {
+        resultingElement.elements.push(...typeNodes.map(node => {
+          const stm: Statement = {
+            ...cur,
+            sub: [
+              ...(cur.sub?.filter(s => s.key !== 'type') || []),
+              node,
+            ],
+          };
+          return {
+            ...this.getViewElement(stm, module, parentId, currentPath, isList),
+            id: node.arg!,
+          };
+        }));
+      };
+
+      this._unionsToResolve.push(resolveUnion);
+
+      return resultingElement;
+    } else if (type === 'bits') {
+      const typeNode = this.extractNodes(cur, 'type')[0]!;
+      const bitNodes = this.extractNodes(typeNode, 'bit');
+      return {
+        ...element,
+        uiType: 'bits',
+        flags: bitNodes.reduce<{ [name: string]: number | undefined }>((acc, bitNode) => {
+          if (!bitNode.arg) {
+            throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found bit without name.`);
+          }
+          // const ifClause = this.extractValue(bitNode, 'if-feature');
+          const pos = Number(this.extractValue(bitNode, 'position'));
+          acc[bitNode.arg] = pos === pos ? pos : undefined;
+          return acc;
+        }, {}),
+      };
+    } else if (type === 'binary') {
+      return {
+        ...element,
+        uiType: 'binary',
+        length: extractRange(0, +18446744073709551615, 'length'),
+      };
+    } else if (type === 'instance-identifier') {
+      // https://tools.ietf.org/html/rfc7950#page-168
+      return {
+        ...element,
+        uiType: 'string',
+        length: extractRange(0, +18446744073709551615, 'length'),
+      };
+    } else {
+      // not a build in type, need to resolve type
+      let typeRef = this.resolveType(type, module);
+      if (typeRef == null) console.error(new Error(`Could not resolve type ${type} in [${module.name}][${currentPath}].`));
+
+      if (isViewElementString(typeRef)) {
+        typeRef = this.resolveStringType(typeRef, extractPattern(), extractRange(0, +18446744073709551615));
+      } else if (isViewElementNumber(typeRef)) {
+        typeRef = this.resolveNumberType(typeRef, extractRange(typeRef.min, typeRef.max));
+      }
+
+      const res = {
+        id: element.id,
+      } as ViewElement;
+
+      this._typeRefToResolve.push(() => {
+        // spoof date type here from special string type
+        if ((type === 'date-and-time' || type.endsWith(':date-and-time')) && typeRef.module === 'ietf-yang-types') {
+          Object.assign(res, {
+            ...typeRef,
+            ...element,
+            description: description,
+            uiType: 'date',
+          });
+        } else {
+          Object.assign(res, {
+            ...typeRef,
+            ...element,
+            description: description,
+          });
+        }
+      });
+      
+      return res;
+    }
+  }
+
+  private resolveStringType(parentElement: ViewElementString, pattern: Expression<RegExp> | undefined, length: { expression: Expression<YangRange> | undefined; min: number; max: number }) {
+    return {
+      ...parentElement,
+      pattern: pattern != null && parentElement.pattern
+        ? { operation: 'AND', arguments: [pattern, parentElement.pattern] }
+        : parentElement.pattern
+          ? parentElement.pattern
+          : pattern,
+      length: length.expression != null && parentElement.length
+        ? { operation: 'AND', arguments: [length.expression, parentElement.length] }
+        : parentElement.length
+          ? parentElement.length
+          : length?.expression,
+    } as ViewElementString;
+  }
+
+  private resolveNumberType(parentElement: ViewElementNumber, range: { expression: Expression<YangRange> | undefined; min: number; max: number }) {
+    return {
+      ...parentElement,
+      range: range.expression != null && parentElement.range
+        ? { operation: 'AND', arguments: [range.expression, parentElement.range] }
+        : parentElement.range
+          ? parentElement.range
+          : range,
+      min: range.min,
+      max: range.max,
+    } as ViewElementNumber;
+  }
+
+  private resolveReferencePath(vPath: string, module: Module) {
+    const vPathParser = /(?:(?:([^\/\:]+):)?([^\/]+))/g; // 1 = opt: namespace / 2 = property
+    return vPath.replace(vPathParser, (_, ns, property) => {
+      const nameSpace = ns && module.imports[ns] || module.name;
+      return `${nameSpace}:${property}`;
+    });
+  }
+
+  private resolveReference(vPath: string, currentPath: string) {
+    const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g; // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
+    let element: ViewElement | null = null;
+    let moduleName = '';
+
+    const vPathParts = splitVPath(vPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }));
+    const resultPathParts = !vPath.startsWith('/')
+      ? splitVPath(currentPath, vPathParser).map(p => { moduleName = p[1] || moduleName; return { ns: moduleName, property: p[2], ind: p[3] }; })
+      : [];
+
+    for (let i = 0; i < vPathParts.length; ++i) {
+      const vPathPart = vPathParts[i];
+      if (vPathPart.property === '..') {
+        resultPathParts.pop();
+      } else if (vPathPart.property !== '.') {
+        resultPathParts.push(vPathPart);
+      }
+    }
+
+    // resolve element by path
+    for (let j = 0; j < resultPathParts.length; ++j) {
+      const pathPart = resultPathParts[j];
+      if (j === 0) {
+        moduleName = pathPart.ns;
+        const rootModule = this._modules[moduleName];
+        if (!rootModule) throw new Error('Could not resolve module [' + moduleName + '].\r\n' + vPath);
+        element = rootModule.elements[`${pathPart.ns}:${pathPart.property}`];
+      } else if (element && isViewElementObjectOrList(element)) {
+        const view: ViewSpecification = this._views[+element.viewId];
+        if (moduleName !== pathPart.ns) {
+          moduleName = pathPart.ns;
+        }
+        element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
+      } else {
+        throw new Error('Could not resolve reference.\r\n' + vPath);
+      }
+      if (!element) throw new Error('Could not resolve path [' + pathPart.property + '] in [' + currentPath + '] \r\n' + vPath);
+    }
+
+    moduleName = ''; // create the vPath for the resolved element, do not add the element itself this will be done later in the res(...) function
+    return [element, resultPathParts.slice(0, -1).map(p => `${moduleName !== p.ns ? `${moduleName = p.ns}:` : ''}${p.property}${p.ind || ''}`).join('/')];
+  }
+
+  private resolveView(vPath: string) {
+    const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g; // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
+    let element: ViewElement | null = null;
+    let partMatch: RegExpExecArray | null;
+    let view: ViewSpecification | null = null;
+    let moduleName = '';
+    if (vPath) do {
+      partMatch = vPathParser.exec(vPath);
+      if (partMatch) {
+        if (element === null) {
+          moduleName = partMatch[1]!;
+          const rootModule = this._modules[moduleName];
+          if (!rootModule) return null;
+          element = rootModule.elements[`${moduleName}:${partMatch[2]!}`];
+        } else if (isViewElementObjectOrList(element)) {
+          view = this._views[+element.viewId];
+          if (moduleName !== partMatch[1]) {
+            moduleName = partMatch[1];
+            element = view.elements[`${moduleName}:${partMatch[2]}`];
+          } else {
+            element = view.elements[partMatch[2]];
+          }
+        } else {
+          return null;
+        }
+        if (!element) return null;
+      }
+    } while (partMatch);
+    return element && isViewElementObjectOrList(element) && this._views[+element.viewId] || null;
+  }
+
+  private resolveType(type: string, module: Module) {
+    const colonInd = type.indexOf(':');
+    const preFix = colonInd > -1 ? type.slice(0, colonInd) : '';
+    const typeName = colonInd > -1 ? type.slice(colonInd + 1) : type;
+
+    const res = preFix
+      ? this._modules[module.imports[preFix]].typedefs[typeName]
+      : module.typedefs[typeName];
+    return res;
+  }
+
+  private resolveGrouping(grouping: string, module: Module) {
+    const collonInd = grouping.indexOf(':');
+    const preFix = collonInd > -1 ? grouping.slice(0, collonInd) : '';
+    const groupingName = collonInd > -1 ? grouping.slice(collonInd + 1) : grouping;
+
+    return preFix
+      ? this._modules[module.imports[preFix]].groupings[groupingName]
+      : module.groupings[groupingName];
+
+  }
+
+  private resolveIdentity(identity: string, module: Module) {
+    const collonInd = identity.indexOf(':');
+    const preFix = collonInd > -1 ? identity.slice(0, collonInd) : '';
+    const identityName = collonInd > -1 ? identity.slice(collonInd + 1) : identity;
+
+    return preFix
+      ? this._modules[module.imports[preFix]].identities[identityName]
+      : module.identities[identityName];
+
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/configurationApp/tsconfig.json
new file mode 100644
index 0000000..c950056
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/tsconfig.json
@@ -0,0 +1,38 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "node",
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/configurationApp/webpack.config.js
new file mode 100644
index 0000000..2f7ab11
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/configurationApp/webpack.config.js
@@ -0,0 +1,150 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+const proxyConf = require('../../proxy.conf');
+
+const policies = require('./policies.json');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      configurationApp: ["./pluginConfiguration.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "configurationApp",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },{
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+     watchOptions: {
+       ignored: /node_modules/
+     },
+
+    devServer: {
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      before: function(app, server, compiler) {
+        app.get('/oauth/policies',(_, res) => res.json(policies));
+      },
+      proxy: proxyConf,
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/.babelrc b/sdnr/wt-odlux/odlux/apps/connectApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/package.json b/sdnr/wt-odlux/odlux/apps/connectApp/package.json
new file mode 100644
index 0000000..9a3c35b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/package.json
@@ -0,0 +1,44 @@
+{
+  "name": "@odlux/connect-app",
+  "version": "0.1.1",
+  "description": "A react based modular UI to display network element/node connect data from a database.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/policies.json b/sdnr/wt-odlux/odlux/apps/connectApp/policies.json
new file mode 100644
index 0000000..2ec7361
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/policies.json
@@ -0,0 +1,12 @@
+[
+  {
+    "path": "/rests/**/node=Sim2230**",
+    "methods": {
+      "get": true,
+      "post": false,
+      "put": false,
+      "delete": false,
+      "patch": false
+    }
+  }
+]
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/pom.xml b/sdnr/wt-odlux/odlux/apps/connectApp/pom.xml
new file mode 100644
index 0000000..12df827
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-connectApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
new file mode 100644
index 0000000..948f2aa
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
@@ -0,0 +1,141 @@
+
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Create an update action that can distinguish whether one or the other view is currently active and update it.
+ * This action is then used for each update in the other actions and when notifications arrive.
+ * create an update action that can distinguish whether one or the other view is currently active and update it.
+ * This action is then used for each update in the other actions and when notifications arrive.
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
+import { guiCutThrough } from '../models/guiCutTrough';
+import { PanelId } from '../models/panelId';
+import { connectService } from '../services/connectService';
+
+
+export class SetPanelAction extends Action {
+  constructor(public panelId: PanelId) {
+    super();
+  }
+}
+
+export class AddWebUriList extends Action {
+  constructor(public searchedElements: guiCutThrough[], public notSearchedElements: string[], public unsupportedElements: string[], public newlySearchedElements?: string[]) {
+    super();
+  }
+}
+
+export class RemoveWebUri extends Action {
+  constructor(public element: string) {
+    super();
+  }
+}
+
+export const removeWebUriAction = (nodeId: string) => {
+  return new RemoveWebUri(nodeId);
+};
+
+export class SetWeburiSearchBusy extends Action {
+  constructor(public isbusy: boolean) {
+    super();
+  }
+}
+
+let isBusy = false;
+export const findWebUrisForGuiCutThroughAsyncAction = (networkElementIds: string[]) => async (dispatcher: Dispatch, getState: () => IApplicationStoreState) => {
+
+  // keep method from executing simultanously; state not used because change of iu isn't needed
+
+  if (isBusy)
+    return;
+  isBusy = true;
+
+  const { connect: { guiCutThrough: guiCutThrough2, networkElements } } = getState();
+
+  let notConnectedElements: string[] = [];
+  let elementsToSearch: string[] = [];
+  let prevFoundElements: string[] = [];
+  let unsupportedElements: string[] = [];
+
+  networkElementIds.forEach(id => {
+    const item = networkElements.rows.find((ne) => ne.id === id);
+    if (item) {
+      if (item.status === 'Connected') {
+
+        // if (item.coreModelCapability !== "Unsupported") {
+        // element is connected and is added to search list, if it doesn't exist already
+        const exists = guiCutThrough2.searchedElements.filter(element => element.id === id).length > 0;
+        if (!exists) {
+          elementsToSearch.push(id);
+
+          //element was found previously, but wasn't connected
+          if (guiCutThrough2.notSearchedElements.length > 0 && guiCutThrough2.notSearchedElements.includes(id)) {
+            prevFoundElements.push(id);
+          }
+        }
+        // } else {
+        //   // element does not support core model and must not be searched for a weburi  
+        //   const id = item.id as string;
+        //   const exists = guiCutThrough.unsupportedElements.filter(element => element === id).length > 0;
+        //   if (!exists) {
+        //     unsupportedElements.push(id);
+
+        //     //element was found previously, but wasn't connected
+        //     if (guiCutThrough.notSearchedElements.length > 0 && guiCutThrough.notSearchedElements.includes(id)) {
+        //       prevFoundElements.push(id);
+        //     }
+        //   }
+        // }
+      } else {
+        // element isn't connected and cannot be searched for a weburi
+        if (!guiCutThrough2.notSearchedElements.includes(id)) {
+          notConnectedElements.push(item.id as string);
+        }
+      }
+    }
+  });
+
+
+  if (elementsToSearch.length > 0 || notConnectedElements.length > 0 || unsupportedElements.length > 0) {
+    const result = await connectService.getAllWebUriExtensionsForNetworkElementListAsync(elementsToSearch);
+    dispatcher(new AddWebUriList(result, notConnectedElements, unsupportedElements, prevFoundElements));
+  }
+  isBusy = false;
+
+};
+
+export const setPanelAction = (panelId: PanelId) => {
+  return new SetPanelAction(panelId);
+};
+
+export const updateCurrentViewAsyncAction = () => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const { connect: { currentOpenPanel } } = getState();
+  if (currentOpenPanel === 'NetworkElements') {
+    return dispatch(networkElementsReloadAction);
+  } else {
+    return dispatch(connectionStatusLogReloadAction);
+  }
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
new file mode 100644
index 0000000..120f991
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
@@ -0,0 +1,82 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+ 
+import { Module, TopologyNode } from '../models/topologyNetconf';
+import { connectService } from '../services/connectService';
+ 
+/** 
+  * Represents the base action. 
+  */
+export class BaseAction extends Action { }
+ 
+/** 
+  * Represents an action causing the store to load all element Yang capabilities.
+  */
+export class LoadAllElementInfoAction extends BaseAction { }
+ 
+/** 
+  * Represents an action causing the store to update element Yang capabilities. 
+  */
+export class AllElementInfoLoadedAction extends BaseAction {
+  /**
+    * Initialize this instance.
+    * @param elementInfo The information of the element which is returned.
+    */
+  constructor(public elementInfo: TopologyNode | null, public error?: string) {
+    super();
+  }
+}
+ 
+/** 
+  * Represents an action causing the store to update element Yang capabilities Module Features. 
+  */
+export class AllElementInfoFeatureLoadedAction extends BaseAction {
+  /**
+    * Initialize this instance.
+    * @param elementFeatureInfo The information of the element which is returned.
+    */
+  constructor(public elementFeatureInfo: Module[] | null | undefined, public error?: string) {
+    super();
+  }
+}
+ 
+/** 
+  * Represents an asynchronous thunk  action to load all yang capabilities. 
+  */
+export const loadAllInfoElementAsync = (nodeId: string) => (dispatch: Dispatch) => {
+  dispatch(new LoadAllElementInfoAction());
+  connectService.infoNetworkElement(nodeId).then(info => {
+    dispatch(new AllElementInfoLoadedAction(info));
+  }, error => {
+    dispatch(new AllElementInfoLoadedAction(null, error));
+  });
+}; 
+ 
+/** 
+  * Represents an asynchronous thunk  action to load all yang features. 
+  */
+export const loadAllInfoElementFeaturesAsync = (nodeId: string) => (dispatch: Dispatch) => {
+  dispatch(new LoadAllElementInfoAction());
+  connectService.infoNetworkElementFeatures(nodeId).then(infoFeatures => {
+    dispatch(new AllElementInfoFeatureLoadedAction(infoFeatures));
+  }, error => {
+    dispatch(new AllElementInfoFeatureLoadedAction(null, error));
+  });
+}; 
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
new file mode 100644
index 0000000..11bac10
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { connectService } from '../services/connectService';
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { updateCurrentViewAsyncAction } from './commonNetworkElementsActions';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an action creator for a async thunk action to mount a network element/node. */
+export const mountNetworkElementAsyncActionCreator = (networkElement: NetworkElementConnection) => (dispatch: Dispatch) => {
+  return connectService.mountNetworkElement(networkElement).then((success) => {
+    if (success) {
+      dispatch(updateCurrentViewAsyncAction());
+      dispatch(new AddSnackbarNotification({ message: `Requesting mount [${networkElement.nodeId}]`, options: { variant: 'info' } }));
+    } else {
+      dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'warning' } }));
+    }
+  }).catch(error => {
+    dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'error' } }));
+    console.error(error);
+  });
+};
+
+/** Represents an action creator for a async thunk action to unmount a network element/node. */
+export const unmountNetworkElementAsyncActionCreator = (nodeId: string) => (dispatch: Dispatch) => {
+  return connectService.unmountNetworkElement(nodeId).then((success) => {
+    if (success) {
+      dispatch(updateCurrentViewAsyncAction());
+      dispatch(new AddSnackbarNotification({ message: `Requesting unmount [${nodeId}]`, options: { variant: 'info' } }));
+    } else {
+      dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${nodeId}]`, options: { variant: 'warning' } }));
+    }
+  }).catch(error => {
+    dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${nodeId}]`, options: { variant: 'error' } }));
+    console.error(error);
+  });
+};
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/networkElementsActions.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/networkElementsActions.ts
new file mode 100644
index 0000000..d22a6c6
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/networkElementsActions.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+
+import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+import { connectService } from '../services/connectService';
+import { updateCurrentViewAsyncAction } from './commonNetworkElementsActions';
+import { unmountNetworkElementAsyncActionCreator } from './mountedNetworkElementsActions';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an async thunk action creator to add an element to the network elements/nodes. */
+export const addNewNetworkElementAsyncActionCreator = (element: NetworkElementConnection) => async (dispatch: Dispatch) => {
+  await connectService.createNetworkElement({ ...element });
+  dispatch(updateCurrentViewAsyncAction());
+  dispatch(new AddSnackbarNotification({ message: `Successfully added [${element.nodeId}]`, options: { variant: 'success' } }));
+};
+
+/** Represents an async thunk action creator to edit network element/node. */
+export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
+  const connectionStatus: ConnectionStatus[] = (await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne))) || [];
+  const currentConnectionStatus = connectionStatus[0].status;
+  if (currentConnectionStatus === 'Disconnected') {
+    await connectService.deleteNetworkElement(element);
+  } else {
+    await connectService.updateNetworkElement(element);
+  }
+  dispatch(updateCurrentViewAsyncAction());
+  dispatch(new AddSnackbarNotification({ message: `Successfully modified [${element.id}]`, options: { variant: 'success' } }));
+};
+
+
+/** Represents an async thunk action creator to delete an element from network elements/nodes. */
+export const removeNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
+  await connectService.deleteNetworkElement(element);
+  await dispatch(unmountNetworkElementAsyncActionCreator(element && element.id));
+  await dispatch(updateCurrentViewAsyncAction());
+};
+
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/tlsKeyActions.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
new file mode 100644
index 0000000..65d23c4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { TlsKeys } from '../models/networkElementConnection';
+import { connectService } from '../services/connectService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+/**
+ * Represents an action causing the store to load all TLS Keys.
+ */
+export class LoadAllTlsKeyListAction extends BaseAction { }
+
+/**
+ * Represents an action causing the store to get all TLS Keys.
+ */
+export class AllTlsKeyListLoadedAction extends BaseAction {
+  /**
+     * Initialize this instance.
+     * 
+     * @param gets all the tlsKey list from the  database.
+     */
+  constructor(public tlsList: TlsKeys[] | null, public error?: string) {
+    super();
+  }
+}
+
+/**
+ * Represents an asynchronous thunk action to load all tlsKeys 
+ */
+
+export const loadAllTlsKeyListAsync = () => async (dispatch: Dispatch) => {
+  dispatch(new LoadAllTlsKeyListAction());
+  connectService.getTlsKeys().then(TlsKeyList => {
+    dispatch(new AllTlsKeyListLoadedAction(TlsKeyList));
+  }).catch(error => {
+    dispatch(new AllTlsKeyListLoadedAction(null, error));
+  });
+};
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/assets/icons/connectAppIcon.svg b/sdnr/wt-odlux/odlux/apps/connectApp/src/assets/icons/connectAppIcon.svg
new file mode 100644
index 0000000..5aca4fa
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/assets/icons/connectAppIcon.svg
@@ -0,0 +1,22 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 650 650">
+
+<g transform="translate(20,0) scale(1,1)">
+
+<path fill="#C8D400" d="M 121.5 10 c -11.5 4.1 -19.6 12.1 -23.6 23.5 c -1.8 5 -1.9 9.2 -1.9 73.9 l 0 48.5 l 37.5 0 l 37.5 0 l 0 -45.9 c 0 -40.3 -0.4 -67.9 -1 -71.2 c -2.3 -11.9 -10.6 -22.5 -21.6 -27.6 c -7.9 -3.6 -18.8 -4.1 -26.9 -1.2 z"/>
+
+<path fill="#C8D400" d="M 347.9 10 c -11.5 4.1 -19.6 12.1 -23.6 23.5 c -1.8 5 -1.9 9.2 -1.9 73.9 l 0 48.5 l 37.5 0 l 37.5 0 l 0 -45.9 c 0 -40.3 -0.4 -67.9 -1 -71.2 c -2.3 -11.9 -10.6 -22.5 -21.6 -27.6 c -7.9 -3.6 -18.8 -4.1 -26.9 -1.2 z"/>
+
+<path fill="#565656" d="m 32.5 190 c -4.9 2.2 -9.1 6.9 -10.5 11.9 c -0.7 2.4 -1 11.9 -0.8 26.3 l 0.3 22.6 l 2.9 4.1 c 4.5 6.5 9.1 8.2 22.4 8.2 l 11.2 0 l 0 17.7 c 0 35.3 3.1 59 10.5 80.3 c 21.5 61.6 70.5 105.9 135.3 122 l 4.2 1.1 l 0 57.9 c 1 27.9 4 72.9 75 75 c 177 -5.1 344 -100.1 345 -204.1 l 1 -75 c -49 124 -165 214 -337 217.1 c -5 -0.1 -7 -3.1 -7 -7.1 l 0 -63.8 l 4.2 -1.1 c 17.1 -4.4 26.1 -7.6 39.6 -14 c 51.7 -24.6 90.3 -74.2 101.7 -130.5 c 3 -14.6 4.5 -33.9 4.5 -57.7 l 0 -17.6 l 12.3 -0.4 c 11.1 -0.3 12.7 -0.5 15.9 -2.7 c 1.9 -1.3 4.6 -4 5.9 -5.9 c 2.3 -3.5 2.4 -4.2 2.7 -26.1 c 0.2 -14.4 -0.1 -23.9 -0.8 -26.3 c -1.4 -5 -5.6 -9.7 -10.5 -11.9 c -3.8 -1.8 -12.4 -1.9 -213 -1.9 c -200.6 0 -209.2 0.1 -213 1.9 z"/>
+
+
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
new file mode 100644
index 0000000..6a8c924
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
@@ -0,0 +1,99 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import Refresh from '@mui/icons-material/Refresh';
+
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler';
+import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog';
+import RefreshConnectionStatusLogDialog, { RefreshConnectionStatusLogDialogMode } from './refreshConnectionStatusLogDialog';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  connectionStatusLogProperties: createConnectionStatusLogProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch),
+});
+
+const ConnectionStatusTable = MaterialTable as MaterialTableCtorType<NetworkElementConnectionLog>;
+
+type ConnectionStatusLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>;
+type ConnectionStatusLogComponentState = {
+  refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode;
+};
+
+let initialSorted = false;
+
+
+class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps, ConnectionStatusLogComponentState > {
+  constructor(props: ConnectionStatusLogComponentProps) {
+    super(props);
+
+    this.state = {
+      refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.None,
+    };
+  }
+
+  render(): JSX.Element {
+    const refreshConnectionStatusLogAction = {
+      icon: Refresh, tooltip: 'Refresh Connection Status Log Table', ariaLabel:'refresh', onClick: () => {
+        this.setState({
+          refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable,
+        });
+      },
+    };
+
+    return (
+    <>
+      <ConnectionStatusTable stickyHeader tableId="connection-status-table" customActionButtons={[refreshConnectionStatusLogAction]}  columns={[
+        { property: 'timestamp', title: 'Timestamp', type: ColumnType.text },
+        { property: 'nodeId', title: 'Node ID', type: ColumnType.text },
+        { property: 'status', title: 'Connection Status', type: ColumnType.text },
+      ]} idProperty="id" {...this.props.connectionStatusLogActions} {...this.props.connectionStatusLogProperties} >
+      </ConnectionStatusTable>
+       <RefreshConnectionStatusLogDialog
+        mode={ this.state.refreshConnectionStatusLogEditorMode }
+        onClose={ this.onCloseRefreshConnectionStatusLogDialog }
+      />
+    </>
+    );
+  }
+
+  private onCloseRefreshConnectionStatusLogDialog = () => {
+    this.setState({
+      refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.None,
+    });
+  };
+
+  componentDidMount() {
+    if (!initialSorted) {
+      initialSorted = true;
+      this.props.connectionStatusLogActions.onHandleExplicitRequestSort('timestamp', 'desc');
+    } else {
+      this.props.connectionStatusLogActions.onRefresh();
+    }
+  }
+}
+
+export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent);
+export default ConnectionStatusLog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
new file mode 100644
index 0000000..b0db634
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -0,0 +1,425 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+import FormControl from '@mui/material/FormControl';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import InputLabel from '@mui/material/InputLabel';
+import MenuItem from '@mui/material/MenuItem';
+import Radio from '@mui/material/Radio';
+import RadioGroup from '@mui/material/RadioGroup';
+import Select from '@mui/material/Select';
+import TextField from '@mui/material/TextField';
+import Typography from '@mui/material/Typography';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { removeWebUriAction } from '../actions/commonNetworkElementsActions';
+import { mountNetworkElementAsyncActionCreator, unmountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
+import {
+  addNewNetworkElementAsyncActionCreator, editNetworkElementAsyncActionCreator, removeNetworkElementAsyncActionCreator,
+} from '../actions/networkElementsActions';
+import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions';
+import { NetworkElementConnection, propertyOf, UpdateNetworkElement } from '../models/networkElementConnection';
+
+export enum EditNetworkElementDialogMode {
+  None = 'none',
+  EditNetworkElement = 'editNetworkElement',
+  RemoveNetworkElement = 'removeNetworkElement',
+  AddNewNetworkElement = 'addNewNetworkElement',
+  MountNetworkElement = 'mountNetworkElement',
+  UnmountNetworkElement = 'unmountNetworkElement',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  addNewNetworkElement: async (element: NetworkElementConnection) => {
+    await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element));
+    await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element));
+  },
+  mountNetworkElement: (element: NetworkElementConnection) => dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)),
+  unmountNetworkElement: (element: NetworkElementConnection) => {
+    dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId));
+  },
+  editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => {
+
+    const values = Object.keys(element);
+    console.log('edit element');
+    console.log(values);
+
+    //make sure properties are there in case they get renamed
+    const idProperty = propertyOf<UpdateNetworkElement>('id');
+    const isRequiredProperty = propertyOf<UpdateNetworkElement>('isRequired');
+
+
+    if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) {
+      // do not mount network element/node, if only isRequired is changed
+      await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
+
+    } else if (!(values.length === 1 && values.includes(idProperty as string))) { //do not edit or mount network element/node , if only id was saved into object (no changes made!)
+      await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
+      await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
+    }
+  },
+  removeNetworkElement: async (element: UpdateNetworkElement) => {
+    await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
+    dispatcher.dispatch(removeWebUriAction(element.id));
+  },
+  getAvailableTlsKeys: async () => dispatcher.dispatch(loadAllTlsKeyListAsync()),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [EditNetworkElementDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+
+  [EditNetworkElementDialogMode.AddNewNetworkElement]: {
+    dialogTitle: 'Add New Node',
+    dialogDescription: 'Add this new node:',
+    applyButtonText: 'Add node',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+  [EditNetworkElementDialogMode.MountNetworkElement]: {
+    dialogTitle: 'Mount Node',
+    dialogDescription: 'Mount this node:',
+    applyButtonText: 'Mount node',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [EditNetworkElementDialogMode.UnmountNetworkElement]: {
+    dialogTitle: 'Unmount Node',
+    dialogDescription: 'Unmount this node:',
+    applyButtonText: 'Unmount node',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [EditNetworkElementDialogMode.EditNetworkElement]: {
+    dialogTitle: 'Modify Node',
+    dialogDescription: 'Modify this node',
+    applyButtonText: 'Modify',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: false,
+    enableUsernameEditor: true,
+    enableExtendedEditor: false,
+  },
+  [EditNetworkElementDialogMode.RemoveNetworkElement]: {
+    dialogTitle: 'Remove Node',
+    dialogDescription: 'Do you really want to remove this node?',
+    applyButtonText: 'Remove node',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+};
+
+type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: EditNetworkElementDialogMode;
+  initialNetworkElement: NetworkElementConnection;
+  onClose: () => void;
+  radioChecked: string;
+};
+
+type EditNetworkElementDialogComponentState = NetworkElementConnection & {
+  isNameValid: boolean;
+  isHostSet: boolean;
+  isPasswordSelected: boolean;
+  isTlsSelected: boolean;
+  radioSelected: string;
+  showPasswordTextField: boolean;
+  showTlsDropdown: boolean;
+};
+
+class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
+  constructor(props: EditNetworkElementDialogComponentProps) {
+    super(props);
+    this.handleRadioChange = this.handleRadioChange.bind(this);
+    // Initialization of state is partly overwritten by update via react getDerivedStateFromProps() below.
+    // Change initialization values in parent "networkElements.tsx" in "const emptyRequireNetworkElement"
+    this.state = {
+      nodeId: this.props.initialNetworkElement.nodeId,
+      isRequired: this.props.initialNetworkElement.isRequired,
+      host: this.props.initialNetworkElement.host,
+      port: this.props.initialNetworkElement.port,
+      isNameValid: true,
+      isHostSet: true,
+      isPasswordSelected: true,
+      isTlsSelected: false,
+      radioSelected: '',
+      showPasswordTextField: true,
+      showTlsDropdown: false,
+    };
+  }
+
+  public handleRadioChange = (event: any) => {
+    this.setState({
+      radioSelected: event.target.value,
+      showPasswordTextField: event.target.value === 'password',
+      showTlsDropdown: event.target.value === 'tlsKey',
+    });
+  };
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    let { showPasswordTextField, showTlsDropdown, radioSelected } = this.state;
+    radioSelected = this.state.radioSelected.length > 0 ? this.state.radioSelected : this.props.radioChecked;
+
+    if (radioSelected === 'password') {
+      radioSelected = 'password';
+      showPasswordTextField = true;
+      showTlsDropdown = false;
+    } else if (radioSelected === 'tlsKey') {
+      radioSelected = 'tlsKey';
+      showPasswordTextField = false;
+      showTlsDropdown = true;
+    }
+
+    let tlsKeysList = this.props.state.connect.availableTlsKeys ? this.props.state.connect.availableTlsKeys.tlsKeysList ? this.props.state.connect.availableTlsKeys.tlsKeysList : [] : [];
+
+    return (
+      <Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+          <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense"
+            id="name" label="Node ID" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+          {!this.state.isNameValid && <Typography variant="body1" color="error">Node ID cannot be empty.</Typography>}
+          <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense"
+            id="ipaddress" label="Host/IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
+          {!this.state.isHostSet && <Typography variant="body1" color="error">Host/IP address cannot be empty.</Typography>}
+
+          <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense"
+            id="netconfport" label="NETCONF port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()}
+            onChange={(event) => { this.setState({ port: +event.target.value }); }} />
+          {setting.enableUsernameEditor && <TextField variant="standard" disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense"
+            id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null}
+
+          {setting.enableUsernameEditor &&
+            <RadioGroup row aria-label="password-tls-key" name="password-tls-key" value={radioSelected}
+              onChange={this.handleRadioChange} >
+              <FormControlLabel aria-label="passwordSelection" value='password' control={<Radio color="secondary" />} label="Password" onChange={this.onRadioSelect} />
+              <FormControlLabel aria-label="tlsKeySelection" value='tlsKey' control={<Radio color="secondary" />} label="TlsKey" onChange={this.onRadioSelect} />
+            </RadioGroup> || null}
+
+          {setting.enableUsernameEditor && showPasswordTextField &&
+            <TextField variant="standard" disabled={!setting.enableUsernameEditor || !showPasswordTextField} spellCheck={false} margin="dense"
+              id="password" aria-label="password" type="password" fullWidth value={this.state.password}
+              onChange={(event) => { this.setState({ password: event.target.value }); }}
+            /> || null}
+
+          <FormControl variant="standard" fullWidth disabled={!setting.enableUsernameEditor}>
+            {setting.enableUsernameEditor && showTlsDropdown &&
+              <div>
+                <InputLabel htmlFor="pass">--Select tls-key--</InputLabel>
+                <Select variant="standard" disabled={!setting.enableUsernameEditor || !showTlsDropdown}
+                  id="tlsKey" aria-label="tlsKey" value={this.state.tlsKey} fullWidth // displayEmpty
+                  onChange={(event) => { this.setState({ tlsKey: event.target.value as any }); }}
+                  inputProps={{ name: 'tlsKey', id: 'tlsKey' }}  >
+                  <MenuItem value={''} disabled >--Select tls-key--</MenuItem>
+                  {tlsKeysList.map(tlsKey =>
+                    (<MenuItem value={tlsKey.key} key={tlsKey.key} aria-label={tlsKey.key} >{tlsKey.key}</MenuItem>))}
+                </Select>
+              </div>
+            }
+          </FormControl>
+
+          <FormControl variant="standard" fullWidth disabled={!setting.enableUsernameEditor}>
+            <InputLabel htmlFor="active">Required</InputLabel>
+            <Select variant="standard" aria-label="required-selection" value={this.state.isRequired || false} onChange={(event) => {
+              this.setState({ isRequired: event.target.value as any as boolean });
+            }} inputProps={{ name: 'required', id: 'required' }} fullWidth >
+              <MenuItem value={true as any as string} aria-label="true">True</MenuItem>
+              <MenuItem value={false as any as string} aria-label="false">False</MenuItem>
+            </Select>
+          </FormControl>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={(event) => {
+
+            if (this.areRequieredFieldsValid()) {
+              this.onApply({
+                isRequired: this.state.isRequired,
+                id: this.state.nodeId,
+                nodeId: this.state.nodeId,
+                host: this.state.host,
+                port: this.state.port,
+                username: this.state.username,
+                password: this.state.password,
+                tlsKey: this.state.tlsKey,
+              });
+            }
+            event.preventDefault();
+            event.stopPropagation();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={(event) => {
+            this.onCancel();
+            event.preventDefault();
+            event.stopPropagation();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  public renderTlsKeys = () => {
+    try {
+      this.props.getAvailableTlsKeys();
+    } catch (err) {
+      console.log(err);
+    }
+  };
+
+  public componentDidMount() {
+    this.renderTlsKeys();
+  }
+
+  public onRadioSelect = (e: any) => {
+    if (e.target.value == 'password') {
+      this.setState({ isPasswordSelected: true, isTlsSelected: false });
+    } else if (e.target.value == 'tlsKey') {
+      this.setState({ isPasswordSelected: false, isTlsSelected: true });
+    }
+  };
+
+  private onApply = (element: NetworkElementConnection) => {
+    if (this.props.onClose) this.props.onClose();
+    let updateElement: UpdateNetworkElement = {
+      id: this.state.nodeId,
+    };
+    if (this.state.isPasswordSelected) {
+      element.tlsKey = '';
+    } else if (this.state.isTlsSelected) { //check here
+      element.password = '';
+    }
+
+    switch (this.props.mode) {
+      case EditNetworkElementDialogMode.AddNewNetworkElement:
+        if (element) this.props.addNewNetworkElement(element);
+        this.setState({
+          radioSelected: '',
+          isPasswordSelected: true,
+        });
+        break;
+      case EditNetworkElementDialogMode.MountNetworkElement:
+        if (element) this.props.mountNetworkElement(element);
+        break;
+      case EditNetworkElementDialogMode.UnmountNetworkElement:
+        if (element) this.props.unmountNetworkElement(element);
+        break;
+      case EditNetworkElementDialogMode.EditNetworkElement:
+        if (this.props.initialNetworkElement.isRequired !== this.state.isRequired)
+          updateElement.isRequired = this.state.isRequired;
+        if (this.props.initialNetworkElement.username !== this.state.username)
+          updateElement.username = this.state.username;
+        if (this.props.initialNetworkElement.password !== this.state.password && this.state.isPasswordSelected) {
+          updateElement.password = this.state.password;
+          updateElement.tlsKey = '';
+        }
+        if (this.props.initialNetworkElement.tlsKey !== this.state.tlsKey && this.state.isTlsSelected) {
+          updateElement.tlsKey = this.state.tlsKey;
+          updateElement.password = '';
+        }
+        if (element) this.props.editNetworkElement(updateElement, element);
+        this.setState({
+          radioSelected: '',
+        });
+        break;
+      case EditNetworkElementDialogMode.RemoveNetworkElement:
+        if (element) this.props.removeNetworkElement(updateElement);
+        break;
+    }
+
+    this.setState({ password: '', username: '', tlsKey: '' });
+    this.resetRequieredFields();
+  };
+
+  private onCancel = () => {
+    if (this.props.onClose) this.props.onClose();
+    this.setState({ password: '', username: '', tlsKey: '', radioSelected: '' });
+    this.resetRequieredFields();
+  };
+
+  private resetRequieredFields() {
+    this.setState({ isNameValid: true, isHostSet: true });
+  }
+
+  private areRequieredFieldsValid() {
+    let areFieldsValid = true;
+
+    if (this.state.nodeId == undefined || this.state.nodeId.trim().length === 0) {
+      this.setState({ isNameValid: false });
+      areFieldsValid = false;
+    } else {
+      this.setState({ isNameValid: true });
+    }
+
+    if (this.state.host == undefined || this.state.host.trim().length === 0) {
+      this.setState({ isHostSet: false });
+      areFieldsValid = false;
+    } else {
+      this.setState({ isHostSet: true });
+    }
+
+    return areFieldsValid;
+  }
+
+  static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection } {
+    let returnState = state;
+    if (props.initialNetworkElement !== state.initialNetworkElement) {
+      returnState = {
+        ...state,
+        ...props.initialNetworkElement,
+        initialNetworkElement: props.initialNetworkElement,
+      };
+    }
+    return returnState;
+  }
+}
+
+export const EditNetworkElementDialog = connect(undefined, mapDispatch)(EditNetworkElementDialogComponent);
+export default EditNetworkElementDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
new file mode 100644
index 0000000..4841b93
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
@@ -0,0 +1,160 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { AvailableCapabilities } from '../models/yangCapabilitiesType';
+
+export enum InfoNetworkElementDialogMode {
+  None = 'none',
+  InfoNetworkElement = 'infoNetworkElement',
+}
+
+const mapDispatch = () => ({
+});
+
+const InfoElementTable = MaterialTable as MaterialTableCtorType<AvailableCapabilities>;
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  cancelButtonText: string;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [InfoNetworkElementDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    cancelButtonText: '',
+  },
+  [InfoNetworkElementDialogMode.InfoNetworkElement]: {
+    dialogTitle: 'YANG Capabilities of the Node',
+    dialogDescription: '',
+    cancelButtonText: 'OK',
+  },
+};
+
+type InfoNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: InfoNetworkElementDialogMode;
+  initialNetworkElement: NetworkElementConnection;
+  onClose: () => void;
+};
+
+type InfoNetworkElementDialogComponentState = NetworkElementConnection;
+
+class InfoNetworkElementDialogComponent extends React.Component<InfoNetworkElementDialogComponentProps, InfoNetworkElementDialogComponentState> {
+  constructor(props: InfoNetworkElementDialogComponentProps) {
+    super(props);
+
+    this.state = {
+      nodeId: this.props.initialNetworkElement.nodeId,
+      isRequired: false,
+      host: this.props.initialNetworkElement.host,
+      port: this.props.initialNetworkElement.port,
+    };
+  }
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    const availableCapabilities = this.props.state.connect.elementInfo.elementInfo['netconf-node-topology:available-capabilities']['available-capability'];
+    let yangFeatures = this.props.state.connect.elementFeatureInfo.elementFeatureInfo;
+    let yangCapabilities: AvailableCapabilities[] = [];
+
+    availableCapabilities.forEach(value => {
+      const capabilty = value.capability;
+      const indexRevision = capabilty.indexOf('revision=');
+      const indexModule = capabilty.indexOf(')', indexRevision);
+      if (indexRevision > 0 && indexModule > 0) {
+        let moduleName = capabilty.substring(indexModule + 1);
+        let ModuleFeaturesList;
+        for (let index = 0; index < yangFeatures.length; index++) {
+          if (yangFeatures[index].name == moduleName) {
+            ModuleFeaturesList = yangFeatures[index].feature ? yangFeatures[index].feature : null;
+            break;
+          }
+        }
+        const featuresListCommaSeparated = ModuleFeaturesList ? ModuleFeaturesList.toString() : '';
+        let featuresList = featuresListCommaSeparated.replace(',', ', ');
+
+        yangCapabilities.push({
+          module: moduleName,
+          revision: capabilty.substring(indexRevision + 9, indexRevision + 19),
+          features: featuresList,
+        });
+      }
+    });
+
+    yangCapabilities = yangCapabilities.sort((a, b) => a.module === b.module ? 0 : a.module > b.module ? 1 : -1);
+
+    return (
+      <>
+        <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None}  >
+          <DialogTitle id="form-dialog-title">{`${setting.dialogTitle}: "${this.state.nodeId}"`}</DialogTitle>
+          <InfoElementTable stickyHeader isPopup tableId="info-element-table" asynchronus columns={[
+            { property: 'module', title: 'YANG Capability', type: ColumnType.text, width: 900 },
+            {
+              property: 'revision', title: 'Revision', type: ColumnType.custom, customControl: ({ rowData }) => {
+                return (
+                  <div>
+                    <a href={`/yang-schema/${rowData.module}/${rowData.revision}`} target="_blank"  > {rowData.revision} </a>
+                  </div>
+                );
+              },
+            },
+            { property: 'features', title: 'Features', type: ColumnType.text, width: 500 },
+          ]} idProperty="id" rows={yangCapabilities}  >
+          </InfoElementTable>
+          <DialogActions>
+            <Button aria-label="ok-button" onClick={(event) => {
+              this.onCancel();
+              event.preventDefault();
+              event.stopPropagation();
+            }} color="secondary"> {setting.cancelButtonText} </Button>
+          </DialogActions>
+        </Dialog>
+      </>
+    );
+  }
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+
+  static getDerivedStateFromProps(props: InfoNetworkElementDialogComponentProps, state: InfoNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection }): InfoNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection } {
+    let returnState = state;
+    if (props.initialNetworkElement !== state.initialNetworkElement) {
+      returnState = {
+        ...state,
+        ...props.initialNetworkElement,
+        initialNetworkElement: props.initialNetworkElement,
+      };
+    }
+    return returnState;
+  }
+}
+
+export const InfoNetworkElementDialog = connect(undefined, mapDispatch)(InfoNetworkElementDialogComponent);
+export default InfoNetworkElementDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/networkElements.tsx
new file mode 100644
index 0000000..1ce8f0c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -0,0 +1,314 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* 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.
+* ============LICENSE_END==========================================================================
+*/
+import React from 'react';
+
+import AddIcon from '@mui/icons-material/Add';
+import ComputerIcon from '@mui/icons-material/Computer';
+import EditIcon from '@mui/icons-material/Edit';
+import Info from '@mui/icons-material/Info';
+import LinkIcon from '@mui/icons-material/Link';
+import LinkOffIcon from '@mui/icons-material/LinkOff';
+import Refresh from '@mui/icons-material/Refresh';
+import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
+import { Divider, MenuItem, Typography } from '@mui/material';
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+
+import { loadAllInfoElementAsync, loadAllInfoElementFeaturesAsync } from '../actions/infoNetworkElementActions';
+import { createNetworkElementsActions, createNetworkElementsProperties } from '../handlers/networkElementsHandler';
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { ModuleSet, TopologyNode } from '../models/topologyNetconf';
+import { connectService } from '../services/connectService';
+
+import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
+import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog';
+import RefreshNetworkElementsDialog, { RefreshNetworkElementsDialogMode } from './refreshNetworkElementsDialog';
+
+const styles = (theme: Theme) => createStyles({
+  connectionStatusConnected: {
+    color: 'darkgreen',
+  },
+  connectionStatusConnecting: {
+    color: 'blue',
+  },
+  connectionStatusDisconnected: {
+    color: 'red',
+  },
+  button: {
+    margin: 0,
+    padding: '6px 6px',
+    minWidth: 'unset',
+  },
+  spacer: {
+    marginLeft: theme.spacing(1),
+    marginRight: theme.spacing(1),
+    display: 'inline',
+  },
+});
+
+type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any;
+const MenuItemExt: React.FC<GetStatelessComponentProps<typeof MenuItem>> = (props) => {
+  const [disabled, setDisabled] = React.useState(true);
+  const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
+    if (ev.button === 1) {
+      setDisabled(!disabled);
+      ev.preventDefault();
+    }
+  };
+  return (
+    <div onMouseDown={onMouseDown} >
+      <MenuItem {...{ ...props, disabled: props.disabled && disabled }} />
+    </div>
+  );
+};
+
+const mapProps = (state: IApplicationStoreState) => ({
+  networkElementsProperties: createNetworkElementsProperties(state),
+  applicationState: state,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  networkElementsActions: createNetworkElementsActions(dispatcher.dispatch),
+  navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+  networkElementInfo: async (nodeId: string) => dispatcher.dispatch(loadAllInfoElementAsync(nodeId)),
+  networkElementFeaturesInfo: async (nodeId: string) => dispatcher.dispatch(loadAllInfoElementFeaturesAsync(nodeId)),
+});
+
+type NetworkElementsListComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
+type NetworkElementsListComponentState = {
+  networkElementToEdit: NetworkElementConnection;
+  networkElementEditorMode: EditNetworkElementDialogMode;
+  refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode;
+  infoNetworkElementEditorMode: InfoNetworkElementDialogMode;
+  elementInfo: TopologyNode | null;
+  elementInfoFeature: ModuleSet | null;
+};
+
+const emptyRequireNetworkElement: NetworkElementConnection = { id: '', nodeId: '', host: '', port: 830, status: 'Disconnected', isRequired: true };
+let initialSorted = false;
+const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
+
+export class NetworkElementsListComponent extends React.Component<NetworkElementsListComponentProps, NetworkElementsListComponentState> {
+
+  constructor(props: NetworkElementsListComponentProps) {
+    super(props);
+
+    this.state = {
+      networkElementToEdit: emptyRequireNetworkElement,
+      networkElementEditorMode: EditNetworkElementDialogMode.None,
+      refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
+      elementInfo: null,
+      elementInfoFeature: null,
+      infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None,
+    };
+  }
+
+  getContextMenu(rowData: NetworkElementConnection): JSX.Element[] {
+    const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
+    const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri);
+    const canMount = mountPolicy && mountPolicy.POST || false;
+
+    const { configuration } = this.props.applicationState as any;
+    const buttonArray = [
+      <MenuItemExt aria-label={'mount-button'} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkIcon /><Typography>Mount</Typography></MenuItemExt>,
+      <MenuItemExt aria-label={'unmount-button'} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkOffIcon /><Typography>Unmount</Typography></MenuItemExt>,
+      <Divider />,
+      <MenuItem aria-label={'info-button'} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status !== 'Connected'} ><Info /><Typography>Info</Typography></MenuItem>,
+      <MenuItem aria-label={'edit-button'} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
+      <MenuItem aria-label={'remove-button'} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
+      <Divider />,
+      <MenuItem aria-label={'inventory-button'} onClick={() => this.props.navigateToApplication('inventory', rowData.nodeId)}><Typography>Inventory</Typography></MenuItem>,
+      <Divider />,
+      <MenuItem aria-label={'fault-button'} onClick={() => this.props.navigateToApplication('fault', rowData.nodeId)} ><Typography>Fault</Typography></MenuItem>,
+      <MenuItem aria-label={'configure-button'} onClick={() => this.props.navigateToApplication('configuration', rowData.nodeId)} disabled={rowData.status === 'Connecting' || rowData.status === 'Disconnected' || !configuration}><Typography>Configure</Typography></MenuItem>,
+      <MenuItem onClick={() => this.props.navigateToApplication('accounting', rowData.nodeId)} disabled={true}><Typography>Accounting</Typography></MenuItem>,
+      <MenuItem aria-label={'performance-button'} onClick={() => this.props.navigateToApplication('performanceHistory', rowData.nodeId)}><Typography>Performance</Typography></MenuItem>,
+      <MenuItem onClick={() => this.props.navigateToApplication('security', rowData.nodeId)} disabled={true} ><Typography>Security</Typography></MenuItem>,
+    ];
+
+    if (rowData.weburi) {
+      // add an icon for gui cuttrough, if weburi is available
+      return [<MenuItem aria-label={'web-client-button'} onClick={() => window.open(rowData.weburi, '_blank')} ><ComputerIcon /><Typography>Web Client</Typography></MenuItem>].concat(buttonArray);
+    } else {
+      return buttonArray;
+    }
+  }
+
+  //  private navigationCreator
+
+  render(): JSX.Element {
+    //const { classes } = this.props;
+    const { networkElementToEdit } = this.state;
+    let savedRadio = 'password';
+    if (this.state.networkElementToEdit.password && this.state.networkElementToEdit.password.length > 0) {
+      savedRadio = 'password';
+    } else if (this.state.networkElementToEdit.tlsKey && this.state.networkElementToEdit.tlsKey.length > 0) {
+      savedRadio = 'tlsKey';
+    }
+
+    // const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
+    // const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri);
+    // const canAdd =  mountPolicy && mountPolicy.POST || false;
+    const canAdd = true;
+
+    const addRequireNetworkElementAction = {
+      icon: AddIcon, tooltip: 'Add node', ariaLabel: 'add-element', onClick: () => {
+        this.setState({
+          networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
+          networkElementToEdit: emptyRequireNetworkElement,
+        });
+      },
+    };
+
+    const refreshNetworkElementsAction = {
+      icon: Refresh, tooltip: 'Refresh table', ariaLabel: 'refresh', onClick: () => {
+        this.setState({
+          refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable,
+        });
+      },
+    };
+
+    return <>
+      <NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...(canAdd ? [addRequireNetworkElementAction] : [])]} columns={[
+        { property: 'nodeId', title: 'Node ID', type: ColumnType.text },
+        { property: 'status', title: 'Connection Status', type: ColumnType.text, width:'15%' },
+        { property: 'host', title: 'Host', type: ColumnType.text },
+        { property: 'port', title: 'Port', type: ColumnType.numeric },
+        { property: 'isRequired', title: 'Required', type: ColumnType.boolean },
+        { property: 'deviceType', title: 'Type', type: ColumnType.text },
+        //  { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
+        { property: 'deviceFunction', title: 'Function', type: ColumnType.text, width: '25%' },
+      ]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus createContextMenu={rowData => {
+
+        return this.getContextMenu(rowData);
+      }} >
+      </NetworkElementTable>
+      <EditNetworkElementDialog 
+        initialNetworkElement={networkElementToEdit}
+        mode={this.state.networkElementEditorMode}
+        onClose={this.onCloseEditNetworkElementDialog}
+        radioChecked={savedRadio}
+      />
+      <RefreshNetworkElementsDialog
+        mode={this.state.refreshNetworkElementsEditorMode}
+        onClose={this.onCloseRefreshNetworkElementsDialog}
+      />
+      <InfoNetworkElementDialog
+        initialNetworkElement={networkElementToEdit}
+        mode={this.state.infoNetworkElementEditorMode}
+        onClose={this.onCloseInfoNetworkElementDialog}
+      />
+    </>;
+  }
+
+  public componentDidMount() {
+    if (!initialSorted) {
+      initialSorted = true;
+      this.props.networkElementsActions.onHandleRequestSort('node-id');
+    } else {
+      this.props.networkElementsActions.onRefresh();
+    }
+  }
+
+  private onOpenAddNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
+    });
+  };
+
+  private onOpenRemoveNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement,
+    });
+  };
+
+  private onOpenEditNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+    //let radioSaved;
+    //if (element.password && element.password.length > 0)
+    //  radioSaved = 'password';
+    //else if (element.tlsKey && element.tlsKey.length > 0)
+    //  radioSaved = 'tlsKey';
+    this.setState({
+      networkElementToEdit: {
+        nodeId: element.nodeId,
+        isRequired: element.isRequired,
+        host: element.host,
+        port: element.port,
+        username: element.username,
+        password: element.password,
+        tlsKey: element.tlsKey,
+      },
+      networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement,
+    });
+  };
+
+  private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement,
+    });
+  };
+
+  private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement,
+    });
+  };
+
+  private onOpenInfoNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+    this.props.networkElementInfo(element.nodeId);
+    this.props.networkElementFeaturesInfo(element.nodeId);
+    this.setState({
+      networkElementToEdit: element,
+      infoNetworkElementEditorMode: InfoNetworkElementDialogMode.InfoNetworkElement,
+    });
+  };
+
+  private onCloseEditNetworkElementDialog = () => {
+    this.setState({
+      networkElementEditorMode: EditNetworkElementDialogMode.None,
+      networkElementToEdit: emptyRequireNetworkElement,
+    });
+  };
+
+  private onCloseInfoNetworkElementDialog = () => {
+    this.setState({
+      infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None,
+      networkElementToEdit: emptyRequireNetworkElement,
+    });
+  };
+
+  private onCloseRefreshNetworkElementsDialog = () => {
+    this.setState({
+      refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
+    });
+  };
+}
+
+export const NetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(NetworkElementsListComponent));
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx
new file mode 100644
index 0000000..a4aea7f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx
@@ -0,0 +1,114 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
+import { ConnectionStatusLogType } from '../models/connectionStatusLog';
+
+export enum RefreshConnectionStatusLogDialogMode {
+  None = 'none',
+  RefreshConnectionStatusLogTable = 'RefreshConnectionStatusLogTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshConnectionStatusLog: () => dispatcher.dispatch(connectionStatusLogReloadAction),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshConnectionStatusLogDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable]: {
+    dialogTitle: 'Do you want to refresh the Connection Status Log table?',
+    dialogDescription: '',
+    applyButtonText: 'Yes',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+};
+
+type RefreshConnectionStatusLogDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshConnectionStatusLogDialogMode;
+  onClose: () => void;
+};
+
+type RefreshConnectionStatusLogDialogComponentState = ConnectionStatusLogType & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshConnectionStatusLogDialogComponent extends React.Component<RefreshConnectionStatusLogDialogComponentProps, RefreshConnectionStatusLogDialogComponentState> {
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshConnectionStatusLogDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={() => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={() => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshConnectionStatusLog();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+}
+
+export const RefreshConnectionStatusLogDialog = connect(undefined, mapDispatch)(RefreshConnectionStatusLogDialogComponent);
+export default RefreshConnectionStatusLogDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx
new file mode 100644
index 0000000..e41fd27
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx
@@ -0,0 +1,114 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
+import { NetworkElementConnection } from '../models/networkElementConnection';
+
+export enum RefreshNetworkElementsDialogMode {
+  None = 'none',
+  RefreshNetworkElementsTable = 'RefreshNetworkElementsTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshNetworkElement: () => dispatcher.dispatch(networkElementsReloadAction),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshNetworkElementsDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable]: {
+    dialogTitle: 'Do you want to refresh the nodes table?',
+    dialogDescription: '',
+    applyButtonText: 'Yes',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+};
+
+type RefreshNetworkElementsDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshNetworkElementsDialogMode;
+  onClose: () => void;
+};
+
+type RefreshNetworkElementsDialogComponentState = NetworkElementConnection & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshNetworkElementsDialogComponent extends React.Component<RefreshNetworkElementsDialogComponentProps, RefreshNetworkElementsDialogComponentState> {
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshNetworkElementsDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={() => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={() => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshNetworkElement();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+}
+
+export const RefreshNetworkElementsDialog = connect(undefined, mapDispatch)(RefreshNetworkElementsDialogComponent);
+export default RefreshNetworkElementsDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
new file mode 100644
index 0000000..b386dcd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -0,0 +1,100 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { AddWebUriList, RemoveWebUri, SetPanelAction } from '../actions/commonNetworkElementsActions';
+import { guiCutThrough } from '../models/guiCutTrough';
+import { PanelId } from '../models/panelId';
+import { connectionStatusLogActionHandler, IConnectionStatusLogState } from './connectionStatusLogHandler';
+import { IInfoNetworkElementFeaturesState, IInfoNetworkElementsState, infoNetworkElementFeaturesActionHandler, infoNetworkElementsActionHandler } from './infoNetworkElementHandler';
+import { INetworkElementsState, networkElementsActionHandler } from './networkElementsHandler';
+import { availableTlsKeysActionHandler, IAvailableTlsKeysState } from './tlsKeyHandler';
+
+export interface IConnectAppStoreState {
+  networkElements: INetworkElementsState;
+  connectionStatusLog: IConnectionStatusLogState;
+  currentOpenPanel: PanelId;
+  elementInfo: IInfoNetworkElementsState;
+  elementFeatureInfo: IInfoNetworkElementFeaturesState;
+  guiCutThrough: guiCutThroughState;
+  availableTlsKeys: IAvailableTlsKeysState;
+}
+
+const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
+  if (action instanceof SetPanelAction) {
+    state = action.panelId;
+  }
+  return state;
+};
+
+interface guiCutThroughState {
+  searchedElements: guiCutThrough[];
+  notSearchedElements: string[];
+  unsupportedElements: string[];
+}
+
+const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { searchedElements: [], notSearchedElements: [], unsupportedElements: [] }, action) => {
+  if (action instanceof AddWebUriList) {
+    let notSearchedElements: string[];
+    let searchedElements: guiCutThrough[];
+    let unsupportedElements: string[];
+
+    notSearchedElements = state.notSearchedElements.concat(action.notSearchedElements);
+    unsupportedElements = state.unsupportedElements.concat(action.unsupportedElements);
+
+    //remove elements, which were just searched
+    if (action.newlySearchedElements) {
+      action.newlySearchedElements.forEach(item => {
+        notSearchedElements = notSearchedElements.filter(id => id !== item);
+      });
+    }
+
+    searchedElements = state.searchedElements.concat(action.searchedElements);
+
+    state = { searchedElements: searchedElements, notSearchedElements: notSearchedElements, unsupportedElements: unsupportedElements };
+
+  } else if (action instanceof RemoveWebUri) {
+    const nodeId = action.element;
+    const webUris = state.searchedElements.filter(item => item.id !== nodeId);
+    const knownElements = state.notSearchedElements.filter(item => item !== nodeId);
+    const unsupportedElement = state.unsupportedElements.filter(item => item != nodeId);
+    state = { notSearchedElements: knownElements, searchedElements: webUris, unsupportedElements: unsupportedElement };
+  }
+  return state;
+};
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    connect: IConnectAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  networkElements: networkElementsActionHandler,
+  connectionStatusLog: connectionStatusLogActionHandler,
+  currentOpenPanel: currentOpenPanelHandler,
+  elementInfo: infoNetworkElementsActionHandler,
+  elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
+  guiCutThrough: guiCutThroughHandler,
+  availableTlsKeys: availableTlsKeysActionHandler,
+};
+
+export const connectAppRootHandler = combineActionHandler<IConnectAppStoreState>(actionHandlers);
+export default connectAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
new file mode 100644
index 0000000..264b6c1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog';
+
+export interface IConnectionStatusLogState extends IExternalTableState<NetworkElementConnectionLog> { }
+
+// create eleactic search material data fetch handler
+const connectionStatusLogSearchHandler = createSearchDataHandler<NetworkElementConnectionLog>('connectionlog');
+
+export const {
+  actionHandler: connectionStatusLogActionHandler,
+  createActions: createConnectionStatusLogActions,
+  createProperties: createConnectionStatusLogProperties,
+  reloadAction: connectionStatusLogReloadAction,
+
+  // set value action, to change a value
+} = createExternal<NetworkElementConnectionLog>(connectionStatusLogSearchHandler, appState => appState.connect.connectionStatusLog);
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
new file mode 100644
index 0000000..692e63a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
@@ -0,0 +1,92 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllElementInfoFeatureLoadedAction, AllElementInfoLoadedAction, LoadAllElementInfoAction } from '../actions/infoNetworkElementActions';
+import { Module, TopologyNode } from '../models/topologyNetconf';
+ 
+export interface IInfoNetworkElementsState {
+  elementInfo: TopologyNode;
+  busy: boolean;
+}
+ 
+export interface IInfoNetworkElementFeaturesState {
+  elementFeatureInfo: Module[];
+  busy: boolean;
+}
+ 
+const infoNetworkElementsStateInit: IInfoNetworkElementsState = {
+  elementInfo: {
+    'node-id': '',
+    'netconf-node-topology:available-capabilities': {
+      'available-capability': [],
+    },
+  },
+  busy: false,
+};
+ 
+const infoNetworkElementFeaturesStateInit: IInfoNetworkElementFeaturesState = {
+  elementFeatureInfo: [],
+  busy: false,
+};
+ 
+export const infoNetworkElementsActionHandler: IActionHandler<IInfoNetworkElementsState> = (state = infoNetworkElementsStateInit, action) => {
+  if (action instanceof LoadAllElementInfoAction) {
+    state = {
+      ...state,
+      busy: true,
+    };
+  } else if (action instanceof AllElementInfoLoadedAction) {
+    if (!action.error && action.elementInfo) {
+      state = {
+        ...state,
+        elementInfo: action.elementInfo,
+        busy: false,
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false,
+      };
+    }
+  }
+  return state;
+};
+ 
+export const infoNetworkElementFeaturesActionHandler: IActionHandler<IInfoNetworkElementFeaturesState> = (state = infoNetworkElementFeaturesStateInit, action) => {
+  if (action instanceof LoadAllElementInfoAction) {
+    state = {
+      ...state,
+      busy: true,
+    };
+  } else if (action instanceof AllElementInfoFeatureLoadedAction) {
+    if (!action.error && action.elementFeatureInfo) {
+      state = {
+        ...state,
+        elementFeatureInfo: action.elementFeatureInfo,
+        busy: false,
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false,
+      };
+    }
+  }
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
new file mode 100644
index 0000000..42d2824
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
@@ -0,0 +1,64 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { connectService } from '../services/connectService';
+
+export interface INetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
+
+// create eleactic search material data fetch handler
+const networkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection');
+
+export const {
+  actionHandler: networkElementsActionHandler,
+  createActions: createNetworkElementsActions,
+  createProperties: createNetworkElementsProperties,
+  reloadAction: networkElementsReloadAction,
+
+  // set value action, to change a value
+} = createExternal<NetworkElementConnection>(networkElementsSearchHandler, appState => {
+
+  const webUris = appState.connect.guiCutThrough.searchedElements;
+  // add weburi links, if element is connected & weburi available
+  if (appState.connect.networkElements.rows && webUris.length > 0) {
+
+    appState.connect.networkElements.rows.forEach(element => {
+
+      if (element.status === 'Connected') {
+        const webUri = webUris.find(item => item.id === element.id as string);
+        if (webUri) {
+          element.weburi = webUri.weburi;
+          element.isWebUriUnreachable = false;
+        } else {
+          element.isWebUriUnreachable = true;
+        }
+      }
+    });
+  }
+
+  return appState.connect.networkElements;
+}, (ne) => {
+  if (!ne || !ne.id) return true;
+  const neUrl = connectService.getNetworkElementUri(ne.id);
+  const policy = getAccessPolicyByUrl(neUrl);
+  return !(policy.GET || policy.POST);
+});
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
new file mode 100644
index 0000000..20badcb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllTlsKeyListLoadedAction, LoadAllTlsKeyListAction } from '../actions/tlsKeyActions';
+import { TlsKeys } from '../models/networkElementConnection';
+
+export interface IAvailableTlsKeysState {
+  tlsKeysList: TlsKeys[];
+  busy: boolean;
+}
+
+const tlsKeysStateInit: IAvailableTlsKeysState = {
+  tlsKeysList: [],
+  busy: false,
+};
+
+export const availableTlsKeysActionHandler: IActionHandler<IAvailableTlsKeysState> = (state = tlsKeysStateInit, action) => {
+  if (action instanceof LoadAllTlsKeyListAction) {
+    state = {
+      ...state,
+      busy: true,
+    };
+
+  } else if (action instanceof AllTlsKeyListLoadedAction) {
+    if (!action.error && action.tlsList) {
+      state = {
+        ...state,
+        tlsKeysList: action.tlsList,
+        busy: false,
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false,
+      };
+    }
+  }
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/index.html b/sdnr/wt-odlux/odlux/apps/connectApp/src/index.html
new file mode 100644
index 0000000..1a16876
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <link rel="stylesheet" href="./vendor.css">
+  <title>connectApp</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "connectApp", "faultApp", "inventoryApp", "configurationApp"], function (app, connectApp, faultApp, inventoryApp, configurationApp) {
+      connectApp.register();
+      faultApp.register();
+      inventoryApp.register();
+      app("./app.tsx").configureApplication({ authentication:"basic",  enablePolicy:  false, transportpceUrl:"http://test.de"});
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/connectionStatusLog.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/connectionStatusLog.ts
new file mode 100644
index 0000000..82b49a0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/connectionStatusLog.ts
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type ConnectionStatusLogType = {
+  _id: string;
+  elementStatus: string;
+  timeStamp: string;
+  objectId: string;
+  type: string;
+  newValue: string;
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/guiCutTrough.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/guiCutTrough.ts
new file mode 100644
index 0000000..0fd46a8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/guiCutTrough.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type guiCutThrough = {
+  id: string;
+  weburi?: string;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementBase.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementBase.ts
new file mode 100644
index 0000000..a46a30e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementBase.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type NetworkElementBaseType = {
+  mountId: string;
+  host: string;
+  port: number;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementConnection.ts
new file mode 100644
index 0000000..bb076c7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -0,0 +1,69 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type NetworkElementConnection = {
+  id?: string;
+  nodeId: string;
+  isRequired: boolean;
+  host: string;
+  port: number;
+  username?: string;
+  password?: string;
+  tlsKey?: string;
+  weburi?: string;
+  isWebUriUnreachable?: boolean;
+  status?: 'Connected' | 'mounted' | 'unmounted' | 'Connecting' | 'Disconnected' | 'idle';
+  coreModelCapability?: string;
+  deviceType?: string;
+  deviceFunction?: string;
+  nodeDetails?: {
+    availableCapabilites: {
+      capabilityOrigin: string;
+      capability: string;
+    }[];
+    unavailableCapabilities: {
+      failureReason: string;
+      capability: string;
+    }[];
+  };
+};
+
+
+export type UpdateNetworkElement = {
+  id: string;
+  isRequired?: boolean;
+  username?: string;
+  password?: string;
+  tlsKey?: string;
+};
+
+export type ConnectionStatus = {
+  status: string;
+};
+
+export type TlsKeys = {
+  key: string;
+};
+
+
+/**
+ * Checks if a object has a given propertyname, if yes, the name is returned as string.
+ * @throws at compile time if property is not available
+ * @param name propertyname
+ */
+export const propertyOf = <TObj>(name: keyof TObj) => name;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
new file mode 100644
index 0000000..4b4e283
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type NetworkElementConnectionLog = {
+  id: string;
+  nodeId: string;
+  status: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
+  timestamp: string;
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/panelId.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/panelId.ts
new file mode 100644
index 0000000..2861f10
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/panelId.ts
@@ -0,0 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type PanelId = null | 'NetworkElements' | 'ConnectionStatusLog';
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/topologyNetconf.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/topologyNetconf.ts
new file mode 100644
index 0000000..85a1a71
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/topologyNetconf.ts
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export interface AvailableCapability {
+  'capability-origin': string;
+  capability: string;
+}
+
+export interface NetconfNodeTopologyAvailableCapabilities {
+  'available-capability': AvailableCapability[];
+}
+
+export interface TopologyNode {
+  'node-id': string;
+  'netconf-node-topology:available-capabilities': NetconfNodeTopologyAvailableCapabilities;
+}
+
+export interface Topology {
+  'topology-id': string;
+  'network-topology:node': TopologyNode[];
+}
+
+/**
+  * Represents the type of the features of the Module. 
+  */
+export interface Module {
+  feature?: string[];
+  location?: string[];
+  name: string;
+  namespace?: string;
+  revision?: string;
+}
+
+export interface ModuleFeatures {
+  module: Module[];
+}
+
+export interface ModuleSet {
+  'module-set': ModuleFeatures[];
+}
+
+export interface FeatureTopology {
+  'ietf-yang-library:yang-library' : ModuleSet; 
+}
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
new file mode 100644
index 0000000..b69993f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
@@ -0,0 +1,24 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type AvailableCapabilities = {
+  id?: string;
+  module: string;
+  revision: string;
+  features: string;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/pluginConnect.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/pluginConnect.tsx
new file mode 100644
index 0000000..c290716
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/pluginConnect.tsx
@@ -0,0 +1,109 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
+
+import { AddSnackbarNotification } from '../../../framework/src/actions/snackbarActions';
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IFormatedMessage, subscribe } from '../../../framework/src/services/notificationService';
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+
+import { findWebUrisForGuiCutThroughAsyncAction, SetPanelAction, updateCurrentViewAsyncAction } from './actions/commonNetworkElementsActions';
+import { NetworkElementsList } from './components/networkElements';
+import connectAppRootHandler from './handlers/connectAppRootHandler';
+import { createNetworkElementsActions, createNetworkElementsProperties, networkElementsReloadAction } from './handlers/networkElementsHandler';
+import { PanelId } from './models/panelId';
+import ConnectApplication from './views/connectView';
+
+const appIcon = require('./assets/icons/connectAppIcon.svg');  // select app icon
+
+let currentStatus: string | undefined = undefined;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  networkElementDashboardProperties: createNetworkElementsProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  networkElementsDashboardActions: createNetworkElementsActions(dispatcher.dispatch, true),
+  setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+});
+
+const ConnectApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ status?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+  
+  // TODO: move into useEffect!
+  if (currentStatus !== props.match.params.status) {
+    currentStatus = props.match.params.status || undefined;
+    window.setTimeout(() => {
+      if (currentStatus) {
+        props.setCurrentPanel('NetworkElements');
+        props.networkElementsDashboardActions.onFilterChanged('status', currentStatus);
+        if (!props.networkElementDashboardProperties.showFilter) {
+          props.networkElementsDashboardActions.onToggleFilter(false);
+          props.networkElementsDashboardActions.onRefresh();
+        } else
+          props.networkElementsDashboardActions.onRefresh();
+      }
+    });
+  }
+  return (
+    <NetworkElementsList />
+  );
+});
+
+
+const App = withRouter((props: RouteComponentProps) => (
+  <Switch>
+    <Route path={`${props.match.path}/connectionStatus/:status?`} component={ConnectApplicationRouteAdapter} />
+    <Route path={`${props.match.path}`} component={ConnectApplication} />
+    <Redirect to={`${props.match.path}`} />
+  </Switch>
+));
+
+export function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: 'connect',
+    icon: appIcon,
+    rootComponent: App,
+    rootActionHandler: connectAppRootHandler,
+    menuEntry: 'Connect',
+  });
+
+  // subscribe to the websocket notifications
+  subscribe<IFormatedMessage>(['object-creation-notification', 'object-deletion-notification', 'attribute-value-changed-notification'], (msg => {
+    const store = applicationApi.applicationStore;
+    if (msg && msg.type.type === 'object-creation-notification' && store) {
+      store.dispatch(new AddSnackbarNotification({ message: `Adding node [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
+    } else if (msg && (msg.type.type === 'object-deletion-notification' || msg.type.type === 'attribute-value-changed-notification') && store) {
+      store.dispatch(new AddSnackbarNotification({ message: `Updating node [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
+    }
+    if (store) {
+      store.dispatch(updateCurrentViewAsyncAction() as any).then(() => {
+        if (msg['node-id']) {
+          store.dispatch(findWebUrisForGuiCutThroughAsyncAction([msg['node-id']]));
+        }
+      });
+    }
+  }));
+
+  applicationApi.applicationStoreInitialized.then(store => {
+    store.dispatch(networkElementsReloadAction);
+  });
+
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt-odlux/odlux/apps/connectApp/src/services/connectService.ts
new file mode 100644
index 0000000..1d74f85
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/services/connectService.ts
@@ -0,0 +1,305 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { requestRest } from '../../../../framework/src/services/restService';
+import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+import { TlsKeys } from '../models/networkElementConnection';
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { Result } from '../../../../framework/src/models/elasticSearch';
+
+import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topologyNetconf';
+import { guiCutThrough } from '../models/guiCutTrough';
+
+/**
+* Represents a web api accessor service for all network element/node actions.
+*/
+class ConnectService {
+  public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
+
+  public getNetworkElementConnectDataProviderUri = (operation: 'create' | 'update' | 'delete') => `/rests/operations/data-provider:${operation}-network-element-connection`;
+
+  public getAllWebUriExtensionsForNetworkElementListUri = (nodeId: string) => this.getNetworkElementUri(nodeId) + '/yang-ext:mount/core-model:network-element';
+
+  public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig';
+
+  /**
+   * Inserts a network element/node.
+   */
+  public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
+    const path = this.getNetworkElementConnectDataProviderUri('create');
+    const result = await requestRest<NetworkElementConnection>(path, {
+      method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': element }, replaceUpperCase)),
+    });
+    return result || null;
+  }
+
+  /**
+  * Updates a network element/node.
+  */
+  public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+    const path = this.getNetworkElementConnectDataProviderUri('update');
+    const result = await requestRest<NetworkElementConnection>(path, {
+      method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': element }, replaceUpperCase)),
+    });
+    return result || null;
+  }
+
+  /**
+    * Deletes a network element/node.
+    */
+  public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+    const query = {
+      'id': element.id,
+    };
+    const path = this.getNetworkElementConnectDataProviderUri('delete');
+    const result = await requestRest<NetworkElementConnection>(path, {
+      method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': query }, replaceUpperCase)),
+    });
+    return result || null;
+  }
+
+  /** Mounts network element/node */
+  public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
+    const path = this.getNetworkElementUri(networkElement.nodeId);
+    const mountXml = [
+      '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+      `<node-id>${networkElement.nodeId}</node-id>`,
+      `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+      `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+      `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+      `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</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('');
+
+    const tlsXml = [
+      '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+      `<node-id>${networkElement.nodeId}</node-id>`,
+      '<key-based xmlns="urn:opendaylight:netconf-node-topology">',
+      `<key-id xmlns="urn:opendaylight:netconf-node-topology">${networkElement.tlsKey}</key-id>`,
+      `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+      '</key-based>',
+      `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+      `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+      '<tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+      '<protocol xmlns="urn:opendaylight:netconf-node-topology">',
+      '<name xmlns="urn:opendaylight:netconf-node-topology">TLS</name>',
+      ' </protocol>',
+      '<max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">2</max-connection-attempts>',
+      '</node>'].join('');
+    let bodyXml;
+    if (networkElement.password) {
+      bodyXml = mountXml;
+    } else {
+      bodyXml = tlsXml;
+    }
+
+    try {
+      const result = await requestRest<string>(path, {
+        method: 'PUT',
+        headers: {
+          'Content-Type': 'application/xml',
+          'Accept': 'application/xml',
+        },
+        body: bodyXml,
+      });
+      // expect an empty answer
+      return result !== null;
+    } catch {
+      return false;
+    }
+  }
+
+  /** Unmounts a network element by its id. */
+  public async unmountNetworkElement(nodeId: string): Promise<boolean> {
+    const path = this.getNetworkElementUri(nodeId);
+
+    try {
+      const result = await requestRest<string>(path, {
+        method: 'DELETE',
+        headers: {
+          'Content-Type': 'application/xml',
+          'Accept': 'application/xml',
+        },
+      });
+      // expect an empty answer
+      return result !== null;
+
+    } catch {
+      return false;
+    }
+  }
+
+  /** Yang capabilities of the selected network element/node */
+  public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
+    const path = this.getNetworkElementUri(nodeId);
+    const topologyRequestPomise = requestRest<Topology>(path, { method: 'GET' });
+
+    return topologyRequestPomise && topologyRequestPomise.then(result => {
+      return result && result['network-topology:node'] && result['network-topology:node'][0] || null;
+    });
+  }
+
+
+  /** Yang features of the selected network element/node module */
+  public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
+    const path = this.getNetworkElementYangLibraryFeature(nodeId);
+    const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: 'GET' });
+
+    return topologyRequestPomise && topologyRequestPomise.then(result => {
+      const resultFinal = result && result['ietf-yang-library:yang-library']
+        && result['ietf-yang-library:yang-library']['module-set'] &&
+        result['ietf-yang-library:yang-library']['module-set'][0] &&
+        result['ietf-yang-library:yang-library']['module-set'][0].module || null;
+      return resultFinal;
+    });
+  }
+
+
+
+  /**
+   * Get the connection state of the network element/ node
+   */
+  public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
+    const path = '/rests/operations/data-provider:read-network-element-connection-list';
+    const query = {
+      'data-provider:input': {
+        'filter': [{
+          'property': 'node-id',
+          'filtervalue': element,
+        }],
+        'pagination': {
+          'size': 20,
+          'page': 1,
+        },
+      },
+    };
+    const result = await requestRest<Result<ConnectionStatus>>(path, { method: 'POST', body: JSON.stringify(query) });
+    return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+      status: ne.status,
+    })) || null;
+  }
+
+  /**
+  * Gets all available tlsKeys.
+  */
+
+  public async getTlsKeys(): Promise<(TlsKeys)[] | null> {
+    const path = '/rests/operations/data-provider:read-tls-key-entry';
+    const query = {
+      'data-provider:input': {
+        'filter': [],
+        'sortorder': [],
+        'pagination': {
+          'size': 20,
+          'page': 1,
+        },
+      },
+    };
+
+    const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(query) });
+    return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+      key: ne,
+    })) || null;
+  }
+
+  public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(guiCutThrough)[]> {
+    const path = '/rests/operations/data-provider:read-gui-cut-through-entry';
+    let webUriList: guiCutThrough[] = [];
+    const query = {
+      'data-provider:input': {
+        'filter': [{
+          'property': 'id',
+          'filtervalues': neList,
+        }],
+        'pagination': {
+          'size': 20,
+          'page': 1,
+        },
+      },
+    };
+
+    const result = await requestRest<Result<guiCutThrough>>(path, { method: 'POST', body: JSON.stringify(query) });
+    const resultData = result && result['data-provider:output'] && result['data-provider:output'].data;
+    neList.forEach(nodeId => {
+      let entryNotFound = true;
+      if (resultData) {
+        try {
+          resultData.forEach(entry => {
+            if (entry.id == nodeId) {
+              entryNotFound = false;
+              if (entry.weburi) {
+                webUriList.push({ id: nodeId, weburi: entry.weburi });
+              } else {
+                webUriList.push({ id: nodeId, weburi: undefined });
+              }
+              throw new Error();
+            }
+          });
+        } catch (e) { }
+      }
+      if (entryNotFound)
+        webUriList.push({ id: nodeId, weburi: undefined });
+    });
+    return webUriList;
+  }
+
+  //  public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
+
+  //   let promises: any[] = [];
+  //   let webUris: guiCutThrough[] = []
+
+  //   ne.forEach(nodeId => {
+  //     const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
+
+  // // add search request to array
+  //     promises.push(requestRest<any>(path, { method: "GET" })
+  //       .then(result => {
+  //         if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
+  //           const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
+  //           if (webUri) {
+  //             webUris.push({ weburi: webUri.value, id: nodeId });
+  //           } else {
+  //             webUris.push({ weburi: undefined, id: nodeId });
+  //           }
+  //         } else {
+  //           webUris.push({ weburi: undefined, id: nodeId });
+  //         }
+  //       })
+  //       .catch(error => {
+  //         webUris.push({ weburi: undefined, id: nodeId });
+  //       }))
+  //   })
+  //   // wait until all promises are done and return weburis
+  //   return Promise.all(promises).then(result => { return webUris });
+  // }
+
+}
+
+
+
+export const connectService = new ConnectService();
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/views/connectView.tsx
new file mode 100644
index 0000000..a6fcb7c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/views/connectView.tsx
@@ -0,0 +1,102 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import { AppBar, Tab, Tabs } from '@mui/material';
+
+import { useApplicationDispatch, useSelectApplicationState } from '../../../../framework/src/flux/connect';
+
+import { findWebUrisForGuiCutThroughAsyncAction, setPanelAction } from '../actions/commonNetworkElementsActions';
+import { ConnectionStatusLog } from '../components/connectionStatusLog';
+import { NetworkElementsList } from '../components/networkElements';
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { PanelId } from '../models/panelId';
+
+const ConnectApplicationComponent:  React.FC<{}> = () => {
+
+  const panelId = useSelectApplicationState(state => state.connect.currentOpenPanel);
+  const netWorkElements = useSelectApplicationState(state => state.connect.networkElements);
+
+  const dispatch = useApplicationDispatch();
+  const onLoadNetworkElements = () => dispatch(networkElementsReloadAction);
+  const loadWebUris = (networkElements: NetworkElementConnection[]) => dispatch(findWebUrisForGuiCutThroughAsyncAction(networkElements.map((ne) => ne.id!)));
+  const onLoadConnectionStatusLog = () => dispatch(connectionStatusLogReloadAction);
+  const switchActivePanel = (panelId2: PanelId) => dispatch(setPanelAction(panelId2));
+
+  const onTogglePanel = (panelId2: PanelId) => {
+    const nextActivePanel = panelId2;
+    switchActivePanel(nextActivePanel);
+
+    switch (nextActivePanel) {
+      case 'NetworkElements':
+        onLoadNetworkElements();
+        break;
+      case 'ConnectionStatusLog':
+        onLoadConnectionStatusLog();
+        break;
+      case null:
+        // do nothing if all panels are closed
+        break;
+      default:
+        console.warn('Unknown nextActivePanel [' + nextActivePanel + '] in connectView');
+        break;
+    }
+  };
+
+  const onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
+    switchActivePanel(newValue);
+  };
+
+  React.useEffect(()=>{
+    if (panelId === null) { //don't change tabs, if one is selected already
+      onTogglePanel('NetworkElements');
+    }
+  }, []);
+
+  React.useEffect(()=>{
+    const networkElements = netWorkElements;
+
+    if (networkElements.rows.length > 0) {
+      // Search for weburi client for all netWorkElements in case of table data changes.
+      // e.G: Pagination of the table data (there is no event)
+      loadWebUris(networkElements.rows);
+    }
+  }, [netWorkElements]);
+
+  return (
+    <>
+      <AppBar enableColorOnDark position="static">
+        <Tabs indicatorColor="secondary" textColor="inherit" value={panelId} onChange={onHandleTabChange} aria-label="connect-app-tabs">
+          <Tab aria-label="network-elements-list-tab" label="NODES" value="NetworkElements" />
+          <Tab aria-label="connection-status-log-tab" label="Connection Status Log" value="ConnectionStatusLog" />
+        </Tabs>
+      </AppBar>
+      {panelId === 'NetworkElements'
+        ? <NetworkElementsList />
+        : panelId === 'ConnectionStatusLog'
+          ? <ConnectionStatusLog />
+          : null
+      }
+    </>
+  );
+};
+
+export const ConnectApplication = ConnectApplicationComponent;
+export default ConnectApplication;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/connectApp/tsconfig.json
new file mode 100644
index 0000000..18956db
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/tsconfig.json
@@ -0,0 +1,6 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "./dist",
+   },
+}
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/connectApp/webpack.config.js
new file mode 100644
index 0000000..b7aebb9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/connectApp/webpack.config.js
@@ -0,0 +1,202 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+const policies = require('./policies.json');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      connectApp: ["./pluginConnect.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },{
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      before: function(app, server, compiler) {
+        app.get('/oauth/policies',(_, res) => res.json(policies));
+      },
+       proxy: {
+        "/about": {
+          target: "http://sdnr:8181",
+          secure: false
+        }, 
+        "/yang-schema/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },   
+        "/oauth/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/database/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/userdata": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/userdata/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/help/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+         "/about/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/tree/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/websocket": {
+          target: "http://sdnr:8181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        },
+        "/apidoc": {
+          target: "http://sdnr:8181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/.babelrc b/sdnr/wt-odlux/odlux/apps/demoApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/package.json b/sdnr/wt-odlux/odlux/apps/demoApp/package.json
new file mode 100644
index 0000000..6a31bc3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/package.json
@@ -0,0 +1,46 @@
+{
+  "name": "@odlux/demo-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI framework",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@fortawesome/fontawesome-svg-core": "1.2.35",
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@fortawesome/react-fontawesome": "0.1.14",
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/pom.xml b/sdnr/wt-odlux/odlux/apps/demoApp/pom.xml
new file mode 100644
index 0000000..71e4c10
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-demoApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/actions/authorActions.ts b/sdnr/wt-odlux/odlux/apps/demoApp/src/actions/authorActions.ts
new file mode 100644
index 0000000..f22d1e0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/actions/authorActions.ts
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
+
+import { IAuthor } from '../models/author';
+import { authorService } from '../services/authorService';
+
+export class ApplicationBaseAction extends Action { }
+
+
+export class LoadAllAuthorsAction extends ApplicationBaseAction {
+  
+}
+
+// in React Action is most times a Message
+export class AllAuthorsLoadedAction extends ApplicationBaseAction {
+  constructor(public authors: IAuthor[] | null, public error?: string) {
+    super();
+  }
+}
+
+export const loadAllAuthorsAsync = (dispatch: Dispatch) => {
+  dispatch(new LoadAllAuthorsAction());
+  authorService.getAllAuthors().then(authors => {
+    dispatch(new AllAuthorsLoadedAction(authors));
+  }, error => {
+    dispatch(new AllAuthorsLoadedAction(null, error));
+    dispatch(new AddErrorInfoAction(error));
+  });
+}; 
+
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/components/counter.tsx b/sdnr/wt-odlux/odlux/apps/demoApp/src/components/counter.tsx
new file mode 100644
index 0000000..1aad974
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/components/counter.tsx
@@ -0,0 +1,29 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React, { FC, useState } from 'react';
+
+const Counter: FC = () => {
+  const [counter, setCounter] = useState(0);
+  return (
+    <button onClick={() => setCounter(counter + 1 )} color="inherit">{counter}</button>
+  );
+};
+
+Counter.displayName = 'Counter';
+
+export { Counter };
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
new file mode 100644
index 0000000..1f920f2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { listAuthorsHandler, IListAuthors } from './listAuthorsHandler';
+import { editAuthorHandler, IEditAuthor } from './editAuthorHandler';
+
+export interface IDemoAppStoreState {
+  listAuthors: IListAuthors;
+  editAuthor: IEditAuthor;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    demo: IDemoAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  listAuthors: listAuthorsHandler,
+  editAuthor: editAuthorHandler,
+};
+
+export const demoAppRootHandler = combineActionHandler <IDemoAppStoreState>(actionHandlers);
+export default demoAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts b/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
new file mode 100644
index 0000000..1d37a36
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { IAuthor } from '../models/author';
+export interface IEditAuthor {
+  author: IAuthor | null;
+  isDirty: boolean;
+}
+
+const editAuthorInit: IEditAuthor = {
+  author: null,
+  isDirty: false,
+};
+
+export const editAuthorHandler: IActionHandler<IEditAuthor> = (state = editAuthorInit, _action) => {
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts b/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
new file mode 100644
index 0000000..c85eaff
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
@@ -0,0 +1,57 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { IAuthor } from '../models/author';
+import { LoadAllAuthorsAction, AllAuthorsLoadedAction } from '../actions/authorActions';
+
+export interface IListAuthors {
+  authors: IAuthor[];
+  busy: boolean;
+}
+
+const listAuthorsInit: IListAuthors = {
+  authors: [],
+  busy: false,
+};
+
+export const listAuthorsHandler: IActionHandler<IListAuthors> = (state = listAuthorsInit, action) => {
+  if (action instanceof LoadAllAuthorsAction) {
+
+    state = {
+      ...state,
+      busy: true,
+    };
+  
+  } else if (action instanceof AllAuthorsLoadedAction) {
+    if (!action.error && action.authors) {
+      state = {
+        ...state,
+        authors: action.authors,
+        busy: false,
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false,
+      };
+    }
+  }
+
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/index.html b/sdnr/wt-odlux/odlux/apps/demoApp/src/index.html
new file mode 100644
index 0000000..521c890
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>Demo App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app","demoApp"], function (app, demoApp) {
+      demoApp.register();
+      app("./app.tsx").configureApplication({ authentication:"oauth",  enablePolicy:  true,});
+      app("./app.tsx");
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/models/author.ts b/sdnr/wt-odlux/odlux/apps/demoApp/src/models/author.ts
new file mode 100644
index 0000000..bdd414c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/models/author.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents an author.
+ */
+export interface IAuthor {
+  /**
+   * Defines the unique id of the author. 
+   */
+  id: number;
+
+  /**
+   * Defines the first name of this author.
+   */
+  firstName: string;
+
+  /**
+   * Defines the last name of this author.
+   */
+  lastName: string;
+}
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/plugin.tsx b/sdnr/wt-odlux/odlux/apps/demoApp/src/plugin.tsx
new file mode 100644
index 0000000..7b29b40
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/plugin.tsx
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faAddressBook } from '@fortawesome/free-solid-svg-icons/faAddressBook';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { connect, Connect } from '../../../framework/src/flux/connect';
+
+import { demoAppRootHandler } from './handlers/demoAppRootHandler';
+
+import AuthorsList from './views/authorsList';
+import EditAuthor from './views/editAuthor';
+
+import { Counter } from './components/counter';
+
+type AppProps = RouteComponentProps & Connect;
+
+const App = (props: AppProps) => (
+  <Switch>
+    <Route exact path={ `${ props.match.path }/authors` } component={AuthorsList} />
+    <Route path={ `${ props.match.path }/authors/:authorId` } component={EditAuthor } />
+    <Redirect to={ `${ props.match.path }/authors` } />
+   </Switch>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+  applicationManager.registerApplication({
+    name: 'demo',
+    icon: faAddressBook,
+    rootComponent: FinalApp,
+    rootActionHandler: demoAppRootHandler,
+    exportedComponents: { counter: Counter },
+    menuEntry: 'Demo',
+  });
+}
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/services/authorService.ts b/sdnr/wt-odlux/odlux/apps/demoApp/src/services/authorService.ts
new file mode 100644
index 0000000..deaa2ff
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/services/authorService.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IAuthor } from '../models/author';
+
+import * as $ from 'jquery';
+
+const base_url = 'https://api.mfico.de/v1/authors';
+
+/** 
+ * Represents a web api accessor service for all author related actions.
+ */
+class AuthorService {
+
+  /**
+   * Gets all known authors from the backend.
+   * @returns A promise of the type array of @see {@link IAuthor} containing all known authors.
+   */
+  public getAllAuthors(): Promise<IAuthor[]> {
+    return new Promise((resolve: (value: IAuthor[]) => void, reject: (err: any) => void) => {
+      $.ajax({ method: 'GET', url: base_url })
+        .then((data) => { resolve(data); }, (err) => { reject(err); });
+    });
+  }
+
+  /**
+   * Gets an author by its id from the backend.
+   * @returns A promise of the type @see {@link IAuthor} containing the author to get.
+   */
+  public getAuthorById(id: string | number): Promise<IAuthor> {
+    return new Promise((resolve: (value: IAuthor) => void, reject: (err: any) => void) => {
+      $.ajax({ method: 'GET', url: base_url + '/' + id })
+        .then((data) => { resolve(data); }, (err) => { reject(err); });
+    });
+  }
+
+
+  /**
+ * Saves the given author to the backend api.
+ * @returns A promise of the type @see {@link IAuthor} containing the autor returned by the backend api.
+ */
+  public saveAuthor(author: IAuthor): Promise<IAuthor> {
+    return new Promise((resolve: (value: IAuthor) => void, reject: (err: any) => void) => {
+      // simulate server save
+      window.setTimeout(() => {
+        if (Math.random() > 0.8) {
+          reject('Could not save author.');
+        } else {
+          resolve(author);
+        }
+      }, 800); // simulate a short network delay
+    });
+  }
+}
+
+// return as a singleton
+export const authorService = new AuthorService();
+export default authorService;
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/views/authorsList.tsx b/sdnr/wt-odlux/odlux/apps/demoApp/src/views/authorsList.tsx
new file mode 100644
index 0000000..5d9f13a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/views/authorsList.tsx
@@ -0,0 +1,93 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import Table from '@mui/material/Table';
+import TableBody from '@mui/material/TableBody';
+import TableCell from '@mui/material/TableCell';
+import TableHead from '@mui/material/TableHead';
+import TableRow from '@mui/material/TableRow';
+import Paper from '@mui/material/Paper'; // means border
+
+import { connect } from '../../../../framework/src/flux/connect';
+
+import { loadAllAuthorsAsync } from '../actions/authorActions';
+import { IAuthor } from '../models/author';
+
+interface IAuthorsListProps {
+  authors: IAuthor[];
+  busy: boolean;
+  onLoadAllAuthors: () => void;
+}
+
+class AuthorsListComponent extends React.Component<RouteComponentProps & IAuthorsListProps> {
+
+  render(): JSX.Element {
+    const { authors, busy } = this.props;
+    return busy
+      ? (
+        <Paper>
+          Loading
+        </Paper>
+      )
+      : (
+      <Paper>
+        <Table padding="normal" >
+          <TableHead>
+            <TableRow>
+              <TableCell align="right">Id</TableCell>
+              <TableCell >First Name</TableCell>
+              <TableCell >Last Name</TableCell>
+            </TableRow>
+          </TableHead>
+          <TableBody>
+            {authors.map(author => (
+              <TableRow key={author.id} onClick={(_e) => this.editAuthor(author)}>
+                <TableCell>{author.id}</TableCell>
+                <TableCell>{author.firstName}</TableCell>
+                <TableCell>{author.lastName}</TableCell>
+              </TableRow>
+            ))}
+          </TableBody>
+        </Table>
+      </Paper>
+      );
+  }
+
+  public componentDidMount() {
+    this.props.onLoadAllAuthors();
+  }
+
+  private editAuthor = (author: IAuthor) => {
+    if (author) this.props.history.push(this.props.match.path + '/' + author.id);
+  };
+}
+
+export const AuthorsList = withRouter(
+  connect(
+    ({ demo: state }) => ({
+      authors: state.listAuthors.authors,
+      busy: state.listAuthors.busy,
+    }),
+    (dispatcher) => ({
+      onLoadAllAuthors: () => {
+        dispatcher.dispatch(loadAllAuthorsAsync);
+      },
+    }))(AuthorsListComponent));
+export default AuthorsList;
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/src/views/editAuthor.tsx b/sdnr/wt-odlux/odlux/apps/demoApp/src/views/editAuthor.tsx
new file mode 100644
index 0000000..0da619b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/src/views/editAuthor.tsx
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+type EditAuthorProps = RouteComponentProps<{ authorId: string }>;
+
+class EditAuthorComponent extends React.Component<EditAuthorProps> {
+  render(): JSX.Element {
+    return (
+      <div>
+        <h2>Edit Author { this.props.match.params.authorId }</h2>
+      </div>
+    );
+  }
+}
+
+export const EditAuthor = withRouter(EditAuthorComponent);
+export default EditAuthor;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/demoApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/demoApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/demoApp/webpack.config.js
new file mode 100644
index 0000000..0476c30
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/demoApp/webpack.config.js
@@ -0,0 +1,134 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      demoApp: ["./plugin.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }]
+    },
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/api": {
+          target: "http://localhost:3001",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/.babelrc b/sdnr/wt-odlux/odlux/apps/eventLogApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/package.json b/sdnr/wt-odlux/odlux/apps/eventLogApp/package.json
new file mode 100644
index 0000000..fb6cedf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/package.json
@@ -0,0 +1,43 @@
+{
+  "name": "@odlux/eventlog-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI to display event log from a database.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Sai Neetha Phulmali",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/pom.xml b/sdnr/wt-odlux/odlux/apps/eventLogApp/pom.xml
new file mode 100644
index 0000000..c3ab9ac
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-eventLogApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/assets/icons/eventLogAppIcon.svg b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/assets/icons/eventLogAppIcon.svg
new file mode 100644
index 0000000..743167d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/assets/icons/eventLogAppIcon.svg
@@ -0,0 +1,21 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512">

+

+<g>

+<path fill="#C8D400" d="M192,224c-17.672,0-32,14.328-32,32s14.328,32,32,32h128c17.672,0,32-14.328,32-32s-14.328-32-32-32H192z"/>

+

+<path fill="#C8D400" d="M256,320h-64c-17.672,0-32,14.328-32,32s14.328,32,32,32h64c17.672,0,32-14.328,32-32S273.672,320,256,320z"/>

+

+<path fill="#565656" d="M416,32h-80c0-17.674-11.938-32-26.668-32H202.668C187.938,0,176,14.326,176,32H96c-17.672,0-32,14.328-32,32v416

+		c0,17.672,14.328,32,32,32h320c17.672,0,32-14.328,32-32V64C448,46.328,433.672,32,416,32z M256,32c17.672,0,32,14.326,32,32

+		c0,17.673-14.328,32-32,32s-32-14.327-32-32C224,46.326,238.328,32,256,32z M384,448H128V96h48v32h160V96h48V448z"/>

+</g>

+</svg>

diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/components/refreshEventLogDialog.tsx b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/components/refreshEventLogDialog.tsx
new file mode 100644
index 0000000..8b5d951
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/components/refreshEventLogDialog.tsx
@@ -0,0 +1,117 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { eventLogReloadAction } from '../handlers/eventLogHandler';
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { EventLogType } from '../models/eventLogType';
+
+export enum RefreshEventLogDialogMode {
+  None = "none",
+  RefreshEventLogTable = "RefreshEventLogTable",
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshEventLog: () => dispatcher.dispatch(eventLogReloadAction)
+});
+
+type DialogSettings = {
+  dialogTitle: string,
+  dialogDescription: string,
+  applyButtonText: string,
+  cancelButtonText: string,
+  enableMountIdEditor: boolean,
+  enableUsernameEditor: boolean,
+  enableExtendedEditor: boolean,
+}
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshEventLogDialogMode.None]: {
+    dialogTitle: "",
+    dialogDescription: "",
+    applyButtonText: "",
+    cancelButtonText: "",
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshEventLogDialogMode.RefreshEventLogTable]: {
+    dialogTitle: "Do you want to refresh the Event Log?",
+    dialogDescription: "",
+    applyButtonText: "Yes",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  }
+}
+
+type RefreshEventLogDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshEventLogDialogMode;
+  onClose: () => void;
+};
+
+type RefreshEventLogDialogComponentState = EventLogType & { isNameValid: boolean, isHostSet: boolean };
+
+class RefreshEventLogDialogComponent extends React.Component<RefreshEventLogDialogComponentProps, RefreshEventLogDialogComponentState> {
+  constructor(props: RefreshEventLogDialogComponentProps) {
+    super(props);
+  }
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshEventLogDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={(event) => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={(event) => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshEventLog();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  }
+}
+
+export const RefreshEventLogDialog = connect(undefined, mapDispatch)(RefreshEventLogDialogComponent);
+export default RefreshEventLogDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts
new file mode 100644
index 0000000..6e2d40e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts
@@ -0,0 +1,45 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* 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.
+* ============LICENSE_END==========================================================================
+*/
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// ** do not remove **
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { IEventLogState, eventLogActionHandler } from './eventLogHandler';
+
+
+export interface IEventLogAppStateState {
+  logEntries: IEventLogState
+}
+
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    eventLog: IEventLogAppStateState;
+  }
+}
+
+const actionHandlers = {
+  logEntries: eventLogActionHandler
+};
+
+export const EventLogAppRootHandler = combineActionHandler<IEventLogAppStateState>(actionHandlers);
+export default EventLogAppRootHandler;
+
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx
new file mode 100644
index 0000000..300a8f7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { EventLogType } from '../models/eventLogType';
+
+export interface IEventLogState extends IExternalTableState<EventLogType> { }
+
+// create eleactic search material data fetch handler
+const eventLogSearchHandler = createSearchDataHandler<EventLogType>("eventlog");
+
+export const {
+  actionHandler: eventLogActionHandler,
+  createActions: createEventLogActions,
+  createProperties: createEventLogProperties,
+  reloadAction: eventLogReloadAction,
+
+  // set value action, to change a value
+} = createExternal<EventLogType>(eventLogSearchHandler, appState => appState.eventLog.logEntries);
+
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/index.html b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/index.html
new file mode 100644
index 0000000..8027509
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>EventLog App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app","connectApp", "eventLogApp"], function (app, connectApp, eventLogApp) {
+      connectApp.register();
+      eventLogApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/models/eventLogType.ts b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/models/eventLogType.ts
new file mode 100644
index 0000000..7c68e64
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/models/eventLogType.ts
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+export type EventLogType = {
+  nodeId: string;
+  counter: number;
+  timestamp: string;
+  objectId: string;
+  attributeName: string;
+  newValue: string;
+  sourceType: string;
+}
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/pluginEventLog.tsx b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/pluginEventLog.tsx
new file mode 100644
index 0000000..8ee322a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/pluginEventLog.tsx
@@ -0,0 +1,42 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* 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.
+* ============LICENSE_END==========================================================================
+*/
+// app configuration and main entry point for the app
+
+import React, { FC } from 'react';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { EventLog } from './views/eventLog';
+import eventLogAppRootHandler from './handlers/eventLogAppRootHandler';
+
+const appIcon = require('./assets/icons/eventLogAppIcon.svg');  // select app icon
+
+const App : FC = () => {
+  return <EventLog />;
+};
+
+export function register() {
+  applicationManager.registerApplication({
+    name: 'eventLog',
+    icon: appIcon,
+    rootActionHandler: eventLogAppRootHandler,
+    rootComponent: App,
+    menuEntry: 'EventLog',
+  });
+}
+
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/src/views/eventLog.tsx b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/views/eventLog.tsx
new file mode 100644
index 0000000..1fc53f2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/src/views/eventLog.tsx
@@ -0,0 +1,102 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import Refresh from '@mui/icons-material/Refresh';
+
+import { EventLogType } from '../models/eventLogType';
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { createEventLogProperties, createEventLogActions } from "../handlers/eventLogHandler";
+import RefreshEventLogDialog, { RefreshEventLogDialogMode } from '../components/refreshEventLogDialog';
+
+const EventLogTable = MaterialTable as MaterialTableCtorType<EventLogType & { _id: string }>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  eventLogProperties: createEventLogProperties(state),
+  eventLog: state.eventLog.logEntries
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  eventLogActions: createEventLogActions(dispatcher.dispatch)
+});
+
+type EventLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>;
+type EventLogComponentState = {
+  refreshEventLogEditorMode: RefreshEventLogDialogMode
+}
+let initalSorted = false;
+
+class EventLogComponent extends React.Component<EventLogComponentProps, EventLogComponentState> {
+  constructor(props: EventLogComponentProps) {
+    super(props);
+
+    this.state = {
+      refreshEventLogEditorMode: RefreshEventLogDialogMode.None
+    };
+  }
+
+  render(): JSX.Element {
+
+    const refreshEventLogAction = {
+      icon: Refresh, tooltip: 'Refresh Event log', ariaLabel:'refresh', onClick: () => {
+        this.setState({
+          refreshEventLogEditorMode: RefreshEventLogDialogMode.RefreshEventLogTable
+        });
+      }
+    };
+    return (
+      <>
+        <EventLogTable stickyHeader title="Event Log" tableId="event-log-table" idProperty="_id" customActionButtons={[refreshEventLogAction]}
+          columns={[
+            { property: "nodeId", title: "Node Name" },
+            { property: "counter", title: "Counter" },
+            { property: "timestamp", title: "Timestamp" },
+            { property: "objectId", title: "Object ID" },
+            { property: "attributeName", title: "Attribute Name" },
+            { property: "newValue", title: "Message" },
+            { property: "sourceType", title: "Source" }
+          ]}  {...this.props.eventLogActions} {...this.props.eventLogProperties} >
+        </EventLogTable>
+        <RefreshEventLogDialog
+          mode={this.state.refreshEventLogEditorMode}
+          onClose={this.onCloseRefreshEventLogDialog}
+        />
+      </>
+    )
+  }
+
+  private onCloseRefreshEventLogDialog = () => {
+    this.setState({
+      refreshEventLogEditorMode: RefreshEventLogDialogMode.None
+    });
+  }
+  componentDidMount() {
+
+    if (!initalSorted) {
+      initalSorted = true;
+      this.props.eventLogActions.onHandleExplicitRequestSort("timestamp", "desc");
+    } else {
+      this.props.eventLogActions.onRefresh();
+    }
+  }
+}
+
+export const EventLog = connect(mapProps, mapDispatch)(EventLogComponent);
+export default EventLog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/eventLogApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/eventLogApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/eventLogApp/webpack.config.js
new file mode 100644
index 0000000..3d056ec
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/eventLogApp/webpack.config.js
@@ -0,0 +1,165 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      eventLogApp: ["./pluginEventLog.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }, {
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/oauth2/": {
+          target: "http://localhost:28181",
+          secure: false
+        },
+        "/database/": {
+          target: "http://localhost:28181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://localhost:28181",
+          secure: false
+        },
+        "/help/": {
+          target: "http://localhost:28181",
+          secure: false
+        },
+        "/websocket/": {
+          target: "http://localhost:28181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/.babelrc b/sdnr/wt-odlux/odlux/apps/faultApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/package.json b/sdnr/wt-odlux/odlux/apps/faultApp/package.json
new file mode 100644
index 0000000..9531055
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/package.json
@@ -0,0 +1,46 @@
+{
+  "name": "@odlux/fault-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI to demo the fault management.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*",
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@fortawesome/react-fontawesome": "0.1.14"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0",
+    "react-chartjs-2": "^3.0.3"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/pom.xml b/sdnr/wt-odlux/odlux/apps/faultApp/pom.xml
new file mode 100644
index 0000000..3e74918
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-faultApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
new file mode 100644
index 0000000..7aac8ba
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { clearStuckAlarms } from '../services/faultStatusService';
+import { FaultApplicationBaseAction } from './notificationActions';
+
+export class AreStuckAlarmsCleared extends FaultApplicationBaseAction {
+  constructor(public isBusy: boolean) {
+    super();
+  }
+}
+
+
+export const clearStuckAlarmAsyncAction = (dispatch: Dispatch) => async (nodeNames: string[]) => {
+  dispatch(new AreStuckAlarmsCleared(true));
+  const result = await clearStuckAlarms(nodeNames).catch(error => { console.error(error); return undefined; });
+  dispatch(new AreStuckAlarmsCleared(false));
+  return result;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts
new file mode 100644
index 0000000..584e7cd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+
+import { FaultAlarmNotification } from '../models/fault';
+
+export class FaultApplicationBaseAction extends Action { }
+
+
+export class AddFaultNotificationAction extends FaultApplicationBaseAction {
+  constructor(public fault:FaultAlarmNotification) {
+    super();
+  }
+}
+
+export class ResetFaultNotificationsAction extends FaultApplicationBaseAction {
+ 
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts
new file mode 100644
index 0000000..fb29e9c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+
+import { PanelId } from '../models/panelId';
+
+export class SetPanelAction extends Action {
+  constructor(public panelId: PanelId) {
+    super();
+  }
+}
+
+export class RememberCurrentPanelAction extends Action {
+  constructor(public panelId: PanelId) {
+    super();
+  }
+}
+
+export const setPanelAction = (panelId: PanelId) => {
+  return new SetPanelAction(panelId);
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts
new file mode 100644
index 0000000..8b631b9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { getFaultStateFromDatabase } from '../services/faultStatusService';
+import { FaultApplicationBaseAction } from './notificationActions';
+
+
+export class SetFaultStatusAction extends FaultApplicationBaseAction {
+  constructor(public criticalFaults: number, public majorFaults: number, public minorFaults: number, public warnings: number,
+    public isLoadingAlarmStatusChart: boolean, public ConnectedCount: number, public ConnectingCount: number, public DisconnectedCount: number,
+    public MountedCount: number, public UnableToConnectCount: number, public UndefinedCount: number, public UnmountedCount: number,
+    public totalCount: number, public isLoadingConnectionStatusChart: boolean) {
+    super();
+  }
+}
+
+
+export const refreshFaultStatusAsyncAction = async (dispatch: Dispatch) => {
+
+  // dispatch(new SetFaultStatusAction(0, 0, 0, 0, true, 0, 0, 0, 0, 0, 0, 0, 0, true));
+  const result = await getFaultStateFromDatabase().catch(_ => null);
+  if (result) {
+    const statusAction = new SetFaultStatusAction(
+      result.Critical || 0,
+      result.Major || 0,
+      result.Minor || 0,
+      result.Warning || 0,
+      false,
+      result.Connected || 0,
+      result.Connecting || 0,
+      result.Disconnected || 0,
+      result.Mounted || 0,
+      result.UnableToConnect || 0,
+      result.Undefined || 0,
+      result.Unmounted || 0,
+      result.total || 0,
+      false,
+    );
+    dispatch(statusAction);
+    return;
+  } else {
+    dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
+  }
+};
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg b/sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg
new file mode 100644
index 0000000..aabbf4c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg
@@ -0,0 +1,19 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg viewBox="0 0 500 540" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
+    <g transform="matrix(27.7762,0,0,27.7762,-13.8603,-27.7762)">
+
+ <path fill="#565656" d="M 16.8 15.101 C 15.656 14.242 15 12.929 15 11.5 L 15 8.5 C 15 5.987 13.306 3.862 11 3.208 L 11 2.5 C 11 1.673 10.327 1 9.5 1 C 8.673 1 8 1.673 8 2.5 L 8 3.208 C 5.694 3.863 4 5.987 4 8.5 L 4 11.5 C 4 12.929 3.344 14.241 2.2 15.101 C 2.028 15.23 1.958 15.455 2.026 15.659 C 2.094 15.863 2.285 16.001 2.5 16.001 L 16.499 16.001 C 16.714 16.001 16.905 15.863 16.973 15.659 C 17.041 15.455 16.971 15.23 16.799 15.101 L 16.8 15.101 Z" />
+
+ <path fill="#D81036" d="m 7.05 17.001 c -0.033 0.164 -0.051 0.331 -0.051 0.5 c 0 1.378 1.122 2.5 2.5 2.5 c 1.378 0 2.5 -1.122 2.5 -2.5 c 0 -0.168 -0.017 -0.336 -0.05 -0.5 l -4.899 0 z" />
+
+
+    </g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
new file mode 100644
index 0000000..e86b756
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
@@ -0,0 +1,138 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+
+import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { clearStuckAlarmAsyncAction } from '../actions/clearStuckAlarmsAction';
+import { currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+
+export enum ClearStuckAlarmsDialogMode {
+  None = 'none',
+  Show = 'show',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  clearStuckAlarmsAsync: clearStuckAlarmAsyncAction(dispatcher.dispatch),
+  reloadCurrentAlarmsAction: () => dispatcher.dispatch(currentAlarmsReloadAction),
+});
+
+type clearStuckAlarmsProps = Connect<typeof undefined, typeof mapDispatch> & {
+  numberDevices: Number;
+  mode: ClearStuckAlarmsDialogMode;
+  stuckAlarms: string[];
+  onClose: () => void;
+};
+
+type ClearStuckAlarmsState = {
+  clearAlarmsSuccessful: boolean;
+  errormessage: string;
+  unclearedAlarms: string[];
+};
+
+class ClearStuckAlarmsDialogComponent extends React.Component<clearStuckAlarmsProps, ClearStuckAlarmsState> {
+  constructor(props: clearStuckAlarmsProps) {
+    super(props);
+    this.state = {
+      clearAlarmsSuccessful: true,
+      errormessage: '',
+      unclearedAlarms: [],
+    };
+  }
+
+  onClose = (event: React.MouseEvent) => {
+    event.stopPropagation();
+    event.preventDefault();
+    this.props.onClose();
+  };
+
+  onRefresh = async (event: React.MouseEvent) => {
+    event.stopPropagation();
+    event.preventDefault();
+    const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms);
+
+    if (result && result['devicemanager:output'].nodenames && result['devicemanager:output'].nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared
+      const undeletedAlarm = this.props.stuckAlarms.filter(item => !result['devicemanager:output'].nodenames.includes(item));
+      const error = 'The alarms of the following devices couldn\'t be refreshed: ';
+      this.setState({ clearAlarmsSuccessful: false, errormessage: error, unclearedAlarms: undeletedAlarm });
+      return;
+
+    } else { //show errormessage if no devices were cleared
+      this.setState({ clearAlarmsSuccessful: false, errormessage: 'Alarms couldn\'t be refreshed.', unclearedAlarms: [] });
+    }
+
+    this.props.reloadCurrentAlarmsAction();
+    this.props.onClose();
+  };
+
+  onOk = (event: React.MouseEvent) => {
+
+    event.stopPropagation();
+    event.preventDefault();
+    if (this.state.unclearedAlarms.length > 0)
+      this.props.reloadCurrentAlarmsAction();
+    this.props.onClose();
+  };
+
+  render() {
+    console.log(this.props.stuckAlarms);
+    const device = this.props.numberDevices > 1 ? 'devices' : 'device';
+    const defaultMessage = 'Are you sure you want to refresh all alarms for ' + this.props.numberDevices + ' ' + device + '?';
+    const message = this.state.clearAlarmsSuccessful ? defaultMessage : this.state.errormessage;
+
+    const defaultTitle = 'Refresh Confirmation';
+    const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result';
+
+    return (
+      <Dialog open={this.props.mode !== ClearStuckAlarmsDialogMode.None}>
+        <DialogTitle>{title}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {message}
+          </DialogContentText>
+          {
+            this.state.unclearedAlarms.map(item =>
+              <DialogContentText>
+                {item}
+              </DialogContentText>,
+            )
+          }
+        </DialogContent>
+        <DialogActions>
+          {
+            this.state.clearAlarmsSuccessful &&
+            <>
+              <Button color="inherit" onClick={this.onRefresh}>Yes</Button>
+              <Button color="inherit" onClick={this.onClose}>No</Button>
+            </>
+          }
+
+          {
+            !this.state.clearAlarmsSuccessful && <Button color="inherit" onClick={this.onOk}>Ok</Button>
+          }
+        </DialogActions>
+      </Dialog>
+    );
+  }
+}
+
+const ClearStuckAlarmsDialog = connect(undefined, mapDispatch)(ClearStuckAlarmsDialogComponent);
+export default ClearStuckAlarmsDialog;
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx
new file mode 100644
index 0000000..a3e32c4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx
@@ -0,0 +1,473 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import { Doughnut } from 'react-chartjs-2';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+const styles = () => createStyles({
+  pageWidthSettings: {
+    width: '50%',
+    float: 'left',
+  },
+});
+
+const scrollbar = { overflow: 'auto', paddingRight: '20px' };
+
+let connectionStatusinitialLoad = true;
+let connectionStatusinitialStateChanged = false;
+let connectionStatusDataLoad: number[] = [0, 0, 0, 0];
+let connectionTotalCount = 0;
+
+let alarmStatusinitialLoad = true;
+let alarmStatusinitialStateChanged = false;
+let alarmStatusDataLoad: number[] = [0, 0, 0, 0];
+let alarmTotalCount = 0;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  alarmStatus: state.fault.faultStatus,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+});
+
+type HomeComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+class DashboardHome extends React.Component<HomeComponentProps>  {
+  constructor(props: HomeComponentProps) {
+    super(props);
+    this.state = {
+    };
+  }
+
+  render(): JSX.Element {
+
+    if (!this.props.alarmStatus.isLoadingConnectionStatusChart) {
+      connectionStatusDataLoad = [
+        this.props.alarmStatus.Connected,
+        this.props.alarmStatus.Connecting,
+        this.props.alarmStatus.Disconnected,
+        this.props.alarmStatus.UnableToConnect,
+        this.props.alarmStatus.Undefined,
+      ];
+      connectionTotalCount = this.props.alarmStatus.Connected + this.props.alarmStatus.Connecting
+        + this.props.alarmStatus.Disconnected + this.props.alarmStatus.UnableToConnect + this.props.alarmStatus.Undefined;
+
+    }
+
+    if (!this.props.alarmStatus.isLoadingAlarmStatusChart) {
+      alarmStatusDataLoad = [
+        this.props.alarmStatus.critical,
+        this.props.alarmStatus.major,
+        this.props.alarmStatus.minor,
+        this.props.alarmStatus.warning,
+      ];
+      alarmTotalCount = this.props.alarmStatus.critical + this.props.alarmStatus.major
+        + this.props.alarmStatus.minor + this.props.alarmStatus.warning;
+    }
+
+    /** Available Network Connection Status chart data */
+    const connectionStatusData = {
+      labels: [
+        'Connected: ' + this.props.alarmStatus.Connected,
+        'Connecting: ' + this.props.alarmStatus.Connecting,
+        'Disconnected: ' + this.props.alarmStatus.Disconnected,
+        'UnableToConnect: ' + this.props.alarmStatus.UnableToConnect,
+        'Undefined: ' + this.props.alarmStatus.Undefined,
+      ],
+      datasets: [{
+        labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect', 'Undefined'],
+        data: connectionStatusDataLoad,
+        backgroundColor: [
+          'rgb(0, 153, 51)',
+          'rgb(255, 102, 0)',
+          'rgb(191, 191, 191)',
+          'rgb(191, 191, 191)',
+          'rgb(242, 240, 240)',
+        ],
+      }],
+    };
+
+
+    /** No Devices available */
+    const connectionStatusUnavailableData = {
+      labels: ['No Devices available'],
+      datasets: [{
+        data: [1],
+        backgroundColor: [
+          'rgb(255, 255, 255)',
+        ],
+      }],
+    };
+
+    /** Loading Connection Status chart */
+    const connectionStatusisLoading = {
+      labels: ['Loading chart...'],
+      datasets: [{
+        data: [1],
+        backgroundColor: [
+          'rgb(255, 255, 255)',
+        ],
+      }],
+    };
+
+    /** Loading Alarm Status chart */
+    const alarmStatusisLoading = {
+      labels: ['Loading chart...'],
+      datasets: [{
+        data: [1],
+        backgroundColor: [
+          'rgb(255, 255, 255)',
+        ],
+      }],
+    };
+
+    /** Connection status options */
+    let labels: String[] = ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect', 'Undefined'];
+    const connectionStatusOptions = {
+      tooltips: {
+        callbacks: {
+          label: (tooltipItem: any, data: any) => {
+            let label =
+              (data.datasets[tooltipItem.datasetIndex].labels &&
+                data.datasets[tooltipItem.datasetIndex].labels[
+                  tooltipItem.index
+                ]) ||
+              data.labels[tooltipItem.index] ||
+              '';
+            if (label) {
+              label += ': ';
+            }
+            label +=
+              data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
+              (data.datasets[tooltipItem.datasetIndex].labelSuffix || '');
+
+            return label;
+          },
+        },
+      },
+      responsive: true,
+      maintainAspectRatio: false,
+      animation: {
+        duration: 0,
+      },
+      plugins: {
+        legend: {
+          display: true,
+          position: 'top',
+        },
+      },
+      onClick: (event: MouseEvent, item: any) => {
+        if (item[0]) {
+          let connectionStatus = labels[item[0]._index] + '';
+          this.props.navigateToApplication('connect', '/connectionStatus/' + connectionStatus);
+        }
+      },
+    };
+
+    /** Connection status unavailable options */
+    const connectionStatusUnavailableOptions = {
+      responsive: true,
+      maintainAspectRatio: false,
+      animation: {
+        duration: 0,
+      },
+      plugins: {
+        legend: {
+          display: true,
+          position: 'top',
+        },
+        tooltip: {
+          enabled: false,
+        },
+      },
+    };
+
+    /** Add text inside the doughnut chart for Connection Status */
+    const connectionStatusPlugins = [{
+      beforeDraw: function (chart: any) {
+        var width = chart.width,
+          height = chart.height,
+          ctx = chart.ctx;
+        ctx.restore();
+        var fontSize = (height / 480).toFixed(2);
+        ctx.font = fontSize + 'em sans-serif';
+        ctx.textBaseline = 'top';
+        var text = 'Network Connection Status',
+          textX = Math.round((width - ctx.measureText(text).width) / 2),
+          textY = height / 2;
+        ctx.fillText(text, textX, textY);
+        ctx.save();
+      },
+    }];
+
+    /** Alarm status Data */
+    const alarmStatusData = {
+      labels: [
+        'Critical : ' + this.props.alarmStatus.critical,
+        'Major : ' + this.props.alarmStatus.major,
+        'Minor : ' + this.props.alarmStatus.minor,
+        'Warning : ' + this.props.alarmStatus.warning,
+      ],
+      datasets: [{
+        labels: ['Critical', 'Major', 'Minor', 'Warning'],
+        data: alarmStatusDataLoad,
+        backgroundColor: [
+          'rgb(240, 25, 10)',
+          'rgb(240, 133, 10)',
+          'rgb(240, 240, 10)',
+          'rgb(46, 115, 176)',
+        ],
+      }],
+    };
+
+    /** No Alarm status available */
+    const alarmStatusUnavailableData = {
+      labels: ['No Alarms available'],
+      datasets: [{
+        data: [1],
+        backgroundColor: [
+          'rgb(0, 153, 51)',
+        ],
+      }],
+    };
+
+    /** Alarm status Options */
+    let alarmLabels: String[] = ['Critical', 'Major', 'Minor', 'Warning'];
+    const alarmStatusOptions = {
+      tooltips: {
+        callbacks: {
+          label: (tooltipItem: any, data: any) => {
+            let label =
+              (data.datasets[tooltipItem.datasetIndex].labels &&
+                data.datasets[tooltipItem.datasetIndex].labels[
+                  tooltipItem.index
+                ]) ||
+              data.labels[tooltipItem.index] ||
+              '';
+            if (label) {
+              label += ': ';
+            }
+            label +=
+              data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
+              (data.datasets[tooltipItem.datasetIndex].labelSuffix || '');
+
+            return label;
+          },
+        },
+      },
+      responsive: true,
+      maintainAspectRatio: false,
+      animation: {
+        duration: 0,
+      },
+      plugins: {
+        legend: {
+          display: true,
+          position: 'top',
+        },
+      },
+      onClick: (event: MouseEvent, item: any) => {
+        if (item[0]) {
+          let severity = alarmLabels[item[0]._index] + '';
+          this.props.navigateToApplication('fault', '/alarmStatus/' + severity);
+        }
+      },
+    };
+
+    /** Alarm status unavailable options */
+    const alarmStatusUnavailableOptions = {
+      responsive: true,
+      maintainAspectRatio: false,
+      animation: {
+        duration: 0,
+      },
+      plugins: {
+        legend: {
+          display: true,
+          position: 'top',
+        },
+        tooltip: {
+          enabled: false,
+        },
+      },
+    };
+    /** Add text inside the doughnut chart for Alarm Status */
+    const alarmStatusPlugins = [{
+      beforeDraw: function (chart: any) {
+        var width = chart.width,
+          height = chart.height,
+          ctx = chart.ctx;
+        ctx.restore();
+        var fontSize = (height / 480).toFixed(2);
+        ctx.font = fontSize + 'em sans-serif';
+        ctx.textBaseline = 'top';
+        var text = 'Network Alarm Status',
+          textX = Math.round((width - ctx.measureText(text).width) / 2),
+          textY = height / 2;
+        ctx.fillText(text, textX, textY);
+        ctx.save();
+      },
+    }];
+
+    return (
+      <>
+        <div style={scrollbar} >
+          <h1 aria-label="welcome-to-odlux">Welcome to ODLUX</h1>
+          <div style={{ width: '50%', float: 'left' }}>
+            {this.checkElementsAreLoaded() ?
+              this.checkConnectionStatus() && connectionTotalCount != 0 ?
+                <Doughnut
+                  data={connectionStatusData}
+                  type={Doughnut}
+                  width={500}
+                  height={500}
+                  options={connectionStatusOptions}
+                  plugins={connectionStatusPlugins}
+                />
+                : <Doughnut
+                  data={connectionStatusUnavailableData}
+                  type={Doughnut}
+                  width={500}
+                  height={500}
+                  options={connectionStatusUnavailableOptions}
+                  plugins={connectionStatusPlugins} />
+              : <Doughnut
+                data={connectionStatusisLoading}
+                type={Doughnut}
+                width={500}
+                height={500}
+                options={connectionStatusUnavailableOptions}
+                plugins={connectionStatusPlugins}
+              />
+            }
+          </div>
+          <div style={{ width: '50%', float: 'left' }}>
+            {this.checkAlarmsAreLoaded() ?
+              this.checkAlarmStatus() && alarmTotalCount != 0 ?
+                <Doughnut
+                  data={alarmStatusData}
+                  type={Doughnut}
+                  width={500}
+                  height={500}
+                  options={alarmStatusOptions}
+                  plugins={alarmStatusPlugins}
+                />
+                : <Doughnut
+                  data={alarmStatusUnavailableData}
+                  type={Doughnut}
+                  width={500}
+                  height={500}
+                  options={alarmStatusUnavailableOptions}
+                  plugins={alarmStatusPlugins}
+                />
+              : <Doughnut
+                data={alarmStatusisLoading}
+                type={Doughnut}
+                width={500}
+                height={500}
+                options={alarmStatusUnavailableOptions}
+                plugins={alarmStatusPlugins}
+              />
+            }
+          </div>
+        </div>
+      </>
+    );
+  }
+
+  /** Check if connection status data available */
+  public checkConnectionStatus = () => {
+    let statusCount = this.props.alarmStatus;
+    if (statusCount.isLoadingConnectionStatusChart) {
+      return true;
+    }
+    if (statusCount.Connected == 0 && statusCount.Connecting == 0 && statusCount.Disconnected == 0
+      && statusCount.UnableToConnect == 0 && statusCount.Undefined == 0) {
+      return false;
+    } else {
+      return true;
+    }
+  };
+
+  /** Check if connection status chart data is loaded */
+  public checkElementsAreLoaded = () => {
+    let isLoadingCheck = this.props.alarmStatus;
+    if (connectionStatusinitialLoad && !isLoadingCheck.isLoadingConnectionStatusChart) {
+      if (this.checkConnectionStatus()) {
+        connectionStatusinitialLoad = false;
+        return true;
+      }
+      return false;
+    } else if (connectionStatusinitialLoad && isLoadingCheck.isLoadingConnectionStatusChart) {
+      connectionStatusinitialLoad = false;
+      connectionStatusinitialStateChanged = true;
+      return !isLoadingCheck.isLoadingConnectionStatusChart;
+    } else if (connectionStatusinitialStateChanged) {
+      if (!isLoadingCheck.isLoadingConnectionStatusChart) {
+        connectionStatusinitialStateChanged = false;
+      }
+      return !isLoadingCheck.isLoadingConnectionStatusChart;
+    }
+    return true;
+  };
+
+  /** Check if alarms data available */
+  public checkAlarmStatus = () => {
+    let alarmCount = this.props.alarmStatus;
+    if (alarmCount.isLoadingAlarmStatusChart) {
+      return true;
+    }
+    if (alarmCount.critical == 0 && alarmCount.major == 0 && alarmCount.minor == 0 && alarmCount.warning == 0) {
+      return false;
+    } else {
+      return true;
+    }
+  };
+
+  /** Check if alarm status chart data is loaded */
+  public checkAlarmsAreLoaded = () => {
+    let isLoadingCheck = this.props.alarmStatus;
+    if (alarmStatusinitialLoad && !isLoadingCheck.isLoadingAlarmStatusChart) {
+      if (this.checkAlarmStatus()) {
+        alarmStatusinitialLoad = false;
+        return true;
+      }
+      return false;
+    } else if (alarmStatusinitialLoad && isLoadingCheck.isLoadingAlarmStatusChart) {
+      alarmStatusinitialLoad = false;
+      alarmStatusinitialStateChanged = true;
+      return !isLoadingCheck.isLoadingAlarmStatusChart;
+    } else if (alarmStatusinitialStateChanged) {
+      if (!isLoadingCheck.isLoadingAlarmStatusChart) {
+        alarmStatusinitialStateChanged = false;
+      }
+      return !isLoadingCheck.isLoadingAlarmStatusChart;
+    }
+    return true;
+  };
+}
+
+export default (withRouter(connect(mapProps, mapDispatch)(DashboardHome)));
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/faultStatus.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/faultStatus.tsx
new file mode 100644
index 0000000..57374dd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/faultStatus.tsx
@@ -0,0 +1,106 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import Typography from '@mui/material/Typography';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+import Tooltip from '@mui/material/Tooltip';
+
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+
+const styles = () => createStyles({
+  icon: {
+    marginLeft: 8,
+    marginRight: 8,
+  },
+  critical: {
+    color: 'red',
+  },
+  major: {
+    color: 'orange',
+  },
+  minor: {
+    color: '#f7f700',
+  },
+  warning: {
+    color: '#428bca',
+  },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  faultStatus: state.fault.faultStatus,
+});
+
+
+type FaultStatusComponentProps = & WithStyles<typeof styles> & Connect<typeof mapProps>;
+
+class FaultStatusComponent extends React.Component<FaultStatusComponentProps> {
+  render(): JSX.Element {
+    const { classes, faultStatus } = this.props;
+
+    return (
+      <>
+        <Typography variant="body1" color="inherit">
+          Alarm Status:
+          <Tooltip title="Critical Alarms" arrow>
+            <span aria-label="critical-alarms">
+              <FontAwesomeIcon className={`${classes.icon} ${classes.critical}`} icon={faExclamationTriangle} />
+            </span>
+          </Tooltip>
+          {faultStatus.critical} |
+        </Typography>
+
+        <Typography variant="body1" color="inherit">
+          <Tooltip title="Major Alarms" arrow>
+            <span aria-label="major-alarms">
+              <FontAwesomeIcon className={`${classes.icon} ${classes.major}`} icon={faExclamationTriangle} />
+            </span>
+          </Tooltip>
+          {faultStatus.major} |
+        </Typography>
+
+        <Typography variant="body1" color="inherit">
+          <Tooltip title="Minor Alarms" arrow>
+            <span aria-label="minor-alarms">
+              <FontAwesomeIcon className={`${classes.icon} ${classes.minor}`} icon={faExclamationTriangle} />
+            </span>
+          </Tooltip>
+          {faultStatus.minor} |
+        </Typography>
+
+        <Typography variant="body1" color="inherit">
+          <Tooltip title="Warning Alarms" arrow>
+            <span aria-label="warning-alarms">
+              <FontAwesomeIcon className={`${classes.icon} ${classes.warning}`} icon={faExclamationTriangle} />
+            </span>
+          </Tooltip>
+          {faultStatus.warning} |
+        </Typography>
+      </>
+    );
+  }
+}
+
+export const FaultStatus = withStyles(styles)(connect(mapProps)(FaultStatusComponent));
+export default FaultStatus;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
new file mode 100644
index 0000000..59657d8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
@@ -0,0 +1,112 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
+import { Fault } from '../models/fault';
+
+export enum RefreshAlarmLogDialogMode {
+  None = 'none',
+  RefreshAlarmLogTable = 'RefreshAlarmLogTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshAlarmLog: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshAlarmLogDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshAlarmLogDialogMode.RefreshAlarmLogTable]: {
+    dialogTitle: 'Do you want to refresh the Alarm Log?',
+    dialogDescription: '',
+    applyButtonText: 'Yes',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+};
+
+type RefreshAlarmLogDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshAlarmLogDialogMode;
+  onClose: () => void;
+};
+
+type RefreshAlarmLogDialogComponentState = Fault & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshAlarmLogDialogComponent extends React.Component<RefreshAlarmLogDialogComponentProps, RefreshAlarmLogDialogComponentState> {
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshAlarmLogDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={() => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={() => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshAlarmLog();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+}
+
+export const RefreshAlarmLogDialog = connect(undefined, mapDispatch)(RefreshAlarmLogDialogComponent);
+export default RefreshAlarmLogDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx
new file mode 100644
index 0000000..20cd514
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx
@@ -0,0 +1,113 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+import { Fault } from '../models/fault';
+
+export enum RefreshCurrentAlarmsDialogMode {
+  None = 'none',
+  RefreshCurrentAlarmsTable = 'RefreshCurrentAlarmsTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshCurrentAlarms: () => dispatcher.dispatch(currentAlarmsReloadAction),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshCurrentAlarmsDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshCurrentAlarmsDialogMode.RefreshCurrentAlarmsTable]: {
+    dialogTitle: 'Do you want to refresh the Current Alarms List?',
+    dialogDescription: '',
+    applyButtonText: 'Yes',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+};
+
+type RefreshCurrentAlarmsDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshCurrentAlarmsDialogMode;
+  onClose: () => void;
+};
+
+type RefreshCurrentAlarmsDialogComponentState = Fault & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshCurrentAlarmsDialogComponent extends React.Component<RefreshCurrentAlarmsDialogComponentProps, RefreshCurrentAlarmsDialogComponentState> {
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshCurrentAlarmsDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={() => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={() => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshCurrentAlarms();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+}
+
+export const RefreshCurrentAlarmsDialog = connect(undefined, mapDispatch)(RefreshCurrentAlarmsDialogComponent);
+export default RefreshCurrentAlarmsDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
new file mode 100644
index 0000000..bdd4596
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault } from '../models/fault';
+
+export interface IAlarmLogEntriesState extends IExternalTableState<Fault> { }
+
+// create eleactic search data fetch handler
+const alarmLogEntriesSearchHandler = createSearchDataHandler< Fault>('faultlog');
+
+export const {
+  actionHandler: alarmLogEntriesActionHandler,
+  createActions: createAlarmLogEntriesActions,
+  createProperties: createAlarmLogEntriesProperties,
+  reloadAction: alarmLogEntriesReloadAction,
+
+  // set value action, to change a value
+} = createExternal<Fault>(alarmLogEntriesSearchHandler, appState => appState.fault.alarmLogEntries);
+
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
new file mode 100644
index 0000000..0d5a8c7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AreStuckAlarmsCleared } from '../actions/clearStuckAlarmsAction';
+
+export interface IStuckAlarms {
+  areAlarmsCleared: boolean;
+}
+
+const initialState: IStuckAlarms = {
+  areAlarmsCleared: false,
+};
+
+export const stuckAlarmHandler: IActionHandler<IStuckAlarms> = (state = initialState, action) => {
+  if (action instanceof AreStuckAlarmsCleared) {
+    state = { ...state, areAlarmsCleared: action.isBusy };
+  }
+
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts
new file mode 100644
index 0000000..70aa1c2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault } from '../models/fault';
+
+export interface ICurrentAlarmsState extends IExternalTableState<Fault> { }
+
+// create eleactic search data fetch handler
+const currentAlarmsSearchHandler = createSearchDataHandler<Fault>('faultcurrent');
+
+export const {
+  actionHandler: currentAlarmsActionHandler,
+  createActions: createCurrentAlarmsActions,
+  createProperties: createCurrentAlarmsProperties,
+  reloadAction: currentAlarmsReloadAction,
+
+  // set value action, to change a value
+} = createExternal<Fault>(currentAlarmsSearchHandler, appState => appState.fault.currentAlarms);
+
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
new file mode 100644
index 0000000..e4a19ae
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -0,0 +1,63 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// ** do not remove **
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { PanelId } from '../models/panelId';
+import { alarmLogEntriesActionHandler, IAlarmLogEntriesState } from './alarmLogEntriesHandler';
+import { currentAlarmsActionHandler, ICurrentAlarmsState } from './currentAlarmsHandler';
+import { faultStatusHandler, IFaultStatus } from './faultStatusHandler';
+import { faultNotificationsHandler, IFaultNotifications } from './notificationsHandler';
+
+export interface IFaultAppStoreState {
+  currentAlarms: ICurrentAlarmsState;
+  faultNotifications: IFaultNotifications;
+  alarmLogEntries: IAlarmLogEntriesState;
+  currentOpenPanel: PanelId | null;
+  faultStatus: IFaultStatus;
+}
+
+const currentOpenPanelHandler: IActionHandler<PanelId | null> = (state = null, action) => {
+  if (action instanceof SetPanelAction) {
+    state = action.panelId;
+  }
+  return state;
+};
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    fault: IFaultAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  currentAlarms: currentAlarmsActionHandler,
+  faultNotifications: faultNotificationsHandler,
+  alarmLogEntries: alarmLogEntriesActionHandler,
+  currentOpenPanel: currentOpenPanelHandler,
+  faultStatus: faultStatusHandler,
+};
+
+export const faultAppRootHandler = combineActionHandler<IFaultAppStoreState>(actionHandlers);
+export default faultAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
new file mode 100644
index 0000000..21b033e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { SetFaultStatusAction } from '../actions/statusActions';
+
+export interface IFaultStatus {
+  critical: number;
+  major: number;
+  minor: number;
+  warning: number;
+  isLoadingAlarmStatusChart: boolean;
+  Connected: number;
+  Connecting: number;
+  Disconnected: number;
+  Mounted: number;
+  UnableToConnect: number;
+  Undefined: number;
+  Unmounted: number;
+  total: number;
+  isLoadingConnectionStatusChart: boolean;
+}
+
+const faultStatusInit: IFaultStatus = {
+  critical: 0,
+  major: 0,
+  minor: 0,
+  warning: 0,
+  isLoadingAlarmStatusChart: false,
+  Connected: 0,
+  Connecting: 0,
+  Disconnected: 0,
+  Mounted: 0,
+  UnableToConnect: 0,
+  Undefined: 0,
+  Unmounted: 0,
+  total: 0,
+  isLoadingConnectionStatusChart: false,
+};
+
+export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultStatusInit, action) => {
+  if (action instanceof SetFaultStatusAction) {
+    state = {
+      critical: action.criticalFaults,
+      major: action.majorFaults,
+      minor: action.minorFaults,
+      warning: action.warnings,
+      isLoadingAlarmStatusChart: action.isLoadingAlarmStatusChart,
+      Connected: action.ConnectedCount,
+      Connecting: action.ConnectingCount,
+      Disconnected: action.DisconnectedCount,
+      Mounted: action.MountedCount,
+      UnableToConnect: action.UnableToConnectCount,
+      Undefined: action.UndefinedCount,
+      Unmounted: action.UnmountedCount,
+      total: action.totalCount,
+      isLoadingConnectionStatusChart: action.isLoadingConnectionStatusChart,
+    };
+  }
+
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
new file mode 100644
index 0000000..3d960bf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions';
+import { FaultAlarmNotification } from '../models/fault';
+
+export interface IFaultNotifications {
+  faults: FaultAlarmNotification[];
+  since: Date;
+}
+
+const faultNotoficationsInit: IFaultNotifications = {
+  faults: [],
+  since: new Date(),
+};
+
+export const faultNotificationsHandler: IActionHandler<IFaultNotifications> = (state = faultNotoficationsInit, action) => {
+  if (action instanceof AddFaultNotificationAction) {
+    state = {
+      ...state,
+      faults: [...state.faults, action.fault],
+    };
+  } else if (action instanceof ResetFaultNotificationsAction) {
+    state = {
+      ...state,
+      faults: [],
+      since: new Date(),
+    };
+  }
+
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/index.html b/sdnr/wt-odlux/odlux/apps/faultApp/src/index.html
new file mode 100644
index 0000000..c379680
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css"> -->
+  <title>Minimal App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "faultApp", "connectApp" ], function (app, faultApp, connectApp) {
+        faultApp.register();
+        connectApp.register();
+        app("./app.tsx").runApplication();
+      });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts
new file mode 100644
index 0000000..c70253e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts
@@ -0,0 +1,97 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type Fault = {
+  id: string;
+  nodeId: string;
+  counter: number;
+  timestamp: string;
+  objectId: string;
+  problem: string;
+  severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical' | 'NonAlarmed';
+  type: string;
+  sourceType?: string;
+};
+
+export type FaultAlarmNotification = {
+  id: string;
+  timeStamp: string;
+  nodeName: string;
+  counter: number;
+  objectId: string;
+  problem: string;
+  severity: string;
+};
+
+export type FaultAlarmNotificationWS = {
+  'node-id': string;
+  'data': {
+    'counter': number;
+    'time-stamp': string;
+    'object-id-ref': string;
+    'problem': string;
+    'severity': null | 'Warning' | 'Minor' | 'Major' | 'Critical' | 'NonAlarmed';
+  };
+  'type': {
+    'namespace': string;
+    'revision': string;
+    'type': string;
+  };
+  'event-time': string;
+};
+
+/**
+ * Fault status return type
+ */
+export type FaultsReturnType = {
+  criticals: number;
+  majors: number;
+  minors: number;
+  warnings: number;
+  Connected: number;
+  Connecting: number;
+  Disconnected: number;
+  Mounted: number;
+  UnableToConnect: number;
+  Undefined: number;
+  Unmounted: number;
+  total: number;
+};
+
+export type FaultType = {
+  Critical: number;
+  Major: number;
+  Minor: number;
+  Warning: number;
+  Connected: number;
+  Connecting: number;
+  Disconnected: number;
+  Mounted: number;
+  UnableToConnect: number;
+  Undefined: number;
+  Unmounted: number;
+  total: number;
+};
+
+export type Faults = {
+  faults: FaultsReturnType;
+  'network-element-connections': FaultsReturnType;
+};
+
+export type DeletedStuckAlarms = {
+  nodenames: string[];
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts
new file mode 100644
index 0000000..daebad0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts
@@ -0,0 +1,18 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type PanelId = null | 'CurrentAlarms' | 'AlarmNotifications' | 'AlarmLog';
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx
new file mode 100644
index 0000000..2ef243c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx
@@ -0,0 +1,171 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IFormatedMessage, subscribe } from '../../../framework/src/services/notificationService';
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+
+import { AddFaultNotificationAction } from './actions/notificationActions';
+import { SetPanelAction } from './actions/panelChangeActions';
+import { refreshFaultStatusAsyncAction, SetFaultStatusAction } from './actions/statusActions';
+import DashboardHome from './components/dashboardHome';
+import { FaultStatus } from './components/faultStatus';
+import { createCurrentAlarmsActions, createCurrentAlarmsProperties, currentAlarmsReloadAction } from './handlers/currentAlarmsHandler';
+import { faultAppRootHandler } from './handlers/faultAppRootHandler';
+import { FaultAlarmNotificationWS } from './models/fault';
+import { PanelId } from './models/panelId';
+import { FaultApplication } from './views/faultApplication';
+
+const appIcon = require('./assets/icons/faultAppIcon.svg');  // select app icon
+
+let currentMountId: string | undefined = undefined;
+let currentSeverity: string | undefined = undefined;
+let refreshInterval: ReturnType<typeof window.setInterval> | null = null;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  currentAlarmsProperties: createCurrentAlarmsProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch, true),
+  setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+});
+
+const FaultApplicationRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
+  if (currentMountId !== props.match.params.mountId) {
+    // route parameter has changed
+    currentMountId = props.match.params.mountId || undefined;
+    // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+    window.setTimeout(() => {
+      if (currentMountId) {
+        props.setCurrentPanel('CurrentAlarms');
+        props.currentAlarmsActions.onFilterChanged('nodeId', currentMountId);
+        if (!props.currentAlarmsProperties.showFilter) {
+          props.currentAlarmsActions.onToggleFilter(false);
+          props.currentAlarmsActions.onRefresh();
+        } else
+          props.currentAlarmsActions.onRefresh();
+      }
+    });
+  }
+  return (
+    <FaultApplication />
+  );
+});
+
+const FaultApplicationAlarmStatusRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ severity?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
+  if (currentSeverity !== props.match.params.severity) {
+    currentSeverity = props.match.params.severity || undefined;
+    window.setTimeout(() => {
+      if (currentSeverity) {
+        props.setCurrentPanel('CurrentAlarms');
+        props.currentAlarmsActions.onFilterChanged('severity', currentSeverity);
+        if (!props.currentAlarmsProperties.showFilter) {
+          props.currentAlarmsActions.onToggleFilter(false);
+          props.currentAlarmsActions.onRefresh();
+        } else
+          props.currentAlarmsActions.onRefresh();
+      }
+    });
+  }
+  return (
+    <FaultApplication />
+  );
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+  <Switch>
+    <Route path={`${props.match.path}/alarmStatus/:severity?`} component={FaultApplicationAlarmStatusRouteAdapter} />
+    <Route path={`${props.match.path}/:mountId?`} component={FaultApplicationRouteAdapter} />
+    <Redirect to={`${props.match.path}`} />
+  </Switch>
+));
+
+export function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: 'fault',
+    icon: appIcon,
+    rootComponent: App,
+    rootActionHandler: faultAppRootHandler,
+    statusBarElement: FaultStatus,
+    dashbaordElement: DashboardHome,
+    menuEntry: 'Fault',
+  });
+
+  let counter = 0;
+  // subscribe to the websocket notifications
+  subscribe<FaultAlarmNotificationWS & IFormatedMessage>('problem-notification', (fault => {
+    const store = applicationApi && applicationApi.applicationStore;
+    if (fault && store) {
+
+      store.dispatch(new AddFaultNotificationAction({
+        id: String(counter++),
+        nodeName: fault['node-id'],
+        counter: +fault.data.counter,
+        objectId: fault.data['object-id-ref'],
+        problem: fault.data.problem,
+        severity: fault.data.severity || '',
+        timeStamp: fault.data['time-stamp'],
+      }));
+    }
+  }));
+
+  applicationApi.applicationStoreInitialized.then(store => {
+    store.dispatch(currentAlarmsReloadAction);
+  });
+
+  applicationApi.applicationStoreInitialized.then(store => {
+    store.dispatch(refreshFaultStatusAsyncAction);
+  });
+
+  applicationApi.logoutEvent.addHandler(()=>{
+
+    applicationApi.applicationStoreInitialized.then(store => {
+      store.dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
+      clearInterval(refreshInterval!);
+    });
+  });
+
+  function startRefreshInterval()  {
+    const refreshFaultStatus = window.setInterval(() => {
+      applicationApi.applicationStoreInitialized.then(store => {
+  
+        store.dispatch(refreshFaultStatusAsyncAction);
+      });
+    }, 15000);
+
+    return refreshFaultStatus;
+  }
+
+  applicationApi.loginEvent.addHandler(()=>{
+    if (refreshInterval) {
+      clearInterval(refreshInterval);
+    }
+    refreshInterval = startRefreshInterval() as any;
+  });
+
+  applicationApi.logoutEvent.addHandler(()=>{
+    refreshInterval && window.clearInterval(refreshInterval);
+    refreshInterval = null;
+  });
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts
new file mode 100644
index 0000000..0c7a215
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts
@@ -0,0 +1,69 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Result } from '../../../../framework/src/models/elasticSearch';
+import { requestRest } from '../../../../framework/src/services/restService';
+
+import { Faults, FaultType } from '../models/fault';
+
+
+export const getFaultStateFromDatabase = async (): Promise<FaultType | null> => {
+  const path = 'rests/operations/data-provider:read-status';
+  const result = await requestRest<Result<Faults>>(path, { method: 'POST' });
+
+  let faultType: FaultType = {
+    Critical: 0,
+    Major: 0,
+    Minor: 0,
+    Warning: 0,
+    Connected: 0,
+    Connecting: 0,
+    Disconnected: 0,
+    Mounted: 0,
+    UnableToConnect: 0,
+    Undefined: 0,
+    Unmounted: 0,
+    total: 0,
+  };
+  let faults: Faults[] | null = null;
+
+  if (result && result['data-provider:output'] && result['data-provider:output'].data) {
+    faults = result['data-provider:output'].data;
+    faultType = {
+      Critical: faults[0].faults.criticals,
+      Major: faults[0].faults.majors,
+      Minor: faults[0].faults.minors,
+      Warning: faults[0].faults.warnings,
+      Connected: faults[0]['network-element-connections'].Connected,
+      Connecting: faults[0]['network-element-connections'].Connecting,
+      Disconnected: faults[0]['network-element-connections'].Disconnected,
+      Mounted: faults[0]['network-element-connections'].Mounted,
+      UnableToConnect: faults[0]['network-element-connections'].UnableToConnect,
+      Undefined: faults[0]['network-element-connections'].Undefined,
+      Unmounted: faults[0]['network-element-connections'].Unmounted,
+      total: faults[0]['network-element-connections'].total,
+    };
+  }
+
+  return faultType;
+};
+
+export const clearStuckAlarms = async (nodeNames: string[]) => {
+  const path = 'rests/operations/devicemanager:clear-current-fault-by-nodename';
+  const result = await requestRest<any>(path, { method: 'Post', body: JSON.stringify({ input: { nodenames: nodeNames } }) });
+  return result;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx
new file mode 100644
index 0000000..b9f115e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -0,0 +1,247 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import Refresh from '@mui/icons-material/Refresh';
+import Sync from '@mui/icons-material/Sync';
+import { AppBar, Tab, Tabs } from '@mui/material';
+
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { setPanelAction } from '../actions/panelChangeActions';
+import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog';
+import RefreshAlarmLogDialog, { RefreshAlarmLogDialogMode } from '../components/refreshAlarmLogDialog';
+import RefreshCurrentAlarmsDialog, { RefreshCurrentAlarmsDialogMode } from '../components/refreshCurrentAlarmsDialog';
+import { alarmLogEntriesReloadAction, createAlarmLogEntriesActions, createAlarmLogEntriesProperties } from '../handlers/alarmLogEntriesHandler';
+import { createCurrentAlarmsActions, createCurrentAlarmsProperties, currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+import { Fault, FaultAlarmNotification } from '../models/fault';
+import { PanelId } from '../models/panelId';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  panelId: state.fault.currentOpenPanel,
+  currentAlarmsProperties: createCurrentAlarmsProperties(state),
+  faultNotifications: state.fault.faultNotifications,
+  alarmLogEntriesProperties: createAlarmLogEntriesProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch),
+  alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch),
+  reloadCurrentAlarms: () => dispatcher.dispatch(currentAlarmsReloadAction),
+  reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
+  switchActivePanel: (panelId: PanelId) => {
+    dispatcher.dispatch(setPanelAction(panelId));
+  },
+});
+
+type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
+
+type FaultApplicationState = {
+  clearAlarmDialogMode: ClearStuckAlarmsDialogMode;
+  stuckAlarms: string[];
+  refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode;
+  refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode;
+};
+
+
+const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
+const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>;
+
+let currentAlarmsInitalSorted = false;
+let alarmLogInitialSorted = false;
+
+class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState> {
+  constructor(props: FaultApplicationComponentProps) {
+    super(props);
+    this.state = {
+      clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None,
+      stuckAlarms: [],
+      refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
+      refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
+    };
+  }
+
+  onDialogClose = () => {
+    this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] });
+  };
+
+  onDialogOpen = () => {
+    const stuckAlarms = [...new Set(this.props.currentAlarmsProperties.rows.map(item => item.nodeId))];
+    this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.Show, stuckAlarms: stuckAlarms });
+  };
+
+  private onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
+    this.onToggleTabs(newValue);
+  };
+
+  private onToggleTabs = (panelId: PanelId) => {
+    const nextActivePanel = panelId;
+    this.props.switchActivePanel(nextActivePanel);
+    switch (nextActivePanel) {
+      case 'CurrentAlarms':
+        if (!currentAlarmsInitalSorted) {
+          currentAlarmsInitalSorted = true;
+          this.props.currentAlarmsActions.onHandleExplicitRequestSort('timestamp', 'desc');
+        } else {
+          this.props.reloadCurrentAlarms();
+        }
+        break;
+      case 'AlarmLog':
+        if (!alarmLogInitialSorted) {
+          alarmLogInitialSorted = true;
+          this.props.alarmLogEntriesActions.onHandleExplicitRequestSort('timestamp', 'desc');
+        } else {
+          this.props.reloadAlarmLogEntries();
+        }
+        break;
+      case 'AlarmNotifications':
+      case null:
+      default:
+        // nothing to do
+        break;
+    }
+  };
+
+
+
+  render(): JSX.Element {
+
+    const clearAlarmsAction = {
+      icon: Sync, tooltip: 'Clear stuck alarms', ariaLabel:'clear-stuck-alarms', onClick: this.onDialogOpen,
+    };
+
+    const refreshCurrentAlarmsAction = {
+      icon: Refresh, tooltip: 'Refresh Current Alarms List', ariaLabel:'refresh', onClick: () => {
+        this.setState({
+          refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.RefreshCurrentAlarmsTable,
+        });
+      },
+    };
+
+    const refreshAlarmLogAction = {
+      icon: Refresh, tooltip: 'Refresh Alarm log table', ariaLabel:'refresh', onClick: () => {
+        this.setState({
+          refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.RefreshAlarmLogTable,
+        });
+      },
+    };
+
+    const areFaultsAvailable = this.props.currentAlarmsProperties.rows && this.props.currentAlarmsProperties.rows.length > 0;
+    const customActions = areFaultsAvailable ? [clearAlarmsAction, refreshCurrentAlarmsAction] : [refreshCurrentAlarmsAction];
+
+    const { panelId: activePanelId } = this.props;
+
+    return (
+      <>
+        <AppBar enableColorOnDark position="static" >
+          <Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="fault-tabs">
+            <Tab aria-label="current-alarms-list-tab" label="Current Alarms" value="CurrentAlarms" />
+            <Tab aria-label="alarm-notifications-list-tab" label={`Alarm Notifications (${this.props.faultNotifications.faults.length})`} value="AlarmNotifications" />
+            <Tab aria-label="alarm-log-tab" label="Alarm Log" value="AlarmLog" />
+          </Tabs>
+        </AppBar>
+        {
+          activePanelId === 'CurrentAlarms' &&
+          <>
+            <FaultTable stickyHeader tableId="current-alarms-table" idProperty="id" customActionButtons={customActions} columns={[
+              // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+              { property: 'severity', title: 'Severity', type: ColumnType.text, width: '140px' },
+              { property: 'timestamp', type: ColumnType.text, title: 'Timestamp' },
+              { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
+              { property: 'counter', title: 'Count', type: ColumnType.numeric, width: '100px' },
+              { property: 'objectId', title: 'Object Id', type: ColumnType.text },
+              { property: 'problem', title: 'Alarm Type', type: ColumnType.text },
+            ]} {...this.props.currentAlarmsProperties} {...this.props.currentAlarmsActions} />
+            <RefreshCurrentAlarmsDialog
+              mode={this.state.refreshCurrentAlarmsEditorMode}
+              onClose={this.onCloseRefreshCurrentAlarmsDialog}
+            />
+          </>
+        }
+        {activePanelId === 'AlarmNotifications' &&
+
+          <FaultAlarmNotificationTable stickyHeader tableId="alarm-notifications-table" idProperty="id" defaultSortColumn='timeStamp' defaultSortOrder='desc' rows={this.props.faultNotifications.faults} asynchronus columns={[
+            // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+            { property: 'severity', title: 'Severity', width: '140px', type: ColumnType.text },
+            { property: 'timeStamp', title: 'Timestamp', type: ColumnType.text },
+            { property: 'nodeName', title: 'Node Name', type: ColumnType.text },
+            { property: 'counter', title: 'Count', width: '100px', type: ColumnType.numeric },
+            { property: 'objectId', title: 'Object Id', type: ColumnType.text },
+            { property: 'problem', title: 'Alarm Type', type: ColumnType.text },
+          ]} />
+        }
+
+        {activePanelId === 'AlarmLog' &&
+          <>
+            <FaultTable stickyHeader idProperty={'id'} tableId="alarm-log-table" customActionButtons={[refreshAlarmLogAction]}
+              columns={[
+                // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+                { property: 'severity', title: 'Severity', width: '140px' },
+                { property: 'timestamp', title: 'Timestamp' },
+                { property: 'nodeId', title: 'Node Name' },
+                { property: 'counter', title: 'Count', type: ColumnType.numeric, width: '100px' },
+                { property: 'objectId', title: 'Object Id' },
+                { property: 'problem', title: 'Alarm Type' },
+                { property: 'sourceType', title: 'Source', width: '140px' },
+              ]} {...this.props.alarmLogEntriesProperties} {...this.props.alarmLogEntriesActions} />
+            <RefreshAlarmLogDialog
+              mode={this.state.refreshAlarmLogEditorMode}
+              onClose={this.onCloseRefreshAlarmLogDialog}
+            />
+          </>
+
+        }
+        {
+          this.state.clearAlarmDialogMode !== ClearStuckAlarmsDialogMode.None && <ClearStuckAlarmsDialog mode={this.state.clearAlarmDialogMode} numberDevices={this.state.stuckAlarms.length} stuckAlarms={this.state.stuckAlarms} onClose={this.onDialogClose} />
+        }
+      </>
+    );
+  }
+
+  public componentDidMount() {
+    if (this.props.panelId === null) { //set default tab if none is set
+      this.onToggleTabs('CurrentAlarms');
+    } else {
+      this.onToggleTabs(this.props.panelId);
+    }
+  }
+
+  // private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
+  //   return (
+  //     <FontAwesomeIcon icon={faExclamationTriangle} />
+  //   );
+  // };
+
+  private onCloseRefreshAlarmLogDialog = () => {
+    this.setState({
+      refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
+    });
+  };
+
+  private onCloseRefreshCurrentAlarmsDialog = () => {
+    this.setState({
+      refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
+    });
+  };
+}
+
+export const FaultApplication = withRouter(connect(mapProps, mapDisp)(FaultApplicationComponent));
+export default FaultApplication;
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js
new file mode 100644
index 0000000..bc26de1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js
@@ -0,0 +1,166 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      faultApp: ["./pluginFault.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },{
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        })
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+       proxy: {
+        "/oauth2/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/database/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/help/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/websocket": {
+          target: "http://sdnc-web:8080",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/.babelrc b/sdnr/wt-odlux/odlux/apps/helpApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/package.json b/sdnr/wt-odlux/odlux/apps/helpApp/package.json
new file mode 100644
index 0000000..5bcfdce
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/package.json
@@ -0,0 +1,48 @@
+{
+  "name": "@odlux/help-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI providing the help functionaliy.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*",
+    "@types/highlight.js": "9.12.3",
+    "@types/marked": "0.6.0",
+    "github-markdown-css": "2.10.0",
+    "highlight.js": "9.13.1",
+    "marked": "0.6.0"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/pom.xml b/sdnr/wt-odlux/odlux/apps/helpApp/pom.xml
new file mode 100644
index 0000000..aad2e96
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-helpApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/actions/helpActions.ts b/sdnr/wt-odlux/odlux/apps/helpApp/src/actions/helpActions.ts
new file mode 100644
index 0000000..3cebfd6
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/actions/helpActions.ts
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { TocTreeNode } from '../models/tocNode';
+import helpService from '../services/helpService';
+
+export class LoadTocAction extends Action {
+  constructor() {
+    super();
+
+  }
+}
+
+export class TocLoadedAction extends Action {
+  constructor(public toc?: TocTreeNode[], error?: string) {
+    super();
+    
+  }
+}
+
+export const requestTocAsyncAction = async (dispatch: Dispatch) => {
+  dispatch(new LoadTocAction);
+  try {
+    const toc = await helpService.getTableOfContents();
+    if (toc) {
+      dispatch(new TocLoadedAction(toc));
+    } else {
+      dispatch(new TocLoadedAction(undefined, "Could not load TOC."));
+    }
+  } catch (err) {
+    dispatch(new TocLoadedAction(undefined, err));
+  }
+}
+
+export class LoadDocumentAction extends Action {
+  constructor() {
+    super();
+
+  }
+}
+
+export class DocumentLoadedAction extends Action {
+  constructor(public document?: string, public documentPath?: string, error?: string) {
+    super();
+
+  }
+}
+
+export const requestDocumentAsyncActionCreator = (path: string) => async (dispatch: Dispatch) => {
+  dispatch(new LoadDocumentAction);
+  try {
+    const doc = await helpService.getDocument(path);
+    if (doc) {
+      dispatch(new DocumentLoadedAction(doc, path));
+    } else {
+      dispatch(new DocumentLoadedAction(undefined, undefined, "Could not load document."));
+    }
+  } catch (err) {
+    dispatch(new DocumentLoadedAction(undefined, undefined, err));
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/assets/icons/helpAppIcon.svg b/sdnr/wt-odlux/odlux/apps/helpApp/src/assets/icons/helpAppIcon.svg
new file mode 100644
index 0000000..298eaa1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/assets/icons/helpAppIcon.svg
@@ -0,0 +1,27 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="310 250 400 400">
+
+<g transform="translate(0,1024) scale(0.1,-0.1)">
+
+<path fill="#565656" d="M4926 7634 c-126 -17 -209 -38 -318 -79 -79 -31 -195 -89 -208 -104
+-10 -12 -69 -51 -77 -51 -4 0 -42 -28 -83 -63 -227 -190 -375 -475 -375 -722
+0 -81 3 -95 30 -143 111 -201 365 -252 514 -103 46 46 88 124 121 226 28 87
+109 255 153 315 67 95 172 168 275 192 86 20 268 21 346 2 113 -28 152 -50
+240 -137 64 -63 88 -95 104 -137 49 -125 52 -225 12 -332 -38 -102 -132 -209
+-360 -409 -153 -134 -329 -309 -375 -374 -97 -136 -148 -274 -166 -448 -19
+-192 12 -305 104 -379 64 -50 141 -72 228 -65 82 7 125 24 177 71 49 45 73
+100 105 241 59 258 63 263 528 687 218 198 295 284 374 419 134 230 138 543 9
+803 -101 202 -252 349 -474 461 -246 124 -573 172 -884 129z"/>
+
+<path fill="#36A9E1" d="M 5098 4587 C 4582 4587 4582 3845 5098 3845 C 5614 3847 5614 4585 5098 4587 Z"/>
+
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/components/helpStatus.tsx b/sdnr/wt-odlux/odlux/apps/helpApp/src/components/helpStatus.tsx
new file mode 100644
index 0000000..985b404
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/components/helpStatus.tsx
@@ -0,0 +1,83 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router';
+
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';  // select app icon
+
+import Typography from '@mui/material/Typography';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
+
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+const styles = (theme: Theme) => createStyles({
+  icon: {
+    marginLeft: 8,
+    marginRight: 8
+  },
+  disabled: {
+    color: theme.palette.grey[400]
+  },
+  link: {
+    cursor: "pointer",
+    '&:hover': {
+      textDecoration: "underline"
+    }
+  }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  appId: state.framework.applicationState.appId,
+  toc: state.help.toc
+});
+
+
+type HelpStatusComponentProps = & RouteComponentProps & WithStyles<typeof styles> & Connect<typeof mapProps>;
+
+class HelpStatusComponent extends React.Component<HelpStatusComponentProps> {
+  render() {
+    const { classes, history, toc, appId } = this.props;
+    const rootNode = toc && toc.find(t => t.id === "sdnr");
+    const helpNode = appId
+      ? rootNode && rootNode.nodes && rootNode.nodes.find(n => n.id === appId || n.id === appId + "App")
+      : rootNode;
+    return helpNode
+      ? (
+        <Typography variant="body1" color="inherit" className={classes.link} onClick={(event) => { event.stopPropagation(); history.push(`/help/${helpNode.uri}`) }} >
+          <FontAwesomeIcon className={classes.icon} icon={faQuestionCircle} />
+          Help
+        </Typography>
+      )
+      : (
+        <Typography variant="body1" className={classes.disabled}>
+          <FontAwesomeIcon className={classes.icon} icon={faQuestionCircle} />
+          Help
+        </Typography>
+      );
+  };
+
+}
+
+export const HelpStatus = withRouter(withStyles(styles)(connect(mapProps)(HelpStatusComponent) as any) as any);
+export default HelpStatus;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/components/markdown.tsx b/sdnr/wt-odlux/odlux/apps/helpApp/src/components/markdown.tsx
new file mode 100644
index 0000000..a713783
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/components/markdown.tsx
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import * as marked from 'marked';
+import * as hljs from 'highlight.js';
+
+type MarkdownComponentProps = {
+  text: string;
+  className?: string;
+  markedOptions?: marked.MarkedOptions;
+  style?: React.CSSProperties
+}
+
+const defaultRenderer = new marked.Renderer();
+defaultRenderer.link = (href, title, text) => (
+  `<a target="_blank" rel="noopener noreferrer" href="${ href }" title="${ title }">${ text }</a>`
+);
+
+
+class MarkdownComponent extends React.Component<MarkdownComponentProps> {
+  constructor(props: MarkdownComponentProps) {
+    super(props);
+
+    const markedOptions: marked.MarkedOptions = {
+      gfm: true,
+      tables: true,
+      breaks: false,
+      pedantic: false,
+      sanitize: true,
+      smartLists: true,
+      smartypants: false,
+      langPrefix: 'hljs ',
+      ...(this.props.markedOptions || {}),
+      highlight: (code, lang) => {
+        if (!!(lang && hljs.getLanguage(lang))) {
+          return hljs.highlight(lang, code).value;
+        }
+        return code;
+      }
+    };
+
+    marked.setOptions(markedOptions);
+  }
+  render() {
+    const { text, className, style } = this.props;
+    
+ 
+    const html = (marked(text || '', { renderer: this.props.markedOptions && this.props.markedOptions.renderer || defaultRenderer }));
+
+    return (
+      <div
+        dangerouslySetInnerHTML={ { __html: html } }
+        className={ className }
+        style={ style }
+      />
+    );
+  }
+}
+
+export const Markdown = MarkdownComponent;
+
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/components/tocEntry.tsx b/sdnr/wt-odlux/odlux/apps/helpApp/src/components/tocEntry.tsx
new file mode 100644
index 0000000..295b3ca
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/components/tocEntry.tsx
@@ -0,0 +1,85 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from "react"
+import { TocTreeNode } from "../models/tocNode"
+import { Typography, Link, Theme } from "@mui/material";
+
+import makeStyles from '@mui/styles/makeStyles';
+import createStyles from '@mui/styles/createStyles';
+
+const useStyles = makeStyles((theme: Theme) =>
+    createStyles({
+        link: {
+            color: "blue",
+        },
+        sublink: {
+            margin: theme.spacing(1),
+            color: "blue",
+        },
+        container: {
+            display: "flex",
+            flexDirection: "row",
+            flexWrap: "wrap",
+        }
+    }),
+);
+
+type tocEntryProps = {
+    label: string,
+    overviewUri: string,
+    nodes?: TocTreeNode[],
+    loadDocument(uri: string): any
+}
+
+const TocEntry: React.FunctionComponent<tocEntryProps> = (props) => {
+    const classes = useStyles();
+    const areNodesEmpty = !props.nodes || props.nodes.length === 0
+
+    const navigate = (event: React.SyntheticEvent, uri: string) => {
+        event.preventDefault();
+        event.stopPropagation();
+        props.loadDocument(uri);
+    }
+
+    return (<div>
+        {
+            areNodesEmpty ? <Typography variant="h6">
+                <Link underline="hover" onClick={(event: any) => navigate(event, props.overviewUri)} className={classes.link}> {props.label}</Link>
+            </Typography> :
+                <>
+                    <Typography variant="h6">
+                        {props.label}
+                    </Typography>
+                    <div className={classes.container}>
+                        <Typography variant="body1">
+                            <Link underline="hover" onClick={(event: any) => navigate(event, props.overviewUri)} className={classes.sublink}>Overview</Link>
+                        </Typography>
+                        {props.nodes !== undefined && props.nodes.map((item, index) =>
+                            <Typography variant="body1" key={index + 'x' + item.id}>
+                                <Link underline="hover" onClick={(event: any) => navigate(event, item.uri)} className={classes.sublink}>{item.label}</Link>
+                            </Typography>
+                        )}
+                    </div>
+                </>
+        }
+    </div >)
+}
+
+
+export default TocEntry;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
new file mode 100644
index 0000000..29e0795
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
@@ -0,0 +1,76 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { LoadTocAction, TocLoadedAction, LoadDocumentAction, DocumentLoadedAction } from '../actions/helpActions';
+import { TocTreeNode } from '../models/tocNode';
+
+export interface IHelpAppStoreState {
+  busy: boolean;
+  toc: TocTreeNode[] | undefined;
+  content: string | undefined;
+  currentPath: string | undefined;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    help: IHelpAppStoreState
+  }
+}
+
+const helpAppStoreStatcurrentPatheInit: IHelpAppStoreState = {
+  busy: false,
+  toc: undefined,
+  content: undefined,
+  currentPath: undefined
+};
+
+export const helpAppRootHandler: IActionHandler<IHelpAppStoreState> = (state = helpAppStoreStatcurrentPatheInit, action) => {
+  if (action instanceof LoadTocAction) {
+    state = {
+      ...state,
+      busy: true
+    };
+  } else if (action instanceof TocLoadedAction) {
+    state = {
+      ...state,
+      busy: false,
+      toc: action.toc
+    };
+  } else if (action instanceof LoadDocumentAction) {
+    state = {
+      ...state,
+      busy: true
+    };
+  } else if (action instanceof DocumentLoadedAction) {
+    state = {
+      ...state,
+      busy: false,
+      content: action.document,
+      currentPath: action.documentPath
+    };
+  }
+
+  return state;
+}
+
+
+export default helpAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/index.html b/sdnr/wt-odlux/odlux/apps/helpApp/src/index.html
new file mode 100644
index 0000000..2344708
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css"> -->
+  <title>Minimal App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "helpApp"], function (app, helpApp) {
+      //connectApp.register();
+      //faultApp.register();
+      //configurationApp.register();
+      //maintenanceApp.register();
+      helpApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/models/tocNode.ts b/sdnr/wt-odlux/odlux/apps/helpApp/src/models/tocNode.ts
new file mode 100644
index 0000000..dbefeec
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/models/tocNode.ts
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type VersionInfo = {
+  label: string,
+  path: string,
+  date: string
+}
+
+export type TocNode  = {
+  label: string;
+  versions: {
+    [versionKey: string]: VersionInfo,
+    current: VersionInfo
+  };
+  nodes?: TocNodeCollection;
+}
+
+export type TocNodeCollection = { [tocNodeKey: string]: TocNode };
+
+
+export type TocTreeNode = {
+  id: string;
+  label: string;
+  uri: string;
+  nodes?: TocTreeNode[];
+  disabled?: boolean;
+}
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/plugin.tsx b/sdnr/wt-odlux/odlux/apps/helpApp/src/plugin.tsx
new file mode 100644
index 0000000..5d860e5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/plugin.tsx
@@ -0,0 +1,91 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { requestTocAsyncAction, requestDocumentAsyncActionCreator } from "./actions/helpActions";
+import { helpAppRootHandler } from './handlers/helpAppRootHandler';
+
+import { HelpApplication } from './views/helpApplication';
+import { HelpStatus } from "./components/helpStatus";
+
+import '!style-loader!css-loader!highlight.js/styles/default.css';
+import HelpTocApp from "./views/helpTocApp";
+
+const appIcon = require('./assets/icons/helpAppIcon.svg');  // select app icon
+
+const mapProps = (state: IApplicationStoreState) => ({
+
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  requestDocument: (path: string) => {
+    dispatcher.dispatch(requestDocumentAsyncActionCreator(path));
+  }
+});
+
+let currentHelpPath: string | undefined = undefined;
+
+const HelpApplicationRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ '0'?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
+
+  if (currentHelpPath !== props.match.params["0"]) {
+    // route parameter has changed
+    currentHelpPath = props.match.params["0"] || undefined;
+    // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+    window.setTimeout(() => {
+      if (currentHelpPath) {
+        props.requestDocument(currentHelpPath);
+      }
+    });
+  }
+
+  return (
+    <HelpApplication />
+  )
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+  <Switch>
+    <Route exact path={`${props.match.path}/`} component={HelpTocApp} />
+    <Route path={`${props.match.path}/*`} component={HelpApplicationRouteAdapter} />
+    <Route path={`${props.match.path}`} component={HelpTocApp} />
+  </Switch>
+));
+
+export async function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: "help",
+    icon: appIcon,
+    rootComponent: App,
+    rootActionHandler: helpAppRootHandler,
+    statusBarElement: HelpStatus,
+    menuEntry: "Help",
+    //subMenuEntry: SubMenuEntry 
+  });
+
+  // start the initial toc request after the application store is initialized
+  const store = await applicationApi.applicationStoreInitialized;
+  store.dispatch(requestTocAsyncAction);
+
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/services/helpService.ts b/sdnr/wt-odlux/odlux/apps/helpApp/src/services/helpService.ts
new file mode 100644
index 0000000..728f243
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/services/helpService.ts
@@ -0,0 +1,65 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest } from '../../../../framework/src/services/restService';
+import { TocTreeNode, TocNodeCollection } from '../models/tocNode';
+
+class HelpService {
+
+  private tocNodeCollection: TocTreeNode[] | null = null;
+  private documents: { [path: string]: string | null } = {};
+
+  public async getDocument(path: string): Promise<string | null> {
+    // check if the result is allready in the cache
+    if (this.documents[path]) return Promise.resolve(this.documents[path]);
+
+    // request the document
+    const result = await requestRest<string>(`/help/${path}`.replace(/\/{2,}/i, '/'));
+    if (result) {
+      this.documents[path] = result;
+    }
+    return this.documents[path] || null;
+  }
+
+  public async getTableOfContents(): Promise<TocTreeNode[] | null> {
+    // check if the result is allready in the cache
+    if (this.tocNodeCollection) return Promise.resolve(this.tocNodeCollection);
+
+    // request the table of contents
+    const result = await requestRest<TocNodeCollection>('/help/?meta', undefined, false);
+    if (result !== null) {
+      const mapNodesCollection = (col: TocNodeCollection): TocTreeNode[] => {
+        return Object.keys(col).reduce<TocTreeNode[]>((acc, key) => {
+          const current = col[key];
+          acc.push({
+            id: key,
+            label: current.label,
+            uri: current.versions.current.path,
+            nodes: current.nodes && mapNodesCollection(current.nodes) || undefined
+          });
+          return acc;
+        }, []);
+      }
+
+      this.tocNodeCollection = result && mapNodesCollection(result) || null;
+    }
+    return this.tocNodeCollection || null;
+  }
+}
+
+export const helpService = new HelpService();
+export default helpService;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/utilities/path.ts b/sdnr/wt-odlux/odlux/apps/helpApp/src/utilities/path.ts
new file mode 100644
index 0000000..412bdfb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/utilities/path.ts
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export const resolvePath = (...paths: string[]): string => {
+  function resolve(pathA: string, pathB: string) {
+    //  ‘a’     => ['a']
+    //  'a/b'   => ['a', 'b']
+    //  '/a/b'  => ['', 'a', 'b']
+    //  '/a/b/' => ['', 'a', 'b', '']
+    const pathBParts = pathB.split('/');
+    if (pathBParts[0] === '') {
+      return pathBParts.join('/');
+    }
+    const pathAParts = pathA.split('/');
+    const aLastIndex = pathAParts.length - 1;
+    if (pathAParts[aLastIndex] !== '') {
+      pathAParts[aLastIndex] = '';
+    }
+
+    let part: string;
+    let i = 0;
+    while (typeof (part = pathBParts[i]) === 'string') {
+      switch (part) {
+        case '..':
+          pathAParts.pop();
+          pathAParts.pop();
+          pathAParts.push('');
+          break;
+        case '.':
+          pathAParts.pop();
+          pathAParts.push('');
+          break;
+        default:
+          pathAParts.pop();
+          pathAParts.push(part);
+          pathAParts.push('');
+          break;
+      }
+      i++;
+    }
+    if (pathBParts[pathBParts.length - 1] !== '') pathAParts.pop(); 
+    return pathAParts.join('/');
+  }
+
+  let i = 0;
+  let path: string;
+  let 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/wt-odlux/odlux/apps/helpApp/src/views/helpApplication.tsx b/sdnr/wt-odlux/odlux/apps/helpApp/src/views/helpApplication.tsx
new file mode 100644
index 0000000..5940517
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/views/helpApplication.tsx
@@ -0,0 +1,84 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import * as marked from 'marked';
+
+import { resolvePath } from '../utilities/path';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { Markdown } from "../components/markdown";
+
+import '!style-loader!css-loader!github-markdown-css/github-markdown.css'
+
+const mapProps = (state: IApplicationStoreState) => ({
+  content: state.help.content,
+  currentPath: state.help.currentPath
+});
+
+const containerStyle = {
+  overflow: "auto",
+  height: "100%",
+  width: "100%"
+};
+
+const styles = {
+  maxWidth: "960px",
+  margin: "1.5em auto",
+
+};
+
+type HelpApplicationComponentProps = Connect<typeof mapProps>;
+
+class HelpApplicationComponent extends React.Component<HelpApplicationComponentProps> {
+
+  /**
+   * Initializes a new instance.
+   */
+  constructor(props: HelpApplicationComponentProps) {
+    super(props);
+
+    this.renderer = new marked.Renderer();
+
+    this.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/', this.props.currentPath || '/', href)}" title="${title}" >${text}</a>`
+    };
+
+    this.renderer.image = (href: string, title: string) => {
+      return `<img src="${resolvePath('/help/', this.props.currentPath || '/', href)}" alt="${title}" />`
+    };
+
+  }
+
+  render(): JSX.Element {
+    return this.props.content ? (
+      <div style={containerStyle}>
+        <Markdown text={this.props.content} markedOptions={{ renderer: this.renderer }} className="markdown-body"
+          style={styles} />
+      </div>
+    ) : (<h2>Loading ...</h2>)
+  }
+
+  private renderer: marked.Renderer;
+}
+
+export const HelpApplication = connect(mapProps)(HelpApplicationComponent);
+export default HelpApplication;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/src/views/helpTocApp.tsx b/sdnr/wt-odlux/odlux/apps/helpApp/src/views/helpTocApp.tsx
new file mode 100644
index 0000000..6a6a891
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/src/views/helpTocApp.tsx
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react'
+import {connect, Connect, IDispatcher } from "../../../../framework/src/flux/connect";
+
+import { NavigateToApplication } from "../../../../framework/src/actions/navigationActions";
+import { FunctionComponent } from "react";
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import TocEntry from "../components/tocEntry";
+import { Typography } from "@mui/material";
+
+const mapProps = (state: IApplicationStoreState) => ({
+    helpToc: state.help.toc,
+})
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+    requestDocument: (uri: string) => dispatcher.dispatch(new NavigateToApplication("help", uri))
+});
+
+const HelpTocComponent: FunctionComponent<Connect<typeof mapProps, typeof mapDisp>> = (props) => {
+
+    return (
+        <div>
+            <Typography aria-label="help" style={{ marginBottom: '30px' }} variant="h5">
+                Help &amp; FAQ
+            </Typography>
+            <Typography style={{ marginBottom: '30px' }} variant="body1">
+                On our Help site, you can find general information about SDN-R, detailed information about our applications, frequently asked questions and a list of used abbreviations.
+            </Typography>
+            {
+                props.helpToc && props.helpToc.map((item, index) => <TocEntry key={index} overviewUri={item.uri} nodes={item.nodes} label={item.label} loadDocument={props.requestDocument} />)
+            }
+        </div>
+    )
+}
+
+export const HelpTocApp = connect(mapProps, mapDisp)(HelpTocComponent)
+
+export default HelpTocApp;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/helpApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/helpApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/helpApp/webpack.config.js
new file mode 100644
index 0000000..a48f7b9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/helpApp/webpack.config.js
@@ -0,0 +1,189 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const autoprefixer = require('autoprefixer');
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      helpApp: ["./plugin.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }, {
+        test: /\.css$/,
+        use: [{
+          loader: 'style-loader'
+        }, {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: env !== "release" ? '[name]_[local]_[hash:base64:5]' : '[hash]'
+          }
+        }, {
+          loader: 'postcss-loader',
+          options: {
+            plugins: () => [autoprefixer]
+          }
+        }]
+      }, {
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/oauth2/": {
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/database/": {
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/restconf/": {
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/help/": {
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/websocket/": {
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/.babelrc b/sdnr/wt-odlux/odlux/apps/inventoryApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/package.json b/sdnr/wt-odlux/odlux/apps/inventoryApp/package.json
new file mode 100644
index 0000000..5e37c52
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/package.json
@@ -0,0 +1,43 @@
+{
+  "name": "@odlux/inventory-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI to display network inventory data from a database.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/pom.xml b/sdnr/wt-odlux/odlux/apps/inventoryApp/pom.xml
new file mode 100644
index 0000000..da2023c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-inventoryApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/inventoryDeviceListActions.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/inventoryDeviceListActions.ts
new file mode 100644
index 0000000..710959a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/inventoryDeviceListActions.ts
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+import { inventoryService } from '../services/inventoryService';
+
+/** 
+ * Represents the base action. 
+ */
+export class BaseAction extends Action { }
+
+/** 
+ * Represents an action causing the store to load all nodes. 
+ */
+export class LoadAllInventoryDeviceListAction extends BaseAction { }
+
+/** 
+ * Represents an action causing the store to update all nodes. 
+ */
+export class AllInventoryDeviceListLoadedAction extends BaseAction {
+  /**
+   * Initialize this instance.
+   * 
+   * @param inventoryDeviceList All the distinct nodes from the Inventory  database.
+   */
+  constructor(public inventoryDeviceList: InventoryDeviceListType[] | null, public error?: string) {
+    super();
+  }
+}
+
+/** 
+ * Represents an asynchronous thunk  action to load all nodes. 
+ */
+export const loadAllInventoryDeviceListAsync = async (dispatch: Dispatch) => {
+  dispatch(new LoadAllInventoryDeviceListAction());
+  const inventoryDeviceList: InventoryDeviceListType[] = (await inventoryService.getInventoryDeviceList().then(ne =>
+    (ne))) || [];
+  return inventoryDeviceList && dispatch(new AllInventoryDeviceListLoadedAction(inventoryDeviceList));
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
new file mode 100644
index 0000000..2c6a0ed
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
@@ -0,0 +1,101 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { InventoryTreeNode, InventoryType, TreeDemoItem } from '../models/inventory';
+import { inventoryService } from '../services/inventoryService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+export class SetBusyAction extends BaseAction {
+  constructor(public busy: boolean = true) {
+    super();
+
+  }
+}
+
+export class SetSearchTextAction extends BaseAction {
+  constructor(public searchTerm: string = '') {
+    super();
+
+  }
+}
+
+export class UpdateInventoryTreeAction extends BaseAction {
+  constructor(public rootNode: InventoryTreeNode) {
+    super();
+
+  }
+}
+
+export class UpdateSelectedNodeAction extends BaseAction {
+  constructor(public selectedNode?: InventoryType) {
+    super();
+
+  }
+}
+
+export class UpdateExpandedNodesAction extends BaseAction {
+  constructor(public expandedNodes?: TreeDemoItem[]) {
+    super();
+
+  }
+}
+
+export const setSearchTermAction = (searchTerm: string) => (dispatch: Dispatch) =>{
+  dispatch(new SetSearchTextAction(searchTerm));
+};
+
+
+export const updateInventoryTreeAsyncAction = (mountId: string, searchTerm?: string) => async (dispatch: Dispatch) => {
+  dispatch(new SetBusyAction(true));
+  dispatch(new SetSearchTextAction(searchTerm));
+  try {
+    const result = await inventoryService.getInventoryTree(mountId, searchTerm);
+    if (!result) {
+      dispatch(new AddErrorInfoAction({ title: 'Error', message: `Could not load inventory tree for [${mountId}]. Please check you connection to the server and try later.` }));
+      dispatch(new NavigateToApplication('inventory'));
+    } else {
+      dispatch(new UpdateInventoryTreeAction(result));
+    }
+  } catch (err) {
+    throw new Error('Could not load inventory tree from server.');
+  } finally {
+    dispatch(new SetBusyAction(false));
+  }
+};
+
+export const selectInventoryNodeAsyncAction = (nodeId: string) => async (dispatch: Dispatch) => {
+  dispatch(new SetBusyAction(true));
+  try {
+    const result = await inventoryService.getInventoryEntry(nodeId);
+    if (!result) throw new Error('Could not load inventory tree from server.');
+    dispatch(new UpdateSelectedNodeAction(result));
+  } catch (err) {
+    throw new Error('Could not load inventory tree from server.');
+  } finally {
+    dispatch(new SetBusyAction(false));
+  }
+};
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/panelActions.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/panelActions.ts
new file mode 100644
index 0000000..d666082
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/actions/panelActions.ts
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+
+import { PanelId } from '../models/panelId';
+
+export class SetPanelAction extends Action {
+  constructor(public panelId: PanelId) {
+    super();
+  }
+}
+
+export const setPanelAction = (panelId: PanelId) => {
+  return new SetPanelAction(panelId);
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/assets/icons/inventoryAppIcon.svg b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/assets/icons/inventoryAppIcon.svg
new file mode 100644
index 0000000..507a835
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/assets/icons/inventoryAppIcon.svg
@@ -0,0 +1,23 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-224 -202 882 882">
+
+<path fill="#565656" d="M 576 544 H -64 V -160 C -64 -177.673 -49.673 -192 -32 -192 H 544 C 561.673 -192 576 -177.673 576 -160 V 544 Z "/>
+
+<path fill="#ffffff" d="M 480 0 H 32 C 14.327 0 0 -14.327 0 -32 V -96 C 0 -113.673 14.327 -128 32 -128 H 480 C 497.673 -128 512 -113.673 512 -96 V -32 C 512 -14.327 497.673 0 480 0 Z M 432 -88 C 418.745 -88 408 -77.255 408 -64 S 418.745 -40 432 -40 S 456 -50.745 456 -64 S 445.255 -88 432 -88 Z M 368 -88 C 354.745 -88 344 -77.255 344 -64 S 354.745 -40 368 -40 S 392 -50.745 392 -64 S 381.255 -88 368 -88 Z "/>
+
+<path fill="#ffffff" d="M 480 160 H 32 C 14.327 160 0 145.673 0 128 V 64 C 0 46.327 14.327 32 32 32 H 480 C 497.673 32 512 46.327 512 64 V 128 C 512 145.673 497.673 160 480 160 Z M 432 72 C 418.745 72 408 82.745 408 96 S 418.745 120 432 120 S 456 109.255 456 96 S 445.255 72 432 72 Z M 368 72 C 354.745 72 344 82.745 344 96 S 354.745 120 368 120 S 392 109.255 392 96 S 381.255 72 368 72 Z "/>
+
+<path fill="#ffffff" d="M 480 320 H 32 C 14.327 320 0 305.673 0 288 V 224 C 0 206.327 14.327 192 32 192 H 480 C 497.673 192 512 206.327 512 224 V 288 C 512 305.673 497.673 320 480 320 Z M 432 232 C 418.745 232 408 242.745 408 256 S 418.745 280 432 280 S 456 269.255 456 256 S 445.255 232 432 232 Z M 368 232 C 354.745 232 344 242.745 344 256 S 354.745 280 368 280 S 392 269.255 392 256 S 381.255 232 368 232 Z "/>
+
+<path fill="#ffffff" d="M 480 480 H 32 C 14.327 480 0 465.673 0 448 V 384 C 0 366.327 14.327 352 32 352 H 480 C 497.673 352 512 366.327 512 384 V 448 C 512 465.673 497.673 480 480 480 Z M 432 392 C 418.745 392 408 402.745 408 416 S 418.745 440 432 440 S 456 429.255 456 416 S 445.255 392 432 392 Z M 368 392 C 354.745 392 344 402.745 344 416 S 354.745 440 368 440 S 392 429.255 392 416 S 381.255 392 368 392 Z"/>
+
+<path fill="#C8D400" d="M 480 670 H -96 C -155 670 -190 631 -192 574 H 576 C 575 622 543 670 480 670 Z"/>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx
new file mode 100644
index 0000000..0276222
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx
@@ -0,0 +1,113 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { inventoryElementsReloadAction } from '../handlers/inventoryElementsHandler';
+
+import { InventoryType } from '../models/inventory';
+
+export enum RefreshInventoryDialogMode {
+  None = 'none',
+  RefreshInventoryTable = 'RefreshInventoryTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshInventory: () => dispatcher.dispatch(inventoryElementsReloadAction),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshInventoryDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshInventoryDialogMode.RefreshInventoryTable]: {
+    dialogTitle: 'Do you want to refresh the Inventory table?',
+    dialogDescription: '',
+    applyButtonText: 'Yes',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+};
+
+type RefreshInventoryDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshInventoryDialogMode;
+  onClose: () => void;
+};
+
+type RefreshInventoryDialogComponentState = InventoryType & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshInventoryDialogComponent extends React.Component<RefreshInventoryDialogComponentProps, RefreshInventoryDialogComponentState> {
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshInventoryDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={() => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={() => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshInventory();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+}
+
+export const RefreshInventoryDialog = connect(undefined, mapDispatch)(RefreshInventoryDialogComponent);
+export default RefreshInventoryDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/fakeData/index.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/fakeData/index.ts
new file mode 100644
index 0000000..136b908
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/fakeData/index.ts
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
+
+import { InventoryTreeNode, InventoryType } from "../models/inventory";
+
+const data = [
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.5", "part-type-id": "3FE25774AA01", "model-identifier": "VAUIAEYAAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#5", "type-name": "a2.module", "serial": "0003548168", "id": "robot_sim_2_equipment/a2.module-1.1.1.5", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.15.0.0"], "date": "2005-11-09T00:00:00.0Z" },
+  { "manufacturer-identifier": "SAN", "version": "234", "uuid": "CARD-1.1.6.0", "part-type-id": "part-number-12", "model-identifier": "model-id-12", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module", "type-name": "p8.module", "serial": "serial-number-124", "id": "robot_sim_2_equipment/CARD-1.1.6.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.6.5", "PORT-1.1.6.8", "PORT-1.1.6.7", "PORT-1.1.6.6"], "date": "2013-11-23T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.6.5", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module/a2.module#5", "type-name": "a2.module", "serial": "310330008", "id": "robot_sim_2_equipment/a2.module-1.1.6.5", "parent-uuid": "CARD-1.1.6.0", "contained-holder": ["SUBRACK-1.65.0.0"], "date": "2013-04-13T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "2017", "uuid": "CARD-1.55.1.4", "part-type-id": "partNo2017-12", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#55Ch#1/RxDiv", "type-name": "RxDiv", "serial": "Serie2017-12", "id": "robot_sim_2_equipment/CARD-1.55.1.4", "parent-uuid": "IDU-1.55.0.0", "date": "2014-01-07T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.56.1.2", "part-type-id": "Partnumber", "model-identifier": "model-id", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#56Ch#1/a2.moduletraff", "type-name": "a2.module", "serial": "Serial1", "id": "robot_sim_2_equipment/a2.module-1.56.1.2", "parent-uuid": "ODU-1.56.0.0", "date": "2017-09-09T00:00:00.0Z" },
+  { "manufacturer-identifier": "SAN", "version": "123", "uuid": "CARD-1.1.1.0", "part-type-id": "part-number-2", "model-identifier": "model-id-2", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN", "type-name": "latest", "serial": "asdf-asdasd-asd", "id": "robot_sim_2_equipment/CARD-1.1.1.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.1.8", "PORT-1.1.1.7", "PORT-1.1.1.6", "PORT-1.1.1.5"], "date": "2015-08-17T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.8", "part-type-id": "1AB376720002", "model-identifier": "NGI7AMLMAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#8", "type-name": "a2.module", "serial": "01T441601301", "id": "robot_sim_2_equipment/a2.module-1.1.1.8", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.18.0.0"], "date": "2010-02-05T00:00:00.0Z" },
+  { "manufacturer-identifier": "SAN", "version": "234", "uuid": "CARD-1.1.5.0", "part-type-id": "part-number-12", "model-identifier": "model-id-12", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module", "type-name": "p8.module", "serial": "africa", "id": "robot_sim_2_equipment/CARD-1.1.5.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.5.6", "PORT-1.1.5.5", "PORT-1.1.5.8", "PORT-1.1.5.7"], "date": "2013-10-21T00:00:00.0Z" },
+  { "manufacturer-identifier": "", "version": "", "uuid": "a2.module-1.1.5.6", "part-type-id": "", "model-identifier": "", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module/a2.module#6", "type-name": "a2.module", "serial": "", "id": "robot_sim_2_equipment/a2.module-1.1.5.6", "parent-uuid": "CARD-1.1.5.0", "contained-holder": ["SUBRACK-1.56.0.0"] }, { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "MWR-ng", "uuid": "IDU-1.65.0.0", "part-type-id": "3DB76047BAAA02", "model-identifier": "model-id-s3s", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "MWR-ng Dir#6.5-Ch#1", "type-name": "MWR-ng", "serial": "WAUZZI", "id": "robot_sim_2_equipment/IDU-1.65.0.0", "parent-uuid": "network-element", "contained-holder": ["PORT-1.65.1.4", "PORT-1.65.1.2"], "date": "2014-01-16T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.65.1.2", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#65Ch#1/a2.moduletraff", "type-name": "a2.module", "serial": "310330008", "id": "robot_sim_2_equipment/a2.module-1.65.1.2", "parent-uuid": "IDU-1.65.0.0", "date": "2013-04-13T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.5.5", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module/a2.module#5", "type-name": "a2.module", "serial": "310330015", "id": "robot_sim_2_equipment/a2.module-1.1.5.5", "parent-uuid": "CARD-1.1.5.0", "contained-holder": ["SUBRACK-1.55.0.0"], "date": "2013-04-13T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "unknown", "uuid": "CARD-1.1.8.0", "part-type-id": "unknown", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/DS3", "type-name": "p4.module", "serial": "sd-dsa-eqw", "id": "robot_sim_2_equipment/CARD-1.1.8.0", "parent-uuid": "SHELF-1.1.0.0", "date": "2008-10-21T00:00:00.0Z" },
+  { "manufacturer-identifier": "CIT", "version": "wind", "uuid": "CARD-1.1.9.0", "part-type-id": "party-yea", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/wind", "type-name": "wind", "serial": "proto-type", "id": "robot_sim_2_equipment/CARD-1.1.9.0", "parent-uuid": "SHELF-1.1.0.0", "date": "2007-02-19T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.55.1.2", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#55Ch#1/a2.moduletraff", "type-name": "a2.module", "serial": "310330015", "id": "robot_sim_2_equipment/a2.module-1.55.1.2", "parent-uuid": "IDU-1.55.0.0", "date": "2013-04-13T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "SHELF-1.1.0.0", "part-type-id": "Partnumber", "model-identifier": "model-id", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "WS-8", "type-name": "WS-8", "serial": "Serial1", "id": "robot_sim_2_equipment/SHELF-1.1.0.0", "parent-uuid": "network-element", "contained-holder": ["SLOT-1.1.9.0", "SLOT-1.1.7.0", "SLOT-1.1.8.0", "SLOT-1.1.5.0", "SLOT-1.1.6.0", "SLOT-1.1.3.0", "SLOT-1.1.4.0", "SLOT-1.1.2.0", "SLOT-1.1.1.0"], "date": "2017-09-09T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "MWR-ng", "uuid": "IDU-1.55.0.0", "part-type-id": "3DB76047BAAA02", "model-identifier": "model-id-s3s", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "MWR-ng Dir#5.5-Ch#1", "type-name": "MWR-ng", "serial": "Serie2017-14", "id": "robot_sim_2_equipment/IDU-1.55.0.0", "parent-uuid": "network-element", "contained-holder": ["PORT-1.55.1.2", "PORT-1.55.1.4"], "date": "2014-01-15T00:00:00.0Z" },
+  { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "2017", "uuid": "CARD-1.65.1.4", "part-type-id": "partNo2017-12", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#55Ch#0/RxDiv", "type-name": "RxDiv", "serial": "Serie2017-13", "id": "robot_sim_2_equipment/CARD-1.65.1.4", "parent-uuid": "IDU-1.65.0.0", "date": "2014-01-08T00:00:00.0Z" }, { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.7", "part-type-id": "1AB187280031", "model-identifier": "mod2", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#7", "type-name": "a2.module", "serial": "91T403003322", "id": "robot_sim_2_equipment/a2.module-1.1.1.7", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.17.0.0"], "date": "2009-01-19T00:00:00.0Z" },
+  { "manufacturer-identifier": "CIT", "version": "p1.module", "uuid": "CARD-1.1.7.0", "part-type-id": "part-number-s3s", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/DS1", "type-name": "p1.module_A", "serial": "serial-number-s3s", "id": "robot_sim_2_equipment/CARD-1.1.7.0", "parent-uuid": "SHELF-1.1.0.0", "date": "2007-08-27T00:00:00.0Z" },
+  { "manufacturer-identifier": "", "version": "extrem-hyper", "uuid": "ODU-1.56.0.0", "part-type-id": "", "model-identifier": "", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "MWR-hyper Dir#5.6-Ch#1", "type-name": "MWR-hyper", "serial": "", "id": "robot_sim_2_equipment/ODU-1.56.0.0", "parent-uuid": "network-element", "contained-holder": ["PORT-1.56.1.3", "PORT-1.56.1.4", "PORT-1.56.1.2"] }
+];
+
+const deleay = (time: number) => () => new Promise<number>(resolve => setTimeout(resolve, time, time));
+
+const getTreeElements = (searchTerm: string | null, treeLevel: number = 0, parentUUID: string | null = null): [InventoryTreeNode, boolean] => {
+  const elements = (data.filter(e => e["tree-level"] === treeLevel && (!parentUUID || e["parent-uuid"] === parentUUID)) || [])
+  let elementMatch = false;
+  const treeNode = elements.reduce<InventoryTreeNode>((acc, cur) => {
+    const [children, childMatch] = getTreeElements(searchTerm, treeLevel + 1, cur["uuid"]);
+    const isMatch = searchTerm ? Object.keys(cur).some(k => String((cur as any)[k]).indexOf(searchTerm) > -1) : false;
+    elementMatch = elementMatch || isMatch || childMatch;
+    if (!searchTerm || isMatch || childMatch) {
+      acc[cur["uuid"]] = {
+        label: cur["uuid"],
+        children: children,
+        isMatch: isMatch,
+      };
+    }
+    return acc;
+  }, {});
+
+  return [treeNode, elementMatch]
+};
+
+export const getTree = async (searchTerm: string | null = null): Promise<InventoryTreeNode> => {
+  await deleay(600);
+  const [node] = getTreeElements(searchTerm);
+  return node;
+};
+
+export const getElement = async (id: string): Promise<InventoryType | undefined> => {
+  await deleay(600);
+  const res = data.find(e => e.uuid === id);
+  return res && convertPropertyNames(res, replaceHyphen) as unknown as InventoryType;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
new file mode 100644
index 0000000..b1a0c58
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
@@ -0,0 +1,53 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* 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.
+* ============LICENSE_END==========================================================================
+*/
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// ** do not remove **
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { PanelId } from '../models/panelId';
+import { IInventoryDeviceListState, inventoryDeviceListActionHandler } from './inventoryDeviceListActionHandler';
+import { IInventoryElementsState, inventoryElementsActionHandler } from './inventoryElementsHandler';
+import { IInvenroryTree, inventoryTreeHandler } from './inventoryTreeHandler';
+import { currentOpenPanelHandler } from './panelHandler';
+
+export interface IInventoryAppStateState {
+  inventoryTree: IInvenroryTree;
+  currentOpenPanel: PanelId;
+  inventoryElements: IInventoryElementsState;
+  inventoryDeviceList: IInventoryDeviceListState;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    inventory: IInventoryAppStateState;
+  }
+}
+
+const actionHandlers = {
+  inventoryTree: inventoryTreeHandler,
+  currentOpenPanel: currentOpenPanelHandler,
+  inventoryElements: inventoryElementsActionHandler,
+  inventoryDeviceList: inventoryDeviceListActionHandler,
+};
+
+export const inventoryAppRootHandler = combineActionHandler<IInventoryAppStateState>(actionHandlers);
+export default inventoryAppRootHandler;
+
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryDeviceListActionHandler.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryDeviceListActionHandler.ts
new file mode 100644
index 0000000..7c06cad
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryDeviceListActionHandler.ts
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllInventoryDeviceListLoadedAction, LoadAllInventoryDeviceListAction } from '../actions/inventoryDeviceListActions';
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+
+export interface IInventoryDeviceListState {
+  inventoryDeviceList: InventoryDeviceListType[];
+  busy: boolean;
+}
+
+const inventoryDeviceListListStateInit: IInventoryDeviceListState = {
+  inventoryDeviceList: [],
+  busy: false,
+};
+
+export const inventoryDeviceListActionHandler: IActionHandler<IInventoryDeviceListState> = (state = inventoryDeviceListListStateInit, action) => {
+  if (action instanceof LoadAllInventoryDeviceListAction) {
+
+    state = {
+      ...state,
+      busy: true,
+    };
+
+  } else if (action instanceof AllInventoryDeviceListLoadedAction) {
+    if (!action.error && action.inventoryDeviceList) {
+      state = {
+        ...state,
+        inventoryDeviceList: action.inventoryDeviceList,
+        busy: false,
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false,
+      };
+    }
+  }
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
new file mode 100644
index 0000000..7bac8f6
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { InventoryType } from '../models/inventory';
+
+export interface IInventoryElementsState extends IExternalTableState<InventoryType> { }
+
+// create eleactic search material data fetch handler
+const inventoryElementsSearchHandler = createSearchDataHandler<InventoryType>('inventory');
+
+export const {
+  actionHandler: inventoryElementsActionHandler,
+  createActions: createInventoryElementsActions,
+  createProperties: createInventoryElementsProperties,
+  reloadAction: inventoryElementsReloadAction,
+
+  // set value action, to change a value
+} = createExternal<InventoryType>(inventoryElementsSearchHandler, appState => appState.inventory.inventoryElements);
+
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
new file mode 100644
index 0000000..fe90d98
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
@@ -0,0 +1,68 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { SetBusyAction, SetSearchTextAction, UpdateExpandedNodesAction, UpdateInventoryTreeAction, UpdateSelectedNodeAction } from '../actions/inventoryTreeActions';
+import { InventoryTreeNode, InventoryType, TreeDemoItem } from '../models/inventory';
+
+
+export interface IInvenroryTree {
+  isBusy: boolean;
+  rootNodes: TreeDemoItem[];
+  selectedNode?: InventoryType;
+  expandedItems: TreeDemoItem[];
+  searchTerm: string;
+}
+
+const initialState: IInvenroryTree = {
+  isBusy: false,
+  rootNodes: [],
+  searchTerm: '',
+  selectedNode: undefined,
+  expandedItems: [],
+};
+
+
+const getTreeDataFromInvetoryTreeNode = (node: InventoryTreeNode): TreeDemoItem[] => Object.keys(node).reduce<TreeDemoItem[]>((acc, key) => {
+  const cur = node[key];
+  acc.push({
+    isMatch: cur.isMatch,
+    content: cur.label || key,
+    value: key,
+    children: cur.children && getTreeDataFromInvetoryTreeNode(cur.children),
+  });
+  return acc;
+}, []);
+
+export const inventoryTreeHandler: IActionHandler<IInvenroryTree> = (state = initialState, action) => {
+  if (action instanceof SetBusyAction) {
+    state = { ...state, isBusy: action.busy };
+  } else if (action instanceof SetSearchTextAction) {
+    state = { ...state, searchTerm: action.searchTerm };
+  } else if (action instanceof UpdateInventoryTreeAction) {
+    const rootNodes = getTreeDataFromInvetoryTreeNode(action.rootNode);
+    state = { ...state, rootNodes: rootNodes, expandedItems: [], selectedNode: undefined };
+  } else if (action instanceof UpdateSelectedNodeAction) {
+    state = { ...state, selectedNode: action.selectedNode };
+  } else if (action instanceof UpdateExpandedNodesAction) {
+    state = { ...state, expandedItems: action.expandedNodes || [] };
+  }
+
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/panelHandler.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
new file mode 100644
index 0000000..7912d0e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
@@ -0,0 +1,11 @@
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { SetPanelAction } from '../actions/panelActions';
+import { PanelId } from '../models/panelId';
+
+export const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
+  if (action instanceof SetPanelAction) {
+    state = action.panelId;
+  }
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/index.html b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/index.html
new file mode 100644
index 0000000..2c44424
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>Inventory App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "inventoryApp", "connectApp", "configurationApp", "faultApp"], function (app, inventoryApp, connectApp, configurationApp, faultApp) {
+      inventoryApp.register();
+      connectApp.register();
+      configurationApp.register();
+      faultApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/inventory.ts
new file mode 100644
index 0000000..a09fd7e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/inventory.ts
@@ -0,0 +1,50 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ExternalTreeItem } from '../../../../framework/src/components/material-ui/treeView';
+
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+export type InventoryType = {
+  treeLevel: number;
+  parentUuid: string;
+  nodeId: string;
+  uuid: string;
+  containedHolder?: (string)[] | null;
+  manufacturerName?: string;
+  manufacturerIdentifier: string;
+  serial: string;
+  date: string;
+  version: string;
+  description: string;
+  partTypeId: string;
+  modelIdentifier: string;
+  typeName: string;
+};
+
+export type InventoryTreeNode = {
+  [key: string]: {
+    label: string;
+    children?: InventoryTreeNode;
+    isMatch?: boolean;
+    ownSeverity?: string;
+    childrenSeveritySummary?: string;
+  };
+};
+
+export type TreeDemoItem = ExternalTreeItem<string>;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/inventoryDeviceListType.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/inventoryDeviceListType.ts
new file mode 100644
index 0000000..ab24114
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/inventoryDeviceListType.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents all the distinct devices from the inventory history data.
+ */
+
+export type InventoryDeviceListType = {
+  nodeId: string;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/networkElementConnection.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
new file mode 100644
index 0000000..e1ef1ea
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type NetworkElementConnection = {
+  id?: string;
+  nodeId: string;
+  host: string;
+  port: number;
+  username?: string;
+  password?: string;
+  isRequired?: boolean;
+  status?: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
+  coreModelCapability?: string;
+  deviceType?: string;
+  nodeDetails?: {
+    availableCapabilities: string[];
+    unavailableCapabilities: {
+      failureReason: string;
+      capability: string;
+    }[];
+  };
+};
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/panelId.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/panelId.ts
new file mode 100644
index 0000000..8f8224c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/models/panelId.ts
@@ -0,0 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type PanelId = null | 'Equipment' | 'TreeView';
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/pluginInventory.tsx b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/pluginInventory.tsx
new file mode 100644
index 0000000..8198599
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/pluginInventory.tsx
@@ -0,0 +1,88 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* 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.
+* ============LICENSE_END==========================================================================
+*/
+// app configuration and main entry point for the app
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+import { SetPanelAction } from './actions/panelActions';
+import inventoryAppRootHandler from './handlers/inventoryAppRootHandler';
+import { createInventoryElementsActions, createInventoryElementsProperties } from './handlers/inventoryElementsHandler';
+import { PanelId } from './models/panelId';
+import Dashboard from './views/dashboard';
+import { InventoryTreeView } from './views/treeview';
+
+const appIcon = require('./assets/icons/inventoryAppIcon.svg');  // select app icon
+
+let currentMountId: string | undefined = undefined;
+const mapProps = (state: IApplicationStoreState) => ({
+  inventoryProperties: createInventoryElementsProperties(state),
+  panelId: state.inventory.currentOpenPanel,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  inventoryActions: createInventoryElementsActions(dispatcher.dispatch, true),
+  setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+});
+
+const InventoryTableApplicationRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
+  if (currentMountId !== props.match.params.mountId) {
+    // route parameter has changed
+    currentMountId = props.match.params.mountId || undefined;
+    // Hint: This timeout is needed, since it is not recommended to change the state while rendering is in progress !
+    window.setTimeout(() => {
+      if (currentMountId) {
+        if (props.panelId) {
+          props.setCurrentPanel(props.panelId);
+        } else {
+          props.setCurrentPanel('Equipment');
+        }
+        props.inventoryActions.onFilterChanged('nodeId', currentMountId);
+        if (!props.inventoryProperties.showFilter) {
+          props.inventoryActions.onToggleFilter(false);
+        }
+        props.inventoryActions.onRefresh();
+      }
+    });
+  }
+  return (
+    <Dashboard />
+  );
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+  <Switch>
+    <Route path={`${props.match.path}/dashboard/:mountId`} component={InventoryTableApplicationRouteAdapter} />
+    <Route path={`${props.match.path}/:mountId`} component={InventoryTreeView} />
+    <Route path={`${props.match.path}`} component={Dashboard} />
+    <Redirect to={`${props.match.path}`} />
+  </Switch>
+));
+
+export function register() {
+  applicationManager.registerApplication({
+    name: 'inventory',
+    icon: appIcon,
+    rootActionHandler: inventoryAppRootHandler,
+    rootComponent: App,
+    menuEntry: 'Inventory',
+  });
+}
+
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/services/inventoryService.ts b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/services/inventoryService.ts
new file mode 100644
index 0000000..4014fcf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/services/inventoryService.ts
@@ -0,0 +1,92 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Result } from '../../../../framework/src/models/elasticSearch';
+import { requestRest } from '../../../../framework/src/services/restService';
+
+import { InventoryTreeNode, InventoryType } from '../models/inventory';
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+
+/**
+ * Represents a web api accessor service for all maintenence entries related actions.
+ */
+class InventoryService {
+  public async getInventoryTree(mountId: string, searchTerm: string = ''): Promise<InventoryTreeNode | null> {
+    //return await getTree(searchTerm);
+    const path = `/tree/read-inventoryequipment-tree/${mountId}`;
+    const body = {
+      'query': searchTerm,
+    };
+    const inventoryTree = await requestRest<InventoryTreeNode>(path, { method: 'POST', body: JSON.stringify(body) });
+    return inventoryTree && inventoryTree || null;
+  }
+
+  public async getInventoryEntry(id: string): Promise<InventoryType | undefined> {
+    const path = '/rests/operations/data-provider:read-inventory-list';
+    const body = {
+      'data-provider:input': {
+        'filter': [
+          { property: 'id', filtervalue: id },
+        ],
+        'sortorder': [],
+        'pagination': {
+          'size': 1,
+          'page': 1,
+        },
+      },
+    };
+    const inventoryTreeElement = await requestRest<{
+      'data-provider:output': {
+        'pagination': {
+          'size': number;
+          'page': number;
+          'total': number;
+        };
+        'data': InventoryType[];
+      };
+    }>(path, { method: 'POST', body: JSON.stringify(body) });
+
+    return inventoryTreeElement && inventoryTreeElement['data-provider:output'] && inventoryTreeElement['data-provider:output'].pagination && inventoryTreeElement['data-provider:output'].pagination.total >= 1 &&
+      inventoryTreeElement['data-provider:output'].data && inventoryTreeElement['data-provider:output'].data[0] || undefined;
+    // return await getElement(id);
+  }
+
+  /**
+   * Gets all nodes from the inventory device list.
+   */
+  public async getInventoryDeviceList(): Promise<(InventoryDeviceListType)[] | null> {
+    const path = '/rests/operations/data-provider:read-inventory-device-list';
+    const query = {
+      'data-provider:input': {
+        'filter': [],
+        'sortorder': [],
+        'pagination': {
+          'size': 20,
+          'page': 1,
+        },
+      },
+    };
+
+    const result = await requestRest<Result<any>>(path, { method: 'POST', body: JSON.stringify(query) });
+    return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+      nodeId: ne,
+    })) || null;
+  }
+
+}
+
+export const inventoryService = new InventoryService();
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/dashboard.tsx
new file mode 100644
index 0000000..acd2c62
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/dashboard.tsx
@@ -0,0 +1,202 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import Refresh from '@mui/icons-material/Refresh';
+import { AppBar, MenuItem, Tab, Tabs, Typography } from '@mui/material';
+
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { loadAllInventoryDeviceListAsync } from '../actions/inventoryDeviceListActions';
+import { updateInventoryTreeAsyncAction } from '../actions/inventoryTreeActions';
+import { setPanelAction } from '../actions/panelActions';
+import RefreshInventoryDialog, { RefreshInventoryDialogMode } from '../components/refreshInventoryDialog';
+import { createInventoryElementsActions, createInventoryElementsProperties } from '../handlers/inventoryElementsHandler';
+import { InventoryType } from '../models/inventory';
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+import { PanelId } from '../models/panelId';
+
+const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & { _id: string }>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  panelId: state.inventory.currentOpenPanel,
+  inventoryElementsProperties: createInventoryElementsProperties(state),
+  inventoryElements: state.inventory.inventoryElements,
+  inventoryDeviceList: state.inventory.inventoryDeviceList.inventoryDeviceList,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  switchActivePanel: (panelId: PanelId) => {
+    dispatcher.dispatch(setPanelAction(panelId));
+  },
+  inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch),
+  navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+  updateInventoryTree: (mountId: string, searchTerm?: string) => dispatcher.dispatch(updateInventoryTreeAsyncAction(mountId, searchTerm)),
+  getAllInventoryDeviceList: async () => {
+    await dispatcher.dispatch(loadAllInventoryDeviceListAsync);
+  },
+});
+
+let treeViewInitialSorted = false;
+let inventoryInitialSorted = false;
+
+const InventoryDeviceListTable = MaterialTable as MaterialTableCtorType<InventoryDeviceListType>;
+
+type DashboardComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch>;
+type DashboardComponentState = {
+  refreshInventoryEditorMode: RefreshInventoryDialogMode;
+};
+
+class DashboardSelectorComponent extends React.Component<DashboardComponentProps, DashboardComponentState> {
+  constructor(props: DashboardComponentProps) {
+    super(props);
+
+    this.state = {
+      refreshInventoryEditorMode: RefreshInventoryDialogMode.None,
+    };
+  }
+
+  private onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
+    this.onTogglePanel(newValue);
+  };
+
+  private onTogglePanel = (panelId: PanelId) => {
+    const nextActivePanel = panelId;
+    this.props.switchActivePanel(nextActivePanel);
+
+    switch (nextActivePanel) {
+      case 'Equipment':
+
+        if (!inventoryInitialSorted) {
+          this.props.inventoryElementsActions.onHandleExplicitRequestSort('nodeId', 'asc');
+          inventoryInitialSorted = true;
+        } else {
+          this.props.inventoryElementsActions.onRefresh();
+
+        }
+        break;
+      case 'TreeView':
+        this.props.getAllInventoryDeviceList();
+        break;
+      case null:
+        // do nothing if all panels are closed
+        break;
+      default:
+        console.warn('Unknown nextActivePanel [' + nextActivePanel + '] in connectView');
+        break;
+    }
+
+  };
+
+  getContextMenu = (rowData: InventoryType) => {
+    return [
+      <MenuItem aria-label={'inventory-button'} onClick={() => { this.props.updateInventoryTree(rowData.nodeId, rowData.uuid); this.props.navigateToApplication('inventory', rowData.nodeId); }}><Typography>View in Treeview</Typography></MenuItem>,
+    ];
+
+  };
+
+  render() {
+
+    const refreshInventoryAction = {
+      icon: Refresh, tooltip: 'Refresh Inventory', ariaLabel: 'refresh', onClick: () => {
+        this.setState({
+          refreshInventoryEditorMode: RefreshInventoryDialogMode.RefreshInventoryTable,
+        });
+      },
+    };
+    const { panelId: activePanelId } = this.props;
+    return (
+      <>
+        <AppBar enableColorOnDark position="static">
+          <Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="inventory-app-tabs">
+            <Tab label="Equipment" value="Equipment" aria-label="equipment-tab" />
+            <Tab label="Tree View" value="TreeView" aria-label="treeview-tab" />
+          </Tabs>
+        </AppBar>
+
+        {
+
+          activePanelId === 'Equipment' &&
+          <>
+            <InventoryTable stickyHeader idProperty="_id" tableId="inventory-table" customActionButtons={[refreshInventoryAction]} columns={[
+              { property: 'nodeId', title: 'Node Name' },
+              { property: 'manufacturerIdentifier', title: 'Manufacturer' },
+              { property: 'parentUuid', title: 'Parent' },
+              { property: 'uuid', title: 'Name' },
+              { property: 'serial', title: 'Serial' },
+              { property: 'version', title: 'Version' },
+              { property: 'date', title: 'Date' },
+              { property: 'description', title: 'Description' },
+              { property: 'partTypeId', title: 'Part Type Id' },
+              { property: 'modelIdentifier', title: 'Model Identifier' },
+              { property: 'typeName', title: 'Type' },
+              { property: 'treeLevel', title: 'Containment Level' },
+            ]}  {...this.props.inventoryElementsActions} {...this.props.inventoryElementsProperties}
+              createContextMenu={rowData => {
+
+                return this.getContextMenu(rowData);
+              }} >
+            </InventoryTable>
+            <RefreshInventoryDialog
+              mode={this.state.refreshInventoryEditorMode}
+              onClose={this.onCloseRefreshInventoryDialog}
+            />
+          </>
+
+        }
+        {
+          activePanelId === 'TreeView' &&
+          <>
+            <InventoryDeviceListTable stickyHeader tableId="treeview-networkelement-selection-table"
+              defaultSortColumn={'nodeId'} defaultSortOrder="asc"
+              onHandleClick={(e, row) => {
+                this.props.navigateToApplication('inventory', row.nodeId);
+                this.props.updateInventoryTree(row.nodeId, '*');
+              }}
+              rows={this.props.inventoryDeviceList} asynchronus
+              columns={[
+                { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
+              ]} idProperty="nodeId" >
+            </InventoryDeviceListTable>
+          </>
+        }
+      </>
+    );
+  }
+
+  private onCloseRefreshInventoryDialog = () => {
+    this.setState({
+      refreshInventoryEditorMode: RefreshInventoryDialogMode.None,
+    });
+  };
+
+  componentDidMount() {
+    if (this.props.panelId === null) { //set default tab if none is set
+      this.onTogglePanel('Equipment');
+    }
+  }
+}
+
+export const Dashboard = withRouter(connect(mapProps, mapDispatch)(DashboardSelectorComponent));
+export default Dashboard;
+
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/detail.tsx b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/detail.tsx
new file mode 100644
index 0000000..8d47ec3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/detail.tsx
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import Button from '@mui/material/Button';
+import { Theme } from '@mui/material/styles'; // infra for styling
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+
+const styles = (theme: Theme) => createStyles({
+  warnButton: {
+    backgroundColor: theme.palette.primary.dark,
+  },
+});
+
+type DetailProps = RouteComponentProps<{ id: string }> & WithStyles<typeof styles>;
+
+export const Detail = withStyles( styles )( withRouter( (props: DetailProps) => (
+  <div>
+    <h1>Detail {props.match.params.id}</h1>
+    <p>This are the information about {props.staticContext}.</p>
+    <Button color={'secondary'} variant={'contained'}>Start</Button>
+    <Button color="inherit" className={ props.classes.warnButton } variant={'contained'}>Stop</Button>
+  </div>
+)));
+
+export default Detail;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/treeview.tsx b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/treeview.tsx
new file mode 100644
index 0000000..954c074
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/src/views/treeview.tsx
@@ -0,0 +1,155 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import Breadcrumbs from '@mui/material/Breadcrumbs';
+import Link from '@mui/material/Link';
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+import { RouteComponentProps } from 'react-router-dom';
+import { SearchMode, TreeView, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView';
+import { renderObject } from '../../../../framework/src/components/objectDump';
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { selectInventoryNodeAsyncAction, setSearchTermAction, UpdateExpandedNodesAction, updateInventoryTreeAsyncAction, UpdateSelectedNodeAction } from '../actions/inventoryTreeActions';
+import { TreeDemoItem } from '../models/inventory';
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    flex: '1 0 0%',
+    display: 'flex',
+    flexDirection: 'row',
+  },
+  tree: {
+    wordWrap: 'break-word',
+    minWidth: '250px',
+    padding: `0px ${theme.spacing(1)}`,
+  },
+  details: {
+    flex: '5 0 0%',
+    padding: `0px ${theme.spacing(1)}`,
+  },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  isBusy: state.inventory.inventoryTree.isBusy,
+  rootNodes: state.inventory.inventoryTree.rootNodes,
+  searchTerm: state.inventory.inventoryTree.searchTerm,
+  selectedNode: state.inventory.inventoryTree.selectedNode,
+  expendedItems: state.inventory.inventoryTree.expandedItems,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  updateExpendedNodes: (expendedNodes: TreeDemoItem[]) => dispatcher.dispatch(new UpdateExpandedNodesAction(expendedNodes)),
+  updateInventoryTree: (mountId: string, searchTerm?: string) => dispatcher.dispatch(updateInventoryTreeAsyncAction(mountId, searchTerm)),
+  selectTreeNode: (nodeId?: string) => nodeId ? dispatcher.dispatch(selectInventoryNodeAsyncAction(nodeId)) : dispatcher.dispatch(new UpdateSelectedNodeAction(undefined)),
+  setSearchTerm: (searchTerm: string) => dispatcher.dispatch(setSearchTermAction(searchTerm)),
+});
+
+const propsChache = Symbol('PropsCache');
+const InventoryTree = TreeView as any as TreeViewCtorType<string>;
+
+
+
+type TreeviewComponentProps = RouteComponentProps<{ mountId: string }> & WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
+
+type TreeviewComponentState = {
+  [propsChache]: {
+    rootNodes?: TreeDemoItem[];
+  };
+  rootNodes: TreeDemoItem[];
+};
+
+
+class DashboardComponent extends React.Component<TreeviewComponentProps, TreeviewComponentState> {
+
+  constructor(props: TreeviewComponentProps) {
+    super(props);
+
+    this.state = {
+      [propsChache]: {},
+      rootNodes: [],
+    };
+  }
+
+  static getDerivedStateFromProps(props: TreeviewComponentProps, state: TreeviewComponentState) {
+    if (state[propsChache].rootNodes != props.rootNodes) {
+      // eslint-disable-next-line no-param-reassign
+      state = { ...state, rootNodes: props.rootNodes };
+    }
+    return state;
+  }
+
+  render() {
+    const { classes, updateInventoryTree, updateExpendedNodes, expendedItems, selectedNode, selectTreeNode, searchTerm, match: { params: { mountId } } } = this.props;
+    const scrollbar = { overflow: 'auto', paddingRight: '20px' };
+
+    let filteredDashboardPath = `/inventory/dashboard/${this.props.match.params.mountId}`;
+    let basePath = `/inventory/${this.props.match.params.mountId}`;
+
+    return (
+      <div style={scrollbar} >
+        <div >
+          <Breadcrumbs aria-label="breadcrumbs">
+            <Link underline="hover" color="inherit" href="#" aria-label="back-breadcrumb"
+              onClick={(event: React.MouseEvent<HTMLElement>) => {
+                event.preventDefault();
+                this.props.history.push(filteredDashboardPath);
+              }}>Back</Link>
+            <Link underline="hover" color="inherit" href="#"
+              aria-label={this.props.match.params.mountId + '-breadcrumb'}
+              onClick={(event: React.MouseEvent<HTMLElement>) => {
+                event.preventDefault();
+                this.props.history.push(basePath);
+              }}><span>{this.props.match.params.mountId}</span></Link>
+          </Breadcrumbs>
+        </div>
+        <br />
+        <div style={scrollbar} className={classes.root}>
+          <InventoryTree className={classes.tree} items={this.state.rootNodes} enableSearchBar initialSearchTerm={searchTerm} searchMode={SearchMode.OnEnter} searchTerm={searchTerm}
+            // eslint-disable-next-line @typescript-eslint/no-shadow
+            onSearch={(searchTerm) => updateInventoryTree(mountId, searchTerm)} expandedItems={expendedItems} onFolderClick={(item) => {
+              const indexOfItemToToggle = expendedItems.indexOf(item);
+              if (indexOfItemToToggle === -1) {
+                updateExpendedNodes([...expendedItems, item]);
+              } else {
+                updateExpendedNodes([
+                  ...expendedItems.slice(0, indexOfItemToToggle),
+                  ...expendedItems.slice(indexOfItemToToggle + 1),
+                ]);
+              }
+            }}
+            onItemClick={(elm) => selectTreeNode(elm.value)} />
+          <div className={classes.details}>{
+            selectedNode && renderObject(selectedNode, 'tree-view') || null
+          }</div>
+        </div>
+      </div>
+    );
+  }
+
+  componentWillUnmount() {
+    this.props.setSearchTerm('*');
+  }
+}
+
+export const InventoryTreeView = connect(mapProps, mapDispatch)(withStyles(styles)(DashboardComponent));
+export default InventoryTreeView;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/inventoryApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/inventoryApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/inventoryApp/webpack.config.js
new file mode 100644
index 0000000..6a78056
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/inventoryApp/webpack.config.js
@@ -0,0 +1,178 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      inventoryApp: ["./pluginInventory.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },{
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/oauth2/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/database/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/help/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/tree/": {
+          target: "http://sdnc-web:8080",
+          secure: false
+        },
+        "/websocket": {
+          target: "http://sdnc-web:8080",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        },
+        "/yang-schema": {
+          target: "http://sdnc-web:8080",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/.babelrc b/sdnr/wt-odlux/odlux/apps/maintenanceApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/package.json b/sdnr/wt-odlux/odlux/apps/maintenanceApp/package.json
new file mode 100644
index 0000000..d7c3254
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/package.json
@@ -0,0 +1,46 @@
+{
+  "name": "@odlux/maintenance-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI for the maintenance app.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/connect-app": "*",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0",
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@fortawesome/react-fontawesome": "0.1.14"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/pom.xml b/sdnr/wt-odlux/odlux/apps/maintenanceApp/pom.xml
new file mode 100644
index 0000000..03832f7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-maintenanceApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
new file mode 100644
index 0000000..740abff
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
@@ -0,0 +1,77 @@
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { maintenanceEntriesReloadAction } from '../handlers/maintenanceEntriesHandler';
+import { MaintenanceEntry, spoofSymbol } from '../models/maintenanceEntryType';
+import { maintenenceService } from '../services/maintenenceService';
+
+export class BaseAction extends Action { }
+
+export class LoadAllMainteneceEntriesAction extends BaseAction { }
+
+export class AllMainteneceEntriesLoadedAction extends BaseAction {
+
+  constructor(public maintenenceEntries: MaintenanceEntry[] | null) {
+    super();
+
+  }
+}
+
+
+export class UpdateMaintenanceEntry extends BaseAction {
+  constructor(public maintenenceEntry: MaintenanceEntry) {
+    super();
+  }
+}
+
+/** Represents an async thunk action creator to add an element to the maintenence entries. */
+export const addOrUpdateMaintenenceEntryAsyncActionCreator = (entry: MaintenanceEntry) => (dispatch: Dispatch) => {
+  maintenenceService.writeMaintenenceEntry(entry).then(result => {
+    result && window.setTimeout(() => {
+      // dispatch(loadAllMountedNetworkElementsAsync);
+      dispatch(new UpdateMaintenanceEntry(entry));
+      dispatch(new AddSnackbarNotification({ message: `Successfully ${result && result.created ? 'created' : 'updated'} maintenance settings for [${entry.nodeId}]`, options: { variant: 'success' } }));
+    }, 900);
+    dispatch(maintenanceEntriesReloadAction);
+  });
+};
+
+/** Represents an async thunk action creator to delete an element from the maintenence entries. */
+export const removeFromMaintenenceEntrysAsyncActionCreator = (entry: MaintenanceEntry) => (dispatch: Dispatch) => {
+  maintenenceService.deleteMaintenenceEntry(entry).then(result => {
+    result && window.setTimeout(() => {
+      dispatch(new UpdateMaintenanceEntry({
+        [spoofSymbol]: true,
+        mId: entry.mId,
+        nodeId: entry.nodeId,
+        description: '',
+        start: '',
+        end: '',
+        active: false,
+      }));
+      dispatch(new AddSnackbarNotification({ message: `Successfully removed [${entry.nodeId}]`, options: { variant: 'success' } }));
+    }, 900);
+    dispatch(maintenanceEntriesReloadAction);
+  });
+};
+
+// Hint: since there is no notification of changed required network elements, this code is not aware of changes caused outiside of this browser.
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/assets/icons/maintenanceAppIcon.svg b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/assets/icons/maintenanceAppIcon.svg
new file mode 100644
index 0000000..8b99a5e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/assets/icons/maintenanceAppIcon.svg
@@ -0,0 +1,50 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 684.000000 684.000000">
+
+<g transform="translate(0.000000,684.000000) scale(0.100000,-0.100000)">
+
+<path fill="#565656" d="M3044 6693 c-12 -2 -33 -17 -48 -32 -35 -37 -55 -136 -96 -476 -17
+-142 -32 -260 -33 -260 -1 -1 -60 -19 -132 -40 -243 -71 -406 -139 -600 -250
+-99 -57 -120 -66 -138 -57 -12 6 -124 91 -249 189 -124 98 -252 193 -283 212
+-57 34 -57 34 -89 17 -81 -43 -421 -374 -513 -500 -24 -32 -43 -67 -43 -78 0
+-36 98 -173 337 -472 57 -70 103 -132 103 -138 0 -5 -17 -35 -39 -66 -98 -144
+-275 -566 -301 -715 -14 -78 26 -65 -335 -112 -384 -51 -423 -62 -447 -125 -5
+-14 -9 -179 -9 -376 0 -414 0 -416 78 -433 43 -10 213 -35 518 -77 183 -25
+167 -12 221 -182 75 -238 160 -433 278 -637 l35 -61 -175 -219 c-206 -259
+-274 -357 -274 -393 0 -22 50 -76 258 -282 142 -141 275 -269 295 -284 l36
+-28 38 23 c62 38 177 124 380 286 l193 153 92 -57 c168 -102 383 -193 633
+-269 66 -19 123 -39 127 -43 9 -8 19 -76 53 -361 14 -113 33 -243 42 -289 23
+-119 0 -114 455 -113 237 0 373 4 386 11 44 23 61 101 106 485 l32 269 149 46
+c227 71 395 139 395 160 0 5 -125 127 -277 272 -194 186 -283 263 -297 262
+-12 -1 -75 -11 -141 -23 -318 -56 -700 -29 -973 69 -278 101 -476 226 -685
+435 -275 275 -445 609 -504 988 -23 152 -23 432 1 586 60 394 215 705 493 984
+166 169 314 278 498 368 292 143 539 191 912 176 194 -8 297 -24 446 -72 485
+-156 879 -500 1098 -959 134 -278 196 -617 170 -918 -6 -73 -21 -186 -33 -251
+l-22 -119 274 -268 c268 -261 275 -268 292 -248 23 27 88 198 133 351 31 104
+41 127 59 132 11 3 131 19 266 36 402 50 463 65 477 118 5 15 8 192 8 393 0
+353 -1 368 -20 389 -36 40 -79 49 -469 100 -132 18 -249 36 -261 40 -18 7 -29
+33 -59 137 -66 223 -139 392 -292 669 l-28 51 126 159 c193 246 265 343 294
+399 l27 52 -31 45 c-101 147 -505 538 -555 538 -30 0 -234 -146 -506 -362
+l-104 -82 -51 28 c-244 136 -390 201 -606 271 -63 21 -136 46 -161 57 l-46 19
+-36 297 c-50 403 -58 430 -136 452 -34 9 -671 12 -717 3z"/>
+
+<path fill="#006C4B" d="M3080 4653 c-77 -8 -195 -35 -232 -54 -21 -10 -45 -30 -54 -44 -15
+-23 -15 -27 0 -49 22 -35 111 -101 277 -207 247 -158 343 -239 384 -326 35
+-74 -5 -237 -108 -438 -40 -77 -68 -116 -122 -170 -77 -77 -194 -145 -249
+-145 -39 0 -127 48 -339 184 -194 124 -291 176 -330 176 -60 0 -105 -86 -86
+-167 28 -127 262 -492 423 -662 101 -106 236 -191 333 -211 27 -5 138 -14 248
+-20 372 -20 506 -66 689 -240 87 -83 629 -652 1291 -1355 181 -192 439 -465
+573 -607 244 -255 245 -256 281 -251 220 32 406 139 512 295 50 73 98 174 106
+222 5 32 0 42 -53 108 -113 140 -296 342 -1073 1183 -513 554 -980 1066 -1074
+1178 -117 137 -174 252 -196 394 -6 39 -15 171 -21 294 -6 123 -15 257 -20
+297 -28 207 -209 414 -464 532 -97 45 -172 66 -286 80 -78 9 -330 11 -410 3z"/>
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
new file mode 100644
index 0000000..9ab147c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
@@ -0,0 +1,207 @@
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+import TextField from '@mui/material/TextField';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { FormControl, InputLabel, MenuItem, Select, Typography } from '@mui/material';
+import {
+  addOrUpdateMaintenenceEntryAsyncActionCreator,
+  removeFromMaintenenceEntrysAsyncActionCreator,
+} from '../actions/maintenenceActions';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+
+export enum EditMaintenenceEntryDialogMode {
+  None = 'none',
+  AddMaintenenceEntry = 'addMaintenenceEntry',
+  EditMaintenenceEntry = 'editMaintenenceEntry',
+  RemoveMaintenenceEntry = 'removeMaintenenceEntry',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  addOrUpdateMaintenenceEntry: (entry: MaintenanceEntry) => {
+    dispatcher.dispatch(addOrUpdateMaintenenceEntryAsyncActionCreator(entry));
+  },
+  removeMaintenenceEntry: (entry: MaintenanceEntry) => {
+    dispatcher.dispatch(removeFromMaintenenceEntrysAsyncActionCreator(entry));
+  },
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableTimeEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [EditMaintenenceEntryDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableTimeEditor: false,
+  },
+  [EditMaintenenceEntryDialogMode.AddMaintenenceEntry]: {
+    dialogTitle: 'Add new maintenence entry',
+    dialogDescription: '',
+    applyButtonText: 'Add',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableTimeEditor: true,
+  },
+  [EditMaintenenceEntryDialogMode.EditMaintenenceEntry]: {
+    dialogTitle: 'Edit maintenence entry',
+    dialogDescription: '',
+    applyButtonText: 'Save',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: false,
+    enableTimeEditor: true,
+  },
+  [EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry]: {
+    dialogTitle: 'Remove maintenence entry',
+    dialogDescription: '',
+    applyButtonText: 'Remove',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: false,
+    enableTimeEditor: false,
+  },
+};
+
+type EditMaintenenceEntryDIalogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: EditMaintenenceEntryDialogMode;
+  initialMaintenenceEntry: MaintenanceEntry;
+  onClose: () => void;
+};
+
+type EditMaintenenceEntryDIalogComponentState = MaintenanceEntry & { isErrorVisible: boolean };
+
+class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenceEntryDIalogComponentProps, EditMaintenenceEntryDIalogComponentState> {
+  constructor(props: EditMaintenenceEntryDIalogComponentProps) {
+    super(props);
+
+    this.state = {
+      ...this.props.initialMaintenenceEntry,
+      isErrorVisible: false,
+    };
+  }
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== EditMaintenenceEntryDialogMode.None}>
+        <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+          <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+          {this.state.isErrorVisible && <Typography variant="body1" color="error" >Name must not be empty.</Typography>}
+          <TextField variant="standard" disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="start"
+            label="Start (Local DateTime)" type="datetime-local" fullWidth value={this.state.start} onChange={(event) => { this.setState({ start: event.target.value }); }} />
+          <TextField variant="standard" disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="end"
+            label="End (Local DateTime)" type="datetime-local" fullWidth value={this.state.end} onChange={(event) => { this.setState({ end: event.target.value }); }} />
+          <FormControl variant="standard" fullWidth disabled={!setting.enableTimeEditor}>
+            <InputLabel htmlFor="active">Active</InputLabel>
+            <Select variant="standard" value={this.state.active || false} onChange={(event) => {
+              this.setState({ active: event.target.value as any as boolean });
+            }} inputProps={{ name: 'active', id: 'active' }} fullWidth >
+              <MenuItem value={true as any as string}>active</MenuItem>
+              <MenuItem value={false as any as string}>not active</MenuItem>
+            </Select>
+          </FormControl>
+        </DialogContent>
+        <DialogActions>
+          <Button onClick={(event) => {
+
+            if (this.props.mode === EditMaintenenceEntryDialogMode.AddMaintenenceEntry && this.state.nodeId.trim().length === 0) {
+              this.setState({ isErrorVisible: true });
+            } else {
+              this.onApply({
+                mId: this.state.mId || this.state.nodeId,
+                nodeId: this.state.nodeId,
+                description: this.state.description,
+                start: this.state.start,
+                end: this.state.end,
+                active: this.state.active,
+              });
+              this.setState({ isErrorVisible: false });
+            }
+
+            event.preventDefault();
+            event.stopPropagation();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button onClick={(event) => {
+            this.onCancel();
+            event.preventDefault();
+            event.stopPropagation();
+            this.setState({ isErrorVisible: false });
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onApply = (entry: MaintenanceEntry) => {
+    this.props.onClose && this.props.onClose();
+    switch (this.props.mode) {
+      case EditMaintenenceEntryDialogMode.AddMaintenenceEntry:
+        entry && this.props.addOrUpdateMaintenenceEntry(entry);
+        break;
+      case EditMaintenenceEntryDialogMode.EditMaintenenceEntry:
+        entry && this.props.addOrUpdateMaintenenceEntry(entry);
+        break;
+      case EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry:
+        entry && this.props.removeMaintenenceEntry(entry);
+        break;
+    }
+  };
+
+
+  private onCancel = () => {
+    this.props.onClose && this.props.onClose();
+  };
+
+  static getDerivedStateFromProps(props: EditMaintenenceEntryDIalogComponentProps, state: EditMaintenenceEntryDIalogComponentState & { initialMaintenenceEntrie: MaintenanceEntry }): EditMaintenenceEntryDIalogComponentState & { initialMaintenenceEntrie: MaintenanceEntry } {
+    if (props.initialMaintenenceEntry !== state.initialMaintenenceEntrie) {
+      // eslint-disable-next-line no-param-reassign
+      state = {
+        ...state,
+        ...props.initialMaintenenceEntry,
+        initialMaintenenceEntrie: props.initialMaintenenceEntry,
+      };
+    }
+    return state;
+  }
+
+}
+
+export const EditMaintenenceEntryDIalog = connect(undefined, mapDispatch)(EditMaintenenceEntryDIalogComponent);
+export default EditMaintenenceEntryDIalog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx
new file mode 100644
index 0000000..e8bd635
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx
@@ -0,0 +1,113 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { maintenanceEntriesReloadAction } from '../handlers/maintenanceEntriesHandler';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+
+export enum RefreshMaintenanceEntriesDialogMode {
+  None = 'none',
+  RefreshMaintenanceEntriesTable = 'RefreshMaintenanceEntriesTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshMaintenanceEntries: () => dispatcher.dispatch(maintenanceEntriesReloadAction),
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  enableMountIdEditor: boolean;
+  enableUsernameEditor: boolean;
+  enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshMaintenanceEntriesDialogMode.None]: {
+    dialogTitle: '',
+    dialogDescription: '',
+    applyButtonText: '',
+    cancelButtonText: '',
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshMaintenanceEntriesDialogMode.RefreshMaintenanceEntriesTable]: {
+    dialogTitle: 'Do you want to refresh Maintenance Entries?',
+    dialogDescription: '',
+    applyButtonText: 'Yes',
+    cancelButtonText: 'Cancel',
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+};
+
+type RefreshMaintenanceEntriesDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshMaintenanceEntriesDialogMode;
+  onClose: () => void;
+};
+
+type RefreshMaintenanceEntriesDialogComponentState = MaintenanceEntry & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshMaintenanceEntriesDialogComponent extends React.Component<RefreshMaintenanceEntriesDialogComponentProps, RefreshMaintenanceEntriesDialogComponentState> {
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshMaintenanceEntriesDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={() => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={() => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshMaintenanceEntries();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  };
+}
+
+export const RefreshMaintenanceEntriesDialog = connect(undefined, mapDispatch)(RefreshMaintenanceEntriesDialogComponent);
+export default RefreshMaintenanceEntriesDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
new file mode 100644
index 0000000..ced7f21
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
@@ -0,0 +1,39 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IMaintenanceEntriesState, maintenanceEntriesActionHandler } from './maintenanceEntriesHandler';
+
+export interface IMaintenanceAppStoreState {
+  maintenanceEntries : IMaintenanceEntriesState;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    maintenance: IMaintenanceAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  maintenanceEntries: maintenanceEntriesActionHandler,
+};
+
+export const maintenanceAppRootHandler = combineActionHandler<IMaintenanceAppStoreState>(actionHandlers);
+export default maintenanceAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/handlers/maintenanceEntriesHandler.ts b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/handlers/maintenanceEntriesHandler.ts
new file mode 100644
index 0000000..c3fe51e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/handlers/maintenanceEntriesHandler.ts
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+export interface IMaintenanceEntriesState extends IExternalTableState<MaintenanceEntry> { }
+
+// create elastic search material data fetch handler
+const maintenanceEntriesSearchHandler = createSearchDataHandler<MaintenanceEntry>('maintenance');
+
+export const {
+  actionHandler: maintenanceEntriesActionHandler,
+  createActions: createmaintenanceEntriesActions,
+  createProperties: createmaintenanceEntriesProperties,
+  reloadAction: maintenanceEntriesReloadAction,
+
+  // set value action, to change a value
+} = createExternal<MaintenanceEntry>(maintenanceEntriesSearchHandler, appState => appState.maintenance.maintenanceEntries);
+
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/index.html b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/index.html
new file mode 100644
index 0000000..c84aece
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css"> -->
+  <title>Minimal App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app","connectApp", "maintenanceApp"], function (app, connectApp, maintenanceApp) {
+      connectApp.register();
+      maintenanceApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/models/maintenanceEntryType.ts b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/models/maintenanceEntryType.ts
new file mode 100644
index 0000000..27cdc8c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/models/maintenanceEntryType.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+/** Represents the elestic search db type for maintenence enrties */
+
+
+export const spoofSymbol = Symbol('Spoof');
+
+/** Represents the type for an maintenence entry. */
+export type MaintenanceEntry = {
+  mId: string;
+  nodeId: string;
+  description?: string;
+  end: string;
+  start: string;
+  active: boolean;
+  [spoofSymbol]?: boolean;
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
new file mode 100644
index 0000000..0f686cb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import React, { FC } from 'react';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { maintenanceAppRootHandler } from './handlers/maintenanceAppRootHandler';
+
+import { MaintenanceView } from './views/maintenanceView';
+
+const appIcon = require('./assets/icons/maintenanceAppIcon.svg');  // select app icon
+
+const App : FC = () => {
+  return <MaintenanceView />;
+};
+
+export function register() {
+  applicationManager.registerApplication({
+    name: 'maintenance',
+    icon: appIcon,
+    rootComponent: App,
+    rootActionHandler: maintenanceAppRootHandler,
+    menuEntry: 'Maintenance',
+  });
+}
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/services/maintenenceService.ts b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
new file mode 100644
index 0000000..5fdccc3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { DeleteResponse, PostResponse } from '../../../../framework/src/models/elasticSearch';
+import { requestRest } from '../../../../framework/src/services/restService';
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+
+import { convertToISODateString } from '../utils/timeUtils';
+
+
+export const maintenenceEntryDatabasePath = 'mwtn/maintenancemode';
+
+/**
+ * Represents a web api accessor service for all maintenence entries related actions.
+ */
+class MaintenenceService {
+
+  /**
+  * Adds or updates one maintenence entry to the backend.
+  */
+  public async writeMaintenenceEntry(maintenenceEntry: MaintenanceEntry): Promise<PostResponse | null> {
+    const path = '/rests/operations/data-provider:create-maintenance';
+
+    const query = {
+      'id': maintenenceEntry.mId,
+      'node-id': maintenenceEntry.nodeId,
+      'active': maintenenceEntry.active,
+      'description': maintenenceEntry.description,
+      'end': convertToISODateString(maintenenceEntry.end),
+      'start': convertToISODateString(maintenenceEntry.start),
+    };
+
+    const result = await requestRest<PostResponse>(path, { method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': query }, replaceUpperCase)) });
+    return result || null;
+  }
+
+  /**
+  * Deletes one maintenence entry by its mountId from the backend.
+  */
+  public async deleteMaintenenceEntry(maintenenceEntry: MaintenanceEntry): Promise<(DeleteResponse) | null> {
+    const path = '/rests/operations/data-provider:delete-maintenance';
+
+    const query = {
+      'id': maintenenceEntry.mId,
+      'node-id': maintenenceEntry.nodeId,
+      'active': maintenenceEntry.active,
+      'description': maintenenceEntry.description,
+      'end': convertToISODateString(maintenenceEntry.end),
+      'start': convertToISODateString(maintenenceEntry.start),
+    };
+    const result = await requestRest<DeleteResponse>(path, { method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': query }, replaceUpperCase)) });
+    return result || null;
+  }
+}
+
+export const maintenenceService = new MaintenenceService();
+export default maintenenceService;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/utils/timeUtils.ts b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
new file mode 100644
index 0000000..0fde5fc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export function convertToGMTString(dateString: string): string {
+  const date = new Date(dateString);
+  const pad = (n: number) => (n < 10) ? '0' + n : n;
+
+  return date.getUTCFullYear() +
+    '-' + pad(date.getUTCMonth() + 1) +
+    '-' + pad(date.getUTCDate()) +
+    'T' + pad(date.getUTCHours()) +
+    ':' + pad(date.getUTCMinutes()) +
+    '+00:00';
+}
+
+export function convertToLocaleString(rawDate: string | number): string {
+  const date = new Date(rawDate);
+  const pad = (n: number) => (n < 10) ? '0' + n : n;
+
+  return date.getFullYear() +
+    '-' + pad(date.getMonth() + 1) +
+    '-' + pad(date.getDate()) +
+    'T' + pad(date.getHours()) +
+    ':' + pad(date.getMinutes());
+}
+
+export function convertToISODateString(rawDate: string | number): string {
+  const date = new Date(rawDate);
+  const displayDate = date.toISOString();
+  return displayDate.replace(/\.[0-9]{2}/, '.');
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/views/maintenanceView.tsx b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/views/maintenanceView.tsx
new file mode 100644
index 0000000..d54d63c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/src/views/maintenanceView.tsx
@@ -0,0 +1,246 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import { faBan } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import AddIcon from '@mui/icons-material/Add';
+import EditIcon from '@mui/icons-material/Edit';
+import Refresh from '@mui/icons-material/Refresh';
+import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
+import { Divider, MenuItem, Theme, Typography } from '@mui/material';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+
+import MaterialTable, { ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import EditMaintenenceEntryDialog, { EditMaintenenceEntryDialogMode } from '../components/editMaintenenceEntryDialog';
+import RefreshMaintenanceEntriesDialog, { RefreshMaintenanceEntriesDialogMode } from '../components/refreshMaintenanceEntries';
+import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenanceEntriesHandler';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+import { convertToLocaleString } from '../utils/timeUtils';
+
+const styles = (theme: Theme) => createStyles({
+  button: {
+    margin: 0,
+    padding: '6px 6px',
+    minWidth: 'unset',
+  },
+  spacer: {
+    marginLeft: theme.spacing(1),
+    marginRight: theme.spacing(1),
+    display: 'inline',
+  },
+});
+
+const MaintenanceEntriesTable = MaterialTable as MaterialTableCtorType<MaintenanceEntry>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  maintenanceEntriesProperties: createmaintenanceEntriesProperties(state),
+});
+
+const mapDispatcher = (dispatcher: IDispatcher) => ({
+  maintenanceEntriesActions: createmaintenanceEntriesActions(dispatcher.dispatch),
+  onLoadMaintenanceEntries: async () => {
+    await dispatcher.dispatch(maintenanceEntriesReloadAction);
+  },
+});
+
+const emptyMaintenenceEntry: MaintenanceEntry = {
+  mId: '',
+  nodeId: '',
+  description: '',
+  start: convertToLocaleString(new Date().valueOf()),
+  end: convertToLocaleString(new Date().valueOf()),
+  active: false,
+};
+
+type MaintenanceViewComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof styles> & {};
+
+type MaintenenceViewComponentState = {
+  maintenenceEntryToEdit: MaintenanceEntry;
+  maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode;
+  refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode;
+};
+
+let initialSorted = false;
+
+class MaintenenceViewComponent extends React.Component<MaintenanceViewComponentProps, MaintenenceViewComponentState> {
+
+  constructor(props: MaintenanceViewComponentProps) {
+    super(props);
+
+    this.state = {
+      maintenenceEntryToEdit: emptyMaintenenceEntry,
+      maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
+      refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None,
+    };
+
+  }
+
+  getContextMenu(rowData: MaintenanceEntry): JSX.Element[] {
+    let buttonArray = [
+      <MenuItem aria-label={'1hr-from-now'} onClick={event => this.onOpenPlus1hEditMaintenenceEntryDialog(event, rowData)}><Typography>+1h</Typography></MenuItem>,
+      <MenuItem aria-label={'8hr-from-now'} onClick={event => this.onOpenPlus8hEditMaintenenceEntryDialog(event, rowData)}><Typography>+8h</Typography></MenuItem>,
+      <Divider />,
+      <MenuItem aria-label={'edit'} onClick={event => this.onOpenEditMaintenenceEntryDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
+      <MenuItem aria-label={'remove'} onClick={event => this.onOpenRemoveMaintenenceEntryDialog(event, rowData)}><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
+    ];
+    return buttonArray;
+  }
+
+  render() {
+    const addMaintenenceEntryAction = {
+      icon: AddIcon, tooltip: 'Add', ariaLabel:'add-element', onClick: () => {
+        const startTime = (new Date().valueOf());
+        const endTime = startTime;
+        this.setState({
+          maintenenceEntryToEdit: {
+            ...emptyMaintenenceEntry,
+            start: convertToLocaleString(startTime),
+            end: convertToLocaleString(endTime),
+          },
+          maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.AddMaintenenceEntry,
+        });
+      },
+    };
+
+    const refreshMaintenanceEntriesAction = {
+      icon: Refresh, tooltip: 'Refresh Maintenance Entries', ariaLabel: 'refresh', onClick: () => {
+        this.setState({
+          refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.RefreshMaintenanceEntriesTable,
+        });
+      },
+    };
+
+    const now = new Date().valueOf();
+    return (
+      <>
+        <MaintenanceEntriesTable stickyHeader tableId="maintenance-table" title={'Maintenance'} customActionButtons={[refreshMaintenanceEntriesAction, addMaintenenceEntryAction]} columns={
+          [
+            { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
+            {
+              property: 'notifications', title: 'Notification', width: 50, align: 'center', type: ColumnType.custom, customControl: ({ rowData }) => (
+                rowData.active && (Date.parse(rowData.start).valueOf() <= now) && (Date.parse(rowData.end).valueOf() >= now) && <FontAwesomeIcon icon={faBan} /> || null
+              ),
+            },
+            { property: 'active', title: 'Activation State', type: ColumnType.boolean, labels: { 'true': 'active', 'false': 'not active' } },
+            { property: 'start', title: 'Start Date (UTC)', type: ColumnType.text },
+            { property: 'end', title: 'End Date (UTC)', type: ColumnType.text },
+          ]
+        } idProperty={'mId'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus createContextMenu={rowData => {
+          return this.getContextMenu(rowData);
+        }} >
+        </MaintenanceEntriesTable>
+        <EditMaintenenceEntryDialog initialMaintenenceEntry={this.state.maintenenceEntryToEdit} mode={this.state.maintenanceEntryEditorMode}
+          onClose={this.onCloseEditMaintenenceEntryDialog} />
+        <RefreshMaintenanceEntriesDialog mode={this.state.refreshMaintenenceEntriesEditorMode}
+          onClose={this.onCloseRefreshMaintenenceEntryDialog} />
+      </>
+    );
+  }
+
+  public componentDidMount() {
+
+    if (!initialSorted) {
+      initialSorted = true;
+      this.props.maintenanceEntriesActions.onHandleRequestSort('node-id');
+    } else {
+      this.props.onLoadMaintenanceEntries();
+    }
+
+
+  }
+
+  private onOpenPlus1hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
+    // event.preventDefault();
+    // event.stopPropagation();
+    const startTime = (new Date().valueOf());
+    const endTime = startTime + (1 * 60 * 60 * 1000);
+    this.setState({
+      maintenenceEntryToEdit: {
+        ...entry,
+        start: convertToLocaleString(startTime),
+        end: convertToLocaleString(endTime),
+      },
+      maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry,
+    });
+  };
+
+  private onOpenPlus8hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
+    // event.preventDefault();
+    // event.stopPropagation();
+    const startTime = (new Date().valueOf());
+    const endTime = startTime + (8 * 60 * 60 * 1000);
+    this.setState({
+      maintenenceEntryToEdit: {
+        ...entry,
+        start: convertToLocaleString(startTime),
+        end: convertToLocaleString(endTime),
+      },
+      maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry,
+    });
+  };
+
+  private onOpenEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
+    // event.preventDefault();
+    // event.stopPropagation();
+    const startTime = (new Date().valueOf());
+    const endTime = startTime;
+    this.setState({
+      maintenenceEntryToEdit: {
+        ...entry,
+        ...(entry.start && endTime ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) } : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }),
+      },
+      maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry,
+    });
+  };
+
+  private onOpenRemoveMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
+    // event.preventDefault();
+    // event.stopPropagation();
+    const startTime = (new Date().valueOf());
+    const endTime = startTime;
+    this.setState({
+      maintenenceEntryToEdit: {
+        ...entry,
+        ...(entry.start && endTime ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) } : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }),
+      },
+      maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry,
+    });
+  };
+
+  private onCloseEditMaintenenceEntryDialog = () => {
+    this.setState({
+      maintenenceEntryToEdit: emptyMaintenenceEntry,
+      maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
+    });
+  };
+
+  private onCloseRefreshMaintenenceEntryDialog = () => {
+    this.setState({
+      refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None,
+    });
+  };
+}
+
+export const MaintenanceView = withStyles(styles)(connect(mapProps, mapDispatcher)(MaintenenceViewComponent));
+
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/maintenanceApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/maintenanceApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/maintenanceApp/webpack.config.js
new file mode 100644
index 0000000..845fc43
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/maintenanceApp/webpack.config.js
@@ -0,0 +1,168 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      maintenanceApp: ["./pluginMaintenance.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }, {
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+       proxy: {
+        "/oauth2/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/database/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/help/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/websocket": {
+          target: "http://10.20.6.29:48181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/.babelrc b/sdnr/wt-odlux/odlux/apps/mediatorApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/package.json b/sdnr/wt-odlux/odlux/apps/mediatorApp/package.json
new file mode 100644
index 0000000..867a879
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/package.json
@@ -0,0 +1,44 @@
+{
+  "name": "@odlux/mediator-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI to demo the mediator possible app.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/pom.xml b/sdnr/wt-odlux/odlux/apps/mediatorApp/pom.xml
new file mode 100644
index 0000000..547c91e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-mediatorApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts
new file mode 100644
index 0000000..3f56b05
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+
+import { MediatorServer } from '../models/mediatorServer';
+import { avaliableMediatorServersReloadAction } from '../handlers/avaliableMediatorServersHandler';
+import mediatorService from '../services/mediatorService';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an async thunk action that will add a server to the avaliable mediator servers. */
+export const addAvaliableMediatorServerAsyncActionCreator = (server: MediatorServer) => (dispatch: Dispatch) => {
+    mediatorService.insertMediatorServer(server).then(_ => {
+      window.setTimeout(() => {
+        dispatch(avaliableMediatorServersReloadAction);
+        dispatch(new AddSnackbarNotification({ message: `Successfully added [${ server.name }]`, options: { variant: 'success' } }));
+      }, 900);
+    });
+  };
+
+  /** Represents an async thunk action that will add a server to the avaliable mediator servers. */
+export const updateAvaliableMediatorServerAsyncActionCreator = (server: MediatorServer) => (dispatch: Dispatch) => {
+  mediatorService.updateMediatorServer(server).then(_ => {
+    window.setTimeout(() => {
+      dispatch(avaliableMediatorServersReloadAction);
+      dispatch(new AddSnackbarNotification({ message: `Successfully updated [${ server.name }]`, options: { variant: 'success' } }));
+    }, 900);
+  });
+};
+  
+  /** Represents an async thunk action that will delete a server from the avaliable mediator servers. */
+  export const removeAvaliableMediatorServerAsyncActionCreator = (server: MediatorServer) => (dispatch: Dispatch) => {
+    mediatorService.deleteMediatorServer(server).then(_ => {
+      window.setTimeout(() => {
+        dispatch(avaliableMediatorServersReloadAction);
+        dispatch(new AddSnackbarNotification({ message: `Successfully removed [${ server.name }]`, options: { variant: 'success' } }));
+      }, 900);
+    });
+  };
+  
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts
new file mode 100644
index 0000000..516515a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts
@@ -0,0 +1,154 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import mediatorService from '../services/mediatorService';
+import { MediatorConfig, MediatorConfigResponse } from '../models/mediatorServer';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+export class SetMediatorBusyByName extends BaseAction {
+  constructor(public name: string, public isBusy: boolean) {
+    super();
+  }
+}
+
+export class AddMediatorConfig extends BaseAction {
+  constructor(public mediatorConfig: MediatorConfigResponse) {
+    super();
+  }
+}
+
+export class UpdateMediatorConfig extends BaseAction {
+  constructor(public name: string, public mediatorConfig: MediatorConfigResponse) {
+    super();
+  }
+}
+
+export class RemoveMediatorConfig extends BaseAction {
+  constructor(public name: string) {
+    super();
+  }
+}
+
+
+export const startMediatorByNameAsyncActionCreator = (name: string) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  dispatch(new SetMediatorBusyByName(name, true));
+  const { mediator: { mediatorServerState: { id } } } = getState();
+  if (id) {
+    mediatorService.startMediatorByName(id, name).then(msg => {
+      dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+      // since there is no notification, a timeout will be need here
+      window.setTimeout(() => {
+        mediatorService.getMediatorServerConfigByName(id, name).then(config => {
+          if (config) {
+            dispatch(new UpdateMediatorConfig(name, config));
+          } else {
+            dispatch(new AddSnackbarNotification({ message: `Error: reading mediator config for ${name}.`, options: { variant: 'error' } }));
+          }
+          dispatch(new SetMediatorBusyByName(name, false));
+        });
+      }, 2100);
+    });
+  } else {
+    dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+    dispatch(new SetMediatorBusyByName(name, false));
+  }
+};
+
+export const stopMediatorByNameAsyncActionCreator = (name: string) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  dispatch(new SetMediatorBusyByName(name, true));
+  const { mediator: { mediatorServerState: { id } } } = getState();
+  if (id) {
+    mediatorService.stopMediatorByName(id, name).then(msg => {
+      dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+      // since there is no notification, a timeout will be need here
+      window.setTimeout(() => {
+        mediatorService.getMediatorServerConfigByName(id, name).then(config => {
+          if (config) {
+            dispatch(new UpdateMediatorConfig(name, config));
+          } else {
+            dispatch(new AddSnackbarNotification({ message: `Error: reading mediator config for ${name}.`, options: { variant: 'error' } }));
+          }
+          dispatch(new SetMediatorBusyByName(name, false));
+        });
+      }, 2100);
+    });
+  } else {
+    dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+    dispatch(new SetMediatorBusyByName(name, false));
+  }
+};
+
+export const addMediatorConfigAsyncActionCreator = (config: MediatorConfig) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const { Name: name } = config;
+  const { mediator: { mediatorServerState: { id } } } = getState();
+  if (id) {
+    mediatorService.createMediatorConfig(id, config).then(msg => {
+      dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+      // since there is no notification, a timeout will be need here
+      window.setTimeout(() => {
+        mediatorService.getMediatorServerConfigByName(id, name).then(config => {
+          if (config) {
+            dispatch(new AddMediatorConfig(config));
+          } else {
+            dispatch(new AddSnackbarNotification({ message: `Error: reading mediator config for ${name}.`, options: { variant: 'error' } }));
+          }
+        });
+      }, 2100);
+    });
+  } else {
+    dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+  }
+};
+
+export const updateMediatorConfigAsyncActionCreator = (config: MediatorConfig) => (dispatch: Dispatch) => {
+  // currently not supported be backend
+};
+
+export const removeMediatorConfigAsyncActionCreator = (config: MediatorConfig) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+  const { Name: name } = config;
+  const { mediator: { mediatorServerState: { id } } } = getState();
+  if (id) {
+    mediatorService.deleteMediatorConfigByName(id, name).then(msg => {
+      dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+      // since there is no notification, a timeout will be need here
+      window.setTimeout(() => {
+        mediatorService.getMediatorServerConfigByName(id, config.Name).then(config => {
+          if (!config) {
+            dispatch(new RemoveMediatorConfig(name));
+          } else {
+            dispatch(new AddSnackbarNotification({ message: `Error: deleting mediator config for ${name}.`, options: { variant: 'error' } }));
+          }
+        });
+      }, 2100);
+    });
+  } else {
+    dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+    dispatch(new SetMediatorBusyByName(name, false));
+  }
+};
+
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts
new file mode 100644
index 0000000..79e46df
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts
@@ -0,0 +1,114 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { MediatorServerVersionInfo, MediatorConfig, MediatorConfigResponse, MediatorServerDevice } from '../models/mediatorServer';
+import mediatorService from '../services/mediatorService';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+export class SetMediatorServerBusy extends BaseAction {
+  constructor(public isBusy: boolean) {
+    super();
+  }
+}
+
+export class SetMediatorServerInfo extends BaseAction {
+  /**
+   * Initializes a new instance of this class.
+   */
+  constructor(public id: string | null, public name: string | null, public url: string | null) {
+    super();
+
+  }
+}
+
+export class SetMediatorServerVersion extends BaseAction {
+  /**
+   * Initializes a new instance of this class.
+   */
+  constructor(public versionInfo: MediatorServerVersionInfo | null) {
+    super();
+
+  }
+}
+
+export class SetAllMediatorServerConfigurations extends BaseAction {
+  /**
+   * Initializes a new instance of this class.
+   */
+  constructor(public allConfigurations: MediatorConfigResponse[] | null) {
+    super();
+
+  }
+}
+
+export class SetMediatorServerSupportedDevices extends BaseAction {
+  /**
+   * Initializes a new instance of this class.
+   */
+  constructor(public devices: MediatorServerDevice[] | null) {
+    super();
+
+  }
+}
+
+export class SetMediatorServerReachable extends BaseAction {
+  constructor(public isReachable: boolean) {
+    super();
+  }
+}
+
+export const initializeMediatorServerAsyncActionCreator = (serverId: string) => (dispatch: Dispatch) => {
+  dispatch(new SetMediatorServerBusy(true));
+  mediatorService.getMediatorServerById(serverId).then(mediatorServer => {
+    if (!mediatorServer) {
+      dispatch(new SetMediatorServerBusy(false));
+      dispatch(new AddSnackbarNotification({ message: `Error loading mediator server [${serverId}]`, options: { variant: 'error' } }));
+      dispatch(new NavigateToApplication("mediator"));
+      return;
+    }
+
+    dispatch(new SetMediatorServerInfo(mediatorServer.id, mediatorServer.name, mediatorServer.url));
+
+    Promise.all([
+      mediatorService.getMediatorServerAllConfigs(mediatorServer.id),
+      mediatorService.getMediatorServerSupportedDevices(mediatorServer.id),
+      mediatorService.getMediatorServerVersion(mediatorServer.id)
+    ]).then(([configurations, supportedDevices, versionInfo]) => {
+      if (configurations === null && supportedDevices === null && versionInfo === null) {
+        dispatch(new SetMediatorServerReachable(false));
+      } else {
+        dispatch(new SetMediatorServerReachable(true));
+      }
+      dispatch(new SetAllMediatorServerConfigurations(configurations));
+      dispatch(new SetMediatorServerSupportedDevices(supportedDevices));
+      dispatch(new SetMediatorServerVersion(versionInfo));
+      dispatch(new SetMediatorServerBusy(false));
+    }).catch(error => {
+      dispatch(new SetMediatorServerReachable(false));
+      dispatch(new SetMediatorServerBusy(false));
+    });
+  });
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/assets/icons/mediatorAppIcon.svg b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/assets/icons/mediatorAppIcon.svg
new file mode 100644
index 0000000..b819aa6
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/assets/icons/mediatorAppIcon.svg
@@ -0,0 +1,49 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 980 980">
+
+<g transform="translate(0.000000,890.000000) scale(0.100000,-0.100000)">
+
+<path fill="#36A9E1" d="M4704 7791 c-314 -180 -1992 -1183 -1993 -1191 -2 -12 2183 -1311
+2198 -1307 20 5 1595 947 1856 1109 198 123 295 193 295 210 0 7 -22 26 -48
+42 -352 217 -2060 1224 -2103 1241 -9 3 -94 -40 -205 -104z"/>
+
+<path fill="#36A9E1" d="M2530 5147 l0 -1144 1098 -731 1097 -732 3 1217 c2 966 -1 1220 -10
+1229 -19 17 -2169 1304 -2179 1304 -5 0 -9 -475 -9 -1143z"/>
+
+<path fill="#36A9E1" d="M6163 5638 l-1093 -653 0 -1232 c0 -678 2 -1233 4 -1233 8 0 2161
+1293 2179 1308 16 14 17 62 16 761 -1 410 -5 961 -8 1224 l-6 477 -1092 -652z"/>
+
+<path fill="#565656" d="M7598 4488 c-3 -626 -6 -800 -17 -825 -16 -39 -136 -122 -486 -337
+-132 -81 -249 -154 -260 -162 -20 -15 -19 -16 20 -50 44 -39 414 -264 517
+-315 l66 -32 109 63 c107 62 414 243 838 493 383 226 1199 715 1219 730 19 14
+16 17 -50 59 -97 62 -1941 1168 -1948 1168 -3 0 -6 -357 -8 -792z"/>
+
+<path fill="#565656" d="M1280 4736 c-1071 -644 -1095 -659 -1093 -671 0 -5 492 -303 1092
+-661 l1091 -653 400 197 c219 108 399 199 399 202 0 3 -102 73 -226 155 -333
+220 -653 442 -691 479 -24 24 -35 45 -42 86 -6 30 -13 358 -16 728 -5 477 -10
+672 -18 671 -6 0 -409 -240 -896 -533z"/>
+
+<path fill="#565656" d="M0 2612 l0 -1149 872 -578 c1051 -697 1292 -855 1307 -855 8 0 11
+333 11 1213 l0 1212 -1063 637 c-584 350 -1077 643 -1094 652 l-33 17 0 -1149z"/>
+
+<path fill="#565656" d="M9380 3514 c-217 -129 -704 -420 -1082 -647 l-688 -412 0 -1228 0
+-1228 28 15 c56 29 810 476 1692 1003 l465 278 3 1228 c2 978 0 1227 -10 1227
+-7 0 -191 -106 -408 -236z"/>
+
+<path fill="#565656" d="M3019 2685 l-484 -243 2 -1124 c2 -1073 6 -1308 22 -1308 11 0 1943
+1147 2134 1267 l37 23 0 413 0 412 -378 250 c-331 219 -807 530 -838 548 -6 3
+-229 -103 -495 -238z"/>
+
+<path fill="#565656" d="M6249 2821 c-101 -60 -407 -244 -679 -408 l-495 -299 0 -409 0 -410
+440 -263 c1265 -755 1717 -1022 1733 -1022 9 0 12 292 12 1218 0 669 -4 1222
+-8 1228 -13 19 -788 474 -808 474 -6 0 -93 -49 -195 -109z"/>
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx
new file mode 100644
index 0000000..34ffc5e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx
@@ -0,0 +1,399 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { Theme, Typography, FormControlLabel, Checkbox } from '@mui/material';
+
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+import Select from '@mui/material/Select';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import Tabs from '@mui/material/Tabs';
+import Tab from '@mui/material/Tab';
+
+import Fab from '@mui/material/Fab';
+import AddIcon from '@mui/icons-material/Add';
+import DeleteIcon from '@mui/icons-material/Delete';
+import IconButton from '@mui/material/IconButton';
+
+import { addMediatorConfigAsyncActionCreator, updateMediatorConfigAsyncActionCreator, removeMediatorConfigAsyncActionCreator } from '../actions/mediatorConfigActions';
+import { MediatorConfig, ODLConfig } from '../models/mediatorServer';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+import MenuItem from '@mui/material/MenuItem';
+
+import { Panel } from '../../../../framework/src/components/material-ui/panel';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    display: 'flex',
+    flexDirection: 'column',
+    flex: '1',
+  },
+  fab: {
+    position: 'absolute',
+    bottom: theme.spacing(1),
+    right: theme.spacing(1),
+  },
+  title: {
+    fontSize: 14,
+  },
+  center: {
+    flex: "1",
+    display: "flex",
+    alignItems: "center",
+    justifyContent: "center",
+  },
+  alignInOneLine: {
+    display: 'flex',
+    flexDirection: 'row'
+  },
+  left: {
+    marginRight: theme.spacing(1),
+  },
+  right: {
+    marginLeft: 0,
+  }
+});
+
+const TabContainer: React.SFC = ({ children }) => {
+  return (
+    <div style={{ width: "430px", height: "530px", position: "relative", display: 'flex', flexDirection: 'column' }}>
+      {children}
+    </div>
+  );
+}
+
+export enum EditMediatorConfigDialogMode {
+  None = "none",
+  AddMediatorConfig = "addMediatorConfig",
+  EditMediatorConfig = "editMediatorConfig",
+  RemoveMediatorConfig = "removeMediatorConfig",
+}
+
+const mapProps = (state: IApplicationStoreState) => ({
+  supportedDevices: state.mediator.mediatorServerState.supportedDevices
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  addMediatorConfig: (config: MediatorConfig) => {
+    dispatcher.dispatch(addMediatorConfigAsyncActionCreator(config));
+  },
+  updateMediatorConfig: (config: MediatorConfig) => {
+    dispatcher.dispatch(updateMediatorConfigAsyncActionCreator(config));
+  },
+  removeMediatorConfig: (config: MediatorConfig) => {
+    dispatcher.dispatch(removeMediatorConfigAsyncActionCreator(config));
+  },
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  readonly: boolean;
+  readonlyName: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [EditMediatorConfigDialogMode.None]: {
+    dialogTitle: "",
+    dialogDescription: "",
+    applyButtonText: "",
+    cancelButtonText: "",
+    readonly: true,
+    readonlyName: true,
+  },
+  [EditMediatorConfigDialogMode.AddMediatorConfig]: {
+    dialogTitle: "Add Mediator Configuration",
+    dialogDescription: "",
+    applyButtonText: "Add",
+    cancelButtonText: "Cancel",
+    readonly: false,
+    readonlyName: false,
+  },
+  [EditMediatorConfigDialogMode.EditMediatorConfig]: {
+    dialogTitle: "Edit Mediator Configuration",
+    dialogDescription: "",
+    applyButtonText: "Update",
+    cancelButtonText: "Cancel",
+    readonly: false,
+    readonlyName: true,
+  },
+  [EditMediatorConfigDialogMode.RemoveMediatorConfig]: {
+    dialogTitle: "Remove Mediator Configuration",
+    dialogDescription: "",
+    applyButtonText: "Remove",
+    cancelButtonText: "Cancel",
+    readonly: true,
+    readonlyName: true,
+  },
+};
+
+type EditMediatorConfigDialogComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch> & {
+  mode: EditMediatorConfigDialogMode;
+  mediatorConfig: MediatorConfig;
+  onClose: () => void;
+};
+
+type EditMediatorConfigDialogComponentState = MediatorConfig & { activeTab: number; activeOdlConfig: string, forceAddOdlConfig: boolean, isOdlConfigHostnameEmpty: boolean };
+
+class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConfigDialogComponentProps, EditMediatorConfigDialogComponentState> {
+  constructor(props: EditMediatorConfigDialogComponentProps) {
+    super(props);
+
+    this.state = {
+      ...this.props.mediatorConfig,
+      activeTab: 0,
+      activeOdlConfig: "",
+      forceAddOdlConfig: false,
+      isOdlConfigHostnameEmpty: false
+    };
+  }
+
+  private odlConfigValueChangeHandlerCreator = <THtmlElement extends HTMLElement, TKey extends keyof ODLConfig>(index: number, property: TKey, mapValue: (event: React.ChangeEvent<THtmlElement>) => any) => (event: React.ChangeEvent<THtmlElement>) => {
+    event.stopPropagation();
+    event.preventDefault();
+    this.setState({
+      ODLConfig: [
+        ...this.state.ODLConfig.slice(0, index),
+        { ...this.state.ODLConfig[index], [property]: mapValue(event) },
+        ...this.state.ODLConfig.slice(index + 1)
+      ]
+    });
+  }
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    const { classes } = this.props;
+    return (
+      <Dialog open={this.props.mode !== EditMediatorConfigDialogMode.None}>
+        <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+          <Tabs value={this.state.activeTab} indicatorColor="secondary" textColor="secondary" onChange={(event, value) => this.setState({ activeTab: value })} >
+            <Tab label="Config" />
+            <Tab label="ODL AutoConnect" />
+          </Tabs>
+          {this.state.activeTab === 0 ? <TabContainer >
+            <TextField variant="standard" disabled={setting.readonly || setting.readonlyName} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.Name} onChange={(event) => { this.setState({ Name: event.target.value }); }} />
+            <FormControl variant="standard" fullWidth disabled={setting.readonly}>
+              <InputLabel htmlFor="deviceType">Device</InputLabel>
+              <Select variant="standard" value={this.state.DeviceType} onChange={(event, value) => {
+                const device = this.props.supportedDevices.find(device => device.id === event.target.value);
+                if (device) {
+                  this.setState({
+                    DeviceType: device.id,
+                    NeXMLFile: device.xml
+                  });
+                } else {
+                  this.setState({
+                    DeviceType: -1,
+                    NeXMLFile: ""
+                  });
+                }
+              }} inputProps={{ name: 'deviceType', id: 'deviceType' }} fullWidth >
+                <MenuItem value={-1}><em>None</em></MenuItem>
+                {this.props.supportedDevices.map(device => (<MenuItem key={device.id} value={device.id} >{`${device.vendor} - ${device.device} (${device.version || '0.0.0'}) `}</MenuItem>))}
+              </Select>
+            </FormControl>
+            <TextField variant="standard" disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ipAddress" label="Device IP" type="text" fullWidth value={this.state.DeviceIp} onChange={(event) => { this.setState({ DeviceIp: event.target.value }); }} />
+            <TextField variant="standard" disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="devicePort" label="Device SNMP Port" type="number" fullWidth value={this.state.DevicePort || ""} onChange={(event) => { this.setState({ DevicePort: +event.target.value }); }} />
+            <TextField variant="standard" disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="trapsPort" label="TrapsPort" type="number" fullWidth value={this.state.TrapPort || ""} onChange={(event) => { this.setState({ TrapPort: +event.target.value }); }} />
+            <TextField variant="standard" disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ncUser" label="Netconf User" type="text" fullWidth value={this.state.NcUsername} onChange={(event) => { this.setState({ NcUsername: event.target.value }); }} />
+            <TextField variant="standard" disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ncPassword" label="Netconf Password" type="password" fullWidth value={this.state.NcPassword} onChange={(event) => { this.setState({ NcPassword: event.target.value }); }} />
+            <TextField variant="standard" disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ncPort" label="Netconf Port" type="number" fullWidth value={this.state.NcPort || ""} onChange={(event) => { this.setState({ NcPort: +event.target.value }); }} />
+          </TabContainer> : null}
+          {this.state.activeTab === 1 ? <TabContainer >
+            {this.state.ODLConfig && this.state.ODLConfig.length > 0
+              ? this.state.ODLConfig.map((cfg, ind) => {
+                const panelId = `panel-${ind}`;
+                const deleteButton = (<IconButton
+                  onClick={() => {
+                    this.setState({
+                      ODLConfig: [
+                        ...this.state.ODLConfig.slice(0, ind),
+                        ...this.state.ODLConfig.slice(ind + 1)
+                      ]
+                    });
+                  }}
+                  size="large"><DeleteIcon /></IconButton>)
+                return (
+                  <Panel title={cfg.Server && `${cfg.User ? `${cfg.User}@` : ''}${cfg.Protocol}://${cfg.Server}:${cfg.Port}` || "new odl config"} key={panelId} panelId={panelId} activePanel={this.state.activeOdlConfig} customActionButtons={[deleteButton]}
+                    onToggle={(id) => { this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") }); console.log("activeOdlConfig " + id); this.hideHostnameErrormessage(id) }} >
+                    <div className={classes.alignInOneLine}>
+                      <FormControl variant="standard" className={classes.left} margin={"dense"} >
+                        <InputLabel htmlFor={`protocol-${ind}`}>Protocoll</InputLabel>
+                        <Select variant="standard"  value={cfg.Protocol} onChange={(e, v) => this.odlConfigValueChangeHandlerCreator(ind, "Protocol", e => v)} inputProps={{ name: `protocol-${ind}`, id: `protocol-${ind}` }} fullWidth >
+                          <MenuItem value={"http"}>http</MenuItem>
+                          <MenuItem value={"https"}>https</MenuItem>
+                        </Select>
+                      </FormControl>
+                      <TextField variant="standard" className={classes.left} spellCheck={false} margin="dense" id="hostname" label="Hostname" type="text" value={cfg.Server} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Server", e => e.target.value)} />
+                      <TextField variant="standard" className={classes.right} style={{ maxWidth: "65px" }} spellCheck={false} margin="dense" id="port" label="Port" type="number" value={cfg.Port || ""} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Port", e => +e.target.value)} />
+                    </div>
+                    {
+                      this.state.isOdlConfigHostnameEmpty &&
+                      <Typography component={"div"} className={classes.left} color="error" gutterBottom>Please add a hostname.</Typography>
+                    }
+                    <div className={classes.alignInOneLine}>
+                      <TextField variant="standard" className={classes.left} spellCheck={false} margin="dense" id="username" label="Username" type="text" value={cfg.User} onChange={this.odlConfigValueChangeHandlerCreator(ind, "User", e => e.target.value)} />
+                      <TextField variant="standard" className={classes.right} spellCheck={false} margin="dense" id="password" label="Password" type="password" value={cfg.Password} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Password", e => e.target.value)} />
+                    </div>
+                    <div className={classes.alignInOneLine}>
+                      <FormControlLabel className={classes.right} control={<Checkbox checked={cfg.Trustall} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Trustall", e => e.target.checked)} />} label="Trustall" />
+                    </div>
+                  </Panel>
+                );
+              })
+              : (this.state.forceAddOdlConfig ?
+                <div className={classes.center} >
+                  <Typography component={"div"} className={classes.title} color="error" gutterBottom>Please add at least one ODL auto connect configuration.</Typography>
+                </div>
+                :
+                <div className={classes.center} >
+                  <Typography component={"div"} className={classes.title} color="textSecondary" gutterBottom>Please add an ODL auto connect configuration.</Typography>
+                </div>
+              )
+            }
+            <Fab className={classes.fab} color="primary" aria-label="Add" onClick={() => this.setState({
+              ODLConfig: [...this.state.ODLConfig, { Server: '', Port: 8181, Protocol: 'https', User: 'admin', Password: 'admin', Trustall: false }]
+            })} > <AddIcon /> </Fab>
+
+          </TabContainer> : null}
+
+        </DialogContent>
+        <DialogActions>
+          <Button color="inherit" onClick={(event) => { this.addConfig(event) }} > {setting.applyButtonText} </Button>
+          <Button onClick={(event) => {
+            this.onCancel();
+            event.preventDefault();
+            event.stopPropagation();
+            this.resetPanel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private addConfig = (event: any) => {
+    event.preventDefault();
+    event.stopPropagation();
+
+    if (this.state.ODLConfig.length === 0) {
+      this.setState({ activeTab: 1, forceAddOdlConfig: true });
+    }
+    else
+      if (this.state.ODLConfig.length > 0) {
+        for (let i = 0; i <= this.state.ODLConfig.length; i++) {
+          if (this.isHostnameEmpty(i)) {
+            this.setState({ activeOdlConfig: 'panel-' + i })
+            this.setState({ isOdlConfigHostnameEmpty: true })
+            return;
+          }
+        }
+
+        this.onApply(Object.keys(this.state).reduce<MediatorConfig & { [kex: string]: any }>((acc, key) => {
+          // do not copy additional state properties
+          if (key !== "activeTab" && key !== "activeOdlConfig" && key !== "isOdlConfigHostnameEmpty"
+            && key !== "forceAddOdlConfig" && key !== "_initialMediatorConfig") acc[key] = (this.state as any)[key];
+          return acc;
+        }, {} as MediatorConfig));
+        this.resetPanel();
+      }
+  }
+
+  private resetPanel = () => {
+    this.setState({ forceAddOdlConfig: false, isOdlConfigHostnameEmpty: false, activeTab: 0 });
+  }
+
+
+  private hideHostnameErrormessage = (panelId: string | null) => {
+
+    if (panelId) {
+      let id = Number(panelId.split('-')[1]);
+      if (!this.isHostnameEmpty(id)) {
+        this.setState({ isOdlConfigHostnameEmpty: false })
+      }
+    }
+  }
+
+  private isHostnameEmpty = (id: number) => {
+
+    const element = this.state.ODLConfig[id];
+    if (element) {
+      if (!element.Server) {
+        return true;
+      }
+      else {
+        return false
+      }
+
+    } else {
+      return null;
+    }
+  }
+
+  private onApply = (config: MediatorConfig) => {
+    this.props.onClose && this.props.onClose();
+    switch (this.props.mode) {
+      case EditMediatorConfigDialogMode.AddMediatorConfig:
+        config && this.props.addMediatorConfig(config);
+        break;
+      case EditMediatorConfigDialogMode.EditMediatorConfig:
+        config && this.props.updateMediatorConfig(config);
+        break;
+      case EditMediatorConfigDialogMode.RemoveMediatorConfig:
+        config && this.props.removeMediatorConfig(config);
+        break;
+    }
+  };
+
+  private onCancel = () => {
+    this.props.onClose && this.props.onClose();
+  }
+
+  static getDerivedStateFromProps(props: EditMediatorConfigDialogComponentProps, state: EditMediatorConfigDialogComponentState & { _initialMediatorConfig: MediatorConfig }): EditMediatorConfigDialogComponentState & { _initialMediatorConfig: MediatorConfig } {
+    if (props.mediatorConfig !== state._initialMediatorConfig) {
+      state = {
+        ...state,
+        ...props.mediatorConfig,
+        _initialMediatorConfig: props.mediatorConfig,
+      };
+    }
+    return state;
+  }
+}
+
+export const EditMediatorConfigDialog = withStyles(styles)(connect(mapProps, mapDispatch)(EditMediatorConfigDialogComponent));
+export default EditMediatorConfigDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
new file mode 100644
index 0000000..c8b1587
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
@@ -0,0 +1,221 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { addAvaliableMediatorServerAsyncActionCreator, removeAvaliableMediatorServerAsyncActionCreator, updateAvaliableMediatorServerAsyncActionCreator } from '../actions/avaliableMediatorServersActions';
+import { MediatorServer } from '../models/mediatorServer';
+import { Typography } from '@mui/material';
+
+export enum EditMediatorServerDialogMode {
+  None = "none",
+  AddMediatorServer = "addMediatorServer",
+  EditMediatorServer = "editMediatorServer",
+  RemoveMediatorServer = "removeMediatorServer",
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  addMediatorServer: (element: MediatorServer) => {
+    dispatcher.dispatch(addAvaliableMediatorServerAsyncActionCreator(element));
+  },
+  updateMediatorServer: (element: MediatorServer) => {
+    dispatcher.dispatch(updateAvaliableMediatorServerAsyncActionCreator(element));
+  },
+  removeMediatorServer: (element: MediatorServer) => {
+    dispatcher.dispatch(removeAvaliableMediatorServerAsyncActionCreator(element));
+  },
+});
+
+type DialogSettings = {
+  dialogTitle: string;
+  dialogDescription: string;
+  applyButtonText: string;
+  cancelButtonText: string;
+  readonly: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+  [EditMediatorServerDialogMode.None]: {
+    dialogTitle: "",
+    dialogDescription: "",
+    applyButtonText: "",
+    cancelButtonText: "",
+    readonly: true,
+  },
+  [EditMediatorServerDialogMode.AddMediatorServer]: {
+    dialogTitle: "Add Mediator Server",
+    dialogDescription: "",
+    applyButtonText: "Add",
+    cancelButtonText: "Cancel",
+    readonly: false,
+  },
+  [EditMediatorServerDialogMode.EditMediatorServer]: {
+    dialogTitle: "Edit Mediator Server",
+    dialogDescription: "",
+    applyButtonText: "Update",
+    cancelButtonText: "Cancel",
+    readonly: false,
+  },
+  [EditMediatorServerDialogMode.RemoveMediatorServer]: {
+    dialogTitle: "Remove Mediator Server",
+    dialogDescription: "",
+    applyButtonText: "Remove",
+    cancelButtonText: "Cancel",
+    readonly: true,
+  },
+};
+
+type EditMediatorServerDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: EditMediatorServerDialogMode;
+  mediatorServer: MediatorServer;
+  onClose: () => void;
+};
+
+const urlRegex = RegExp("^https?://");
+
+type EditMediatorServerDialogComponentState = MediatorServer & { errorMessage: string[] };
+
+class EditMediatorServerDialogComponent extends React.Component<EditMediatorServerDialogComponentProps, EditMediatorServerDialogComponentState> {
+  constructor(props: EditMediatorServerDialogComponentProps) {
+    super(props);
+
+    this.state = {
+      ...this.props.mediatorServer,
+      errorMessage: []
+    };
+  }
+
+  areFieldsValid = () => {
+    return this.state.name.trim().length > 0 && this.state.url.trim().length > 0 && urlRegex.test(this.state.url);
+  }
+
+  createErrorMessages = () => {
+
+    let messages = [];
+    if (this.state.name.trim().length === 0 && this.state.url.trim().length === 0) {
+      messages.push("The server name and the url must not be empty.")
+    }
+    else
+      if (this.state.url.trim().length === 0) {
+        messages.push("The server url must not be empty.")
+
+      } else if (this.state.name.trim().length === 0) {
+        messages.push("The server name must not be empty.")
+      }
+
+    if (!urlRegex.test(this.state.url)) {
+      if (messages.length > 0) {
+        return messages.concat(["The server url must start with 'http(s)://'."])
+      } else {
+        return ["The server url must start with 'http(s)://'."]
+      }
+    }
+
+    return messages;
+  }
+
+
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+
+    return (
+      <Dialog open={this.props.mode !== EditMediatorServerDialogMode.None}>
+        <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+          {/* <TextField disabled spellCheck={false} autoFocus margin="dense" id="id" label="Id" type="text" fullWidth value={ this.state._id } onChange={(event)=>{ this.setState({_id: event.target.value}); } } /> */}
+          <TextField variant="standard" disabled={setting.readonly} spellCheck={false} margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.name} onChange={(event) => { this.setState({ name: event.target.value }); }} />
+          <TextField variant="standard" disabled={setting.readonly} spellCheck={false} margin="dense" id="url" label="Url" type="text" fullWidth value={this.state.url} onChange={(event) => { this.setState({ url: event.target.value }); }} />
+
+          <Typography id="errorMessage" component={"div"} color="error">{this.state.errorMessage.map((error, index) => <div key={index}>{error}</div>)}</Typography>
+
+        </DialogContent>
+        <DialogActions>
+          <Button onClick={(event) => {
+
+            if (this.areFieldsValid()) {
+              this.setState({ errorMessage: [] });
+              this.onApply({
+                id: this.state.id,
+                name: this.state.name,
+                url: this.state.url
+              });
+            } else {
+              const errorMessage = this.createErrorMessages()
+              this.setState({ errorMessage: errorMessage })
+            }
+
+            event.preventDefault();
+            event.stopPropagation();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button onClick={(event) => {
+            this.onCancel();
+            this.setState({ errorMessage: [] });
+            event.preventDefault();
+            event.stopPropagation();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    )
+  }
+
+  private onApply = (element: MediatorServer) => {
+    this.props.onClose && this.props.onClose();
+    switch (this.props.mode) {
+      case EditMediatorServerDialogMode.AddMediatorServer:
+        element && this.props.addMediatorServer(element);
+        break;
+      case EditMediatorServerDialogMode.EditMediatorServer:
+        element && this.props.updateMediatorServer(element);
+        break;
+      case EditMediatorServerDialogMode.RemoveMediatorServer:
+        element && this.props.removeMediatorServer(element);
+        break;
+    }
+  };
+
+  private onCancel = () => {
+    this.props.onClose && this.props.onClose();
+  }
+
+  static getDerivedStateFromProps(props: EditMediatorServerDialogComponentProps, state: EditMediatorServerDialogComponentState & { _initialMediatorServer: MediatorServer }): EditMediatorServerDialogComponentState & { _initialMediatorServer: MediatorServer } {
+    if (props.mediatorServer !== state._initialMediatorServer) {
+      state = {
+        ...state,
+        ...props.mediatorServer,
+        _initialMediatorServer: props.mediatorServer,
+      };
+    }
+    return state;
+  }
+}
+
+export const EditMediatorServerDialog = connect(undefined, mapDispatch)(EditMediatorServerDialogComponent);
+export default EditMediatorServerDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/refreshMediatorDialog.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/refreshMediatorDialog.tsx
new file mode 100644
index 0000000..db1ef87
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/refreshMediatorDialog.tsx
@@ -0,0 +1,117 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { avaliableMediatorServersReloadAction } from '../handlers/avaliableMediatorServersHandler';
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { MediatorServer } from '../models/mediatorServer';
+
+export enum RefreshMediatorDialogMode {
+  None = "none",
+  RefreshMediatorTable = "RefreshMediatorTable",
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  refreshMediator: () => dispatcher.dispatch(avaliableMediatorServersReloadAction)
+});
+
+type DialogSettings = {
+  dialogTitle: string,
+  dialogDescription: string,
+  applyButtonText: string,
+  cancelButtonText: string,
+  enableMountIdEditor: boolean,
+  enableUsernameEditor: boolean,
+  enableExtendedEditor: boolean,
+}
+
+const settings: { [key: string]: DialogSettings } = {
+  [RefreshMediatorDialogMode.None]: {
+    dialogTitle: "",
+    dialogDescription: "",
+    applyButtonText: "",
+    cancelButtonText: "",
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [RefreshMediatorDialogMode.RefreshMediatorTable]: {
+    dialogTitle: "Do you want to refresh the Mediator table?",
+    dialogDescription: "",
+    applyButtonText: "Yes",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  }
+}
+
+type RefreshMediatorDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+  mode: RefreshMediatorDialogMode;
+  onClose: () => void;
+};
+
+type RefreshMediatorDialogComponentState = MediatorServer & { isNameValid: boolean, isHostSet: boolean };
+
+class RefreshMediatorDialogComponent extends React.Component<RefreshMediatorDialogComponentProps, RefreshMediatorDialogComponentState> {
+  constructor(props: RefreshMediatorDialogComponentProps) {
+    super(props);
+  }
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={this.props.mode !== RefreshMediatorDialogMode.None}>
+        <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            {setting.dialogDescription}
+          </DialogContentText>
+        </DialogContent>
+        <DialogActions>
+          <Button aria-label="dialog-confirm-button" onClick={(event) => {
+            this.onRefresh();
+          }} color="inherit" > {setting.applyButtonText} </Button>
+          <Button aria-label="dialog-cancel-button" onClick={(event) => {
+            this.onCancel();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    );
+  }
+
+  private onRefresh = () => {
+    this.props.refreshMediator();
+    this.props.onClose();
+  };
+
+  private onCancel = () => {
+    this.props.onClose();
+  }
+}
+
+export const RefreshMediatorDialog = connect(undefined, mapDispatch)(RefreshMediatorDialogComponent);
+export default RefreshMediatorDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
new file mode 100644
index 0000000..f8691ab
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react'
+import { Dialog, DialogTitle, DialogContent, DialogActions, TextField, DialogContentText, Checkbox, Button, FormControlLabel, FormGroup } from '@mui/material';
+import { IApplicationState } from '../../../../framework/src/handlers/applicationStateHandler';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+import { MediatorConfigResponse } from '../models/mediatorServer';
+import { Panel } from '../../../../framework/src/components/material-ui/panel';
+
+export enum MediatorInfoDialogMode {
+    None = "none",
+    ShowDetails = "showDetails"
+}
+
+const mapProps = (state: IApplicationStoreState) => ({ supportedDevices: state.mediator.mediatorServerState.supportedDevices })
+
+type ShowMediatorInfoDialogComponentProps = Connect<typeof mapProps, undefined> &
+{
+    config: MediatorConfigResponse,
+    mode: MediatorInfoDialogMode,
+    onClose: () => void
+}
+
+type ShowMediatorInfoDialogComponentState = {
+    status: string,
+    devicetype: string,
+    activeOdlConfig: string
+}
+
+/*
+Displays all values of a mediator server 
+*/
+class ShowMediatorInfoDialogComponent extends React.Component<ShowMediatorInfoDialogComponentProps, ShowMediatorInfoDialogComponentState> {
+
+    constructor(props: ShowMediatorInfoDialogComponentProps) {
+        super(props);
+        if (this.props.config) {
+            let deviceType = props.supportedDevices.find(element => element.id === this.props.config.DeviceType)
+
+            this.state = {
+                status: props.config.pid > 0 ? "Running" : "Stopped",
+                devicetype: deviceType != undefined ? deviceType.device : 'none',
+                activeOdlConfig: ''
+            }
+        }
+    }
+
+    onClose = (event: React.MouseEvent) => {
+        event.preventDefault();
+        event.stopPropagation();
+        this.props.onClose();
+    }
+
+    render() {
+        return (
+            <Dialog open={this.props.mode !== MediatorInfoDialogMode.None} onBackdropClick={this.props.onClose} >
+                <DialogTitle>{this.props.config.Name}</DialogTitle>
+                <DialogContent>
+                    <TextField variant="standard" disabled margin="dense" id="deviceIp" label="Device IP" fullWidth defaultValue={this.props.config.DeviceIp} />
+                    <TextField variant="standard" disabled margin="dense" id="deviceport" label="Device Port" fullWidth defaultValue={this.props.config.DevicePort} />
+                    <TextField variant="standard" disabled margin="dense" id="status" label="Status" fullWidth defaultValue={this.state.status} />
+                    <TextField variant="standard" disabled margin="dense" id="deviceType" label="Device Type" fullWidth defaultValue={this.state.devicetype} />
+                    <TextField variant="standard" disabled margin="dense" id="ncPort" label="Netconf Port" fullWidth defaultValue={this.props.config.NcPort} />
+                    <FormGroup>
+                        <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.IsNCConnected}></Checkbox>} label="Netconf Connection" />
+                        <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.IsNeConnected}></Checkbox>} label="Network Element Connection" />
+                        <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.fwactive}></Checkbox>} label="Firewall active" />
+                    </FormGroup>
+                    {
+                        this.props.config.ODLConfig.map((element, index) =>
+                            <Panel title={"ODL config " + (this.props.config.ODLConfig.length > 1 ? index + 1 : '')} key={index} panelId={'panel-' + index} activePanel={this.state.activeOdlConfig} onToggle={(id: string) => { this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") }); }}>
+                                <TextField variant="standard" disabled margin="dense" defaultValue={element.Protocol + '://' + element.Server} label="Server" />
+                                <TextField variant="standard" disabled margin="dense" defaultValue={element.Port} label="Port" />
+                                <FormControlLabel control={<Checkbox disabled checked={element.Trustall} />} label="Trustall" />
+                            </Panel>
+                        )
+                    }
+
+                </DialogContent>
+                <DialogActions>
+                    <Button onClick={this.onClose} color="inherit">Close</Button>
+                </DialogActions>
+            </Dialog>
+        )
+    }
+
+}
+
+export const ShowMediatorInfoDialog = connect(mapProps)(ShowMediatorInfoDialogComponent)
+export default ShowMediatorInfoDialog;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts
new file mode 100644
index 0000000..c22252d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { MediatorServer } from '../models/mediatorServer';
+import { mediatorServerResourcePath } from '../services/mediatorService';
+
+export interface IAvaliableMediatorServersState extends IExternalTableState<MediatorServer> { }
+
+// create eleactic search material data fetch handler
+const avaliableMediatorServersSearchHandler = createSearchDataHandler<MediatorServer>(mediatorServerResourcePath);
+
+export const {
+  actionHandler: avaliableMediatorServersActionHandler,
+  createActions: createAvaliableMediatorServersActions,
+  createProperties: createAvaliableMediatorServersProperties,
+  reloadAction: avaliableMediatorServersReloadAction,
+
+  // set value action, to change a value
+} = createExternal<MediatorServer>(avaliableMediatorServersSearchHandler, appState => appState.mediator.avaliableMediatorServers);
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts
new file mode 100644
index 0000000..2642ec8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { IAvaliableMediatorServersState, avaliableMediatorServersActionHandler } from './avaliableMediatorServersHandler' ;
+import { MediatorServerState, mediatorServerHandler } from './mediatorServerHandler';
+
+export interface IMediatorAppStoreState {
+  avaliableMediatorServers: IAvaliableMediatorServersState,
+  mediatorServerState: MediatorServerState,
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    mediator: IMediatorAppStoreState
+  }
+}
+
+const actionHandlers = {
+  avaliableMediatorServers: avaliableMediatorServersActionHandler,
+  mediatorServerState: mediatorServerHandler,
+};
+
+export const mediatorAppRootHandler = combineActionHandler<IMediatorAppStoreState>(actionHandlers);
+export default mediatorAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts
new file mode 100644
index 0000000..246634c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts
@@ -0,0 +1,120 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { XmlFileInfo, MediatorConfig, BusySymbol, MediatorConfigResponse, MediatorServerDevice } from "../models/mediatorServer";
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { SetMediatorServerVersion, SetMediatorServerInfo, SetAllMediatorServerConfigurations, SetMediatorServerBusy, SetMediatorServerSupportedDevices, SetMediatorServerReachable } from "../actions/mediatorServerActions";
+import { SetMediatorBusyByName, UpdateMediatorConfig, AddMediatorConfig, RemoveMediatorConfig } from "../actions/mediatorConfigActions";
+
+export type MediatorServerState = {
+  busy: boolean;
+  name: string | null;
+  url: string | null;
+  id: string | null;
+  serverVersion: string | null;
+  mediatorVersion: string | null;
+  nexmls: XmlFileInfo[];
+  configurations: MediatorConfigResponse[];
+  supportedDevices: MediatorServerDevice[];
+  isReachable: boolean;
+}
+
+const mediatorServerInit: MediatorServerState = {
+  busy: false,
+  name: null,
+  url: null,
+  id: null,
+  serverVersion: null,
+  mediatorVersion: null,
+  nexmls: [],
+  configurations: [],
+  supportedDevices: [],
+  isReachable: true
+}
+
+export const mediatorServerHandler: IActionHandler<MediatorServerState> = (state = mediatorServerInit, action) => {
+  if (action instanceof SetMediatorServerBusy) {
+    state = {
+      ...state,
+      busy: action.isBusy
+    };
+  } else if (action instanceof SetMediatorServerInfo) {
+    state = {
+      ...state,
+      name: action.name,
+      url: action.url,
+      id: action.id,
+    };
+  } else if (action instanceof SetMediatorServerVersion) {
+    state = {
+      ...state,
+      serverVersion: action.versionInfo && action.versionInfo.server,
+      mediatorVersion: action.versionInfo && action.versionInfo.mediator,
+      nexmls: action.versionInfo && [...action.versionInfo.nexmls] || [],
+    };
+  } else if (action instanceof SetAllMediatorServerConfigurations) {
+    state = {
+      ...state,
+      configurations: action.allConfigurations && action.allConfigurations.map(config => ({ ...config, busy: false })) || [],
+    };
+  } else if (action instanceof SetMediatorServerSupportedDevices) {
+    state = {
+      ...state,
+      supportedDevices: action.devices || [],
+    };
+  } else if (action instanceof SetMediatorBusyByName) {
+    const index = state.configurations.findIndex(config => config.Name === action.name);
+    if (index > -1) state = {
+      ...state,
+      configurations: [
+        ...state.configurations.slice(0, index),
+        { ...state.configurations[index], [BusySymbol]: action.isBusy },
+        ...state.configurations.slice(index + 1)
+      ]
+    };
+  } else if (action instanceof AddMediatorConfig) {
+    state = {
+      ...state,
+      configurations: [
+        ...state.configurations,
+        action.mediatorConfig
+      ]
+    };
+  } else if (action instanceof UpdateMediatorConfig) {
+    const index = state.configurations.findIndex(config => config.Name === action.name);
+    if (index > -1) state = {
+      ...state,
+      configurations: [
+        ...state.configurations.slice(0, index),
+        { ...action.mediatorConfig, [BusySymbol]: state.configurations[index][BusySymbol] },
+        ...state.configurations.slice(index + 1)
+      ]
+    };
+  } else if (action instanceof RemoveMediatorConfig) {
+    const index = state.configurations.findIndex(config => config.Name === action.name);
+    if (index > -1) state = {
+      ...state,
+      configurations: [
+        ...state.configurations.slice(0, index),
+        ...state.configurations.slice(index + 1)
+      ]
+    };
+  } else if( action instanceof SetMediatorServerReachable){
+    state = {...state, isReachable: action.isReachable}
+  }
+  return state;
+} 
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/index.html b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/index.html
new file mode 100644
index 0000000..95bf9ec
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css"> -->
+  <title>Mediator App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "mediatorApp" ,"connectApp","inventoryApp","faultApp","helpApp"], function (app, mediatorApp, connectApp,inventoryApp,faultApp,helpApp) {
+      mediatorApp.register();
+      connectApp.register();
+      inventoryApp.register();
+      faultApp.register();
+      helpApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/models/mediatorServer.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/models/mediatorServer.ts
new file mode 100644
index 0000000..6ab6db8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/models/mediatorServer.ts
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type MediatorServer = {
+   id: string;
+   name: string;
+   url: string;
+} 
+
+export type XmlFileInfo = {
+   filename: string;
+   version: string;
+} 
+
+export type MediatorServerVersionInfo = {
+   mediator: string;
+   server: string;
+   nexmls: XmlFileInfo[]; 
+} 
+
+export type ODLConfig = {
+   User: string;
+   Password: string;
+   Port: number;
+   Protocol: "http" | "https";
+   Server: string;
+   Trustall: boolean;
+}; 
+
+export const BusySymbol = Symbol("Busy");
+
+export type MediatorConfig = {
+   Name: string;
+   DeviceIp: string;
+   DevicePort: number;
+   DeviceType: number;
+   TrapPort: number;
+   NcUsername: string;
+   NcPassword: string;
+   NcPort: number;
+   NeXMLFile: string;
+   ODLConfig: ODLConfig[];
+}
+
+export type MediatorConfigResponse = MediatorConfig & {
+   IsNCConnected: boolean;
+   IsNeConnected: boolean;
+   autorun: boolean;
+   fwactive: boolean;
+   islocked: boolean;
+   ncconnections:{}[];
+   pid: number;
+   // extended properties
+   [BusySymbol]: boolean;
+} 
+
+export type MediatorServerDevice = {
+  id: number;       // DeviceType
+  device: string; 
+  vendor: string;
+  version: string;
+  xml: string;      // NeXMLFile
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/plugin.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/plugin.tsx
new file mode 100644
index 0000000..1c30cfc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/plugin.tsx
@@ -0,0 +1,83 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { mediatorAppRootHandler } from './handlers/mediatorAppRootHandler';
+import { avaliableMediatorServersReloadAction } from "./handlers/avaliableMediatorServersHandler";
+
+import { MediatorApplication } from "./views/mediatorApplication";
+import { MediatorServerSelection } from "./views/mediatorServerSelection";
+import { initializeMediatorServerAsyncActionCreator } from "./actions/mediatorServerActions";
+
+const appIcon = require('./assets/icons/mediatorAppIcon.svg');  // select app icon
+
+let currentMediatorServerId: string | undefined = undefined;
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  loadMediatorServer : (mediatorServerId: string) => dispatcher.dispatch(initializeMediatorServerAsyncActionCreator(mediatorServerId)),
+});
+
+const MediatorServerRouteAdapter = connect(undefined, mapDisp)((props: RouteComponentProps<{ mediatorServerId: string }> & Connect<undefined, typeof mapDisp>) => {
+  if (currentMediatorServerId !== props.match.params.mediatorServerId) {
+    // route parameter has changed
+    currentMediatorServerId = props.match.params.mediatorServerId || undefined;
+    // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+    window.setTimeout(() => {
+      if (currentMediatorServerId) {
+        props.loadMediatorServer(currentMediatorServerId);
+      }
+    });
+  }
+  return (
+    <MediatorApplication />
+  )
+});
+
+type AppProps = RouteComponentProps & Connect;
+
+const App = (props: AppProps) => (
+  <Switch>
+    <Route exact path={ `${ props.match.path }` } component={ MediatorServerSelection } />
+    <Route path={ `${ props.match.path }/:mediatorServerId` } component={ MediatorServerRouteAdapter } />
+    <Redirect to={ `${ props.match.path }` } />
+   </Switch>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: "mediator",
+    icon: appIcon,
+    rootComponent: FinalApp,
+    rootActionHandler: mediatorAppRootHandler,
+    menuEntry: "Mediator"
+  });
+
+  // prefetch all available mediator servers
+  applicationApi.applicationStoreInitialized.then(applicationStore => {
+    applicationStore.dispatch(avaliableMediatorServersReloadAction)
+  });
+};
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/services/mediatorService.ts b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/services/mediatorService.ts
new file mode 100644
index 0000000..ede6817
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/services/mediatorService.ts
@@ -0,0 +1,204 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as $ from 'jquery';
+
+import { requestRest, formEncode } from '../../../../framework/src/services/restService';
+import { MediatorServer, MediatorServerVersionInfo, MediatorConfig, MediatorServerDevice, MediatorConfigResponse } from '../models/mediatorServer';
+import { PostResponse, DeleteResponse, Result } from '../../../../framework/src/models';
+
+export const mediatorServerResourcePath = "mediator-server";
+
+type MediatorServerResponse<TData> = { code: number, data: TData };
+type IndexableMediatorServer = MediatorServer & { [key: string]: any; };
+
+/** 
+ * Represents a web api accessor service for all mediator server actions.
+ */
+class MediatorService {
+  /**
+    * Inserts data into the mediator servers table.
+    */
+  public async insertMediatorServer(server: IndexableMediatorServer): Promise<PostResponse | null> {
+    const path = `/restconf/operations/data-provider:create-mediator-server`;
+
+    const data = {
+      "url": server.url,
+      "name": server.name
+    }
+
+    const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+    return result || null;
+  }
+
+  /**
+    * Updates data into the mediator servers table.
+    */
+  public async updateMediatorServer(server: IndexableMediatorServer): Promise<PostResponse | null> {
+    const path = `/restconf/operations/data-provider:update-mediator-server`;
+
+    const data = {
+      "id": server.id,
+      "url": server.url,
+      "name": server.name
+    }
+
+    const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+    return result || null;
+  }
+
+  /**
+    * Deletes data from the mediator servers table.
+    */
+  public async deleteMediatorServer(server: MediatorServer): Promise<DeleteResponse | null> {
+    const path = `/restconf/operations/data-provider:delete-mediator-server`;
+
+    const data = {
+      "id": server.id,
+    }
+
+    const result = await requestRest<DeleteResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+    return result || null;
+  }
+
+  public async getMediatorServerById(serverId: string): Promise<MediatorServer | null> {
+    const path = `/restconf/operations/data-provider:read-mediator-server-list`;
+
+    const data = { "filter": [{ "property": "id", "filtervalue": serverId }] }
+
+
+    const result = await requestRest<Result<MediatorServer>>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+
+    if (result && result["data-provider:output"].data[0]) {
+      const firstResult = result["data-provider:output"].data[0];
+
+      return {
+        id: firstResult.id,
+        name: firstResult.name,
+        url: firstResult.url
+      }
+    }
+    else {
+      return null;
+    }
+  }
+
+  // https://cloud-highstreet-technologies.com/wiki/doku.php?id=att:ms:api
+
+  private async accassMediatorServer<TData = {}>(mediatorServerId: string, task: string, data?: {}): Promise<MediatorServerResponse<TData> | null> {
+    const path = `ms/${mediatorServerId}/api/'?task=${task}`;
+    const result = (await requestRest<string>(path, {
+      method: data ? "POST" : "GET",
+      headers: {
+        'Content-Type': 'application/x-www-form-urlencoded'
+      },
+      body: data ? formEncode({
+        ...data,
+        ...{ task: task }
+      }) : null
+    }, true)) || null;
+
+    return result ? JSON.parse(result) as { code: number, data: TData } : null;
+  }
+  /*
+  private accassMediatorServer<TData = {}>(mediatorServerId: string, task: string, data?: {}): Promise<MediatorServerResponse<TData> | null> {
+    const path = `ms/${mediatorServerId}/api/?task=${task}`;
+    return new Promise<{ code: number, data: TData }>((resolve, reject) => {
+      $.ajax({
+        method: data ? 'POST' : 'GET',
+        url: path,
+        data: { ...{ task: task }, ...data },
+        //contentType: 'application/json'
+      }).then((result: any) => {
+        if (typeof result === "string") {
+          resolve(JSON.parse(result));
+        } else {
+          resolve(result);
+        };
+      });
+    });
+  }*/
+
+  public async getMediatorServerVersion(mediatorServerId: string): Promise<MediatorServerVersionInfo | null> {
+    const result = await this.accassMediatorServer<MediatorServerVersionInfo>(mediatorServerId, 'version');
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerAllConfigs(mediatorServerId: string): Promise<MediatorConfigResponse[] | null> {
+    const result = await this.accassMediatorServer<MediatorConfigResponse[]>(mediatorServerId, 'getconfig');
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerConfigByName(mediatorServerId: string, name: string): Promise<MediatorConfigResponse | null> {
+    const result = await this.accassMediatorServer<MediatorConfigResponse[]>(mediatorServerId, `getconfig&name=${name}`);
+    if (result && result.code === 1 && result.data && result.data.length === 1) return result.data[0];
+    return null;
+  }
+
+  public async getMediatorServerSupportedDevices(mediatorServerId: string): Promise<MediatorServerDevice[] | null> {
+    const result = await this.accassMediatorServer<MediatorServerDevice[]>(mediatorServerId, 'getdevices');
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async startMediatorByName(mediatorServerId: string, name: string): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerId, `start&name=${name}`);
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async stopMediatorByName(mediatorServerId: string, name: string): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerId, `stop&name=${name}`);
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async createMediatorConfig(mediatorServerId: string, config: MediatorConfig): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerId, 'create', { config: JSON.stringify(config) });
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async updateMediatorConfigByName(mediatorServerId: string, config: MediatorConfig): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerId, 'update', { config: JSON.stringify(config) });
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async deleteMediatorConfigByName(mediatorServerId: string, name: string): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerId, `delete&name=${name}`);
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerFreeNcPorts(mediatorServerId: string, limit?: number): Promise<number[] | null> {
+    const result = await this.accassMediatorServer<number[]>(mediatorServerId, 'getncports', { limit });
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerFreeSnmpPorts(mediatorServerId: string, limit?: number): Promise<number[] | null> {
+    const result = await this.accassMediatorServer<number[]>(mediatorServerId, 'getsnmpports', { limit });
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+}
+
+export const mediatorService = new MediatorService;
+export default mediatorService;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
new file mode 100644
index 0000000..03ce453
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
@@ -0,0 +1,291 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { Theme, Tooltip } from '@mui/material';
+
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+
+import AddIcon from '@mui/icons-material/Add';
+import IconButton from '@mui/material/IconButton';
+import EditIcon from '@mui/icons-material/Edit';
+import DeleteIcon from '@mui/icons-material/Delete';
+import InfoIcon from '@mui/icons-material/Info';
+import StartIcon from '@mui/icons-material/PlayArrow';
+import StopIcon from '@mui/icons-material/Stop';
+
+import CircularProgress from '@mui/material/CircularProgress'
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+
+import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/mediatorServer';
+import EditMediatorConfigDialog, { EditMediatorConfigDialogMode } from '../components/editMediatorConfigDialog';
+import { startMediatorByNameAsyncActionCreator, stopMediatorByNameAsyncActionCreator } from '../actions/mediatorConfigActions';
+import mediatorService from '../services/mediatorService';
+import { ShowMediatorInfoDialog, MediatorInfoDialogMode } from '../components/showMeditaorInfoDialog'
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    display: 'flex',
+    flexDirection: 'column',
+    flex: '1',
+  },
+  formControl: {
+    margin: theme.spacing(1),
+    minWidth: 300,
+  },
+  button: {
+    margin: 0,
+    padding: "6px 6px",
+    minWidth: 'unset'
+  },
+  spacer: {
+    marginLeft: theme.spacing(1),
+    marginRight: theme.spacing(1),
+    display: "inline"
+  },
+  progress: {
+    flex: '1 1 100%',
+    display: 'flex',
+    alignItems: 'center',
+    justifyContent: 'center',
+    pointerEvents: 'none'
+  }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  serverName: state.mediator.mediatorServerState.name,
+  serverUrl: state.mediator.mediatorServerState.url,
+  serverId: state.mediator.mediatorServerState.id,
+  serverVersion: state.mediator.mediatorServerState.serverVersion,
+  mediatorVersion: state.mediator.mediatorServerState.mediatorVersion,
+  configurations: state.mediator.mediatorServerState.configurations,
+  supportedDevices: state.mediator.mediatorServerState.supportedDevices,
+  busy: state.mediator.mediatorServerState.busy,
+  isReachable: state.mediator.mediatorServerState.isReachable
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  startMediator: (name: string) => dispatcher.dispatch(startMediatorByNameAsyncActionCreator(name)),
+  stopMediator: (name: string) => dispatcher.dispatch(stopMediatorByNameAsyncActionCreator(name)),
+});
+
+const emptyMediatorConfig: MediatorConfig = {
+  Name: "",
+  DeviceIp: "127.0.0.1",
+  DevicePort: 161,
+  NcUsername: "admin",
+  NcPassword: "admin",
+  DeviceType: -1,
+  NcPort: 4020,
+  TrapPort: 10020,
+  NeXMLFile: "",
+  ODLConfig: []
+};
+
+const MediatorServerConfigurationsTable = MaterialTable as MaterialTableCtorType<MediatorConfigResponse>;
+const MediatorServerUnreachableTable = MaterialTable as MaterialTableCtorType<{ Name: string, status: string, ipAdress: string, device: string, actions: string }>
+
+type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type MediatorServerSelectionComponentState = {
+  busy: boolean,
+  mediatorConfigToEdit: MediatorConfig,
+  mediatorConfigEditorMode: EditMediatorConfigDialogMode,
+  mediatorShowInfoMode: MediatorInfoDialogMode,
+  mediatorConfigToDisplay: MediatorConfigResponse | null
+}
+
+class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> {
+
+  constructor(props: MediatorApplicationComponentProps) {
+    super(props);
+
+    this.state = {
+      busy: false,
+      mediatorConfigToEdit: emptyMediatorConfig,
+      mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
+      mediatorShowInfoMode: MediatorInfoDialogMode.None,
+      mediatorConfigToDisplay: null
+    }
+  }
+
+  render() {
+    const { classes } = this.props;
+
+    const renderActions = (rowData: MediatorConfigResponse) => (
+      <>
+        <div className={classes.spacer}>
+          <Tooltip disableInteractive title={"Start"} >
+            <IconButton disabled={rowData[BusySymbol]} className={classes.button} size="large">
+              <StartIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.startMediator(rowData.Name); }} />
+            </IconButton>
+          </Tooltip>
+          <Tooltip disableInteractive title={"Stop"} >
+            <IconButton disabled={rowData[BusySymbol]} className={classes.button} size="large">
+              <StopIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.stopMediator(rowData.Name); }} />
+            </IconButton>
+          </Tooltip>
+        </div>
+        <div className={classes.spacer}>
+          <Tooltip disableInteractive title={"Info"} ><IconButton
+            className={classes.button}
+            onClick={(event) => { this.onOpenInfoDialog(event, rowData) }}
+            size="large"><InfoIcon /></IconButton></Tooltip>
+        </div>
+        <div className={classes.spacer}>
+          {process.env.NODE_ENV === "development" ? <Tooltip disableInteractive title={"Edit"} ><IconButton
+            disabled={rowData[BusySymbol]}
+            className={classes.button}
+            onClick={event => this.onOpenEditConfigurationDialog(event, rowData)}
+            size="large"><EditIcon /></IconButton></Tooltip> : null}
+          <Tooltip disableInteractive title={"Remove"} ><IconButton
+            disabled={rowData[BusySymbol]}
+            className={classes.button}
+            onClick={event => this.onOpenRemoveConfigutationDialog(event, rowData)}
+            size="large"><DeleteIcon /></IconButton></Tooltip>
+        </div>
+      </>
+    );
+
+    const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', ariaLabel: 'add-element', onClick: this.onOpenAddConfigurationDialog };
+
+    return (
+      <div className={classes.root}>
+        {this.props.busy || this.state.busy
+          ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div>
+          :
+
+          this.props.isReachable ?
+
+            <MediatorServerConfigurationsTable defaultSortColumn={"Name"} tableId={null} defaultSortOrder="asc" stickyHeader title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
+              { property: "Name", title: "Mediator", type: ColumnType.text },
+              { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
+              { property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
+              {
+                property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => {
+                  const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType);
+                  return (
+                    <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span>
+                  )
+                }
+              },
+              { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) },
+            ]} />
+            :
+            <MediatorServerUnreachableTable title={this.props.serverName || ''} tableId={null} idProperty={"Name"} disableFilter={true} disableSorting={true} enableSelection={false} rows={[{ Name: '', status: "Mediator server not found.", ipAdress: '', device: '', actions: '' }]} columns={[
+              { property: "Name", title: "Mediator", type: ColumnType.text },
+              { property: "status", title: "Status", type: ColumnType.text },
+              { property: "ipAdress", title: "IP Adress", type: ColumnType.text },
+              { property: "device", title: "Device", type: ColumnType.text },
+              { property: "actions", title: "Actions", type: ColumnType.text },
+
+            ]} />
+        }
+
+        <EditMediatorConfigDialog
+          mediatorConfig={this.state.mediatorConfigToEdit}
+          mode={this.state.mediatorConfigEditorMode}
+          onClose={this.onCloseEditMediatorConfigDialog} />
+
+        {
+
+          this.state.mediatorShowInfoMode != MediatorInfoDialogMode.None &&
+          <ShowMediatorInfoDialog
+            config={this.state.mediatorConfigToDisplay as MediatorConfigResponse}
+            mode={this.state.mediatorShowInfoMode}
+            onClose={this.onCloseInfoDialog} />
+        }
+      </div>
+    );
+  }
+
+  private onOpenInfoDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfigResponse) => {
+    event.stopPropagation();
+    event.preventDefault();
+    this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.ShowDetails, mediatorConfigToDisplay: configEntry })
+  }
+
+  private onCloseInfoDialog = () => {
+    this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.None, mediatorConfigToDisplay: null })
+  }
+
+  private onOpenAddConfigurationDialog = () => {
+    // Tries to determine a free port for netconf listener and snpm listener
+    // it it could not determine free ports the dialog will open any way
+    // those ports should not be configured from the fontend, furthermore
+    // the backend should auto configure them and tell the user the result
+    // after the creation process.
+    this.setState({
+      busy: true,
+    });
+    this.props.serverId && Promise.all([
+      mediatorService.getMediatorServerFreeNcPorts(this.props.serverId, 1),
+      mediatorService.getMediatorServerFreeSnmpPorts(this.props.serverId, 1),
+    ]).then(([freeNcPorts, freeSnmpPorts]) => {
+      if (freeNcPorts && freeSnmpPorts && freeNcPorts.length > 0 && freeSnmpPorts.length > 0) {
+        this.setState({
+          busy: false,
+          mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
+          mediatorConfigToEdit: {
+            ...emptyMediatorConfig,
+            NcPort: freeNcPorts[0],
+            TrapPort: freeSnmpPorts[0],
+          },
+        });
+      } else {
+        this.setState({
+          busy: false,
+          mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
+          mediatorConfigToEdit: { ...emptyMediatorConfig },
+        });
+      }
+    })
+
+  }
+
+  private onOpenEditConfigurationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
+    event.preventDefault();
+    event.stopPropagation();
+    this.setState({
+      mediatorConfigEditorMode: EditMediatorConfigDialogMode.EditMediatorConfig,
+      mediatorConfigToEdit: configEntry,
+    });
+  }
+
+  private onOpenRemoveConfigutationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
+    event.preventDefault();
+    event.stopPropagation();
+    this.setState({
+      mediatorConfigEditorMode: EditMediatorConfigDialogMode.RemoveMediatorConfig,
+      mediatorConfigToEdit: configEntry,
+    });
+  }
+
+  private onCloseEditMediatorConfigDialog = () => {
+    this.setState({
+      mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
+      mediatorConfigToEdit: emptyMediatorConfig,
+    });
+  }
+}
+
+export const MediatorApplication = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorApplicationComponent));
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
new file mode 100644
index 0000000..fb12f26
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
@@ -0,0 +1,193 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { Theme, Tooltip } from '@mui/material';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import AddIcon from '@mui/icons-material/Add';
+import IconButton from '@mui/material/IconButton';
+import EditIcon from '@mui/icons-material/Edit';
+import DeleteIcon from '@mui/icons-material/Delete';
+import Refresh from '@mui/icons-material/Refresh';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { connect, IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+
+import { createAvaliableMediatorServersProperties, createAvaliableMediatorServersActions } from '../handlers/avaliableMediatorServersHandler';
+
+import { MediatorServer } from '../models/mediatorServer';
+import EditMediatorServerDialog, { EditMediatorServerDialogMode } from '../components/editMediatorServerDialog';
+import RefreshMediatorDialog, { RefreshMediatorDialogMode } from '../components/refreshMediatorDialog';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+const MediatorServersTable = MaterialTable as MaterialTableCtorType<MediatorServer>;
+
+const styles = (theme: Theme) => createStyles({
+  button: {
+    margin: 0,
+    padding: "6px 6px",
+    minWidth: 'unset',
+  },
+  spacer: {
+    marginLeft: theme.spacing(1),
+    marginRight: theme.spacing(1),
+    display: "inline",
+  },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  mediatorServersProperties: createAvaliableMediatorServersProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  mediatorServersActions: createAvaliableMediatorServersActions(dispatcher.dispatch),
+  selectMediatorServer: (mediatorServerId: string) => mediatorServerId && dispatcher.dispatch(new NavigateToApplication("mediator", mediatorServerId)),
+});
+
+const emptyMediatorServer: MediatorServer = {
+  id: "",
+  name: "",
+  url: ""
+};
+
+type MediatorServerSelectionComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type MediatorServerSelectionComponentState = {
+  mediatorServerToEdit: MediatorServer,
+  mediatorServerEditorMode: EditMediatorServerDialogMode,
+  refreshMediatorEditorMode: RefreshMediatorDialogMode
+}
+
+let initialSorted = false;
+
+class MediatorServerSelectionComponent extends React.Component<MediatorServerSelectionComponentProps, MediatorServerSelectionComponentState> {
+
+  constructor(props: MediatorServerSelectionComponentProps) {
+    super(props);
+
+    this.state = {
+      mediatorServerEditorMode: EditMediatorServerDialogMode.None,
+      mediatorServerToEdit: emptyMediatorServer,
+      refreshMediatorEditorMode: RefreshMediatorDialogMode.None
+    }
+  }
+
+  render() {
+    const { classes } = this.props;
+    const refreshMediatorAction = {
+      icon: Refresh, tooltip: 'Refresh Mediator Server Table', ariaLabel:'refresh', onClick: () => {
+        this.setState({
+          refreshMediatorEditorMode: RefreshMediatorDialogMode.RefreshMediatorTable
+        });
+      }
+    };
+
+    const addMediatorServerActionButton = {
+      icon: AddIcon, tooltip: 'Add', ariaLabel:'add-element', onClick: () => {
+        this.setState({
+          mediatorServerEditorMode: EditMediatorServerDialogMode.AddMediatorServer,
+          mediatorServerToEdit: emptyMediatorServer,
+        });
+      }
+    };
+    return <>
+      <MediatorServersTable stickyHeader title={"Mediator"} tableId={null} customActionButtons={[refreshMediatorAction, addMediatorServerActionButton]} idProperty={"id"}
+        {...this.props.mediatorServersActions} {...this.props.mediatorServersProperties} columns={[
+          { property: "name", title: "Name", type: ColumnType.text },
+          { property: "url", title: "Url", type: ColumnType.text },
+          {
+            property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => (
+              <div className={classes.spacer}>
+                <Tooltip disableInteractive title={"Edit"} ><IconButton
+                  className={classes.button}
+                  onClick={event => { this.onEditMediatorServer(event, rowData); }}
+                  size="large"><EditIcon /></IconButton></Tooltip>
+                <Tooltip disableInteractive title={"Remove"} ><IconButton
+                  className={classes.button}
+                  onClick={event => { this.onRemoveMediatorServer(event, rowData); }}
+                  size="large"><DeleteIcon /></IconButton></Tooltip>
+              </div>
+            )
+          }
+        ]} onHandleClick={this.onSelectMediatorServer} />
+      <EditMediatorServerDialog
+        mediatorServer={this.state.mediatorServerToEdit}
+        mode={this.state.mediatorServerEditorMode}
+        onClose={this.onCloseEditMediatorServerDialog} />
+      <RefreshMediatorDialog
+        mode={this.state.refreshMediatorEditorMode}
+        onClose={this.onCloseRefreshMediatorDialog}
+      />
+    </>;
+  }
+
+  public componentDidMount() {
+
+    if (!initialSorted) {
+      initialSorted = true;
+      this.props.mediatorServersActions.onHandleRequestSort("name");
+    } else {
+      this.props.mediatorServersActions.onRefresh();
+    }
+  }
+
+  private onSelectMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
+    event.preventDefault();
+    event.stopPropagation();
+    this.props.selectMediatorServer(server && server.id);
+
+  }
+
+  private onEditMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
+    event.preventDefault();
+    event.stopPropagation();
+    this.setState({
+      mediatorServerEditorMode: EditMediatorServerDialogMode.EditMediatorServer,
+      mediatorServerToEdit: server,
+    });
+  }
+
+  private onRemoveMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
+    event.preventDefault();
+    event.stopPropagation();
+    this.setState({
+      mediatorServerEditorMode: EditMediatorServerDialogMode.RemoveMediatorServer,
+      mediatorServerToEdit: server,
+    });
+  }
+
+  private onCloseEditMediatorServerDialog = () => {
+    this.setState({
+      mediatorServerEditorMode: EditMediatorServerDialogMode.None,
+      mediatorServerToEdit: emptyMediatorServer,
+    });
+  }
+  private onCloseRefreshMediatorDialog = () => {
+    this.setState({
+      refreshMediatorEditorMode: RefreshMediatorDialogMode.None
+    });
+  }
+}
+
+
+export const MediatorServerSelection = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorServerSelectionComponent));
+export default MediatorServerSelection;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/mediatorApp/tsconfig.json
new file mode 100644
index 0000000..c950056
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/tsconfig.json
@@ -0,0 +1,38 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "node",
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/tslint.json b/sdnr/wt-odlux/odlux/apps/mediatorApp/tslint.json
new file mode 100644
index 0000000..b5143e9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/tslint.json
@@ -0,0 +1,4 @@
+{
+  "rules":{
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/mediatorApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/mediatorApp/webpack.config.js
new file mode 100644
index 0000000..813c28f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/mediatorApp/webpack.config.js
@@ -0,0 +1,158 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      mediatorApp: ["./plugin.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },{
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/oauth2/": {
+          target: "http://localhost:3000",
+          secure: false
+        },
+        "/database/": {
+          target: "http://localhost:3000",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://localhost:3000",
+          secure: false
+        },
+        "/help/": {
+          target: "http://localhost:3000",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/.babelrc b/sdnr/wt-odlux/odlux/apps/minimumApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/package.json b/sdnr/wt-odlux/odlux/apps/minimumApp/package.json
new file mode 100644
index 0000000..2c88f30
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/package.json
@@ -0,0 +1,43 @@
+{
+  "name": "@odlux/minimum-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI to demo the minimum possible app.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Matthias Fischer",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/pom.xml b/sdnr/wt-odlux/odlux/apps/minimumApp/pom.xml
new file mode 100644
index 0000000..f23c795
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-minimumApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/src/assets/icons/minimumAppIcon.svg b/sdnr/wt-odlux/odlux/apps/minimumApp/src/assets/icons/minimumAppIcon.svg
new file mode 100644
index 0000000..298eaa1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/src/assets/icons/minimumAppIcon.svg
@@ -0,0 +1,27 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="310 250 400 400">
+
+<g transform="translate(0,1024) scale(0.1,-0.1)">
+
+<path fill="#565656" d="M4926 7634 c-126 -17 -209 -38 -318 -79 -79 -31 -195 -89 -208 -104
+-10 -12 -69 -51 -77 -51 -4 0 -42 -28 -83 -63 -227 -190 -375 -475 -375 -722
+0 -81 3 -95 30 -143 111 -201 365 -252 514 -103 46 46 88 124 121 226 28 87
+109 255 153 315 67 95 172 168 275 192 86 20 268 21 346 2 113 -28 152 -50
+240 -137 64 -63 88 -95 104 -137 49 -125 52 -225 12 -332 -38 -102 -132 -209
+-360 -409 -153 -134 -329 -309 -375 -374 -97 -136 -148 -274 -166 -448 -19
+-192 12 -305 104 -379 64 -50 141 -72 228 -65 82 7 125 24 177 71 49 45 73
+100 105 241 59 258 63 263 528 687 218 198 295 284 374 419 134 230 138 543 9
+803 -101 202 -252 349 -474 461 -246 124 -573 172 -884 129z"/>
+
+<path fill="#36A9E1" d="M 5098 4587 C 4582 4587 4582 3845 5098 3845 C 5614 3847 5614 4585 5098 4587 Z"/>
+
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
new file mode 100644
index 0000000..4a4dc61
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+export interface IMinimumAppStoreState {
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    minimum: IMinimumAppStoreState;
+  }
+}
+
+const actionHandlers = {
+};
+
+export const minimumAppRootHandler = combineActionHandler<IMinimumAppStoreState>(actionHandlers);
+export default minimumAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/src/index.html b/sdnr/wt-odlux/odlux/apps/minimumApp/src/index.html
new file mode 100644
index 0000000..58865ed
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/src/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css"> -->
+  <title>Minimal App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "minimumApp"], function (app) {
+      app("./app.tsx")
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/src/plugin.tsx b/sdnr/wt-odlux/odlux/apps/minimumApp/src/plugin.tsx
new file mode 100644
index 0000000..5c8500a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/src/plugin.tsx
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import React, { FC } from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { connect, Connect } from '../../../framework/src/flux/connect';
+
+import { minimumAppRootHandler } from './handlers/minimumAppRootHandler';
+
+// const appIcon = require('./assets/icons/minimunAppIcon.svg');  // select app icon
+
+type AppProps = RouteComponentProps & Connect;
+
+const App: FC<AppProps> = (_props) => (
+  <div>Start your app here!!</div>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+  applicationManager.registerApplication({
+    name: 'minimum',
+    // icon: appIcon,
+    rootComponent: FinalApp,
+    rootActionHandler: minimumAppRootHandler,
+    menuEntry: 'Minimum',
+  });
+}
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/minimumApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/minimumApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/minimumApp/webpack.config.js
new file mode 100644
index 0000000..50b24e7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/minimumApp/webpack.config.js
@@ -0,0 +1,136 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      minimumApp: ["./plugin.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/api": {
+          target: "http://localhost:3001",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/.babelrc b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/package.json b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/package.json
new file mode 100644
index 0000000..9a08612
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/package.json
@@ -0,0 +1,46 @@
+{
+  "name": "@odlux/performancehistory-app",
+  "version": "0.1.1",
+  "description": "A react based modular UI to display performance history data from a database.",
+  "main": "index.js",
+  "scripts": {
+    "start": "webpack-dev-server --env debug",
+    "build": "webpack --env release --config webpack.config.js",
+    "build:dev": "webpack --env debug --config webpack.config.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+  },
+  "keywords": [
+    "reactjs",
+    "redux",
+    "ui",
+    "framework"
+  ],
+  "author": "Sai Neetha Phulmali",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@odlux/connect-app": "*",
+    "@odlux/framework": "*",
+    "chart.js": "2.8.0",
+    "react-chartjs-2": "2.7.6"
+  },
+  "peerDependencies": {
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "jquery": "3.3.1",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/pom.xml b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/pom.xml
new file mode 100644
index 0000000..eb0160f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-app-performanceHistoryApp</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+         <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
new file mode 100644
index 0000000..fbbf2c5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { DeviceListType } from '../models/deviceListType';
+import { PerformanceHistoryService } from '../services/performanceHistoryService';
+
+/** 
+ * Represents the base action. 
+ */
+export class BaseAction extends Action { }
+
+/** 
+ * Represents an action causing the store to load all devices. 
+ */
+export class LoadAllDeviceListAction extends BaseAction { }
+
+/** 
+ * Represents an action causing the store to update all devices. 
+ */
+export class AllDeviceListLoadedAction extends BaseAction {
+  /**
+   * Initialize this instance.
+   * 
+   * @param deviceList All the distinct devices from the performance history database.
+   */
+  constructor(public deviceList: DeviceListType[] | null, public error?: string) {
+    super();
+  }
+}
+
+/** 
+ * Represents an asynchronous thunk  action to load all devices. 
+ */
+export const loadAllDeviceListAsync = async (dispatch: Dispatch) => {
+  dispatch(new LoadAllDeviceListAction());
+  const deviceListFromPerfHistory: DeviceListType[] = (await PerformanceHistoryService.getDeviceListfromPerf15minHistory().then(ne => (ne))) || [];
+  const deviceListFromPerf24History: DeviceListType[] = (await PerformanceHistoryService.getDeviceListfromPerf24hHistory().then(ne => (ne))) || [];
+  deviceListFromPerf24History.forEach(deviceList24h => {
+    if (deviceListFromPerfHistory.findIndex(deviceList15min => deviceList15min.nodeId === deviceList24h.nodeId) < 0) {
+      deviceListFromPerfHistory.push(deviceList24h);
+    }
+  });
+  return deviceListFromPerfHistory && dispatch(new AllDeviceListLoadedAction(deviceListFromPerfHistory));
+};
+
+/** 
+ * Represents an action causing the store to update mountId. 
+ */
+export class UpdateMountId extends BaseAction {
+  constructor(public nodeId?: string) {
+    super();
+  }
+}
+
+/** 
+ * Represents an asynchronous thunk  action to load updated mountId. 
+ */
+export const updateMountIdActionCreator = (nodeId: string) => async (dispatch: Dispatch) => {
+  return dispatch(new UpdateMountId(nodeId));
+};
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
new file mode 100644
index 0000000..1c333ab
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
@@ -0,0 +1,94 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { LtpIds } from '../models/availableLtps';
+import { PerformanceHistoryService } from '../services/performanceHistoryService';
+
+/** 
+ * Represents the base action. 
+ */
+export class BaseAction extends Action { }
+
+/** 
+ * Represents an action causing the store to load available ltps. 
+ */
+export class LoadAllAvailableLtpsAction extends BaseAction { }
+
+/** 
+ * Represents an action causing the store to update available ltps. 
+ */
+export class AllAvailableLtpsLoadedAction extends BaseAction {
+  /**
+   * Initialize this instance.
+   * @param availableLtps The available ltps which are returned from the database.
+   */
+  constructor(public availableLtps: LtpIds[] | null, public error?: string) {
+    super();
+  }
+}
+
+export class SetInitialLoadedAction extends BaseAction {
+  constructor(public initialLoaded: boolean) {
+    super();
+  }
+}
+
+export class NoLtpsFoundAction extends BaseAction { }
+
+export class ResetLtpsAction extends BaseAction { }
+
+const getDistinctLtps = (distinctLtps: LtpIds[], selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => {
+  let ltpNotSelected: boolean = true;
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+  selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
+  distinctLtps.forEach((value: LtpIds) => {
+    if (value.key === selectedLtp) {
+      ltpNotSelected = false;
+    }
+  });
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+  resetLtp && resetLtp(ltpNotSelected);
+  return distinctLtps;
+};
+
+/** 
+ * Represents an asynchronous thunk action to load available distinctLtps by networkElement from the database and set the returned first Ltp as default. 
+ * @param networkElement The network element sent to database to get its available distinct Ltps.
+ * @param selectedTimePeriod The time period selected sent to database to get the distinct Ltps of the selected network element.
+ * @param selectedLtp The Ltp which is selected in the dropdown.
+ * @param selectFirstLtp The function to get the first ltp returned from the database to be selected as default on selection upon network element.
+ * @param resetLtp The function to verify if the selected ltp is also available in the selected time period database else reset the Ltp dropdown to select.
+ */
+export const loadDistinctLtpsbyNetworkElementAsync = (networkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => (dispatch: Dispatch) => {
+  dispatch(new LoadAllAvailableLtpsAction());
+  PerformanceHistoryService.getDistinctLtpsFromDatabase(networkElement, selectedTimePeriod).then(distinctLtps => {
+    if (distinctLtps) {
+      const ltps = getDistinctLtps(distinctLtps, selectedLtp, selectFirstLtp, resetLtp);
+      dispatch(new AllAvailableLtpsLoadedAction(ltps));
+    } else {
+      if (resetLtp)
+        resetLtp();
+      dispatch(new NoLtpsFoundAction());
+    }
+  }).catch(error => {
+    dispatch(new AllAvailableLtpsLoadedAction(null, error));
+  });
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts
new file mode 100644
index 0000000..8b77cb3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts
@@ -0,0 +1,32 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { PanelId } from '../models/panelId';
+
+/** 
+ * Represents an action causing the store to update the panel. 
+ */
+export class SetPanelAction extends Action {
+  /**
+   * Initialize this instance.
+   * @param panelId Action to set the current panel by its Id.
+   */
+  constructor(public panelId: PanelId) {
+    super();
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts
new file mode 100644
index 0000000..6bd54ce
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+
+export class ReloadAction extends Action {
+  constructor(public show: boolean) {
+    super();
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
new file mode 100644
index 0000000..13214b2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
@@ -0,0 +1,30 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+
+import { PmDataInterval } from '../models/performanceDataType';
+
+export class TimeChangeAction extends Action {
+  /**
+   * Initialize this instance.
+   * @param time Action to set the time interval in dropdown.
+   */
+  constructor(public time: PmDataInterval) {
+    super();
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
new file mode 100644
index 0000000..7921ea5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+
+import { currentViewType } from '../models/toggleDataType';
+
+
+export class SetSubViewAction extends Action {
+  constructor(public currentView: currentViewType, public selectedTab: 'chart' | 'table') {
+    super();
+  }
+}
+
+export class ResetAllSubViewsAction extends Action { }
+
+export class SetFilterVisibility extends Action {
+  constructor(public currentView: currentViewType, public isVisible: boolean) {
+    super();
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/assets/icons/performanceHistoryAppIcon.svg b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/assets/icons/performanceHistoryAppIcon.svg
new file mode 100644
index 0000000..982f1ee
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/assets/icons/performanceHistoryAppIcon.svg
@@ -0,0 +1,50 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500">

+<g>

+	<g>

+		<path fill="#006C4B" d="M 0 447.672 C 0 460.238 4.471 470.99 13.417 479.936 C 22.368 488.882 33.119 493.355 45.681 493.355 H 429.405 C 441.965 493.355 452.717 488.882 461.663 479.936 C 470.608 470.991 475.085 460.239 475.085 447.672 L 0 447.672 Z"/>

+		<rect fill="#565656" x="73.092" y="310.635" width="73.089" height="109.632"/>

+		<rect fill="#565656" x="182.728" y="164.452" width="73.085" height="255.814"/>

+		<rect fill="#565656" x="292.362" y="237.541" width="73.083" height="182.726"/>

+		<rect fill="#565656" x="401.994" y="127.907" width="73.091" height="292.36"/>

+	</g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+<g>

+</g>

+</svg>

diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
new file mode 100644
index 0000000..5dac0bc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
@@ -0,0 +1,489 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createAdaptiveModulationActions, createAdaptiveModulationProperties } from '../handlers/adaptiveModulationHandler';
+import { AdaptiveModulationDatabaseDataType, AdaptiveModulationDataType } from '../models/adaptiveModulationDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  adaptiveModulationProperties: createAdaptiveModulationProperties(state),
+  currentView: state.performanceHistory.subViews.adaptiveModulation.subView,
+  isFilterVisible: state.performanceHistory.subViews.adaptiveModulation.isFilterVisible,
+  existingFilter: state.performanceHistory.adaptiveModulation.filter,
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  adaptiveModulationActions: createAdaptiveModulationActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('adaptiveModulation', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('adaptiveModulation', value)); },
+});
+
+type AdaptiveModulationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const AdaptiveModulationTable = MaterialTable as MaterialTableCtorType<AdaptiveModulationDataType>;
+
+/**
+ * The Component which gets the adaptiveModulation data from the database based on the selected time period.
+ */
+class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+  onChange = (value: 'chart' | 'table') => {
+    this.props.setSubView(value);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.adaptiveModulationActions.onFilterChanged(property, filterTerm);
+    if (!this.props.adaptiveModulationProperties.showFilter)
+      this.props.adaptiveModulationActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.adaptiveModulationProperties;
+    const actions = this.props.adaptiveModulationActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const adaptiveModulationColumns: ColumnModel<AdaptiveModulationDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      }];
+
+    chartPagedData.datasets.forEach(ds => {
+      adaptiveModulationColumns.push(addColumnLabels<AdaptiveModulationDataType>(ds.name, ds.columnLabel));
+    });
+
+    return (
+      <>
+        <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+          existingFilter={this.props.adaptiveModulationProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+          {lineChart(chartPagedData)}
+          <AdaptiveModulationTable stickyHeader idProperty={'_id'} tableId="adaptive-modulation-table" columns={adaptiveModulationColumns} {...properties} {...actions} />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for Adaptive modulation according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: AdaptiveModulationDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'time2StatesS',
+      label: 'QAM2S',
+      borderColor: '#62a309fc',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM2S',
+    }, {
+      name: 'time2States',
+      label: 'QAM2',
+      borderColor: '#62a309fc',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM2',
+    }, {
+      name: 'time2StatesL',
+      label: 'QAM2L',
+      borderColor: '#62a309fc',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM2L',
+    }, {
+      name: 'time4StatesS',
+      label: 'QAM4S',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM4S',
+    }, {
+      name: 'time4States',
+      label: 'QAM4',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM4',
+    }, {
+      name: 'time4StatesL',
+      label: 'QAM4L',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM4L',
+    }, {
+      name: 'time16StatesS',
+      label: 'QAM16S',
+      borderColor: '#9b15e2',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM16S',
+    }, {
+      name: 'time16States',
+      label: 'QAM16',
+      borderColor: '#9b15e2',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM16',
+    }, {
+      name: 'time16StatesL',
+      label: 'QAM16L',
+      borderColor: '#9b15e2',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM16L',
+    }, {
+      name: 'time32StatesS',
+      label: 'QAM32S',
+      borderColor: '#2704f5f0',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM32S',
+    }, {
+      name: 'time32States',
+      label: 'QAM32',
+      borderColor: '#2704f5f0',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM32',
+    }, {
+      name: 'time32StatesL',
+      label: 'QAM32L',
+      borderColor: '#2704f5f0',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM32L',
+    }, {
+      name: 'time64StatesS',
+      label: 'QAM64S',
+      borderColor: '#347692',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM64S',
+    }, {
+      name: 'time64States',
+      label: 'QAM64',
+      borderColor: '#347692',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM64',
+    }, {
+      name: 'time64StatesL',
+      label: 'QAM64L',
+      borderColor: '#347692',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM64L',
+    }, {
+      name: 'time128StatesS',
+      label: 'QAM128S',
+      borderColor: '#885e22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM128S',
+    }, {
+      name: 'time128States',
+      label: 'QAM128',
+      borderColor: '#885e22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM128',
+    }, {
+      name: 'time128StatesL',
+      label: 'QAM128L',
+      borderColor: '#885e22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM128L',
+    }, {
+      name: 'time256StatesS',
+      label: 'QAM256S',
+      borderColor: '#de07807a',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM256S',
+    }, {
+      name: 'time256States',
+      label: 'QAM256',
+      borderColor: '#de07807a',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM256',
+    }, {
+      name: 'time256StatesL',
+      label: 'QAM256L',
+      borderColor: '#de07807a',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM256L',
+    }, {
+      name: 'time512StatesS',
+      label: 'QAM512S',
+      borderColor: '#8fdaacde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM512S',
+    }, {
+      name: 'time512States',
+      label: 'QAM512',
+      borderColor: '#8fdaacde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM512',
+    }, {
+
+      name: 'time512StatesL',
+      label: 'QAM512L',
+      borderColor: '#8fdaacde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM512L',
+    }, {
+
+      name: 'time1024StatesS',
+      label: 'QAM1024S',
+      borderColor: '#435b22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM1024S',
+    }, {
+
+      name: 'time1024States',
+      label: 'QAM1024',
+      borderColor: '#435b22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM1024',
+    }, {
+
+      name: 'time1024StatesL',
+      label: 'QAM1024L',
+      borderColor: '#435b22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM1024L',
+    }, {
+      name: 'time2048StatesS',
+      label: 'QAM2048S',
+      borderColor: '#e87a5b',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM2048S',
+    }, {
+      name: 'time2048States',
+      label: 'QAM2048',
+      borderColor: '#e87a5b',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM2048',
+    }, {
+      name: 'time2048StatesL',
+      label: 'QAM2048L',
+      borderColor: '#e87a5b',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM2048L',
+    }, {
+      name: 'time4096StatesS',
+      label: 'QAM4096S',
+      borderColor: '#5be878',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM4096S',
+    }, {
+      name: 'time4096States',
+      label: 'QAM4096',
+      borderColor: '#5be878',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM4096',
+    }, {
+      name: 'time4096StatesL',
+      label: 'QAM4096L',
+      borderColor: '#5be878',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM4096L',
+    }, {
+      name: 'time8192StatesS',
+      label: 'QAM8192s',
+      borderColor: '#cb5be8',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM8192S',
+    }, {
+      name: 'time8192States',
+      label: 'QAM8192',
+      borderColor: '#cb5be8',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM8192',
+    }, {
+      name: 'time8192StatesL',
+      label: 'QAM8192L',
+      borderColor: '#cb5be8',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'QAM8192L',
+    },
+    ];
+
+    data_rows.forEach(row => {
+      row.time2StatesS = row.performanceData.time2StatesS;
+      row.time2States = row.performanceData.time2States;
+      row.time2StatesL = row.performanceData.time2StatesL;
+      row.time4StatesS = row.performanceData.time4StatesS;
+      row.time4States = row.performanceData.time4States;
+      row.time4StatesL = row.performanceData.time4StatesL;
+      row.time16StatesS = row.performanceData.time16StatesS;
+      row.time16States = row.performanceData.time16States;
+      row.time16StatesL = row.performanceData.time16StatesL;
+      row.time32StatesS = row.performanceData.time32StatesS;
+      row.time32States = row.performanceData.time32States;
+      row.time32StatesL = row.performanceData.time32StatesL;
+      row.time64StatesS = row.performanceData.time64StatesS;
+      row.time64States = row.performanceData.time64States;
+      row.time64StatesL = row.performanceData.time64StatesL;
+      row.time128StatesS = row.performanceData.time128StatesS;
+      row.time128States = row.performanceData.time128States;
+      row.time128StatesL = row.performanceData.time128StatesL;
+      row.time256StatesS = row.performanceData.time256StatesS;
+      row.time256States = row.performanceData.time256States;
+      row.time256StatesL = row.performanceData.time256StatesL;
+      row.time512StatesS = row.performanceData.time512StatesS;
+      row.time512States = row.performanceData.time512States;
+      row.time512StatesL = row.performanceData.time512StatesL;
+      row.time1024StatesS = row.performanceData.time1024StatesS;
+      row.time1024States = row.performanceData.time1024States;
+      row.time1024StatesL = row.performanceData.time1024StatesL;
+      row.time2048StatesS = row.performanceData.time2048StatesS;
+      row.time2048States = row.performanceData.time2048States;
+      row.time2048StatesL = row.performanceData.time2048StatesL;
+      row.time4096StatesS = row.performanceData.time4096StatesS;
+      row.time4096States = row.performanceData.time4096States;
+      row.time4096StatesL = row.performanceData.time4096StatesL;
+      row.time8192StatesS = row.performanceData.time8192StatesS;
+      row.time8192States = row.performanceData.time8192States;
+      row.time8192StatesL = row.performanceData.time8192StatesL;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof AdaptiveModulationDataType] as string,
+          y: row.performanceData[ds.name as keyof AdaptiveModulationDatabaseDataType] as string,
+        });
+      });
+    });
+
+    return {
+      datasets: datasets,
+    };
+  };
+}
+const AdaptiveModulation = withRouter(connect(mapProps, mapDisp)(AdaptiveModulationComponent));
+export default AdaptiveModulation;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
new file mode 100644
index 0000000..021f74a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
@@ -0,0 +1,75 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+import * as React from 'react';
+
+import { TextField, Select, MenuItem, FormControl, InputLabel } from '@mui/material';
+
+import makeStyles from '@mui/styles/makeStyles';
+
+const styles = makeStyles({
+  filterInput: {
+    marginRight: '15px',
+  },
+  filterContainer: {
+    marginLeft: '90px',
+  },
+});
+
+type filterProps = { isVisible: boolean; onFilterChanged: (property: string, filterTerm: string) => void; filters: any };
+
+const ChartFilter: React.FunctionComponent<filterProps> = (props) => {
+
+
+  const classes = styles();
+
+  // make sure suspectIntervalFlag is a string to show the correct value in the select element
+
+  const suspectIntervalFlag = props.filters.suspectIntervalFlag === undefined ? undefined : props.filters.suspectIntervalFlag.toString();
+  return (
+    <>
+      {
+        props.isVisible &&
+        <div className={classes.filterContainer}>
+          <TextField variant="standard" inputProps={{ 'aria-label': 'radio-signal-filter' }} className={classes.filterInput}
+            label="Radio Signal" value={props.filters.radioSignalId || ''} onChange={(event) => props.onFilterChanged('radioSignalId', event.target.value)} InputLabelProps={{
+              shrink: true,
+            }} />
+          <TextField variant="standard" inputProps={{ 'aria-label': 'scanner-id-filter' }} className={classes.filterInput} label="Scanner ID" value={props.filters.scannerId || ''} onChange={(event) => props.onFilterChanged('scannerId', event.target.value)} InputLabelProps={{
+            shrink: true,
+          }} />
+          <TextField variant="standard" inputProps={{ 'aria-label': 'end-time-filter' }} className={classes.filterInput} label="End Time" value={props.filters.timeStamp || ''} onChange={(event) => props.onFilterChanged('timeStamp', event.target.value)} InputLabelProps={{
+            shrink: true,
+          }} />
+          <FormControl variant="standard">
+            <InputLabel id="suspect-interval-label" shrink>Suspect Interval</InputLabel>
+
+            <Select variant="standard" aria-label="suspect-interval-selection" labelId="suspect-interval-label" value={suspectIntervalFlag || ''} onChange={(event) => props.onFilterChanged('suspectIntervalFlag', event.target.value as string)}>
+              <MenuItem value={undefined} aria-label="none">None</MenuItem>
+              <MenuItem value={'true'} aria-label="true">true</MenuItem>
+              <MenuItem value={'false'} aria-label="false">false</MenuItem>
+            </Select>
+          </FormControl>
+        </ div>
+      }
+    </>
+  );
+};
+
+export default ChartFilter;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
new file mode 100644
index 0000000..5f925a9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
@@ -0,0 +1,155 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createCrossPolarDiscriminationActions, createCrossPolarDiscriminationProperties } from '../handlers/crossPolarDiscriminationHandler';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { CrossPolarDiscriminationDatabaseDataType, CrossPolarDiscriminationDataType } from '../models/crossPolarDiscriminationDataType';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+
+const mapProps = (state: IApplicationStoreState) => ({
+  crossPolarDiscriminationProperties: createCrossPolarDiscriminationProperties(state),
+  currentView: state.performanceHistory.subViews.CPD.subView,
+  isFilterVisible: state.performanceHistory.subViews.CPD.isFilterVisible,
+  existingFilter: state.performanceHistory.crossPolarDiscrimination.filter,
+
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  crossPolarDiscriminationActions: createCrossPolarDiscriminationActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('CPD', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('CPD', value));},
+});
+
+type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType<CrossPolarDiscriminationDataType>;
+
+/**
+ * The Component which gets the crossPolarDiscrimination data from the database based on the selected time period.
+ */
+class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+  onChange = (value: 'chart' | 'table') => {
+    this.props.setSubView(value);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.crossPolarDiscriminationActions.onFilterChanged(property, filterTerm);
+    if (!this.props.crossPolarDiscriminationProperties.showFilter)
+      this.props.crossPolarDiscriminationActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.crossPolarDiscriminationProperties;
+    const actions = this.props.crossPolarDiscriminationActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+
+    const cpdColumns: ColumnModel<CrossPolarDiscriminationDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      },
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      cpdColumns.push(addColumnLabels<CrossPolarDiscriminationDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+          existingFilter={this.props.crossPolarDiscriminationProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+          {lineChart(chartPagedData)}
+          <CrossPolarDiscriminationTable stickyHeader idProperty={'_id'} tableId="cross-polar-discrimination-table" columns={cpdColumns} {...properties} {...actions} />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for CPD according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+  private getChartDataValues = (rows: CrossPolarDiscriminationDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'xpdMin',
+      label: 'xpd-min',
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'CPD (min)[db]',
+    }, {
+      name: 'xpdAvg',
+      label: 'xpd-avg',
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'CPD (avg)[db]',
+    }, {
+      name: 'xpdMax',
+      label: 'xpd-max',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'CPD (max)[db]',
+    }];
+
+    data_rows.forEach(row => {
+      row.xpdMin = row.performanceData.xpdMin;
+      row.xpdAvg = row.performanceData.xpdAvg;
+      row.xpdMax = row.performanceData.xpdMax;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof CrossPolarDiscriminationDataType] as string,
+          y: row.performanceData[ds.name as keyof CrossPolarDiscriminationDatabaseDataType] as string,
+        });
+      });
+    });
+    return {
+      datasets: datasets,
+    };
+  };
+}
+const CrossPolarDiscrimination = withRouter(connect(mapProps, mapDisp)(CrossPolarDiscriminationComponent));
+export default CrossPolarDiscrimination;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
new file mode 100644
index 0000000..bd6333b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
@@ -0,0 +1,105 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import { FormControl, MenuItem, Select, SelectChangeEvent, Typography } from '@mui/material';
+import { Theme } from '@mui/material/styles';
+import makeStyles from '@mui/styles/makeStyles';
+import { Loader } from '../../../../framework/src/components/material-ui';
+import { LtpIds } from '../models/availableLtps';
+
+const useStyles = makeStyles((theme: Theme) => ({
+  display: {
+    display: 'inline-block',
+  },
+  selectDropdown: {
+    borderRadius: 1,
+    position: 'relative',
+    backgroundColor: theme.palette.background.paper,
+    border: '1px solid #ced4da',
+    fontSize: 16,
+    width: 'auto',
+    padding: '5px 5px 5px 5px',
+    transition: theme.transitions.create(['border-color', 'box-shadow']),
+  },
+  center: {
+    'flex': '1',
+    'height': '100%',
+    'display': 'flex',
+    'alignItems': 'center',
+    'justifyContent': 'center',
+    flexDirection: 'column',
+  },
+}));
+
+type LtpSelectionProps = {
+  selectedNE: string; error?: string; finishedLoading: boolean; selectedLtp: string;
+  availableLtps: LtpIds[];
+  onChangeLtp(event: SelectChangeEvent<HTMLSelectElement | string>): void;
+  selectedTimePeriod: string;
+  onChangeTimePeriod(event: SelectChangeEvent<HTMLSelectElement | string>): void;
+};
+
+export const LtpSelection = (props: LtpSelectionProps) => {
+  const classes = useStyles();
+  return (
+    <>
+      <h3>Selected Network Element: {props.selectedNE} </h3>
+      <FormControl variant="standard" className={classes.display}>
+        <span>
+          Select LTP
+        </span>
+        <Select variant="standard" className={classes.selectDropdown} value={props.selectedLtp} onChange={props.onChangeLtp} aria-label="ltp-selection" >
+          <MenuItem value={'-1'} aria-label="none"><em>--Select--</em></MenuItem>
+          {props.availableLtps.map(ltp =>
+            (<MenuItem value={ltp.key} key={ltp.key} aria-label={ltp.key}>{ltp.key}</MenuItem>))}
+        </Select>
+        <span> Time-Period </span>
+        <Select variant="standard" className={classes.selectDropdown} value={props.selectedTimePeriod} onChange={props.onChangeTimePeriod} aria-label="time-period-selection">
+          <MenuItem value={'15min'} aria-label="15minutes">15min</MenuItem>
+          <MenuItem value={'24hours'} aria-label="24hours">24hours</MenuItem>
+        </Select>
+      </FormControl>
+      {
+        !props.finishedLoading && !props.error &&
+        <div className={classes.center}>
+          <Loader />
+          <h3>Collecting Data ...</h3>
+        </div>
+      }
+      {
+        props.finishedLoading && props.error &&
+        <div className={classes.center}>
+          <h3>Data couldn't be loaded</h3>
+          <Typography variant="body1">{props.error}</Typography>
+        </div>
+      }
+      {
+        props.selectedLtp === '-1' && props.finishedLoading && !props.error && (props.availableLtps.length > 0 ?
+          <div className={classes.center}>
+            <h3>Please select a LTP</h3>
+          </div>
+          :
+          <div className={classes.center}>
+            <h3>No performance data found</h3>
+          </div>)
+      }
+    </>);
+};
+
+export default LtpSelection;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
new file mode 100644
index 0000000..fb608aa
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
@@ -0,0 +1,150 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createPerformanceDataActions, createPerformanceDataProperties } from '../handlers/performanceDataHandler';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { PerformanceDatabaseDataType, PerformanceDataType } from '../models/performanceDataType';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  performanceDataProperties: createPerformanceDataProperties(state),
+  currentView: state.performanceHistory.subViews.performanceData.subView,
+  isFilterVisible: state.performanceHistory.subViews.performanceData.isFilterVisible,
+  existingFilter: state.performanceHistory.performanceData.filter,
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  performanceDataActions: createPerformanceDataActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('performanceData', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('performanceData', value)); },
+});
+
+type PerformanceDataComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const PerformanceDataTable = MaterialTable as MaterialTableCtorType<PerformanceDataType>;
+
+/**
+ * The Component which gets the performance data from the database based on the selected time period.
+ */
+class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.performanceDataActions.onFilterChanged(property, filterTerm);
+    if (!this.props.performanceDataProperties.showFilter)
+      this.props.performanceDataActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.performanceDataProperties;
+    const actions = this.props.performanceDataActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const performanceColumns: ColumnModel<PerformanceDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      },
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      performanceColumns.push(addColumnLabels<PerformanceDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        <ToggleContainer onToggleFilterButton={() => this.props.toggleFilterButton(!this.props.isFilterVisible)}
+          existingFilter={this.props.existingFilter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} showFilter={this.props.isFilterVisible} onChange={this.props.setSubView}>
+          {lineChart(chartPagedData)}
+          <PerformanceDataTable stickyHeader idProperty={'_id'} tableId="performance-data-table" columns={performanceColumns} {...properties} {...actions} />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for PerformanceData according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+  private getChartDataValues = (rows: PerformanceDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'es',
+      label: 'es',
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'ES',
+    }, {
+      name: 'ses',
+      label: 'ses',
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'SES',
+    }, {
+      name: 'unavailability',
+      label: 'unavailability',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Unavailability',
+    }];
+
+    data_rows.forEach(row => {
+      row.es = row.performanceData.es;
+      row.ses = row.performanceData.ses;
+      row.unavailability = row.performanceData.unavailability;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof PerformanceDataType] as string,
+          y: row.performanceData[ds.name as keyof PerformanceDatabaseDataType] as string,
+        });
+      });
+    });
+
+    return {
+      datasets: datasets,
+    };
+  };
+}
+
+const PerformanceData = withRouter(connect(mapProps, mapDisp)(PerformanceDataComponent));
+export default PerformanceData;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
new file mode 100644
index 0000000..125cc6e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
@@ -0,0 +1,154 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createReceiveLevelActions, createReceiveLevelProperties } from '../handlers/receiveLevelHandler';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { ReceiveLevelDatabaseDataType, ReceiveLevelDataType } from '../models/receiveLevelDataType';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  receiveLevelProperties: createReceiveLevelProperties(state),
+  currentView: state.performanceHistory.subViews.receiveLevel.subView,
+  isFilterVisible: state.performanceHistory.subViews.receiveLevel.isFilterVisible,
+  existingFilter: state.performanceHistory.receiveLevel.filter,
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  receiveLevelActions: createReceiveLevelActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('receiveLevel', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('receiveLevel', value)); },
+});
+
+type ReceiveLevelComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const ReceiveLevelTable = MaterialTable as MaterialTableCtorType<ReceiveLevelDataType>;
+
+/**
+ * The Component which gets the receiveLevel data from the database based on the selected time period.
+ */
+class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+
+  onChange = (value: 'chart' | 'table') => {
+    this.props.setSubView(value);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.receiveLevelActions.onFilterChanged(property, filterTerm);
+    if (!this.props.receiveLevelProperties.showFilter)
+      this.props.receiveLevelActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.receiveLevelProperties;
+    const actions = this.props.receiveLevelActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const receiveLevelColumns: ColumnModel<ReceiveLevelDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      },
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      receiveLevelColumns.push(addColumnLabels<ReceiveLevelDataType>(ds.name, ds.columnLabel));
+    });
+
+    return (
+      <>
+        <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.receiveLevelProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+          {lineChart(chartPagedData)}
+          <ReceiveLevelTable stickyHeader idProperty={'_id'} tableId="receive-level-table" columns={receiveLevelColumns} {...properties} {...actions} />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for ReceiveLevel according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+  private getChartDataValues = (rows: ReceiveLevelDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'rxLevelMin',
+      label: 'rx-level-min',
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Rx min',
+    }, {
+      name: 'rxLevelAvg',
+      label: 'rx-level-avg',
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Rx avg',
+    }, {
+      name: 'rxLevelMax',
+      label: 'rx-level-max',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Rx max',
+    }];
+
+    data_rows.forEach(row => {
+      row.rxLevelMin = row.performanceData.rxLevelMin;
+      row.rxLevelAvg = row.performanceData.rxLevelAvg;
+      row.rxLevelMax = row.performanceData.rxLevelMax;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof ReceiveLevelDataType] as string,
+          y: row.performanceData[ds.name as keyof ReceiveLevelDatabaseDataType] as string,
+        });
+      });
+    });
+    return {
+      datasets: datasets,
+    };
+  };
+}
+
+const ReceiveLevel = withRouter(connect(mapProps, mapDisp)(ReceiveLevelComponent));
+export default ReceiveLevel;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
new file mode 100644
index 0000000..85241fb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
@@ -0,0 +1,156 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createSignalToInterferenceActions, createSignalToInterferenceProperties } from '../handlers/signalToInterferenceHandler';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { SignalToInterferenceDatabaseDataType, SignalToInterferenceDataType } from '../models/signalToInteferenceDataType';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  signalToInterferenceProperties: createSignalToInterferenceProperties(state),
+  currentView: state.performanceHistory.subViews.SINR.subView,
+  isFilterVisible: state.performanceHistory.subViews.SINR.isFilterVisible,
+  existingFilter: state.performanceHistory.signalToInterference.filter,
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  signalToInterferenceActions: createSignalToInterferenceActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('SINR', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('SINR', value)); },
+});
+
+type SignalToInterferenceComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType<SignalToInterferenceDataType>;
+
+/**
+ * The Component which gets the signal to interference data from the database based on the selected time period.
+ */
+class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+  onChange = (value: 'chart' | 'table') => {
+    this.props.setSubView(value);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.signalToInterferenceActions.onFilterChanged(property, filterTerm);
+    if (!this.props.signalToInterferenceProperties.showFilter)
+      this.props.signalToInterferenceActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.signalToInterferenceProperties;
+    const actions = this.props.signalToInterferenceActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+
+    const sinrColumns: ColumnModel<SignalToInterferenceDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      },
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      sinrColumns.push(addColumnLabels<SignalToInterferenceDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+          existingFilter={this.props.signalToInterferenceProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+          {lineChart(chartPagedData)}
+          <SignalToInterferenceTable stickyHeader idProperty={'_id'} tableId="signal-to-interference-table" columns={sinrColumns} {...properties} {...actions}
+          />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for SINR according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: SignalToInterferenceDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'snirMin',
+      label: 'snir-min',
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'SINR (min)[db]',
+    }, {
+      name: 'snirAvg',
+      label: 'snir-avg',
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'SINR (avg)[db]',
+    }, {
+      name: 'snirMax',
+      label: 'snir-max',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'SINR (max)[db]',
+    }];
+
+    data_rows.forEach(row => {
+      row.snirMin = row.performanceData.snirMin;
+      row.snirAvg = row.performanceData.snirAvg;
+      row.snirMax = row.performanceData.snirMax;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof SignalToInterferenceDataType] as string,
+          y: row.performanceData[ds.name as keyof SignalToInterferenceDatabaseDataType] as string,
+        });
+      });
+    });
+    return {
+      datasets: datasets,
+    };
+  };
+}
+
+const SignalToInterference = withRouter(connect(mapProps, mapDisp)(SignalToInterferenceComponent));
+export default SignalToInterference;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/temperature.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
new file mode 100644
index 0000000..d4b8233
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
@@ -0,0 +1,156 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createTemperatureActions, createTemperatureProperties } from '../handlers/temperatureHandler';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { TemperatureDatabaseDataType, TemperatureDataType } from '../models/temperatureDataType';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  temperatureProperties: createTemperatureProperties(state),
+  currentView: state.performanceHistory.subViews.temperatur.subView,
+  isFilterVisible: state.performanceHistory.subViews.temperatur.isFilterVisible,
+  existingFilter: state.performanceHistory.temperature.filter,
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  temperatureActions: createTemperatureActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('Temp', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('Temp', value)); },
+
+});
+
+type TemperatureComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const TemperatureTable = MaterialTable as MaterialTableCtorType<TemperatureDataType>;
+
+/**
+ * The Component which gets the temperature data from the database based on the selected time period.
+ */
+class TemperatureComponent extends React.Component<TemperatureComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+
+  onChange = (value: 'chart' | 'table') => {
+    this.props.setSubView(value);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.temperatureActions.onFilterChanged(property, filterTerm);
+    if (!this.props.temperatureProperties.showFilter)
+      this.props.temperatureActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.temperatureProperties;
+    const actions = this.props.temperatureActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const temperatureColumns: ColumnModel<TemperatureDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      },
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      temperatureColumns.push(addColumnLabels<TemperatureDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+
+        <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.temperatureProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+          {lineChart(chartPagedData)}
+          <TemperatureTable stickyHeader idProperty={'_id'} tableId="temperature-table" columns={temperatureColumns} {...properties} {...actions} />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for Temperature according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: TemperatureDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'rfTempMin',
+      label: 'rf-temp-min',
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Rf Temp Min[deg C]',
+    }, {
+      name: 'rfTempAvg',
+      label: 'rf-temp-avg',
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Rf Temp Avg[deg C]',
+    }, {
+      name: 'rfTempMax',
+      label: 'rf-temp-max',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Rf Temp Max[deg C]',
+    }];
+
+    data_rows.forEach(row => {
+      row.rfTempMin = row.performanceData.rfTempMin;
+      row.rfTempAvg = row.performanceData.rfTempAvg;
+      row.rfTempMax = row.performanceData.rfTempMax;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof TemperatureDataType] as string,
+          y: row.performanceData[ds.name as keyof TemperatureDatabaseDataType] as string,
+        });
+      });
+    });
+    return {
+      datasets: datasets,
+    };
+  };
+}
+
+const Temperature = withRouter(connect(mapProps, mapDisp)(TemperatureComponent));
+export default Temperature;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
new file mode 100644
index 0000000..e883aef
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
@@ -0,0 +1,102 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+
+import BarChartIcon from '@mui/icons-material/BarChart';
+import FilterListIcon from '@mui/icons-material/FilterList';
+import TableChartIcon from '@mui/icons-material/TableChart';
+import ToggleButton from '@mui/material/ToggleButton';
+import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
+import Tooltip from '@mui/material/Tooltip';
+import makeStyles from '@mui/styles/makeStyles';
+
+import ChartFilter from './chartFilter';
+
+const styles = makeStyles({
+  toggleButtonContainer: {
+    display: 'flex',
+    alignItems: 'center',
+    justifyContent: 'center',
+    padding: '10px',
+  },
+  subViewGroup: {
+    padding: '10px',
+  },
+  filterGroup: {
+    marginLeft: '10px',
+  },
+});
+
+type toggleProps = { selectedValue: string; onChange(value: string): void; showFilter: boolean; onToggleFilterButton(): void; onFilterChanged: (property: string, filterTerm: string) => void; existingFilter: any };
+
+const ToggleContainer: React.FunctionComponent<toggleProps> = (props) => {
+
+  const classes = styles();
+
+  const handleChange = (event: React.MouseEvent<HTMLElement>, newView: string) => {
+    if (newView !== null) {
+      props.onChange(newView);
+    }
+  };
+
+  const handleFilterChange = (_event: React.MouseEvent<HTMLElement>) => {
+    props.onToggleFilterButton();
+  };
+
+  const children = React.Children.toArray(props.children);
+
+  //hide filter if visible + table
+  //put current name into state, let container handle stuff itelf, register for togglestate, get right via set name
+
+  return (
+        <>
+            <div className={classes.toggleButtonContainer} >
+                <ToggleButtonGroup className={classes.subViewGroup} size="medium" value={props.selectedValue} exclusive onChange={handleChange}>
+                    <ToggleButton aria-label="display-chart" key={1} value="chart">
+                        <Tooltip disableInteractive title="Chart">
+                            <BarChartIcon />
+                        </Tooltip>
+                    </ToggleButton>
+                    <ToggleButton aria-label="display-table" key={2} value="table">
+                        <Tooltip disableInteractive title="Table">
+                            <TableChartIcon />
+                        </Tooltip>
+                    </ToggleButton>
+                </ToggleButtonGroup>
+
+                <ToggleButtonGroup className={classes.filterGroup} onChange={handleFilterChange} >
+                    <ToggleButton value="" aria-label="show-filter" selected={props.showFilter as boolean} disabled={props.selectedValue !== 'chart'}>
+                        <Tooltip disableInteractive title={props.showFilter ? 'Hide filter' : 'Show available filter'}>
+                            <FilterListIcon />
+                        </Tooltip>
+                    </ToggleButton>
+                </ToggleButtonGroup>
+
+
+            </div>
+            {
+                props.selectedValue === 'chart' &&
+                <ChartFilter filters={props.existingFilter} onFilterChanged={props.onFilterChanged} isVisible={props.showFilter} />
+
+            }
+            {props.selectedValue === 'chart' ? children[0] : props.selectedValue === 'table' && children[1]}
+        </>);
+};
+
+export default ToggleContainer;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
new file mode 100644
index 0000000..db9a7c0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
@@ -0,0 +1,158 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { ColumnModel, ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createTransmissionPowerActions, createTransmissionPowerProperties } from '../handlers/transmissionPowerHandler';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { TransmissionPowerDatabaseDataType, TransmissionPowerDataType } from '../models/transmissionPowerDataType';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  transmissionPowerProperties: createTransmissionPowerProperties(state),
+  currentView: state.performanceHistory.subViews.transmissionPower.subView,
+  isFilterVisible: state.performanceHistory.subViews.transmissionPower.isFilterVisible,
+  existingFilter: state.performanceHistory.transmissionPower.filter,
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  transmissionPowerActions: createTransmissionPowerActions(dispatcher.dispatch),
+  setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('transmissionPower', value)),
+  toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('transmissionPower', value)); },
+
+
+});
+
+type TransmissionPowerComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+  selectedTimePeriod: string;
+};
+
+const TransmissionPowerTable = MaterialTable as MaterialTableCtorType<TransmissionPowerDataType>;
+
+/**
+ * The Component which gets the transmission power data from the database based on the selected time period.
+ */
+class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps> {
+  onToggleFilterButton = () => {
+    this.props.toggleFilterButton(!this.props.isFilterVisible);
+  };
+
+  onChange = (value: 'chart' | 'table') => {
+    this.props.setSubView(value);
+  };
+
+  onFilterChanged = (property: string, filterTerm: string) => {
+    this.props.transmissionPowerActions.onFilterChanged(property, filterTerm);
+    if (!this.props.transmissionPowerProperties.showFilter)
+      this.props.transmissionPowerActions.onToggleFilter(false);
+  };
+
+  render(): JSX.Element {
+    const properties = this.props.transmissionPowerProperties;
+    const actions = this.props.transmissionPowerActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+
+    const transmissionColumns: ColumnModel<TransmissionPowerDataType>[] = [
+      { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+      { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+      { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
+      {
+        property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+      },
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      transmissionColumns.push(addColumnLabels<TransmissionPowerDataType>(ds.name, ds.columnLabel));
+    });
+
+    return (
+      <>
+        <ToggleContainer onChange={this.onChange} onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+          existingFilter={this.props.transmissionPowerProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} >
+          {lineChart(chartPagedData)}
+          <TransmissionPowerTable stickyHeader idProperty={'_id'} tableId="transmission-power-table" columns={transmissionColumns} {...properties} {...actions} />
+        </ToggleContainer>
+      </>
+    );
+  }
+
+  /**
+   * This function gets the performance values for TransmissionPower according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: TransmissionPowerDataType[]): IDataSetsObject => {
+    const data_rows = [...rows];
+    sortDataByTimeStamp(data_rows);
+
+    const datasets: IDataSet[] = [{
+      name: 'txLevelMin',
+      label: 'tx-level-min',
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Tx min',
+    }, {
+      name: 'txLevelAvg',
+      label: 'tx-level-avg',
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Tx avg',
+    }, {
+      name: 'txLevelMax',
+      label: 'tx-level-max',
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: 'Tx max',
+    }];
+
+    data_rows.forEach(row => {
+      row.txLevelMin = row.performanceData.txLevelMin;
+      row.txLevelAvg = row.performanceData.txLevelAvg;
+      row.txLevelMax = row.performanceData.txLevelMax;
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row['timeStamp' as keyof TransmissionPowerDataType] as string,
+          y: row.performanceData[ds.name as keyof TransmissionPowerDatabaseDataType] as string,
+        });
+      });
+    });
+    return {
+      datasets: datasets,
+    };
+  };
+}
+
+const TransmissionPower = withRouter(connect(mapProps, mapDisp)(TransmissionPowerComponent));
+export default TransmissionPower;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
new file mode 100644
index 0000000..9baf545
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { AdaptiveModulationDataType } from '../models/adaptiveModulationDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface IAdaptiveModulationState extends IExternalTableState<AdaptiveModulationDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for Adaptive modulation from historicalperformance database.
+ */
+const adaptiveModulationSearchHandler = createSearchDataHandler<AdaptiveModulationDataType>(getFilter, false, null);
+export const {
+  actionHandler: adaptiveModulationActionHandler,
+  createActions: createAdaptiveModulationActions,
+  createProperties: createAdaptiveModulationProperties,
+  createPreActions: createAdaptiveModulationPreActions,
+  reloadAction: adaptiveModulationReloadAction,
+} = createExternal<AdaptiveModulationDataType>(adaptiveModulationSearchHandler, appState => appState.performanceHistory.adaptiveModulation);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
new file mode 100644
index 0000000..f943ef4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
@@ -0,0 +1,99 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import {
+  AllAvailableLtpsLoadedAction,
+  LoadAllAvailableLtpsAction,
+  SetInitialLoadedAction,
+  NoLtpsFoundAction,
+  ResetLtpsAction,
+} from '../actions/ltpAction';
+
+import { LtpIds } from '../models/availableLtps';
+
+export interface IAvailableLtpsState {
+  distinctLtps: LtpIds[];
+  busy: boolean;
+  loadedOnce: boolean;
+  error: string | undefined;
+}
+
+const ltpListStateInit: IAvailableLtpsState = {
+  distinctLtps: [],
+  busy: false,
+  loadedOnce: false,
+  error: undefined,
+};
+
+export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (state = ltpListStateInit, action) => {
+  if (action instanceof LoadAllAvailableLtpsAction) {
+
+    state = {
+      ...state,
+      busy: true,
+    };
+
+  } else if (action instanceof AllAvailableLtpsLoadedAction) {
+    if (!action.error && action.availableLtps) {
+      state = {
+        ...state,
+        distinctLtps: action.availableLtps,
+        busy: false,
+        error: undefined,
+        loadedOnce: true,
+      };
+    } else if (action.error) {
+      state = {
+        ...state,
+        busy: false,
+        loadedOnce: true,
+        error: action.error,
+      };
+    }
+  } else if (action instanceof SetInitialLoadedAction) {
+
+    state = {
+      ...state,
+      loadedOnce: action.initialLoaded,
+    };
+  } else if (action instanceof NoLtpsFoundAction) {
+    state = {
+      ...state,
+      busy: false,
+      error: undefined,
+      loadedOnce: true,
+      distinctLtps: [],
+    };
+  } else if (action instanceof ResetLtpsAction) {
+    state = {
+      ...state,
+      busy: false,
+      error: undefined,
+      loadedOnce: false,
+      distinctLtps: [],
+    };
+  } else {
+    state = {
+      ...state,
+      busy: false,
+    };
+  }
+
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
new file mode 100644
index 0000000..96cabfa
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { CrossPolarDiscriminationDataType } from '../models/crossPolarDiscriminationDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ICrossPolarDiscriminationState extends IExternalTableState<CrossPolarDiscriminationDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for CPD from historicalperformance database.
+ */
+const crossPolarDiscriminationSearchHandler = createSearchDataHandler<CrossPolarDiscriminationDataType>(getFilter, false, null);
+
+export const {
+  actionHandler: crossPolarDiscriminationActionHandler,
+  createActions: createCrossPolarDiscriminationActions,
+  createProperties: createCrossPolarDiscriminationProperties,
+  createPreActions: createCrossPolarDiscriminationPreActions,
+  reloadAction: crossPolarDiscriminationReloadAction,
+} = createExternal<CrossPolarDiscriminationDataType>(crossPolarDiscriminationSearchHandler, appState => appState.performanceHistory.crossPolarDiscrimination);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
new file mode 100644
index 0000000..11e380a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllDeviceListLoadedAction, LoadAllDeviceListAction } from '../actions/deviceListActions';
+import { DeviceListType } from '../models/deviceListType';
+
+export interface IDeviceListState {
+  deviceList: DeviceListType[];
+  busy: boolean;
+}
+
+const deviceListStateInit: IDeviceListState = {
+  deviceList: [],
+  busy: false,
+};
+
+export const deviceListActionHandler: IActionHandler<IDeviceListState> = (state = deviceListStateInit, action) => {
+  if (action instanceof LoadAllDeviceListAction) {
+
+    state = {
+      ...state,
+      busy: true,
+    };
+
+  } else if (action instanceof AllDeviceListLoadedAction) {
+    if (!action.error && action.deviceList) {
+      state = {
+        ...state,
+        deviceList: action.deviceList,
+        busy: false,
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false,
+      };
+    }
+  }
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
new file mode 100644
index 0000000..664c7cd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
@@ -0,0 +1,39 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { PerformanceDataType } from '../models/performanceDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface IPerformanceDataState extends IExternalTableState<PerformanceDataType> { }
+
+/**
+* Creates elastic search material data fetch handler for performance data from historicalperformance15min database.
+*/
+const performanceDataSearchHandler = createSearchDataHandler<PerformanceDataType>(getFilter, false, null);
+
+export const {
+  actionHandler: performanceDataActionHandler,
+  createActions: createPerformanceDataActions,
+  createProperties: createPerformanceDataProperties,
+  createPreActions: createPerformanceDataPreActions,
+  reloadAction: performanceDataReloadAction,
+} = createExternal<PerformanceDataType>(performanceDataSearchHandler, appState => appState.performanceHistory.performanceData);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
new file mode 100644
index 0000000..c0cee46
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
@@ -0,0 +1,181 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// ** do not remove **
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { IConnectAppStoreState } from '../../../connectApp/src/handlers/connectAppRootHandler';
+import { UpdateMountId } from '../actions/deviceListActions';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { ReloadAction } from '../actions/reloadAction';
+import { TimeChangeAction } from '../actions/timeChangeAction';
+import { ResetAllSubViewsAction, SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { PmDataInterval } from '../models/performanceDataType';
+import { currentViewType, SubTabType } from '../models/toggleDataType';
+import { adaptiveModulationActionHandler, IAdaptiveModulationState } from './adaptiveModulationHandler';
+import { availableLtpsActionHandler, IAvailableLtpsState } from './availableLtpsActionHandler';
+import { crossPolarDiscriminationActionHandler, ICrossPolarDiscriminationState } from './crossPolarDiscriminationHandler';
+import { deviceListActionHandler, IDeviceListState } from './deviceListActionHandler';
+import { IPerformanceDataState, performanceDataActionHandler } from './performanceDataHandler';
+import { IReceiveLevelState, receiveLevelActionHandler } from './receiveLevelHandler';
+import { ISignalToInterferenceState, signalToInterferenceActionHandler } from './signalToInterferenceHandler';
+import { ITemperatureState, temperatureActionHandler } from './temperatureHandler';
+import { ITransmissionPowerState, transmissionPowerActionHandler } from './transmissionPowerHandler';
+
+export interface IPerformanceHistoryStoreState {
+  nodeId: string;
+  networkElements: IDeviceListState;
+  ltps: IAvailableLtpsState;
+  performanceData: IPerformanceDataState;
+  receiveLevel: IReceiveLevelState;
+  transmissionPower: ITransmissionPowerState;
+  adaptiveModulation: IAdaptiveModulationState;
+  temperature: ITemperatureState;
+  signalToInterference: ISignalToInterferenceState;
+  crossPolarDiscrimination: ICrossPolarDiscriminationState;
+  currentOpenPanel: string | null;
+  pmDataIntervalType: PmDataInterval;
+  subViews: toggleViewDataType;
+  isReloadSchedueled: boolean;
+}
+
+const mountIdHandler: IActionHandler<string> = (state = '', action) => {
+  if (action instanceof UpdateMountId) {
+    state = '';
+    if (action.nodeId) {
+      state = action.nodeId;
+    }
+  }
+  return state;
+};
+
+const reloadHandler: IActionHandler<boolean> = (state = false, action) => {
+
+  if (action instanceof ReloadAction) {
+    state = action.show;
+  }
+  return state;
+};
+
+
+const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
+  if (action instanceof SetPanelAction) {
+    state = action.panelId;
+  }
+  return state;
+};
+
+const currentPMDataIntervalHandler: IActionHandler<PmDataInterval> = (state = PmDataInterval.pmInterval15Min, action) => {
+  if (action instanceof TimeChangeAction) {
+    state = action.time;
+  }
+  return state;
+};
+
+type filterableSubview = { subView: SubTabType; isFilterVisible: boolean };
+type toggleViewDataType = {
+  currentSubView: currentViewType;
+  performanceData: filterableSubview;
+  receiveLevel: filterableSubview;
+  transmissionPower: filterableSubview;
+  adaptiveModulation: filterableSubview;
+  temperatur: filterableSubview;
+  SINR: filterableSubview;
+  CPD: filterableSubview;
+};
+
+
+const toogleViewDataHandler: IActionHandler<toggleViewDataType> = (
+  state = {
+    currentSubView: 'performanceData',
+    performanceData: { subView: 'chart', isFilterVisible: true },
+    receiveLevel: { subView: 'chart', isFilterVisible: true },
+    adaptiveModulation: { subView: 'chart', isFilterVisible: true },
+    transmissionPower: { subView: 'chart', isFilterVisible: true },
+    temperatur: { subView: 'chart', isFilterVisible: true },
+    SINR: { subView: 'chart', isFilterVisible: true },
+    CPD: { subView: 'chart', isFilterVisible: true },
+  }, action) => {
+
+  if (action instanceof SetSubViewAction) {
+    switch (action.currentView) {
+      case 'performanceData': state = { ...state, performanceData: { ...state.performanceData, subView: action.selectedTab } }; break;
+      case 'adaptiveModulation': state = { ...state, adaptiveModulation: { ...state.adaptiveModulation, subView: action.selectedTab } }; break;
+      case 'receiveLevel': state = { ...state, receiveLevel: { ...state.receiveLevel, subView: action.selectedTab } }; break;
+      case 'transmissionPower': state = { ...state, transmissionPower: { ...state.transmissionPower, subView: action.selectedTab } }; break;
+      case 'Temp': state = { ...state, temperatur: { ...state.temperatur, subView: action.selectedTab } }; break;
+      case 'SINR': state = { ...state, SINR: { ...state.SINR, subView: action.selectedTab } }; break;
+      case 'CPD': state = { ...state, CPD: { ...state.CPD, subView: action.selectedTab } }; break;
+    }
+  } else if (action instanceof SetFilterVisibility) {
+    switch (action.currentView) {
+      case 'performanceData': state = {
+        ...state, performanceData: { ...state.performanceData, isFilterVisible: action.isVisible },
+      }; break;
+      case 'adaptiveModulation': state = { ...state, adaptiveModulation: { ...state.performanceData, isFilterVisible: action.isVisible } }; break;
+      case 'receiveLevel': state = { ...state, receiveLevel: { ...state.receiveLevel, isFilterVisible: action.isVisible } }; break;
+      case 'transmissionPower': state = { ...state, transmissionPower: { ...state.transmissionPower, isFilterVisible: action.isVisible } }; break;
+      case 'Temp': state = { ...state, temperatur: { ...state.temperatur, isFilterVisible: action.isVisible } }; break;
+      case 'SINR': state = { ...state, SINR: { ...state.SINR, isFilterVisible: action.isVisible } }; break;
+      case 'CPD': state = { ...state, CPD: { ...state.CPD, isFilterVisible: action.isVisible } }; break;
+    }
+  } else if (action instanceof ResetAllSubViewsAction) {
+    state = {
+      ...state, performanceData: { ...state.performanceData, subView: 'chart' },
+      adaptiveModulation: { ...state.adaptiveModulation, subView: 'chart' },
+      receiveLevel: { ...state.receiveLevel, subView: 'chart' },
+      transmissionPower: { ...state.transmissionPower, subView: 'chart' },
+      temperatur: { ...state.temperatur, subView: 'chart' },
+      SINR: { ...state.SINR, subView: 'chart' },
+      CPD: { ...state.CPD, subView: 'chart' },
+    };
+  }
+  return state;
+};
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    performanceHistory: IPerformanceHistoryStoreState;
+    connect: IConnectAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  nodeId: mountIdHandler,
+  networkElements: deviceListActionHandler,
+  ltps: availableLtpsActionHandler,
+  performanceData: performanceDataActionHandler,
+  receiveLevel: receiveLevelActionHandler,
+  transmissionPower: transmissionPowerActionHandler,
+  adaptiveModulation: adaptiveModulationActionHandler,
+  temperature: temperatureActionHandler,
+  signalToInterference: signalToInterferenceActionHandler,
+  crossPolarDiscrimination: crossPolarDiscriminationActionHandler,
+  currentOpenPanel: currentOpenPanelHandler,
+  pmDataIntervalType: currentPMDataIntervalHandler,
+  subViews: toogleViewDataHandler,
+  isReloadSchedueled: reloadHandler,
+};
+
+const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
+export default performanceHistoryRootHandler;
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
new file mode 100644
index 0000000..78626eb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { ReceiveLevelDataType } from '../models/receiveLevelDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface IReceiveLevelState extends IExternalTableState<ReceiveLevelDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for receiveLevel from historicalperformance database.
+ */
+const receiveLevelSearchHandler = createSearchDataHandler<ReceiveLevelDataType>(getFilter, false, null);
+
+export const {
+  actionHandler: receiveLevelActionHandler,
+  createActions: createReceiveLevelActions,
+  createProperties: createReceiveLevelProperties,
+  createPreActions: createReceiveLevelPreActions,
+  reloadAction: receiveLevelReloadAction,
+} = createExternal<ReceiveLevelDataType>(receiveLevelSearchHandler, appState => appState.performanceHistory.receiveLevel);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
new file mode 100644
index 0000000..ab6efab
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { SignalToInterferenceDataType } from '../models/signalToInteferenceDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ISignalToInterferenceState extends IExternalTableState<SignalToInterferenceDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for SINR from historicalperformance database.
+ */
+const signalToInterferenceSearchHandler = createSearchDataHandler<SignalToInterferenceDataType>(getFilter, false, null);
+
+export const {
+  actionHandler: signalToInterferenceActionHandler,
+  createActions: createSignalToInterferenceActions,
+  createProperties: createSignalToInterferenceProperties,
+  createPreActions: createSignalToInterferencePreActions,
+  reloadAction: signalToInterferenceReloadAction,
+} = createExternal<SignalToInterferenceDataType>(signalToInterferenceSearchHandler, appState => appState.performanceHistory.signalToInterference);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
new file mode 100644
index 0000000..02bf69b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { TemperatureDataType } from '../models/temperatureDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ITemperatureState extends IExternalTableState<TemperatureDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for Temperature from historicalperformance database.
+ */
+const temperatureSearchHandler = createSearchDataHandler<TemperatureDataType>(getFilter, false, null);
+
+export const {
+  actionHandler: temperatureActionHandler,
+  createActions: createTemperatureActions,
+  createProperties: createTemperatureProperties,
+  createPreActions: createTemperaturePreActions,
+  reloadAction: temperatureReloadAction,
+} = createExternal<TemperatureDataType>(temperatureSearchHandler, appState => appState.performanceHistory.temperature);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
new file mode 100644
index 0000000..9cf70dc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { TransmissionPowerDataType } from '../models/transmissionPowerDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ITransmissionPowerState extends IExternalTableState<TransmissionPowerDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for Transmission power from historicalperformance database.
+ */
+const transmissionPowerSearchHandler = createSearchDataHandler<TransmissionPowerDataType>(getFilter, false, null);
+
+export const {
+  actionHandler: transmissionPowerActionHandler,
+  createActions: createTransmissionPowerActions,
+  createProperties: createTransmissionPowerProperties,
+  createPreActions: createTransmissionPowerPreActions,
+  reloadAction: transmissionPowerReloadAction,
+} = createExternal<TransmissionPowerDataType>(transmissionPowerSearchHandler, appState => appState.performanceHistory.transmissionPower);
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/index.html b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/index.html
new file mode 100644
index 0000000..8cb775b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>PM History Application</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app", "connectApp", "performanceHistoryApp"], function (app, connectApp, performanceHistoryApp) {
+      connectApp.register();
+      performanceHistoryApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts
new file mode 100644
index 0000000..adb0bcd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts
@@ -0,0 +1,109 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+/**
+ * Represents Adaptive Modulation data fields of the performance history table.
+ */
+export type AdaptiveModulationDatabaseDataType = {
+  _id: string ;
+  time2StatesS: number;
+  time2States: number;
+  time2StatesL: number;
+  time4StatesS: number;
+  time4States: number;
+  time4StatesL: number;
+  time16StatesS: number;
+  time16States: number;
+  time16StatesL: number;
+  time32StatesS: number;
+  time32States: number;
+  time32StatesL: number;
+  time64StatesS: number;
+  time64States: number;
+  time64StatesL: number;
+  time128StatesS: number;
+  time128States: number;
+  time128StatesL: number;
+  time256StatesS: number;
+  time256States: number;
+  time256StatesL: number;
+  time512StatesS: number;
+  time512States: number;
+  time512StatesL: number;
+  time1024StatesS: number;
+  time1024States: number;
+  time1024StatesL: number;
+  time2048StatesS: number;
+  time2048States: number;
+  time2048StatesL: number;
+  time4096StatesS: number;
+  time4096States: number;
+  time4096StatesL: number;
+  time8192StatesS: number;
+  time8192States: number;
+  time8192StatesL: number;
+};
+
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type AdaptiveModulationDataType = {
+  performanceData: AdaptiveModulationDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  time2StatesS: number;
+  time2States: number;
+  time2StatesL: number;
+  time4StatesS: number;
+  time4States: number;
+  time4StatesL: number;
+  time16StatesS: number;
+  time16States: number;
+  time16StatesL: number;
+  time32StatesS: number;
+  time32States: number;
+  time32StatesL: number;
+  time64StatesS: number;
+  time64States: number;
+  time64StatesL: number;
+  time128StatesS: number;
+  time128States: number;
+  time128StatesL: number;
+  time256StatesS: number;
+  time256States: number;
+  time256StatesL: number;
+  time512StatesS: number;
+  time512States: number;
+  time512StatesL: number;
+  time1024StatesS: number;
+  time1024States: number;
+  time1024StatesL: number;
+  time2048StatesS: number;
+  time2048States: number;
+  time2048StatesL: number;
+  time4096StatesS: number;
+  time4096States: number;
+  time4096StatesL: number;
+  time8192StatesS: number;
+  time8192States: number;
+  time8192StatesL: number;
+} & { _id: string };
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
new file mode 100644
index 0000000..6006157
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
@@ -0,0 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type LtpIds = {
+  key: string;
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
new file mode 100644
index 0000000..969c0b3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export interface IData {
+  x: string;
+  y: string;
+}
+
+/**
+ * Structure of chartjs dataset with the chart properties.
+ */
+export interface IDataSet {
+  name: string;
+  label: string;
+  lineTension: 0;
+  bezierCurve: boolean;
+  fill: boolean;
+  borderColor: string;
+  data: IData[];
+  columnLabel: string;
+}
+
+/**
+ * Structure of chartjs dataset which is sent to the chart.
+ */
+export interface IDataSetsObject {
+  datasets: IDataSet[];
+}
+
+/**
+ * Interface used by chart for sorting on time-stamp
+ */
+export interface ITimeStamp {
+  timeStamp: string;
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
new file mode 100644
index 0000000..749624b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type CrossPolarDiscriminationDatabaseDataType = {
+  _id: string;
+  xpdMin: number;
+  xpdAvg: number;
+  xpdMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type CrossPolarDiscriminationDataType = {
+  performanceData: CrossPolarDiscriminationDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  xpdMin: number;
+  xpdAvg: number;
+  xpdMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
new file mode 100644
index 0000000..fbe3141
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents all the distinct devices from the performance history data.
+ */
+
+export type DeviceListType = {
+  nodeId: string;
+};
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/panelId.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/panelId.ts
new file mode 100644
index 0000000..08bf7f8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/panelId.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents PanelIds for the available Expansional panels.
+ */
+export type PanelId = null | 'PerformanceData' | 'ReceiveLevel' | 'TransmissionPower' | 'AdaptiveModulation' | 'Temperature' | 'SINR' | 'CPD';
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
new file mode 100644
index 0000000..f71e09d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+//export { HitEntry, Result } from '../../../../framework/src/models';
+
+/**
+ * Represents performance data fields of the performance history table as used in the database
+ */
+export type PerformanceDatabaseDataType = {
+  _id: string;
+  es: number;
+  ses: number;
+  unavailability: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type PerformanceDataType = {
+
+  performanceData: PerformanceDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  es: number;
+  ses: number;
+  unavailability: number;
+} & { _id: string };
+
+
+/**
+ * Represents performance data time interval.
+ */
+export const enum PmDataInterval {
+  pmInterval15Min,
+  pmInterval24Hours,
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts
new file mode 100644
index 0000000..2748a3d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type ReceiveLevelDatabaseDataType = {
+  _id: string;
+  rxLevelMin: number;
+  rxLevelAvg: number;
+  rxLevelMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type ReceiveLevelDataType = {
+  performanceData: ReceiveLevelDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  rxLevelMin: number;
+  rxLevelAvg: number;
+  rxLevelMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts
new file mode 100644
index 0000000..5c675fe
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type SignalToInterferenceDatabaseDataType = {
+  _id: string; 
+  snirMin: number;
+  snirAvg: number;
+  snirMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type SignalToInterferenceDataType = {
+  performanceData: SignalToInterferenceDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  snirMin: number;
+  snirAvg: number;
+  snirMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
new file mode 100644
index 0000000..5798d5c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type TemperatureDatabaseDataType = {
+  _id: string;
+  rfTempMin: number;
+  rfTempAvg: number;
+  rfTempMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type TemperatureDataType = {
+  performanceData: TemperatureDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  rfTempMin: number;
+  rfTempAvg: number;
+  rfTempMax: number;
+} & { _id: string };
+
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
new file mode 100644
index 0000000..0e71c94
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Specifies possible sub views
+ */
+export type SubTabType = 'chart' | 'table';
+
+export type currentViewType = 'performanceData' | 'receiveLevel' | 'transmissionPower' | 'adaptiveModulation' | 'Temp' | 'SINR' | 'CPD';
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
new file mode 100644
index 0000000..f52af97
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export interface TopologyNode {
+  'node-id': string;
+}
+
+export interface Topology {
+  'topology-id': string;
+  node: TopologyNode[];
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts
new file mode 100644
index 0000000..62c00bf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type TransmissionPowerDatabaseDataType = {
+  _id: string;
+  txLevelMin: number;
+  txLevelAvg: number;
+  txLevelMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type TransmissionPowerDataType = {
+  performanceData: TransmissionPowerDatabaseDataType;
+  radioSignalId: string;
+  scannerId: string;
+  timeStamp: string;
+  suspectIntervalFlag: boolean;
+  txLevelMin: number;
+  txLevelAvg: number;
+  txLevelMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
new file mode 100644
index 0000000..ef939fd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
@@ -0,0 +1,147 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+import { ApplicationStore } from '../../../framework/src/store/applicationStore';
+
+import { updateMountIdActionCreator } from './actions/deviceListActions';
+import { ResetLtpsAction } from './actions/ltpAction';
+import { ReloadAction } from './actions/reloadAction';
+import { ResetAllSubViewsAction } from './actions/toggleActions';
+import performanceHistoryRootHandler from './handlers/performanceHistoryRootHandler';
+import { PmDataInterval } from './models/performanceDataType';
+import PerformanceHistoryApplication from './views/performanceHistoryApplication';
+
+const appIcon = require('./assets/icons/performanceHistoryAppIcon.svg');  // select app icon
+
+let api: {
+  readonly applicationStore: ApplicationStore | null;
+  readonly applicationStoreInitialized: Promise<ApplicationStore>;
+};
+
+const mapProps = () => ({
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  updateMountId: (mountId: string) => dispatcher.dispatch(updateMountIdActionCreator(mountId)),
+  resetLtps: () => dispatcher.dispatch(new ResetLtpsAction()),
+  resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction()),
+  setScheduleReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show)),
+});
+
+let currentMountId: string | null = null;
+let lastUrl: string = '/performanceHistory';
+const PerformanceHistoryApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+  let mountId: string = '';
+
+  const getMountId = (last_url: string) => {
+    let index = last_url.lastIndexOf('performanceHistory/');
+    if (index >= 0) {
+      mountId = last_url.substring(index + 19);
+    } else {
+      mountId = '';
+    }
+
+    return mountId;
+  };
+
+  const scheduleReload = (current_mount_id: string) => {
+    props.updateMountId(current_mount_id);
+    props.resetLtps();
+    props.resetSubViews();
+    props.setScheduleReload(true);
+  };
+  
+  // called when component finished mounting
+  React.useEffect(() => {
+
+    lastUrl = props.location.pathname;
+    mountId = getMountId(lastUrl);
+
+    if (currentMountId !== mountId) { // new element is loaded
+      currentMountId = mountId;
+      scheduleReload(currentMountId);
+    } else
+    if (currentMountId !== '') { // same element is loaded again
+      scheduleReload(currentMountId);
+    }
+  }, []);
+
+  // called when component gets updated
+  React.useEffect(() => {
+
+    lastUrl = props.location.pathname;
+    mountId = getMountId(lastUrl);
+
+    if (currentMountId !== mountId) {
+      currentMountId = mountId;
+      scheduleReload(currentMountId);
+    }
+
+  });
+
+  return (
+    <PerformanceHistoryApplication />
+  );
+});
+
+const PerformanceHistoryRouterApp = withRouter((props: RouteComponentProps) => {
+  props.history.action = 'POP';
+  return (
+    <Switch>
+      <Route path={`${props.match.path}/:mountId`} component={PerformanceHistoryApplicationRouteAdapter} />
+      <Route path={`${props.match.path}`} component={PerformanceHistoryApplicationRouteAdapter} />
+      <Redirect to={`${props.match.path}`} />
+    </Switch>
+  );
+});
+
+export function register() {
+  api = applicationManager.registerApplication({
+    name: 'performanceHistory',
+    icon: appIcon,
+    rootComponent: PerformanceHistoryRouterApp,
+    rootActionHandler: performanceHistoryRootHandler,
+    menuEntry: 'Performance',
+  });
+}
+
+export function setPmDataInterval(pmDataInterval: PmDataInterval): boolean {
+  let reload: boolean = true;
+  if (api && api.applicationStore) {
+    if (api.applicationStore.state.performanceHistory.pmDataIntervalType !== pmDataInterval) {
+      reload = true;
+    }
+    api.applicationStore.state.performanceHistory.pmDataIntervalType = pmDataInterval;
+  }
+  return reload;
+}
+
+
+export function getPmDataInterval(): PmDataInterval {
+  let result = api && api.applicationStore
+    ? api.applicationStore.state.performanceHistory.pmDataIntervalType
+    : PmDataInterval.pmInterval15Min;
+  return result ? result : PmDataInterval.pmInterval15Min;
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
new file mode 100644
index 0000000..ef013f1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Result } from '../../../../framework/src/models/elasticSearch';
+import { requestRest } from '../../../../framework/src/services/restService';
+
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { LtpIds } from '../models/availableLtps';
+import { DeviceListType } from '../models/deviceListType';
+
+/** 
+ * Represents a web api accessor service for Network elements actions.
+ */
+class PerformanceService {
+
+  /**
+   * Get distinct ltps based on the selected network element and time period from the historicalperformance15min database table.
+   */
+  public async getDistinctLtpsFromDatabase(networkElement: string, selectedTimePeriod: string): Promise<LtpIds[] | null> {
+    let path;
+    const query = {
+      'filter': [{
+        'property': 'node-name',
+        'filtervalue': networkElement,
+      }],
+      'sortorder': [],
+      'pagination': {
+        'size': 20,
+        'page': 1,
+      },
+    };
+
+
+    if (selectedTimePeriod === '15min') {
+      path = '/rests/operations/data-provider:read-pmdata-15m-ltp-list';
+    } else {
+      path = '/rests/operations/data-provider:read-pmdata-24h-ltp-list';
+    }
+
+    const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
+    return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({ key: ne })) || null;
+  }
+
+
+
+  /**
+  * Gets all devices from the performanceHistory 15min backend.
+  */
+  public async getDeviceListfromPerf15minHistory(): Promise<(DeviceListType)[] | null> {
+    const path = '/rests/operations/data-provider:read-pmdata-15m-device-list';
+    const query = {
+      'data-provider:input': {
+        'filter': [],
+        'sortorder': [],
+        'pagination': {
+          'size': 20,
+          'page': 1,
+        },
+      },
+    };
+
+    const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(query) });
+    return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+      nodeId: ne,
+    })) || null;
+  }
+
+  /**
+   * Gets all devices from the performanceHistory 24h backend.
+   */
+  public async getDeviceListfromPerf24hHistory(): Promise<(DeviceListType)[] | null> {
+    const path = '/rests/operations/data-provider:read-pmdata-24h-device-list';
+    const query = {
+      'data-provider:input': {
+        'filter': [],
+        'sortorder': [],
+        'pagination': {
+          'size': 20,
+          'page': 1,
+        },
+      },
+    };
+
+    const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(query) });
+    return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+      nodeId: ne,
+    })) || null;
+  }
+}
+
+
+export const PerformanceHistoryService = new PerformanceService();
+export default PerformanceHistoryService;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
new file mode 100644
index 0000000..38abb3e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import moment from 'moment';
+import { Line } from 'react-chartjs-2';
+
+import { IDataSetsObject } from '../models/chartTypes';
+import { ITimeStamp } from '../models/chartTypes';
+
+const style: React.CSSProperties = {
+  height: '80%',
+};
+
+export const lineChart = (chartPagedData: IDataSetsObject) => {
+  return (
+    <div style={style}>
+      <Line ref="chart" data={chartPagedData} options={{
+        responsive: true,
+        maintainAspectRatio: false,
+        scales: {
+          xAxes: [{
+            type: 'time',
+            time: {
+              displayFormats: {
+                'second': 'DD MMM YYYY HH:mm:ss',
+                'minute': 'DD MMM YYYY HH:mm:ss',
+                'hour': 'DD MMM YYYY HH:mm:ss',
+                'year': 'DD MMM YYYY HH:mm:ss',
+              },
+              parser: function (date: string) {
+                let offsetValue = new Date().getTimezoneOffset();
+                var utcDate = moment(date, 'YYYY-MM-DDTHH:mm:ss').utcOffset(offsetValue).utc(false);
+                return utcDate;
+              },
+            },
+            display: true,
+            scaleLabel: {
+              display: true,
+              labelString: 'Timestamp',
+            },
+          }],
+          yAxes: [{
+            ticks: {
+              beginAtZero: true,
+            },
+            scaleLabel: {
+              display: true,
+              labelString: 'Value',
+            },
+          }],
+        },
+      }} />
+    </div>
+  );
+};
+
+export const sortDataByTimeStamp = <T extends ITimeStamp>(_rows: T[]): T[] => {
+  return (_rows.sort((a, b) => {
+    const result = Date.parse(a.timeStamp) - Date.parse(b.timeStamp);
+    return isNaN(result) ? 0 : result;
+  }));
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
new file mode 100644
index 0000000..37fe962
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { ColumnModel, ColumnType } from '../../../../framework/src/components/material-table';
+
+import { PmDataInterval } from '../models/performanceDataType';
+import { getPmDataInterval } from '../pluginPerformance';
+
+export const addColumnLabels = <T>(name: string, title: string, disableFilter = true, disableSorting = true): ColumnModel<T> => {
+  return { property: name as keyof T, title: title, type: ColumnType.text, disableFilter: disableFilter, disableSorting: disableSorting };
+};
+
+export function getFilter(): string {
+  switch (getPmDataInterval()) {
+    case PmDataInterval.pmInterval15Min:
+      return 'pmdata-15m';
+    case PmDataInterval.pmInterval24Hours:
+      return 'pmdata-24h';
+    default:
+      throw new Error('Unknown time intervall');
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
new file mode 100644
index 0000000..a4b9686
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
@@ -0,0 +1,456 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+
+
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { loadAllDeviceListAsync } from '../actions/deviceListActions';
+import { loadDistinctLtpsbyNetworkElementAsync, ResetLtpsAction } from '../actions/ltpAction';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { TimeChangeAction } from '../actions/timeChangeAction';
+import AdaptiveModulation from '../components/adaptiveModulation';
+import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
+import PerformanceData from '../components/performanceData';
+import ReceiveLevel from '../components/receiveLevel';
+import SignalToInterference from '../components/signalToInterference';
+import Temperature from '../components/temperature';
+import TransmissionPower from '../components/transmissionPower';
+import { adaptiveModulationReloadAction, createAdaptiveModulationActions, createAdaptiveModulationPreActions } from '../handlers/adaptiveModulationHandler';
+import { createCrossPolarDiscriminationActions, createCrossPolarDiscriminationPreActions, crossPolarDiscriminationReloadAction } from '../handlers/crossPolarDiscriminationHandler';
+import { createPerformanceDataActions, createPerformanceDataPreActions, performanceDataReloadAction } from '../handlers/performanceDataHandler';
+import { createReceiveLevelActions, createReceiveLevelPreActions, receiveLevelReloadAction } from '../handlers/receiveLevelHandler';
+import { createSignalToInterferenceActions, createSignalToInterferencePreActions, signalToInterferenceReloadAction } from '../handlers/signalToInterferenceHandler';
+import { createTemperatureActions, createTemperaturePreActions, temperatureReloadAction } from '../handlers/temperatureHandler';
+import { createTransmissionPowerActions, createTransmissionPowerPreActions, transmissionPowerReloadAction } from '../handlers/transmissionPowerHandler';
+import { PanelId } from '../models/panelId';
+import { PmDataInterval } from '../models/performanceDataType';
+
+import { AppBar, SelectChangeEvent, Tab, Tabs } from '@mui/material';
+import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ReloadAction } from '../actions/reloadAction';
+import { ResetAllSubViewsAction } from '../actions/toggleActions';
+import LtpSelection from '../components/ltpSelection';
+
+const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
+  root: {
+    display: 'flex',
+    flexWrap: 'wrap',
+  },
+  margin: {
+    margin: theme.spacing(1),
+  },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  ...state.performanceHistory,
+  activePanel: state.performanceHistory.currentOpenPanel,
+  availableLtps: state.performanceHistory.ltps.distinctLtps,
+  networkElements: state.performanceHistory.networkElements.deviceList,
+  initialLoaded: state.performanceHistory.ltps.loadedOnce,
+  error: state.performanceHistory.ltps.error,
+  shouldReload: state.performanceHistory.isReloadSchedueled,
+});
+
+const mapDispatcher = (dispatcher: IDispatcher) => ({
+  enableFilterPerformanceData: createPerformanceDataActions(dispatcher.dispatch),
+  enableFilterReceiveLevel: createReceiveLevelActions(dispatcher.dispatch),
+  enableFilterTransmissionPower: createTransmissionPowerActions(dispatcher.dispatch),
+  enableFilterAdaptiveModulation: createAdaptiveModulationActions(dispatcher.dispatch),
+  enableFilterTemperature: createTemperatureActions(dispatcher.dispatch),
+  enableFilterSinr: createSignalToInterferenceActions(dispatcher.dispatch),
+  enableFilterCpd: createCrossPolarDiscriminationActions(dispatcher.dispatch),
+  reloadPerformanceData: () => dispatcher.dispatch(performanceDataReloadAction),
+  reloadReceiveLevel: () => dispatcher.dispatch(receiveLevelReloadAction),
+  reloadTransmissionPower: () => dispatcher.dispatch(transmissionPowerReloadAction),
+  reloadAdaptiveModulation: () => dispatcher.dispatch(adaptiveModulationReloadAction),
+  reloadTemperature: () => dispatcher.dispatch(temperatureReloadAction),
+  reloadSignalToInterference: () => dispatcher.dispatch(signalToInterferenceReloadAction),
+  reloadCrossPolarDiscrimination: () => dispatcher.dispatch(crossPolarDiscriminationReloadAction),
+  performanceDataPreActions: createPerformanceDataPreActions(dispatcher.dispatch),
+  receiveLevelPreActions: createReceiveLevelPreActions(dispatcher.dispatch),
+  transmissionPowerPreActions: createTransmissionPowerPreActions(dispatcher.dispatch),
+  adaptiveModulationPreActions: createAdaptiveModulationPreActions(dispatcher.dispatch),
+  temperaturePreActions: createTemperaturePreActions(dispatcher.dispatch),
+  signalToInterferencePreActions: createSignalToInterferencePreActions(dispatcher.dispatch),
+  crossPolarDiscriminationPreActions: createCrossPolarDiscriminationPreActions(dispatcher.dispatch),
+  getAllDevicesPMdata: async () => {
+    await dispatcher.dispatch(loadAllDeviceListAsync);
+  },
+  getDistinctLtpsIds: (
+    selectedNetworkElement: string, 
+    selectedTimePeriod: string, 
+    selectedLtp: string, 
+    selectFirstLtp?: Function, 
+    resetLTP?: Function,
+  ) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
+  setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+  timeIntervalChange: (time: PmDataInterval) => dispatcher.dispatch(new TimeChangeAction(time)),
+  changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => {
+    dispatch(new NavigateToApplication('performanceHistory', nodeId));
+  }),
+  resetLtps: () => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new ResetLtpsAction()); }),
+  resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction()),
+  setShouldReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show)),
+});
+
+export type NetworkElementType = {
+  nodeId: string;
+};
+
+const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementType>;
+
+type PerformanceHistoryComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof PerformanceHistoryComponentStyles>;
+
+type PerformanceHistoryComponentState = {
+  selectedNetworkElement: string;
+  selectedTimePeriod: string;
+  selectedLtp: string;
+  showNetworkElementsTable: boolean;
+  showLtps: boolean;
+  showPanels: boolean;
+  preFilter:
+  {
+    'node-name': string;
+    'uuid-interface': string;
+  } | {};
+};
+
+/**
+* Represents the component for Performance history application.
+*/
+class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComponentProps, PerformanceHistoryComponentState> {
+  /**
+  * Initialises this instance
+  */
+  constructor(props: PerformanceHistoryComponentProps) {
+    super(props);
+    this.state = {
+      selectedNetworkElement: props.nodeId !== '' ? props.nodeId : '-1',
+      selectedTimePeriod: '15min',
+      selectedLtp: '-1',
+      showNetworkElementsTable: true,
+      showLtps: false,
+      showPanels: false,
+      preFilter: {},
+    };
+  }
+
+  onChangeTabs = (event: React.SyntheticEvent, newValue: PanelId) => {
+    const nextActivePanel = newValue;
+    this.changeTabs(nextActivePanel);
+  };
+
+  changeTabs = (nextActivePanel: PanelId) => {
+    this.props.setCurrentPanel(nextActivePanel);
+    const preFilter = this.state.preFilter;
+    switch (nextActivePanel) {
+      case 'PerformanceData':
+        if (this.props.performanceData.preFilter !== {} && this.props.performanceData.preFilter === preFilter) {
+          this.props.reloadPerformanceData();
+        } else {
+          this.props.performanceDataPreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      case 'ReceiveLevel':
+        if (this.props.receiveLevel.preFilter !== {} && this.props.receiveLevel.preFilter === preFilter) {
+          this.props.reloadReceiveLevel();
+        } else {
+          this.props.receiveLevelPreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      case 'TransmissionPower':
+        if (this.props.transmissionPower.preFilter !== {} && this.props.transmissionPower.preFilter === preFilter) {
+          this.props.reloadTransmissionPower();
+        } else {
+          this.props.transmissionPowerPreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      case 'AdaptiveModulation':
+        if (this.props.adaptiveModulation.preFilter !== {} && this.props.adaptiveModulation.preFilter === preFilter) {
+          this.props.reloadAdaptiveModulation();
+        } else {
+          this.props.adaptiveModulationPreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      case 'Temperature':
+        if (this.props.temperature.preFilter !== {} && this.props.temperature.preFilter === preFilter) {
+          this.props.reloadTemperature();
+        } else {
+          this.props.temperaturePreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      case 'SINR':
+        if (this.props.signalToInterference.preFilter !== {} && this.props.signalToInterference.preFilter === preFilter) {
+          this.props.reloadSignalToInterference();
+        } else {
+          this.props.signalToInterferencePreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      case 'CPD':
+        if (this.props.crossPolarDiscrimination.preFilter !== {} && this.props.crossPolarDiscrimination.preFilter === preFilter) {
+          this.props.reloadCrossPolarDiscrimination();
+        } else {
+          this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(preFilter);
+        }
+        break;
+      default:
+        // do nothing if all panels are closed
+        break;
+    }
+  };
+
+  render(): JSX.Element {
+    const { activePanel, nodeId } = this.props;
+    if (nodeId === '') {
+      return (
+        <>
+          <NetworkElementTable tableId="performance-data-element-selection-table" defaultSortColumn={'nodeId'} defaultSortOrder="asc" stickyHeader title={'Please select the network element!'} idProperty={'nodeId'} rows={this.props.networkElements} asynchronus
+            onHandleClick={(event, rowData) => { this.handleNetworkElementSelect(rowData.nodeId); }} columns={
+              [{ property: 'nodeId', title: 'Node Name' }]
+            } />
+        </>
+      );
+    } else {
+      this.handleURLChange(nodeId);
+      return (
+        <>
+          {this.state.showLtps &&
+
+            <LtpSelection error={this.props.error} selectedNE={this.state.selectedNetworkElement} selectedLtp={this.state.selectedLtp} selectedTimePeriod={this.state.selectedTimePeriod}
+              availableLtps={this.props.availableLtps} finishedLoading={this.props.initialLoaded} onChangeTimePeriod={this.handleTimePeriodChange}
+              onChangeLtp={this.handleLtpChange}
+            />
+          }
+          {this.state.showPanels &&
+            <>
+
+              <AppBar enableColorOnDark position="static" >
+                <Tabs indicatorColor="secondary" textColor="inherit" value={activePanel} onChange={this.onChangeTabs} variant="scrollable" scrollButtons="auto" aria-label="performance-data-tabs">
+                  <Tab label="Performance Data" value="PerformanceData" aria-label="performance-data" />
+                  <Tab label="Receive Level" value="ReceiveLevel" aria-label="receive-level" />
+                  <Tab label="Transmission Power" value="TransmissionPower" aria-label="transmission-power" />
+                  <Tab label="Adaptive Modulation" value="AdaptiveModulation" aria-label="adaptive-modulation" />
+                  <Tab label="Temperature" value="Temperature" aria-label="temperature"  />
+                  <Tab label="Signal-to-interference-plus-noise ratio (SINR)" value="SINR" aria-label="sinr" />
+                  <Tab label="Cross Polar Discrimination" value="CPD" aria-label="cross-polar-discrimination" />
+                </Tabs>
+              </AppBar>
+              {
+                activePanel === 'PerformanceData' &&
+                <PerformanceData selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+
+              {
+                activePanel === 'ReceiveLevel' &&
+                <ReceiveLevel selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+
+              {
+                activePanel === 'TransmissionPower' &&
+                <TransmissionPower selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+
+              {
+                activePanel === 'AdaptiveModulation' &&
+                <AdaptiveModulation selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+              {
+                activePanel === 'Temperature' &&
+                <Temperature selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+
+              {
+                activePanel === 'SINR' &&
+                <SignalToInterference selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+
+              {
+                activePanel === 'CPD' &&
+                <CrossPolarDiscrimination selectedTimePeriod={this.state.selectedTimePeriod} />
+              }
+            </>
+          }
+        </>
+      );
+    }
+  }
+
+
+  public componentDidMount() {
+    this.props.setCurrentPanel(null);
+    this.props.getAllDevicesPMdata();
+  }
+
+  /**
+  * Function which selects the first ltp returned from the database on selection of network element.
+  */
+  private selectFirstLtp = (firstLtp: string) => {
+    this.setState({
+      showPanels: true,
+      selectedLtp: firstLtp,
+    });
+    this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, firstLtp);
+    this.changeTabs('PerformanceData');
+  };
+
+  /**
+  * A function which reloads the visible table, if available, based on prefilters defined by network element and ltp on selected time period.
+  */
+  private preFilterChangeAndReload = (networkElement: string, timePeriod: string, ltp: string) => {
+    const newPreFilter = {
+      'node-name': networkElement,
+      'uuid-interface': ltp,
+    };
+
+    const activePanel = this.props.activePanel;
+
+    if (this.props.activePanel !== null) {
+      // set prefilter and reload data if panel is open
+
+      switch (activePanel) {
+        case 'PerformanceData':
+          this.props.performanceDataPreActions.onPreFilterChanged(newPreFilter);
+          break;
+        case 'ReceiveLevel':
+          this.props.receiveLevelPreActions.onPreFilterChanged(newPreFilter);
+          break;
+        case 'TransmissionPower':
+          this.props.transmissionPowerPreActions.onPreFilterChanged(newPreFilter);
+          break;
+        case 'AdaptiveModulation':
+          this.props.adaptiveModulationPreActions.onPreFilterChanged(newPreFilter);
+          break;
+        case 'Temperature':
+          this.props.temperaturePreActions.onPreFilterChanged(newPreFilter);
+          break;
+        case 'SINR':
+          this.props.signalToInterferencePreActions.onPreFilterChanged(newPreFilter);
+          break;
+        case 'CPD':
+          this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(newPreFilter);
+          break;
+        default:
+          // do nothing if all panels are closed
+          break;
+      }
+    }
+
+    // set prefilter
+    this.setState({ preFilter: newPreFilter });
+
+  };
+
+  /**
+   * Function which handles network element changes.
+   */
+  private handleNetworkElementSelect = (selectedNetworkElement: string) => {
+
+    this.setState({
+      showLtps: true,
+      selectedNetworkElement: selectedNetworkElement,
+      showNetworkElementsTable: false,
+      showPanels: false,
+      selectedLtp: '-1',
+    });
+
+    this.props.resetSubViews();
+    this.props.resetLtps();
+    this.setState({ preFilter: {} });
+    this.props.changeNode(selectedNetworkElement);
+    this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, '-1', this.selectFirstLtp);
+  };
+
+  private handleURLChange = (selectedNetworkElement: string) => {
+
+    if (this.props.shouldReload) {
+
+      this.setState({
+        showLtps: true,
+        selectedNetworkElement: selectedNetworkElement,
+        showPanels: false,
+        selectedLtp: '-1',
+      });
+      this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, '-1', this.selectFirstLtp);
+      this.props.setShouldReload(false);
+    }
+  };
+
+  /**
+    * Function which resets the ltps to "--select--" in the state if the passed parameter @ltpNotSelected is true.
+    * @param ltpNotSelected: true, if existing selected is not available in the given time period, else false
+    */
+  private resetLtpDropdown = (ltpNotSelected: boolean) => {
+    if (ltpNotSelected) {
+      this.setState({
+        selectedLtp: '-1',
+        showPanels: false,
+      });
+    }
+  };
+
+  /**
+  * Function which handles the time period changes.
+  */
+  private handleTimePeriodChange = (event: SelectChangeEvent<HTMLSelectElement>) => {
+
+    const selectedTimeInterval = event.target.value === '15min'
+      ? PmDataInterval.pmInterval15Min
+      : PmDataInterval.pmInterval24Hours;
+
+    this.setState({
+      selectedTimePeriod: event.target.value as string,
+    });
+
+    this.props.timeIntervalChange(selectedTimeInterval);
+    this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value as string, this.state.selectedLtp, undefined, this.resetLtpDropdown);
+    this.preFilterChangeAndReload(this.state.selectedNetworkElement, event.target.value as string, this.state.selectedLtp);
+  };
+
+  /**
+  * Function which handles the ltp changes.
+  */
+  private handleLtpChange = (event:SelectChangeEvent<HTMLSelectElement> ) => {
+
+    if (event.target.value === '-1') {
+      this.setState({
+        showPanels: false,
+        selectedLtp: event.target.value,
+      });
+
+    } else if (event.target.value !== this.state.selectedLtp) {
+      this.setState({
+        showPanels: true,
+        selectedLtp: event.target.value as string,
+      });
+      this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, event.target.value as string);
+
+    }
+  };
+}
+
+const PerformanceHistoryApplication = withStyles(PerformanceHistoryComponentStyles)(connect(mapProps, mapDispatcher)(PerformanceHistoryComponent));
+export default PerformanceHistoryApplication;
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/tsconfig.json
new file mode 100644
index 0000000..ca65092
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/webpack.config.js
new file mode 100644
index 0000000..2f25d0d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/performanceHistoryApp/webpack.config.js
@@ -0,0 +1,167 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      performanceHistoryApp: ["./pluginPerformance.tsx"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },{
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "../../framework/src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new CopyWebpackPlugin([{
+            from: 'index.html',
+            to: distPath
+          }]),
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: frameworkPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/oauth2/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/database/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/help/": {
+          target: "http://10.20.6.29:48181",
+          secure: false
+        },
+        "/websocket": {
+          target: "http://10.20.6.29:48181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/framework/.babelrc b/sdnr/wt-odlux/odlux/framework/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/.babelrc
@@ -0,0 +1,17 @@
+{
+  "presets": [
+    ["@babel/preset-react"],
+    ["@babel/preset-env", {
+      "targets": {
+        "chrome": "66"
+      },
+      "spec": true,
+      "loose": false,
+      "modules": false,
+      "debug": false,
+      "useBuiltIns": "usage",
+      "forceAllTransforms": true
+    }]
+  ],
+  "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/framework/LICENSE b/sdnr/wt-odlux/odlux/framework/LICENSE
new file mode 100644
index 0000000..3556ffa
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/LICENSE
@@ -0,0 +1,13 @@
+/*
+ * ============LICENSE_START=============================================================================================================
+ * Copyright (c) 2018 highstreet-technolgies.
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END===============================================================================================================
+ * 
+ */
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/package.json b/sdnr/wt-odlux/odlux/framework/package.json
new file mode 100644
index 0000000..9973d3b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/package.json
@@ -0,0 +1,59 @@
+{

+  "name": "@odlux/framework",

+  "version": "0.1.4",

+  "description": "A react based modular UI framework",

+  "main": "index.js",

+  "scripts": {

+    "start": "webpack-dev-server --env debug",

+    "prebuild": "rimraf dist",

+    "build": "webpack --env release --config webpack.vendor.js && webpack --env release --config webpack.config.js && webpack --env release --config webpack.runner.js",

+    "build:run": "webpack --env release --config webpack.runner.js",

+    "build:dev": "webpack --env debug --config webpack.config.js",

+    "vendor:dev": "webpack --env debug --config webpack.vendor.js"

+  },

+  "repository": {

+    "type": "git",

+    "url": "https://git.mfico.de/highstreet-technologies/odlux.git"

+  },

+  "keywords": [

+    "reactjs",

+    "redux",

+    "ui",

+    "framework"

+  ],

+  "author": "Matthias Fischer",

+  "license": "Apache-2.0",

+  "peerDependencies": {

+    "@fortawesome/fontawesome-svg-core": "1.2.35",

+    "@fortawesome/free-solid-svg-icons": "5.6.3",

+    "@fortawesome/react-fontawesome": "0.1.14",

+    "@types/classnames": "2.2.6",

+    "@types/flux": "3.1.8",

+    "@types/history": "^4.7.9",

+    "@types/jquery": "3.3.10",

+    "@types/jsonwebtoken": "7.2.8",

+    "@types/node": "^12.0.0",

+    "@types/react": "17.0.37",

+    "@types/react-dom": "17.0.11",

+    "@types/react-router-dom": "5.1.7",

+    "jquery": "3.3.1",

+    "history": "^4.9.0",

+    "jsonwebtoken": "8.3.0",

+    "react": "17.0.2",

+    "react-dom": "17.0.2",

+    "react-router-dom": "5.2.0"

+  },

+  "dependencies": {

+    "@babel/polyfill": "^7.0.0",

+    "@emotion/react": "^11.7.0",

+    "@emotion/styled": "^11.6.0",

+    "@mui/icons-material": "^5.2.0",

+    "@mui/material": "^5.2.2",

+    "@mui/styles": "^5.2.2",

+    "@mui/system": "^5.2.2",

+    "@types/x2js": "^3.1.0",

+    "chart.js": "^3.4.0",

+    "http-server": "^0.11.1",

+    "react-chartjs-2": "^3.0.3"

+  }

+}

diff --git a/sdnr/wt-odlux/odlux/framework/pom.xml b/sdnr/wt-odlux/odlux/framework/pom.xml
new file mode 100644
index 0000000..83e5cdd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/pom.xml
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-framework</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <buildtime>${maven.build.timestamp}</buildtime>
+        <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
+        <buildno>172.b89e2c2b(23/10/04)</buildno>
+        <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
+    </properties>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+            <resource>
+                <directory>src2/main/resources</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v16.17.0</nodeVersion>
+                            <yarnVersion>v1.22.19</yarnVersion>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>clear cache</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                        <configuration>
+                            <arguments>cache clean</arguments>
+                            <installDirectory>${project.basedir}</installDirectory>
+                            <workingDirectory>${project.basedir}/../</workingDirectory>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>install lerna</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                        <configuration>
+                            <arguments>add lerna@3.22.1 -W --exact</arguments>
+                            <installDirectory>${project.basedir}</installDirectory>
+                            <workingDirectory>${project.basedir}/../</workingDirectory>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>exec lerna bootstrap</id>
+                        <goals>
+                            <goal>lerna</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                        <configuration>
+                            <lernaInheritsProxyConfigFromMaven>false</lernaInheritsProxyConfigFromMaven>
+                            <arguments>bootstrap</arguments>
+                            <installDirectory>${project.basedir}</installDirectory>
+                            <workingDirectory>${project.basedir}/../</workingDirectory>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>yarn build</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+             <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>properties-maven-plugin</artifactId>
+                <version>1.0.0</version>
+                <executions>
+                    <execution>
+                        <phase>initialize</phase>
+                        <goals>
+                            <goal>read-project-properties</goal>
+                        </goals>
+                        <configuration>
+                            <files>
+                                <file>${basedir}/../odlux.properties</file>
+                            </files>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.google.code.maven-replacer-plugin</groupId>
+                <artifactId>replacer</artifactId>
+                <version>1.5.2</version>
+                <executions>
+                    <execution>
+                        <id>replace version</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>replace</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <basedir>${project.build.directory}/classes/odlux</basedir>
+                    <includes>
+                        <include>app.js</include>
+                        <include>version.json</include>
+                    </includes>
+                    <replacements>
+                        <replacement>
+                            <token>##odlux.version##</token>
+                            <value>${odlux.version}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##buildno##</token>
+                            <value>${buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##build-timestamp##</token>
+                            <value>${buildtime}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.framework.buildno##</token>
+                            <value>${odlux.framework.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.configurationApp.buildno##</token>
+                            <value>${odlux.apps.configurationApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.connectApp.buildno##</token>
+                            <value>${odlux.apps.connectApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.eventLogApp.buildno##</token>
+                            <value>${odlux.apps.eventLogApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.faultApp.buildno##</token>
+                            <value>${odlux.apps.faultApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.helpApp.buildno##</token>
+                            <value>${odlux.apps.helpApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.inventoryApp.buildno##</token>
+                            <value>${odlux.apps.inventoryApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.microwaveApp.buildno##</token>
+                            <value>${odlux.apps.microwaveApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.maintenanceApp.buildno##</token>
+                            <value>${odlux.apps.maintenanceApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.mediatorApp.buildno##</token>
+                            <value>${odlux.apps.mediatorApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.networkMapApp.buildno##</token>
+                            <value>${odlux.apps.networkMapApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.siteManagerApp.buildno##</token>
+                            <value>${odlux.apps.siteManagerApp.buildno}</value>
+                        </replacement>
+                        <replacement>
+                            <token>##odlux.apps.permanceHistoryApp.buildno##</token>
+                            <value>${odlux.apps.permanceHistoryApp.buildno}</value>
+                        </replacement>
+                    </replacements>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/authentication.ts b/sdnr/wt-odlux/odlux/framework/src/actions/authentication.ts
new file mode 100644
index 0000000..1412495
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/authentication.ts
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Dispatch } from '../flux/store';
+import { Action } from '../flux/action';
+import { AuthPolicy, User } from '../models/authentication';
+import { Settings } from '../models/settings';
+import { saveInitialSettings, SetGeneralSettingsAction } from './settingsAction';
+import { endWebsocketSession } from '../services/notificationService';
+import { endUserSession, startUserSession } from '../services/userSessionService';
+import { IApplicationStoreState } from '../store/applicationStore';
+
+export class UpdateUser extends Action {
+
+  constructor(public user?: User) {
+    super();
+  }
+}
+
+export class UpdatePolicies extends Action {
+
+  constructor(public authPolicies?: AuthPolicy[]) {
+    super();
+  }
+}
+
+export const logoutUser = () => (dispatcher: Dispatch, getState: () => IApplicationStoreState) =>{
+
+  const { framework:{ applicationState:{ authentication }, authenticationState: { user } } } = getState();
+  
+  dispatcher(new UpdateUser(undefined));
+  dispatcher(new SetGeneralSettingsAction(null));
+  endWebsocketSession();
+  endUserSession();
+  localStorage.removeItem('userToken');
+
+
+  //only call if a user is currently logged in
+  if (authentication === 'oauth' && user) {
+
+    const url = window.location.origin;
+    window.location.href = `${url}/oauth/logout`;
+  }
+};
+
+/**
+ * Loads the user settings for the given user and dispatches a `saveInitialSettings` action with the result.
+ * @param user The user for which to load the settings.
+ * @param dispatcher The dispatcher function to use for dispatching the `saveInitialSettings` action.
+ */
+const loadUserSettings = (user: User | undefined, dispatcher: Dispatch) => {
+
+  // fetch used, because state change for user login is not done when frameworks restRequest call is started (and is accordingly undefined -> /userdata call yields 401, unauthorized) and triggering an action from inside the handler / login event is impossible
+  // no timeout used, because it's bad practice to add a timeout to hopefully avoid a race condition
+  // hence, fetch used to simply use supplied user data for getting settings
+
+  if (user && user.isValid) {
+
+    fetch('/userdata', {
+      method: 'GET', 
+      headers: {
+        'Content-Type': 'application/json',
+        'Accept': 'application/json',
+        'Authorization': `${user.tokenType} ${user.token}`,
+      },
+    }).then((res: Response)=>{
+      if (res.status == 200) {
+        return res.json();
+      } else {
+        return null;
+      }
+    }).then((result:Settings)=>{
+      dispatcher(saveInitialSettings(result));
+    });
+  }  
+};
+
+/**
+ * Dispatches an `UpdateUser` action with the given user and starts a user session if the user is defined.
+ * Also loads the user settings for the given user and dispatches a `saveInitialSettings` action with the result.
+ * Finally, saves the user token to local storage.
+ * @param user The user to be logged in.
+ * @param dispatcher The dispatcher function to use for dispatching the actions.
+ */
+export const loginUserAction = (user?: User) => (dispatcher: Dispatch) =>{
+  
+  dispatcher(new UpdateUser(user));
+  if (user) {
+    startUserSession(user);
+    loadUserSettings(user, dispatcher);
+    localStorage.setItem('userToken', user.toString());
+  }
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/errorActions.ts b/sdnr/wt-odlux/odlux/framework/src/actions/errorActions.ts
new file mode 100644
index 0000000..ddb0d57
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/errorActions.ts
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+
+import { ErrorInfo } from '../models/errorInfo';
+export { ErrorInfo } from '../models/errorInfo';
+
+export class AddErrorInfoAction extends Action {
+
+  constructor(public errorInfo: ErrorInfo) {
+    super();
+  }
+}
+
+export class RemoveErrorInfoAction extends Action {
+
+  constructor(public errorInfo: ErrorInfo) {
+    super();
+  }
+}
+
+export class ClearErrorInfoAction extends Action {
+
+  constructor() {
+    super();
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/loginProvider.ts b/sdnr/wt-odlux/odlux/framework/src/actions/loginProvider.ts
new file mode 100644
index 0000000..e646711
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/loginProvider.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../flux/action';
+import { Dispatch } from '../flux/store';
+
+import { IApplicationStoreState } from '../store/applicationStore';
+import { ExternalLoginProvider } from '../models/externalLoginProvider';
+
+import authenticationService from '../services/authenticationService';
+
+export class SetExternalLoginProviderAction extends Action {
+    constructor(public externalLoginProvders: ExternalLoginProvider[] | null) {
+        super();
+    }
+}
+
+export const updateExternalLoginProviderAsyncActionCreator = () => async (dispatch: Dispatch, getState: () => IApplicationStoreState ) => {
+    const providers = await authenticationService.getAvaliableExteralProvider();
+    dispatch(new SetExternalLoginProviderAction(providers || null));
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/menuAction.ts b/sdnr/wt-odlux/odlux/framework/src/actions/menuAction.ts
new file mode 100644
index 0000000..ec07965
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/menuAction.ts
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../flux/action';
+
+export class MenuAction extends Action {
+    constructor(public isOpen: boolean) {
+        super();
+    }
+}
+
+export class MenuClosedByUser extends Action {
+    constructor(public isClosed: boolean) {
+        super();
+    }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/navigationActions.ts b/sdnr/wt-odlux/odlux/framework/src/actions/navigationActions.ts
new file mode 100644
index 0000000..6951b97
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/navigationActions.ts
@@ -0,0 +1,64 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from "../flux/action";
+
+export abstract class NavigationAction extends Action { }
+
+export class NavigateToApplication<TState = { }> extends NavigationAction {
+ 
+  constructor(public applicationName: string, public href?: string, public state?: TState, public replace: boolean = false ) {
+    super();
+    
+  }
+}
+
+export class PushAction<TState = { }> extends NavigationAction {
+  constructor(public href: string, public state?: TState) {
+    super();
+
+  }
+}
+
+export class ReplaceAction<TState = { }> extends NavigationAction {
+  constructor(public href: string, public state?: TState) {
+    super();
+
+  }
+}
+
+export class GoAction extends NavigationAction {
+  constructor(public index: number) {
+    super();
+
+  }
+}
+
+export class GoBackAction extends NavigationAction {
+
+}
+
+export class GoForwardeAction extends NavigationAction {
+
+}
+
+export class LocationChanged extends NavigationAction {
+  constructor(public pathname: string, public search: string, public hash: string ) {
+    super();
+    
+  }
+} 
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/settingsAction.ts b/sdnr/wt-odlux/odlux/framework/src/actions/settingsAction.ts
new file mode 100644
index 0000000..fa45f23
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/settingsAction.ts
@@ -0,0 +1,130 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Dispatch } from "../flux/store";
+import { Action } from "../flux/action";
+import { GeneralSettings, Settings, TableSettings, TableSettingsColumn } from "../models/settings";
+import { getUserData, saveUserData } from "../services/userdataService";
+import { startWebsocketSession, suspendWebsocketSession } from "../services/notificationService";
+import { IApplicationStoreState } from "../store/applicationStore";
+
+
+export class SetGeneralSettingsAction extends Action {
+    /**
+     *
+     */
+    constructor(public areNoticationsActive: boolean | null) {
+        super();
+    }
+}
+
+export class SetTableSettings extends Action {
+
+    constructor(public tableName: string, public updatedColumns: TableSettingsColumn[]) {
+        super();
+    }
+}
+
+export class LoadSettingsAction extends Action {
+
+    constructor(public settings: Settings & { isInitialLoadDone: true }) {
+        super();
+    }
+
+}
+
+export class SettingsDoneLoadingAction extends Action {
+
+}
+
+export const setGeneralSettingsAction = (value: boolean) => (dispatcher: Dispatch) => {
+
+    dispatcher(new SetGeneralSettingsAction(value));
+
+    if (value) {
+        startWebsocketSession();
+    } else {
+        suspendWebsocketSession();
+    }
+}
+
+
+export const updateGeneralSettingsAction = (activateNotifications: boolean) => async (dispatcher: Dispatch) => {
+
+    const value: GeneralSettings = { general: { areNotificationsEnabled: activateNotifications } };
+    const result = await saveUserData("/general", JSON.stringify(value.general));
+    dispatcher(setGeneralSettingsAction(activateNotifications));
+
+}
+
+export const updateTableSettings = (tableName: string, columns: TableSettingsColumn[]) => async (dispatcher: Dispatch, getState: () => IApplicationStoreState) => {
+
+
+    //TODO: ask micha how to handle object with variable properties!
+    //fix for now: just safe everything!
+
+     let {framework:{applicationState:{settings:{tables}}}} = getState();
+
+     tables[tableName] = { columns: columns };
+     const json=JSON.stringify(tables);
+
+    // would only save latest entry
+    //const json = JSON.stringify({ [tableName]: { columns: columns } });
+
+    const result = await saveUserData("/tables", json);
+
+    dispatcher(new SetTableSettings(tableName, columns));
+}
+
+export const getGeneralSettingsAction = () => async (dispatcher: Dispatch) => {
+
+    const result = await getUserData<GeneralSettings>();
+
+    if (result && result.general) {
+        dispatcher(new SetGeneralSettingsAction(result.general.areNotificationsEnabled!))
+    }
+}
+
+export const saveInitialSettings = (settings: any) => async (dispatcher: Dispatch) => {
+
+    const defaultSettings = {general:{ areNotificationsEnabled: false }, tables:{}};
+
+    const initialSettings = {...defaultSettings, ...settings};
+
+    if (initialSettings) {
+        if (initialSettings.general) {
+            const settingsActive = initialSettings.general.areNotificationsEnabled;
+
+            if (settingsActive) {
+                startWebsocketSession();
+            } else {
+                suspendWebsocketSession();
+            }
+        }
+
+        dispatcher(new LoadSettingsAction(initialSettings));
+    }
+    else {
+        dispatcher(new SettingsDoneLoadingAction());
+
+    }
+
+
+
+
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/snackbarActions.ts b/sdnr/wt-odlux/odlux/framework/src/actions/snackbarActions.ts
new file mode 100644
index 0000000..ad4d606
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/snackbarActions.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+import { SnackbarItem } from '../models/snackbarItem';
+import { DistributiveOmit } from '@mui/types';
+
+export class AddSnackbarNotification extends Action {
+
+  constructor(notification: DistributiveOmit<SnackbarItem, 'key' >) {
+    super();
+
+    this.notification = { ...notification, key: (new Date().getTime() + Math.random()) }
+  }
+
+  public notification: SnackbarItem
+}
+
+export class RemoveSnackbarNotification extends Action {
+  constructor(public key: number) {
+    super();
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/titleActions.ts b/sdnr/wt-odlux/odlux/framework/src/actions/titleActions.ts
new file mode 100644
index 0000000..4bcfe29
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/titleActions.ts
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+
+import { IconType } from '../models/iconDefinition';
+
+export class SetTitleAction extends Action {
+
+  constructor(public title: string, public icon?: IconType, public appId?: string) {
+    super();
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/actions/websocketAction.ts b/sdnr/wt-odlux/odlux/framework/src/actions/websocketAction.ts
new file mode 100644
index 0000000..0b45f7a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/actions/websocketAction.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from "../flux/action";
+
+
+export class SetWebsocketAction extends Action {
+    constructor(public isConnected: boolean|null) {
+        super();
+    }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/app.css b/sdnr/wt-odlux/odlux/framework/src/app.css
new file mode 100644
index 0000000..9b653b3
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/app.css
@@ -0,0 +1,17 @@
+html, body, #app {
+  height: 100%;
+  min-width: 1000px;
+  padding: 0px;
+  margin: 0px;
+  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+}
+.about-table td{
+  padding:0.5rem 1rem;
+  border-bottom: 1px solid #DDD;
+}
+.about-table pre {
+  background:#FFF;
+  border:1px solid #CCC;
+  padding:1rem;
+  margin: 1rem 0;
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/app.tsx b/sdnr/wt-odlux/odlux/framework/src/app.tsx
new file mode 100644
index 0000000..bbe1f9e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/app.tsx
@@ -0,0 +1,120 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import * as ReactDOM from 'react-dom';
+
+import { ThemeProvider, Theme, StyledEngineProvider } from '@mui/material/styles';
+
+import { Frame } from './views/frame';
+
+import { User } from './models/authentication';
+
+import { AddErrorInfoAction } from './actions/errorActions';
+import { loginUserAction } from './actions/authentication';
+
+import { applicationStoreCreator } from './store/applicationStore';
+import { ApplicationStoreProvider } from './flux/connect';
+
+import { startHistoryListener } from './middleware/navigation';
+import { startSoreService } from './services/storeService';
+
+import { startUserSessionService } from './services/userSessionService';
+import { startNotificationService } from './services/notificationService';
+
+import { startBroadcastChannel } from './services/broadcastService';
+
+import theme from './design/default';
+import '!style-loader!css-loader!./app.css';
+
+declare module '@mui/material/styles' {
+
+  interface IDesign {
+    id: string,
+    name: string,
+    url: string,        // image url of a company logo, which will be presented in the ui header
+    height: number,     // image height [px] as delivered by the url
+    width: number,      // image width [px] as delivered by the url
+    logoHeight: number  // height in [px] of the logo (see url) within the ui header
+  }
+
+  interface Theme {
+    design?: IDesign
+  }
+  interface DeprecatedThemeOptions {
+    design?: IDesign
+  }
+}
+
+
+declare module '@mui/styles/defaultTheme' {
+  // eslint-disable-next-line @typescript-eslint/no-empty-interface (remove this line if you don't have the rule enabled)
+  interface DefaultTheme extends Theme {}
+}
+
+export { configureApplication } from "./handlers/applicationStateHandler";
+
+export const transportPCEUrl = "transportPCEUrl";
+
+export const runApplication = () => {
+  
+  const initialToken = localStorage.getItem("userToken");
+  const applicationStore = applicationStoreCreator();
+
+  startBroadcastChannel(applicationStore);
+  startUserSessionService(applicationStore);
+  
+  if (initialToken) {
+    applicationStore.dispatch(loginUserAction(User.fromString(initialToken) || undefined));
+  }
+
+  window.onerror = function (msg: string, url: string, line: number, col: number, error: Error) {
+    // Note that col & error are new to the HTML 5 spec and may not be
+    // supported in every browser.  It worked for me in Chrome.
+    var extra = !col ? '' : '\ncolumn: ' + col;
+    extra += !error ? '' : '\nerror: ' + error;
+
+    // You can view the information in an alert to see things working like this:
+    applicationStore.dispatch(new AddErrorInfoAction({ error, message: msg, url, line, col, info: { extra } }));
+
+    var suppressErrorAlert = true;
+    // If you return true, then error alerts (like in older versions of
+    // Internet Explorer) will be suppressed.
+    return suppressErrorAlert;
+  };
+  
+
+  startSoreService(applicationStore);
+  startHistoryListener(applicationStore);
+  startNotificationService(applicationStore);
+
+  const App = (): JSX.Element => (
+    <ApplicationStoreProvider applicationStore={applicationStore} >
+      <StyledEngineProvider injectFirst>
+        <ThemeProvider theme={theme}>
+          <Frame />
+        </ThemeProvider>
+      </StyledEngineProvider>
+    </ApplicationStoreProvider>
+  );
+
+  ReactDOM.render(<App />, document.getElementById('app'));
+
+  
+
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/About.svg b/sdnr/wt-odlux/odlux/framework/src/assets/icons/About.svg
new file mode 100644
index 0000000..156e36e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/About.svg
@@ -0,0 +1,18 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">

+

+<path fill="#36A9E1" d="M 13 13 V 17.5 A 1 1 0 0 1 11 17.5 V 13 A 1 1 0 0 1 13 13 Z "/>

+

+<path fill="#36A9E1" d="M 12 11 A 1 1 0 1 0 11 10 A 1 1 0 0 0 12 11 Z "/>

+

+<path fill="#565656" d="M 1.125 20.485 A 1 1 0 0 1 1.152 19.47 L 11.152 3.47 A 1.039 1.039 0 0 1 12.852 3.47 L 22.852 19.47 A 1 1 0 0 1 22 21 H 2 A 1 1 0 0 1 1.125 20.485 Z M 3.8 19 H 20.2 L 12 5.887 Z"/>

+

+</svg>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/Home.svg b/sdnr/wt-odlux/odlux/framework/src/assets/icons/Home.svg
new file mode 100644
index 0000000..0836714
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/Home.svg
@@ -0,0 +1,28 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 460.298 460.297" style="enable-background:new 0 0 460.298 460.297;"

+	 xml:space="preserve">

+<g>

+	<g>

+		<path fill="#565656" d="M230.149,120.939L65.986,256.274c0,0.191-0.048,0.472-0.144,0.855c-0.094,0.38-0.144,0.656-0.144,0.852v137.041

+			c0,4.948,1.809,9.236,5.426,12.847c3.616,3.613,7.898,5.431,12.847,5.431h109.63V303.664h73.097v109.64h109.629

+			c4.948,0,9.236-1.814,12.847-5.435c3.617-3.607,5.432-7.898,5.432-12.847V257.981c0-0.76-0.104-1.334-0.288-1.707L230.149,120.939

+			z"/>

+		<path fill="#565656" d="M457.122,225.438L394.6,173.476V56.989c0-2.663-0.856-4.853-2.574-6.567c-1.704-1.712-3.894-2.568-6.563-2.568h-54.816

+			c-2.666,0-4.855,0.856-6.57,2.568c-1.711,1.714-2.566,3.905-2.566,6.567v55.673l-69.662-58.245

+			c-6.084-4.949-13.318-7.423-21.694-7.423c-8.375,0-15.608,2.474-21.698,7.423L3.172,225.438c-1.903,1.52-2.946,3.566-3.14,6.136

+			c-0.193,2.568,0.472,4.811,1.997,6.713l17.701,21.128c1.525,1.712,3.521,2.759,5.996,3.142c2.285,0.192,4.57-0.476,6.855-1.998

+			L230.149,95.817l197.57,164.741c1.526,1.328,3.521,1.991,5.996,1.991h0.858c2.471-0.376,4.463-1.43,5.996-3.138l17.703-21.125

+			c1.522-1.906,2.189-4.145,1.991-6.716C460.068,229.007,459.021,226.961,457.122,225.438z"/>

+

+<path fill="#246DA2" d="M 457.122 225.438 L 251.849 54.417 L 251.849 54.417 C 245.765 49.468 238.531 46.994 230.155 46.994 C 221.78 46.994 214.547 49.468 208.457 54.417 L 3.172 225.438 C 1.269 226.958 0.226 229.004 0.032 231.574 C -0.161 234.142 0.504 236.385 2.029 238.287 L 19.73 259.415 C 21.255 261.127 23.251 262.174 25.726 262.557 C 28.011 262.749 30.296 262.081 32.581 260.559 L 230.149 95.817 L 427.719 260.558 C 429.245 261.886 431.24 262.549 433.715 262.549 H 434.573 C 437.044 262.173 439.036 261.119 440.569 259.411 L 458.272 238.286 C 459.794 236.38 460.461 234.141 460.263 231.57 C 460.068 229.007 459.021 226.961 457.122 225.438 Z"/>

+	</g>

+</g>

+</svg>

diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/Menu.svg b/sdnr/wt-odlux/odlux/framework/src/assets/icons/Menu.svg
new file mode 100644
index 0000000..ea03128
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/Menu.svg
@@ -0,0 +1,18 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

+

+<path fill="#36A9E1" d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z"/>

+

+<path fill="#36A9E1" d="M28,14H4c-1.104,0-2,0.896-2,2  s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z"/>

+

+<path fill="#36A9E1" d="M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2  S29.104,22,28,22z"/>

+

+</svg>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/Tools.svg b/sdnr/wt-odlux/odlux/framework/src/assets/icons/Tools.svg
new file mode 100644
index 0000000..1595cdc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/Tools.svg
@@ -0,0 +1,35 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 265 265">
+
+<g transform="translate(0.000000,265.000000) scale(0.100000,-0.100000)">
+
+<path fill="#565656" d="M601 2515 c-35 -8 -66 -17 -69 -20 -3 -3 76 -87 175 -188 243 -244
+243 -246 59 -425 -106 -103 -137 -120 -194 -107 -19 4 -88 66 -207 185 -99 99
+-183 180 -186 180 -17 0 -34 -104 -33 -200 0 -82 6 -120 23 -170 61 -174 191
+-306 362 -367 62 -22 93 -27 187 -28 l113 -2 602 -600 c673 -671 633 -638 777
+-638 93 1 151 27 225 101 99 98 129 219 85 339 -21 57 -49 87 -626 665 l-603
+605 5 70 c18 217 -117 451 -316 549 -127 62 -250 78 -379 51z m1696 -1906 c70
+-34 113 -125 93 -199 -31 -116 -158 -168 -262 -107 -77 45 -107 133 -73 214
+21 50 42 72 90 94 53 24 99 24 152 -2z"/>
+
+<path fill="#565656" d="M2183 2496 c-23 -7 -56 -23 -75 -34 -18 -12 -172 -161 -343 -331
+l-310 -311 45 -45 c24 -25 49 -45 55 -45 5 0 152 142 325 315 264 264 319 315
+340 313 19 -2 26 -10 28 -32 3 -26 -26 -59 -315 -348 l-318 -318 38 -37 37
+-38 319 318 c287 287 321 318 347 315 24 -2 30 -8 32 -32 3 -26 -26 -59 -315
+-348 l-318 -318 48 -47 47 -48 320 320 c225 225 327 333 342 365 31 66 30 159
+-4 225 -66 127 -210 198 -325 161z"/>
+
+<path fill="#36A9E1" d="M800 875 l-175 -175 -85 0 -85 0 -135 -222 c-74 -121 -137 -225 -139
+-231 -4 -11 89 -107 104 -107 5 0 109 60 230 134 l220 133 3 84 3 84 177 178
+177 177 -60 60 -60 60 -175 -175z"/>
+
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/User.svg b/sdnr/wt-odlux/odlux/framework/src/assets/icons/User.svg
new file mode 100644
index 0000000..99618cf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/User.svg
@@ -0,0 +1,21 @@
+<!-- highstreet technologies GmbH colour scheme 

+	Grey	#565656

+	LBlue #36A9E1

+	DBlue #246DA2

+	Green #003F2C / #006C4B

+	Yellw #C8D400

+	Red 	#D81036

+-->

+

+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 600">

+

+  <defs>

+    <clipPath id="circular-border">

+      <circle cx="300" cy="300" r="250" />

+    </clipPath>

+  </defs>

+  

+  <circle fill="#36A9E1" cx="300" cy="300" r="280"/>

+  <circle fill="#ffffff" cx="300" cy="230" r="100" />

+  <circle fill="#ffffff" cx="300" cy="550" r="190" clip-path="url(#circular-border)" />

+</svg>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/ht.Connect.png b/sdnr/wt-odlux/odlux/framework/src/assets/icons/ht.Connect.png
new file mode 100644
index 0000000..412390c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/ht.Connect.png
Binary files differ
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/icons/ht.Connect.svg b/sdnr/wt-odlux/odlux/framework/src/assets/icons/ht.Connect.svg
new file mode 100644
index 0000000..c1d74bc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/icons/ht.Connect.svg
@@ -0,0 +1,81 @@
+<!-- highstreet technologies GmbH colour scheme 
+	Grey	#565656
+	LBlue #36A9E1
+	DBlue #246DA2
+	Green #003F2C / #006C4B
+	Yellw #C8D400
+	Red 	#D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 795.000000 139.000000">
+
+<g transform="translate(0.000000,139.000000) scale(0.100000,-0.100000)">
+
+<path fill="#565656" d="M355 1163 c-38 -2 -75 -9 -82 -15 -10 -8 -13 -53 -13 -175 0 -175 -9
+-215 -50 -226 -17 -4 -20 -13 -20 -59 0 -48 3 -56 32 -80 l33 -27 3 -190 c4
+-226 -4 -213 135 -209 l92 3 0 70 0 70 -32 3 -33 3 0 148 c0 135 -2 151 -21
+175 l-20 26 20 26 c19 24 21 40 21 170 l0 143 33 3 32 3 0 70 0 70 -30 1 c-16
+0 -61 -1 -100 -3z"/>
+
+<path fill="#565656" d="M7473 1154 c-2 -6 -3 -38 -1 -70 3 -59 3 -59 36 -62 l32 -3 0 -137
+c0 -119 3 -141 20 -169 20 -33 20 -33 0 -65 -17 -29 -20 -51 -20 -175 l0 -142
+-32 -3 -33 -3 0 -70 0 -70 97 -3 c141 -4 138 -9 138 212 0 96 3 182 6 191 4 9
+17 21 30 26 21 8 24 15 24 67 0 53 -3 60 -30 80 l-30 23 0 172 c0 123 -4 178
+-12 189 -16 20 -217 31 -225 12z"/>
+
+<path fill="#246DA2" d="M645 1138 c-3 -7 -4 -215 -3 -463 l3 -450 90 0 90 0 0 195 c0 215 5
+237 65 280 71 50 146 45 178 -13 14 -27 17 -64 19 -247 l2 -215 88 0 88 0 0
+250 0 250 -27 55 c-33 67 -71 97 -138 110 -89 17 -181 -12 -240 -75 l-25 -27
+-5 179 -5 178 -88 3 c-64 2 -89 -1 -92 -10z"/>
+
+<path fill="#C8D400" d="M2499 1111 c-150 -48 -271 -193 -301 -361 -32 -184 85 -406 259 -492
+165 -81 408 -24 514 120 31 43 31 44 13 61 -10 10 -45 33 -76 50 l-57 32 -15
+-28 c-75 -145 -315 -142 -403 6 -135 226 18 510 249 462 69 -15 114 -42 139
+-86 12 -19 26 -35 31 -35 22 0 138 91 132 103 -89 153 -301 227 -485 168z"/>
+
+<path fill="#246DA2" d="M1467 1094 c-4 -4 -7 -51 -7 -105 l0 -98 -42 -3 -43 -3 0 -70 0 -70
+43 -3 42 -3 0 -197 c0 -185 1 -201 23 -242 26 -53 89 -90 152 -90 45 0 171 32
+187 48 7 7 4 30 -9 74 -16 52 -23 62 -39 60 -73 -11 -101 -12 -114 -3 -12 8
+-16 43 -18 180 l-3 170 68 3 68 3 0 70 0 70 -67 3 -67 3 -3 102 -3 102 -80 3
+c-45 1 -84 0 -88 -4z"/>
+
+<path fill="#C8D400" d="M7017 1094 c-4 -4 -7 -51 -7 -105 l0 -98 -37 -3 -38 -3 0 -70 0 -70
+36 -3 36 -3 7 -67 c3 -37 6 -130 6 -208 0 -130 2 -144 23 -175 27 -41 98 -79
+147 -79 36 0 120 19 172 39 l26 10 -15 58 c-19 74 -28 85 -59 72 -35 -13 -88
+-11 -102 3 -8 8 -12 63 -12 180 l0 167 68 3 67 3 0 70 0 70 -67 3 -67 3 -3
+102 -3 102 -85 3 c-47 1 -89 0 -93 -4z"/>
+
+<path fill="#C8D400" d="M3349 890 c-63 -11 -123 -43 -174 -95 -55 -54 -82 -106 -94 -181 -25
+-161 50 -304 198 -372 77 -36 211 -38 285 -4 75 34 129 84 167 154 32 59 34
+69 34 158 0 82 -4 103 -26 151 -46 98 -138 168 -249 189 -59 11 -75 11 -141 0z
+m168 -178 c44 -31 67 -86 67 -157 0 -113 -53 -176 -153 -183 -70 -5 -115 22
+-148 88 -53 103 -11 233 87 273 31 13 117 1 147 -21z"/>
+
+<path fill="#C8D400" d="M4254 890 c-61 -13 -106 -34 -147 -69 l-36 -32 -3 48 -3 48 -80 0
+-80 0 0 -330 0 -330 85 0 85 0 5 202 c5 184 7 204 26 229 45 60 111 88 171 72
+54 -14 58 -31 63 -278 l5 -225 85 0 85 0 0 266 0 266 -30 48 c-46 74 -132 106
+-231 85z"/>
+
+<path fill="#C8D400" d="M5040 890 c-63 -11 -89 -23 -142 -63 l-47 -36 -3 47 -3 47 -80 0 -80
+0 0 -330 0 -330 90 0 90 0 1 196 c1 158 4 201 18 226 37 73 151 111 205 69 28
+-22 35 -68 40 -276 l6 -215 85 0 85 0 0 245 c-1 264 -7 307 -51 360 -47 55
+-122 76 -214 60z"/>
+
+<path fill="#C8D400" d="M5709 890 c-99 -17 -200 -94 -250 -190 -21 -39 -24 -59 -24 -145 0
+-90 3 -105 28 -153 79 -149 241 -220 407 -178 79 21 145 61 188 118 39 51 34
+58 -54 77 -56 13 -56 13 -88 -16 -17 -16 -44 -35 -59 -41 -42 -18 -117 -15
+-157 7 -33 17 -79 81 -80 108 0 10 60 13 253 15 l252 3 -1 70 c-2 211 -197
+364 -415 325z m151 -150 c36 -19 80 -79 80 -110 0 -6 -56 -10 -160 -10 -149 0
+-160 1 -160 19 0 29 43 85 80 103 46 24 112 23 160 -2z"/>
+
+<path fill="#C8D400" d="M6483 890 c-186 -39 -303 -204 -273 -386 19 -114 95 -214 200 -263
+46 -22 69 -26 145 -26 76 0 99 4 145 26 65 30 125 80 146 120 17 33 15 35 -84
+64 l-62 18 -28 -25 c-40 -38 -65 -48 -120 -48 -91 0 -162 80 -162 182 0 84 36
+148 99 174 65 27 133 15 176 -32 l25 -27 80 23 c44 13 83 26 85 30 6 10 -42
+71 -82 104 -68 58 -194 86 -290 66z"/>
+
+<path fill="#36A9E1" d="M1934 407 c-2 -7 -4 -52 -2 -98 l3 -84 70 0 70 0 0 95 0 95 -68 3
+c-50 2 -69 -1 -73 -11z"/>
+
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/defaultLogo.svg b/sdnr/wt-odlux/odlux/framework/src/assets/images/defaultLogo.svg
new file mode 100644
index 0000000..bd9ddf5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/defaultLogo.svg
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 350.6536 109.43979"
+   height="109.43979"
+   width="350.65359"
+   xml:space="preserve"
+   version="1.1"
+   id="svg2"
+   class="style-svg replaced-svg"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="htlogo_white.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="796"
+     id="namedview50"
+     showgrid="false"
+     inkscape:zoom="3.0651398"
+     inkscape:cx="123.67512"
+     inkscape:cy="44.346735"
+     inkscape:window-x="-8"
+     inkscape:window-y="1072"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g12" /><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+     id="defs6"><linearGradient
+       id="linearGradient58"
+       spreadMethod="pad"
+       gradientTransform="matrix(700.116,-254.822,-254.822,-700.116,227.808,857.597)"
+       gradientUnits="userSpaceOnUse"
+       y2="0"
+       x2="1"
+       y1="0"
+       x1="0"><stop
+         id="stop60"
+         offset="0"
+         style="stop-opacity:1;stop-color:#45a0de" /><stop
+         id="stop62"
+         offset="0.509804"
+         style="stop-opacity:1;stop-color:#2da247" /><stop
+         id="stop64"
+         offset="1"
+         style="stop-opacity:1;stop-color:#f4f01f" /></linearGradient></defs><g
+     transform="matrix(1.25,0,0,-1.25,-25.640145,137.40654)"
+     id="g10"><g
+       transform="scale(0.1,0.1)"
+       id="g12"><path
+         id="path14"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1089.71,559.016 c 0,-19.914 9.13,-38.637 47.77,-38.637 l 11.28,0 c 44.64,0 47.04,19.441 47.04,43.922 l 0,13.437 -16.8,0 0,-9.121 c 0,-25.679 -4.32,-31.437 -31.68,-31.437 l -6.48,0 c -22.57,0 -30.49,6.961 -30.49,29.758 l 0,60.96 81.85,0 0,16.801 -81.85,0 0,29.039 -20.64,0 0,-29.039 -26.88,0 0,-16.801 26.88,0 0,-68.882" /><path
+         id="path16"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1215.44,570.543 c 0,-45.125 30.72,-50.164 57.6,-50.164 l 37.44,0 c 38.39,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.64,0 c -1.2,-18.719 -11.76,-22.082 -37.68,-22.082 l -28.32,0 c -36.01,0 -49.44,7.199 -49.44,35.039 l 0,7.683 136.08,0 0,13.676 c 0,43.68 -26.64,53.043 -63.6,53.043 l -33.12,0 c -29.28,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.08,26.156 -115.44,0 c 1.92,27.84 9.6,33.121 42.24,33.121 l 30.24,0 c 33.6,0 42.96,-12.48 42.96,-24.965 l 0,-8.156" /><path
+         id="path18"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1399.01,569.82 c 0,-44.402 32.88,-49.441 51.36,-49.441 l 46.56,0 c 38.4,0 53.76,12.004 53.76,42.965 l 0,3.594 -19.2,0 0,-4.079 c 0,-19.921 -16.08,-25.679 -35.28,-25.679 l -34.8,0 c -24.96,0 -41.76,6.242 -41.76,33.601 l 0,25.68 c 0,30.477 18.24,33.359 37.68,33.359 l 37.92,0 c 20.64,0 34.08,-4.8 34.08,-25.203 l 0,-2.879 19.2,0 0,3.364 c 0,25.918 -15.12,41.519 -53.52,41.519 l -34.56,0 c -30.24,0 -61.44,-5.047 -61.44,-49.441 l 0,-27.36" /><path
+         id="path20"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1582.36,522.301 20.65,0 0,69.597 c 0,28.805 11.03,37.922 59.28,37.922 l 5.27,0 c 40.08,0 45.12,-11.761 45.12,-29.757 l 0,-77.762 20.64,0 0,82.801 c 0,22.078 -12.24,41.519 -50.88,41.519 l -29.52,0 c -25.68,0 -41.76,-4.078 -49.44,-23.043 l -0.47,0 0,72.481 -20.65,0 0,-173.758" /><path
+         id="path22"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1772.14,522.301 20.65,0 0,69.597 c 0,28.805 11.03,37.922 59.28,37.922 l 5.28,0 c 40.08,0 45.12,-11.761 45.12,-29.757 l 0,-77.762 20.64,0 0,82.801 c 0,22.078 -12.25,41.519 -50.88,41.519 l -30.97,0 c -25.67,0 -41.76,-4.078 -49.43,-23.043 l -0.49,0 0,21.121 -19.2,0 0,-122.398" /><path
+         id="path24"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2102.09,571.258 c 0,-28.559 -16.79,-34.078 -40.8,-34.078 l -42,0 c -23.99,0 -40.8,5.519 -40.8,34.078 l 0,24.484 c 0,28.559 16.81,34.078 40.8,34.078 l 42,0 c 24.01,0 40.8,-5.519 40.8,-34.078 l 0,-24.484 z m -144.25,-1.195 c 0,-40.321 28.57,-49.684 67.69,-49.684 l 29.52,0 c 39.12,0 67.69,9.363 67.69,49.684 l 0,26.875 c 0,40.32 -28.57,49.683 -67.69,49.683 l -29.52,0 c -39.12,0 -67.69,-9.363 -67.69,-49.683 l 0,-26.875" /><path
+         id="path26"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2160.42,522.301 20.6484,0 0,173.758 -20.6484,0 0,-173.758 z" /><path
+         id="path28"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2362.98,571.258 c 0,-28.559 -16.8,-34.078 -40.8,-34.078 l -41.99,0 c -24.01,0 -40.8,5.519 -40.8,34.078 l 0,24.484 c 0,28.559 16.79,34.078 40.8,34.078 l 41.99,0 c 24,0 40.8,-5.519 40.8,-34.078 l 0,-24.484 z m -144.24,-1.195 c 0,-40.321 28.56,-49.684 67.68,-49.684 l 29.52,0 c 39.12,0 67.69,9.363 67.69,49.684 l 0,26.875 c 0,40.32 -28.57,49.683 -67.69,49.683 l -29.52,0 c -39.12,0 -67.68,-9.363 -67.68,-49.683 l 0,-26.875" /><path
+         id="path30"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2569.4,644.699 -19.21,0 0,-21.84 -0.48,0 c -6.47,19.918 -22.08,23.762 -37.68,23.762 l -43.92,0 c -23.04,0 -55.2,-5.047 -55.2,-49.441 l 0,-20.399 c 0,-31.445 17.04,-48.965 51.36,-48.965 l 42.48,0 c 28.8,0 37.2,7.442 41.52,18.965 l 0.47,0 0,-18.242 c 0,-33.121 -16.31,-33.598 -57.12,-33.598 l -20.14,0 c -19.21,0 -35.53,4.559 -35.53,20.395 l 0,3.363 -19.2,0 0,-4.082 c 0,-15.601 10.08,-36.476 48,-36.476 l 46.56,0 c 25.68,0 58.09,7.441 58.09,44.402 l 0,122.156 z M 2548.74,577.5 c 0,-21.117 -10.79,-32.883 -40.31,-32.883 l -39.84,0 c -25.2,0 -35.28,8.645 -35.04,36.723 l 0,22.558 c 0.24,20.157 15.36,25.922 36.48,25.922 l 42,0 c 29.04,0 37.2,-14.64 36.71,-37.437 l 0,-14.883" /><path
+         id="path32"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2611.1,673.5 20.64,0 0,22.559 -20.64,0 0,-22.559 z m 0,-151.199 20.64,0 0,122.398 -20.64,0 0,-122.398" /><path
+         id="path34"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2667.98,570.543 c 0,-45.125 30.71,-50.164 57.6,-50.164 l 37.44,0 c 38.39,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.64,0 c -1.21,-18.719 -11.76,-22.082 -37.69,-22.082 l -28.31,0 c -36.01,0 -49.44,7.199 -49.44,35.039 l 0,7.683 136.08,0 0,13.676 c 0,43.68 -26.64,53.043 -63.6,53.043 l -33.12,0 c -29.29,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.08,26.156 -115.44,0 c 1.91,27.84 9.6,33.121 42.24,33.121 l 30.24,0 c 33.6,0 42.96,-12.48 42.96,-24.965 l 0,-8.156" /><path
+         id="path36"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2852.5,557.098 c 0,-36.719 28.57,-36.719 59.05,-36.719 l 37.92,0 c 25.2,0 56.88,1.195 56.88,35.519 l 0,0.485 c 0,33.117 -21.11,36.238 -52.08,36.238 l -54.48,0 c -21.59,0 -24.96,5.762 -24.96,15.84 l 0,4.559 c 0,13.918 6.48,16.8 35.99,16.8 l 36.01,0 c 22.56,0 35.04,-0.48 35.04,-19.203 l 0,-1.195 19.2,0 0,6.476 c 0,17.286 -6.48,30.723 -53.04,30.723 l -31.68,0 c -50.88,0 -62.16,-11.039 -62.16,-30.957 l 0,-7.203 c 0,-23.281 10.8,-32.641 39.85,-32.641 l 63.59,0 c 24.72,0 28.08,-6.48 28.08,-18.238 l 0,-0.961 c 0,-18.238 -9.84,-19.441 -40.8,-19.441 l -44.17,0 c -21.11,0 -29.03,6.242 -29.03,21.359 l 0,6 -19.21,0 0,-7.441" /><path
+         id="path38"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1078.67,762.301 20.65,0 0,69.597 c 0,28.805 11.03,37.922 59.28,37.922 l 5.28,0 c 40.08,0 45.12,-11.761 45.12,-29.757 l 0,-77.762 20.64,0 0,82.801 c 0,22.078 -12.24,41.519 -50.88,41.519 l -29.52,0 c -25.68,0 -41.76,-4.078 -49.44,-23.043 l -0.48,0 0,72.481 -20.65,0 0,-173.758" /><path
+         id="path40"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1271.34,913.5 20.64,0 0,22.559 -20.64,0 0,-22.559 z m 0,-151.199 20.64,0 0,122.398 -20.64,0 0,-122.398" /><path
+         id="path42"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1484.7,884.699 -19.19,0 0,-21.84 -0.49,0 c -6.48,19.918 -22.08,23.762 -37.68,23.762 l -43.92,0 c -23.04,0 -55.2,-5.047 -55.2,-49.441 l 0,-20.399 c 0,-31.445 17.04,-48.965 51.36,-48.965 l 42.48,0 c 28.8,0 37.2,7.442 41.52,18.965 l 0.48,0 0,-18.242 c 0,-33.121 -16.32,-33.598 -57.12,-33.598 l -20.16,0 c -19.2,0 -35.52,4.559 -35.52,20.395 l 0,3.363 -19.2,0 0,-4.082 c 0,-15.601 10.08,-36.476 48,-36.476 l 46.56,0 c 25.68,0 58.08,7.441 58.08,44.402 l 0,122.156 z M 1464.06,817.5 c 0,-21.117 -10.8,-32.883 -40.32,-32.883 l -39.84,0 c -25.2,0 -35.27,8.645 -35.04,36.723 l 0,22.558 c 0.24,20.157 15.36,25.922 36.48,25.922 l 42,0 c 29.04,0 37.2,-14.64 36.72,-37.437 l 0,-14.883" /><path
+         id="path44"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1523.52,762.301 20.65,0 0,69.597 c 0,28.805 11.04,37.922 59.28,37.922 l 5.28,0 c 40.08,0 45.11,-11.761 45.11,-29.757 l 0,-77.762 20.65,0 0,82.801 c 0,22.078 -12.24,41.519 -50.88,41.519 l -29.52,0 c -25.68,0 -41.76,-4.078 -49.44,-23.043 l -0.48,0 0,72.481 -20.65,0 0,-173.758" /><path
+         id="path46"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1708.75,797.098 c 0,-36.719 28.57,-36.719 59.04,-36.719 l 37.93,0 c 25.19,0 56.87,1.195 56.87,35.519 l 0,0.485 c 0,33.117 -21.11,36.238 -52.08,36.238 l -54.47,0 c -21.61,0 -24.96,5.762 -24.96,15.84 l 0,4.559 c 0,13.918 6.47,16.8 35.99,16.8 l 36.01,0 c 22.56,0 35.04,-0.48 35.04,-19.203 l 0,-1.195 19.2,0 0,6.476 c 0,17.286 -6.49,30.723 -53.04,30.723 l -31.69,0 c -50.88,0 -62.16,-11.039 -62.16,-30.957 l 0,-7.203 c 0,-23.281 10.8,-32.641 39.84,-32.641 l 63.6,0 c 24.72,0 28.09,-6.48 28.09,-18.238 l 0,-0.961 c 0,-18.238 -9.85,-19.441 -40.8,-19.441 l -44.17,0 c -21.12,0 -29.04,6.242 -29.04,21.359 l 0,6 -19.2,0 0,-7.441" /><path
+         id="path48"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1907.92,799.016 c 0,-19.914 9.12,-38.637 47.77,-38.637 l 11.28,0 c 44.64,0 47.04,19.441 47.04,43.922 l 0,13.437 -16.81,0 0,-9.121 c 0,-25.679 -4.32,-31.437 -31.67,-31.437 l -6.48,0 c -22.56,0 -30.48,6.961 -30.48,29.758 l 0,60.96 81.84,0 0,16.801 -81.84,0 0,29.039 -20.65,0 0,-29.039 -26.87,0 0,-16.801 26.87,0 0,-68.882" /><path
+         id="path50"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2040.85,762.301 20.64,0 0,77.762 c 0,15.835 10.55,29.757 32.4,29.757 l 12.71,0 c 36.72,0 42.97,-4.8 42.97,-35.043 l 0,-5.277 19.19,0 0,14.641 c 0,30 -12.71,42.48 -51.35,42.48 l -19.45,0 c -14.16,0 -29.75,-3.844 -37.43,-19.683 l -0.49,0 0,17.761 -19.19,0 0,-122.398" /><path
+         id="path52"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2187.69,810.543 c 0,-45.125 30.72,-50.164 57.6,-50.164 l 37.44,0 c 38.4,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.65,0 C 2322.57,780.543 2312,777.18 2286.09,777.18 l -28.32,0 c -36,0 -49.45,7.199 -49.45,35.039 l 0,7.683 136.09,0 0,13.676 c 0,43.68 -26.64,53.043 -63.61,53.043 l -33.11,0 c -29.28,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.07,26.156 -115.44,0 c 1.93,27.84 9.6,33.121 42.25,33.121 l 30.23,0 c 33.61,0 42.96,-12.48 42.96,-24.965 l 0,-8.156" /><path
+         id="path54"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2371.26,810.543 c 0,-45.125 30.73,-50.164 57.6,-50.164 l 37.44,0 c 38.4,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.64,0 c -1.19,-18.719 -11.76,-22.082 -37.68,-22.082 l -28.32,0 c -36.01,0 -49.44,7.199 -49.44,35.039 l 0,7.683 136.08,0 0,13.676 c 0,43.68 -26.64,53.043 -63.59,53.043 l -33.13,0 c -29.27,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.08,26.156 -115.44,0 c 1.92,27.84 9.6,33.121 42.24,33.121 l 30.25,0 c 33.59,0 42.95,-12.48 42.95,-24.965 l 0,-8.156" /><path
+         id="path56"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2571.4,799.016 c 0,-19.914 9.11,-38.637 47.75,-38.637 l 11.28,0 c 44.64,0 47.04,19.441 47.04,43.922 l 0,13.437 -16.8,0 0,-9.121 c 0,-25.679 -4.31,-31.437 -31.67,-31.437 l -6.49,0 c -22.56,0 -30.48,6.961 -30.48,29.758 l 0,60.96 81.84,0 0,16.801 -81.84,0 0,29.039 -20.63,0 0,-29.039 -26.89,0 0,-16.801 26.89,0 0,-68.882" /><path
+         id="path66"
+         style="fill:url(#linearGradient58);fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 414.316,403.621 c -16.695,10.117 -53.621,35.262 -67.011,51.457 -12.836,8.742 -24.672,17.988 -35.45,27.621 -9.265,7.731 -17.839,16.301 -25.644,25.723 -1.172,1.41 -2.32,2.836 -3.441,4.273 -9.063,10.887 -16.875,22.106 -23.372,33.524 -7.628,13.414 -12.269,22.301 -17.019,40.851 -3.981,19.496 -5.234,32.43 -5.082,47.832 -28.332,58.625 -36.563,123.481 -18.883,186.891 13.09,46.949 38.906,86.59 73.777,118.02 7.528,17.125 16.887,33.05 28.067,47.488 10.691,16.629 20.637,30.769 49.383,49.629 27.644,18.15 77.902,31.47 117.879,30.93 18.476,13.53 40.089,20.71 64.839,24.74 47.262,5.39 79.168,2.22 116.493,-6.39 18.808,-4.33 45.027,-17.46 45.027,-17.46 -54.891,19.82 -87.711,22.51 -144.391,17.57 25.133,-8.53 54.653,-29.87 77.192,-58.13 44.23,28.77 86.351,35.13 116.25,19.84 l -4.11,-0.96 c -25.644,13.11 -58.992,5.79 -97.121,-20.08 91.344,7.4 169.336,-18.14 219.184,-78.318 l 0.125,-2.223 c -45.715,55.191 -120.848,79.461 -205.059,73.911 84.348,-25.176 153.828,-74.512 200.754,-135.11 63.703,-70.281 91.414,-159.559 66.129,-250.23 -15.387,-55.18 -48.344,-101.879 -92.93,-137.551 -2.129,-4.223 -14.382,-26.391 -21.718,-33.938 -13.5,-16.859 -30.008,-31.453 -49.657,-43.25 -26.961,-16.179 -56.652,-25.742 -87.773,-29.222 -3.781,-0.762 -7.613,-1.473 -11.484,-2.129 -11.52,-8.075 -25.625,-14.414 -41.614,-18.914 -6.265,-1.801 -12.777,-3.301 -19.418,-4.543 -36.254,-6.082 -81.039,-4.164 -124.425,7.011 -28.528,7.356 -55.516,18.207 -79.497,31.137 z m 337.618,279.375 -0.184,6.477 c 33.586,2.617 63.285,10.574 94.199,21.816 0,0 -50.402,-10.492 -94.547,-12.828 -0.718,16.012 -1.964,32.266 -3.761,48.687 l -0.34,3.075 c 13.105,37.785 22.176,70.148 22.176,70.148 -6.387,-20.391 -14.071,-41.488 -23.02,-63.016 -5.875,47.676 -16.012,92.579 -29.309,133.036 30.336,-10.758 58.536,-22.903 84.047,-36.328 53.414,-88.161 79.442,-183.672 73.118,-265.227 -4.391,-29.281 -13.012,-56.602 -25.758,-80.918 l -0.825,-0.684 c 0.918,9.688 0.629,19.559 -0.792,29.524 -0.165,-9.938 -1.122,-20.363 -2.911,-31.317 l -0.238,-1.398 c -36.898,-29.387 -82.035,-51.129 -131.93,-63.566 0.157,1.562 9.618,28.707 13.27,43.371 3.305,9.632 6.336,19.73 9.074,30.238 5.145,3.516 10.246,7.141 15.305,10.863 0,0 -5.188,-3.039 -14.551,-7.949 12.02,47.359 18.184,102.902 17.055,162.344 53.453,-42.227 87.926,-93.524 94.926,-142.586 1.113,67.512 -34.336,112.504 -95.004,146.238 z M 333.047,859.52 c -10.301,17.363 -17.945,33.175 -20.547,50.64 10.129,5.113 20.969,9.75 32.434,13.887 22.472,6.043 47.168,10.066 73.519,12.086 l -5.664,-4.117 C 382.016,909.348 355.977,886.105 333.047,859.52 Z m -20.945,53.605 c -1.668,13.578 -0.848,27.012 2.687,40.047 13.629,11.637 28.422,22.25 44.195,31.73 28.508,14.231 57.403,23.548 90.801,30.188 -8.578,-16.223 -19.293,-41.961 -28.226,-74.18 -29.555,-3.914 -52.071,-8.015 -76.625,-16.863 -11.555,-3.106 -22.52,-6.746 -32.832,-10.922 z m 348.73,95.825 c 18.594,-27.942 37.102,-64.559 50.938,-103.044 30.394,-11.972 58.132,-26.027 82.953,-41.59 l -3.489,5.422 c -35.339,54.348 -75.664,98.797 -120.496,132.012 50.84,-32.992 96.559,-79.105 134.168,-136.93 2.684,-4.117 5.285,-8.254 7.809,-12.402 10.969,-7.645 21.273,-15.586 30.898,-23.777 52.621,-35.407 88.274,-77.661 99.668,-125.266 -0.133,63.387 -24.105,127.047 -66.343,181.59 -51.118,56.394 -127.426,101.137 -216.106,123.985 z m 50.363,-345.43 c -23.25,-42.028 -48.918,-80.93 -75.531,-115.211 24.883,-14.922 45.047,-32.543 58.422,-51.286 15.269,6.786 27.965,13.024 37.336,17.86 6.832,43.519 8.812,100.844 4.648,173.199 -4.679,-0.559 -8.5,-0.398 -13.082,-0.754 -3.621,-7.969 -8.105,-17.148 -11.793,-23.808 z m -307.539,95.351 c -24.816,-2.672 -43.742,-6.769 -64.582,-13.402 17.864,8.511 37.91,15.195 59.688,19.832 -28.746,19.629 -51.621,41.957 -67.949,65.793 -18.45,-22.781 -34.235,-46.406 -47.02,-70.227 2.09,-12.176 4.801,-24.461 8.125,-36.797 13.629,8.61 29.48,15.77 47.156,21.399 -17.113,-8.156 -32.226,-17.985 -44.941,-29.293 4.719,-16.25 14.672,-42.125 23.359,-61.703 14.754,-12.203 39.66,-30.582 57.074,-41.969 9.215,33.777 17.274,58.293 33.485,94.824 -2.485,21.758 -4.395,51.543 -4.395,51.543 z M 613.887,373.906 c 13.918,2.422 26.574,6.153 37.629,11.035 l 0.75,0.332 c 2.812,1.266 5.519,2.602 8.113,4.016 -43.27,0.524 -88.383,11.902 -132.074,32.734 14.156,-16.507 28.933,-29.168 43.867,-37.355 26.258,-2.254 51.816,-2.172 76.109,-0.031 -21.16,-3.254 -43.258,-5.032 -65.879,-4.867 10.524,-4.297 21.075,-6.325 31.485,-5.864 z m 79.144,26.282 c 28.856,3.609 56.262,12.652 81.074,27.55 25.086,15.063 45.735,35.051 61.825,58.731 -36.25,-25.774 -79.078,-44.801 -125.723,-55.922 l -0.363,-1.356 c -3.047,-10.918 -8.809,-20.609 -16.813,-29.003 z m -147.797,24.066 c 43.317,-18.582 87.555,-27.516 129.371,-25.621 10.231,8.133 17.657,17.84 21.668,28.851 -47.679,-9.605 -98.953,-11.078 -151.039,-3.23 z m -46.187,634.796 c -9.406,-8.19 -17.121,-16.69 -23.402,-30.59 44.066,9.86 84.668,12.07 132.925,5.93 -37.882,15.93 -72.554,24.28 -109.523,24.66 z m 131.582,-28.07 c -28.652,33.59 -65.481,54.73 -95.899,47.25 -10.156,-3.17 -16.96,-7.05 -25.121,-11.99 38.176,-2.87 73.696,-15.34 121.02,-35.26 z M 571.035,708.031 c 13.711,-3.531 26.285,-7.843 38.695,-10.492 -24.523,1.531 -66.074,7.684 -86.843,12.742 -38.117,9.282 -54.282,16.27 -84.098,31.43 -5.652,-11.711 -10.98,-23.336 -15.98,-34.844 4.886,-40.812 12.664,-79.394 22.64,-114.832 33.672,2.77 70.922,-0.226 107.047,-9.531 27.527,-7.094 53.047,-17.301 75.242,-29.617 26.407,33.894 52.102,72.609 75.555,115.004 3.164,5.714 7.234,12.988 10.238,18.691 -33.445,1.5 -56.398,3.75 -103.801,10.957 36.25,-2.266 109.875,1.176 109.875,1.176 -37.574,16.551 -82.113,30.308 -131.773,43.094 -48.844,12.582 -96.305,18.644 -139.715,18.726 l -1.582,-3.601 c 36.336,-20.719 77.582,-36.817 124.5,-48.903 z m -254.148,-73.84 c -19.922,17.575 -32.805,29.309 -49.817,49.231 -7.968,-12.262 -11.718,-21.731 -14.937,-36.039 -1.153,-5.129 -2.219,-10.285 -3.129,-15.457 18.773,-36.582 45.68,-70.598 79.277,-99.985 5.547,13.598 16.114,25.075 30.332,34.286 -5.121,7.039 -10.097,14.265 -14.906,21.664 -13.184,20.269 -17.164,25.371 -26.82,46.3 z m 108.781,-52.16 10.262,-5.273 -2.106,6.859 c -1.621,-0.234 -6.562,-1.316 -8.156,-1.586 z M 274.469,695.734 c 6.469,-6.199 20.172,-21.121 27.304,-27.211 -3.793,9.981 -11.925,30.747 -14.937,40.735 -3.656,-3.699 -9.203,-9.547 -12.367,-13.524 z m -48.09,118.813 c -4.387,-18.231 -4.055,-36.277 0.418,-54.02 -2.961,5.801 -5.379,11.559 -7.195,17.254 -4.196,-42.461 3.519,-87.199 20.277,-127.246 0.488,2.547 1.344,10.11 2.047,14.195 2.453,15.508 4.5,26.016 8.16,42.129 -11.617,16.539 -18.949,36.438 -23.289,53.668 6.652,-13.035 16.047,-26.269 27.484,-39.457 5.008,15.985 11.407,32 19.157,47.875 -6.043,41.114 -5.258,81.02 2.285,117.629 -25.407,-20 -42.684,-44.324 -49.344,-72.027 z m 709.922,-170 c 7.422,59.746 -26.321,127.641 -92.688,184.094 -8.418,5.664 -17.269,11.152 -26.527,16.461 50.605,-86.379 68.984,-178.438 57.273,-256.524 -1.992,-25.672 -7.187,-49.973 -15.75,-72.219 36.059,32.825 62.625,73.719 75.758,120.797 0.684,2.457 1.328,4.922 1.934,7.391 z M 288.707,901.691 c 4.258,2.336 8.668,4.547 13.223,6.653 -0.895,10.953 -0.469,21.957 1.328,32.918 -5.895,-12.508 -10.746,-25.746 -14.551,-39.571 z m -40.098,-30.046 c 8.368,8.699 18.09,16.539 29.02,23.503 2.473,10.395 5.512,20.497 9.109,30.262 -14.898,-16.504 -27.73,-34.504 -38.129,-53.765 z m -2.246,-260.403 c 1.266,-16.219 5.2,-31.91 10.817,-46.492 12.215,-27.102 33.175,-50.285 59.043,-73.496 4.597,-3.379 9.289,-6.559 14.054,-9.535 -5.996,13.586 -7.953,27.398 -4.929,40.883 -32.395,27.742 -58.981,59.703 -78.493,94.207 -0.195,-1.852 -0.359,-3.711 -0.492,-5.567 z m 30.75,136.61 c -5.777,-11.817 -11.312,-25.586 -15.55,-37.36 2.093,-2.242 3.324,-4.086 5.527,-6.324 4.711,4.633 11.34,10.539 16.988,14.609 -2.691,9.723 -5.012,19.418 -6.965,29.075 z m 137.813,166.109 c -30.09,-22.957 -50.508,-39.84 -73.742,-66.703 17.101,-24.082 32.175,-42.192 61.769,-63.039 0.129,59.617 5.953,98.562 11.973,129.742 z m 63.347,42.805 c -5.769,-3.34 -11.503,-6.809 -17.207,-10.414 8.411,0.515 16.961,0.828 25.625,0.937 -3.015,3.121 -5.82,6.285 -8.418,9.477 z m 5.891,16.363 c 41.988,22.187 80.035,37.611 122.715,46.381 -48.469,6.85 -88.973,8.11 -133.481,0.79 -2.347,-15.62 1.137,-32.628 10.766,-47.171 z m -47.473,-25.246 c 11.52,7.613 21.438,13.832 33.282,20.383 -7.852,12.394 -11.328,23.336 -12.668,35.564 -7.832,-17.58 -14.629,-33.74 -20.614,-55.947 z m -77.476,36.734 c 29.711,17.853 59.988,30.823 95.445,39.893 0,0 14.356,22.66 25.043,34.4 -40.375,-4.82 -65.492,-11.69 -98.254,-28.31 -22.383,-11.36 -37.285,-24.19 -50.422,-43.116 -6.414,-9.73 -10.398,-19.398 -13.824,-28.066 13.11,9.375 27.156,17.781 42.012,25.199 z m -78.559,-201.64 c 11.453,21.168 25.301,41.996 41.426,62.089 -10.82,19.153 -17.516,39.094 -19.762,59.239 -5.382,-3.043 -10.527,-6.235 -15.429,-9.567 -8.5,-34.457 -10.645,-72.351 -6.235,-111.761 z M 688.488,485.801 c -48.293,-26.285 -98.433,-43.637 -147,-51.828 54.532,-8.883 108.055,-7.297 157.36,3.226 2.632,15.403 -1.121,32.106 -10.36,48.602 z m 45.766,228.554 c -2.285,-5.847 -4.633,-11.621 -7.024,-17.242 l 1.067,-0.707 7.168,0.512 c -0.367,5.715 -0.766,11.523 -1.211,17.437 z M 725.172,483.59 c 2.152,8.66 4.066,17.965 5.711,27.953 -10.805,-7.273 -21.766,-14.078 -32.84,-20.406 8.266,-13.121 13.172,-26.696 14.043,-40.196 4.742,10.161 9.109,21.075 13.086,32.649 z M 512.363,445.281 c 37.364,25.75 77.864,62.559 111.164,102.242 -20.925,12.305 -45.597,22.641 -73.281,29.778 -36.816,9.48 -72.16,11.66 -102.891,8.097 0.922,-3.14 4.317,-13.179 5.274,-16.273 39.855,-18.266 82.976,-33.98 82.976,-33.98 -27.621,6.031 -53.914,12.203 -79.226,21.687 15.574,-47.457 55.98,-111.648 55.984,-111.551 z m -67.359,-31.867 c 13.047,3.754 26.023,8.07 39.937,15.262 -40.523,-0.938 -67.214,2.875 -101.777,14.558 22.129,-12.675 35.953,-20.589 61.84,-29.82 z m -30.75,0.816 c 4.848,-2.921 11.637,-2.921 15.141,-2.453 -12.45,4.793 -18.77,7.582 -32.567,14.325 7.016,-5.438 9.473,-7.309 17.426,-11.872 z m -45.274,75.879 c 0.313,-10.523 2.223,-20.601 4.047,-29.406 29.856,-11.246 60.684,-16.226 92.512,-17.066 -35.039,11.902 -67.43,27.664 -96.559,46.472 z m 4.266,56.989 c -2.637,-16.524 -4.094,-32 -4.328,-46.207 33.539,-22.34 71.766,-40.559 113.723,-53.27 -39.629,25.649 -76.993,59.184 -109.395,99.477 z m 2.574,14.547 -0.496,-2.629 c 32.727,-41.637 74.149,-80.024 118.262,-107.895 -19.68,31.887 -38.766,66.445 -53.27,112.07 -8.562,3.965 -22.011,9.454 -30.23,13.563 -17.523,-4.359 -22,-6.926 -34.266,-15.109 z m 6.129,29.183 c -1.758,-9.969 -1.23,-6.445 -2.926,-13.933 9.282,3.906 7.297,3.8 18.157,6.308 -8.414,4.363 -7.239,3.117 -15.231,7.625 z m 29.731,89.004 c -12.203,-29.008 -17.723,-48.094 -25.524,-74.707 15.016,-8.785 18.176,-11.496 30.379,-18.172 4.27,0.656 10.77,2.508 15.188,2.969 -8.993,33.039 -14.309,54.793 -20.043,89.91 z m 147.05,250.07 c -4.3,-5.285 -7.832,-9.629 -12.117,-15.191 37.313,-22.055 80.684,-32.52 80.684,-32.52 -8.387,1.184 -12.859,1.758 -27.449,4.938 -21.16,5.004 -43.539,10.957 -59.344,19.957 -25.684,-33.961 -51.887,-72.035 -75.234,-114.242 -3.782,-6.824 -7.454,-13.641 -11.028,-20.449 41.949,2.105 88,-2.434 135.844,-14.754 49.012,-12.629 93.297,-32.336 130.805,-56.379 4.316,8.605 8.441,17.176 12.382,25.699 -0.507,6.207 -1.062,12.519 -1.644,18.941 -5.008,54.649 -15.656,105.219 -30.172,149.618 -23.234,7.691 -47.613,14.589 -72.91,20.656 -24.172,5.789 -46.348,10.308 -69.817,13.726 z m 84.836,82.848 c -21.144,-15.355 -51.222,-43.402 -75.105,-70.973 21.824,-2.793 42.984,-6.07 65.398,-11.441 21.641,-5.188 42.313,-11.375 61.961,-18.434 -15.25,39.45 -34.152,75 -52.254,100.848 z m -90.449,-68.551 c 24.438,27.528 49.297,50.981 73.449,69.341 -46.043,-9 -90.203,-24.47 -136.121,-49.919 4.145,-4.953 8.61,-11.98 13.539,-16.676 17.067,-0.222 31.352,-0.894 49.133,-2.746 z m -18.551,-22.453 c 3.032,3.727 4.895,6.617 7.946,10.219 -9.293,1.176 -15.43,1.633 -24.543,2.426 5.972,-4.868 10.304,-8.231 16.597,-12.645 z M 436.363,773.141 c 4.457,8.707 9.321,17.078 14.285,25.707 22.571,39.211 49.93,80.941 77.497,115.609 -10.946,6.875 -20.879,14.125 -29.618,21.676 -17.609,1.097 -34.793,1.469 -51.425,1.097 -5.895,-3.98 -10.344,-7.226 -16.145,-11.488 -9.559,-44.469 -14.918,-94.359 -12.781,-151.203 l 3.16,-2.148 c 5.012,0.707 9.871,0.246 15.027,0.75 z M 419.77,736.914 c 1.832,3.973 3.699,7.957 5.601,11.945 -2.273,1.278 -4.519,2.563 -6.738,3.864 0.324,-5.235 0.703,-10.504 1.137,-15.809 z M 365.832,571.656 c 1.977,11.266 2.617,13.098 5.559,25.016 -17.149,10.098 -22.774,13.883 -37.493,24.617 7.684,-15.121 7.758,-13.68 17.375,-28.473 4.707,-7.234 9.563,-14.293 14.559,-21.16 z m -5.91,-64.59 c -0.125,13.739 0.82,28.489 2.793,44.063 -8.481,-8.254 -14.43,-17.691 -17.313,-28.047 -0.41,-1.473 -0.757,-2.949 -1.035,-4.445 5.051,-3.961 10.242,-7.817 15.555,-11.571 z m 4.719,-43.027 c -2.293,9.727 -3.739,20.383 -4.368,31.852 -5.75,3.929 -11.371,7.968 -16.851,12.129 0.098,-13.27 4.816,-27.082 13.492,-40.618 2.559,-1.168 5.137,-2.293 7.727,-3.363 z m 89.195,-61.324 c -4.52,-0.969 -8.941,-1.621 -13.266,-1.957 16.895,-7.879 35.582,-14.621 55.731,-19.813 29.906,-7.703 58.527,-10.898 84.375,-10.238 -6.406,2.5 -12.75,5.773 -19.008,9.762 -22.934,1.386 -46.266,4.855 -69.586,10.863 -13.176,3.395 -25.93,7.203 -38.246,11.383 z m 55.227,24.047 c -15.844,-10.192 -27.801,-15.782 -42.344,-20.543 9.496,-3.114 19.203,-5.957 29.117,-8.508 19.066,-4.914 38.074,-8.527 56.816,-10.949 -13.984,10.609 -31.91,25.652 -43.589,40 z M 631.309,542.75 c -29.774,-37.652 -60.614,-69.477 -90.477,-93.41 54.66,9.137 105.574,27.234 143.426,43.41 -11.699,17.816 -29.731,35.137 -52.949,50" /><path
+         id="path68"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1095.13,368.133 21.29,0 62.34,-124.289 0.38,0 0,124.289 13.43,0 0,-138.867 -21.29,0 -62.34,124.289 -0.38,0 0,-124.289 -13.43,0 0,138.867" /><path
+         id="path70"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1270.6,287.574 c 0,20.715 -0.38,29.918 -22.25,29.918 -21.86,0 -22.25,-9.203 -22.25,-29.918 l 44.5,0 z m -44.5,-12.277 0,-9.016 c 0,-21.289 3.64,-27.426 20.52,-27.426 19.76,0 23.98,0.387 23.98,19.567 l 12.27,0 0,-3.649 c 0,-19.558 -4.79,-27.039 -34.14,-27.039 -32.22,0 -36.06,10.739 -36.06,50.446 0,40.468 6.53,50.441 36.06,50.441 29.35,0 34.14,-11.894 34.14,-38.555 l 0,-14.769 -56.77,0" /><path
+         id="path72"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1306.45,315.961 -10.17,0 0,11.125 10.17,0 0,22.637 12.27,0 0,-22.637 31.65,0 0,-11.125 -31.65,0 0,-65.406 c 0,-8.055 2.49,-11.7 10.55,-11.7 9.21,0 13.24,1.731 13.24,23.399 l 11.12,0 c 0,-31.258 -9.97,-34.52 -24.17,-34.52 -18.03,0 -23.01,5.563 -23.01,20.137 l 0,68.09" /><path
+         id="path74"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1358.22,327.086 12.09,0 19.37,-85.352 0.38,0 18.41,85.352 17.65,0 18.41,-85.543 0.39,0 19.37,85.543 12.08,0 -23.21,-97.82 -17.83,0 -17.84,85.543 -0.39,0 -17.83,-85.543 -17.84,0 -23.21,97.82" /><path
+         id="path76"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1522.18,238.855 c 19.57,0 22.63,2.879 22.63,39.325 0,36.437 -3.06,39.312 -22.63,39.312 -19.56,0 -22.63,-2.875 -22.63,-39.312 0,-36.446 3.07,-39.325 22.63,-39.325 z m 0,89.766 c 32.23,0 36.06,-11.508 36.06,-50.441 0,-40.477 -4.22,-50.446 -36.06,-50.446 -31.84,0 -36.06,9.969 -36.06,50.446 0,38.933 3.84,50.441 36.06,50.441" /><path
+         id="path78"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1576.82,327.086 12.28,0 0,-11.891 0.38,0 c 4.6,9.399 10.36,13.426 22.64,13.426 15.53,0 22.63,-6.715 22.63,-26.277 l 0,-7.864 -11.12,0 c 0.19,18.028 -1.92,23.012 -15.93,23.012 -12.27,0.199 -18.6,-6.707 -18.6,-20.133 l 0,-68.093 -12.28,0 0,97.82" /><path
+         id="path80"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1665.42,275.297 -5.37,0 0,-46.031 -12.27,0 0,138.867 12.27,0 0,-80.559 5.75,0 28.97,39.512 15.15,0 -34.33,-45.266 39.51,-52.554 -16.31,0 -33.37,46.031" /><path
+         id="path82"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1787.76,259.57 c -0.38,-16.875 2.68,-20.715 20.91,-20.715 19.75,0 23.39,2.879 23.39,19.372 0,12.851 -1.33,13.812 -24.55,15.156 -24.55,1.344 -31.26,4.984 -31.26,26.66 0,20.523 3.84,28.578 32.99,28.578 28.59,0 34.14,-6.523 34.14,-27.047 l -12.27,0 c 0,14.965 -4.03,15.918 -22.44,15.918 -17.08,0 -20.14,-1.722 -20.14,-16.875 0,-13.812 1.73,-14.961 22.44,-16.109 28.96,-1.731 33.37,-4.031 33.37,-25.508 0,-23.02 -4.41,-31.266 -36.06,-31.266 -22.44,0 -32.8,2.684 -32.8,31.836 l 12.28,0" /><path
+         id="path84"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1898.8,238.855 c 19.56,0 22.63,2.879 22.63,39.325 0,36.437 -3.07,39.312 -22.63,39.312 -19.57,0 -22.63,-2.875 -22.63,-39.312 0,-36.446 3.06,-39.325 22.63,-39.325 z m 0,89.766 c 32.22,0 36.06,-11.508 36.06,-50.441 0,-40.477 -4.22,-50.446 -36.06,-50.446 -31.84,0 -36.06,9.969 -36.06,50.446 0,38.933 3.84,50.441 36.06,50.441" /><path
+         id="path86"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 1956.7,229.266 12.2813,0 0,138.867 -12.2813,0 0,-138.867 z" /><path
+         id="path88"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 2061.04,229.266 -12.28,0 0,12.664 -0.39,0 c -6.13,-10.555 -12.85,-14.196 -27.04,-14.196 -22.64,0 -28.77,11.313 -28.77,30.301 l 0,69.051 12.28,0 0,-66.172 c 0,-11.316 2.49,-22.059 18.6,-22.059 14.96,0 25.32,5.758 25.32,26.469 l 0,61.762 12.28,0 0,-97.82" /><path
+         id="path90"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 2084.61,315.961 -10.16,0 0,11.125 10.16,0 0,22.637 12.28,0 0,-22.637 31.65,0 0,-11.125 -31.65,0 0,-65.406 c 0,-8.055 2.49,-11.7 10.54,-11.7 9.21,0 13.24,1.731 13.24,23.399 l 11.12,0 c 0,-31.258 -9.97,-34.52 -24.16,-34.52 -18.03,0 -23.02,5.563 -23.02,20.137 l 0,68.09" /><path
+         id="path92"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 2148.47,327.086 12.28,0 0,-97.82 -12.28,0 0,97.82 z m 0,41.047 12.28,0 0,-16.301 -12.28,0 0,16.301" /><path
+         id="path94"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 2218.67,238.855 c 19.56,0 22.62,2.879 22.62,39.325 0,36.437 -3.06,39.312 -22.62,39.312 -19.58,0 -22.64,-2.875 -22.64,-39.312 0,-36.446 3.06,-39.325 22.64,-39.325 z m 0,89.766 c 32.21,0 36.05,-11.508 36.05,-50.441 0,-40.477 -4.22,-50.446 -36.05,-50.446 -31.85,0 -36.07,9.969 -36.07,50.446 0,38.933 3.84,50.441 36.07,50.441" /><path
+         id="path96"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 2273.3,327.086 12.28,0 0,-12.656 0.38,0 c 6.14,10.547 12.85,14.191 27.05,14.191 22.63,0 28.77,-11.316 28.77,-30.305 l 0,-69.05 -12.28,0 0,66.172 c 0,11.32 -2.5,22.054 -18.6,22.054 -14.96,0 -25.32,-5.75 -25.32,-26.461 l 0,-61.765 -12.28,0 0,97.82" /><path
+         id="path98"
+         style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         d="m 2374.17,259.57 c -0.38,-16.875 2.69,-20.715 20.91,-20.715 19.76,0 23.4,2.879 23.4,19.372 0,12.851 -1.34,13.812 -24.55,15.156 -24.55,1.344 -31.26,4.984 -31.26,26.66 0,20.523 3.84,28.578 32.99,28.578 28.58,0 34.14,-6.523 34.14,-27.047 l -12.28,0 c 0,14.965 -4.02,15.918 -22.44,15.918 -17.07,0 -20.14,-1.722 -20.14,-16.875 0,-13.812 1.73,-14.961 22.45,-16.109 28.96,-1.731 33.36,-4.031 33.36,-25.508 0,-23.02 -4.4,-31.266 -36.05,-31.266 -22.44,0 -32.8,2.684 -32.8,31.836 l 12.27,0" /></g></g></svg>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/defaultLogo.svg.d.ts b/sdnr/wt-odlux/odlux/framework/src/assets/images/defaultLogo.svg.d.ts
new file mode 100644
index 0000000..60e4856
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/defaultLogo.svg.d.ts
@@ -0,0 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+declare const path: string;
+export default path;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/home.svg b/sdnr/wt-odlux/odlux/framework/src/assets/images/home.svg
new file mode 100644
index 0000000..080d050
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/home.svg
@@ -0,0 +1,20 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="460.298px" height="460.297px" viewBox="0 0 460.298 460.297" style="enable-background:new 0 0 460.298 460.297;"
+	 xml:space="preserve">
+<g>
+	<g>
+		<path fill="#565656" d="M230.149,120.939L65.986,256.274c0,0.191-0.048,0.472-0.144,0.855c-0.094,0.38-0.144,0.656-0.144,0.852v137.041
+			c0,4.948,1.809,9.236,5.426,12.847c3.616,3.613,7.898,5.431,12.847,5.431h109.63V303.664h73.097v109.64h109.629
+			c4.948,0,9.236-1.814,12.847-5.435c3.617-3.607,5.432-7.898,5.432-12.847V257.981c0-0.76-0.104-1.334-0.288-1.707L230.149,120.939
+			z"/>
+		<path fill="#565656" d="M457.122,225.438L394.6,173.476V56.989c0-2.663-0.856-4.853-2.574-6.567c-1.704-1.712-3.894-2.568-6.563-2.568h-54.816
+			c-2.666,0-4.855,0.856-6.57,2.568c-1.711,1.714-2.566,3.905-2.566,6.567v55.673l-69.662-58.245
+			c-6.084-4.949-13.318-7.423-21.694-7.423c-8.375,0-15.608,2.474-21.698,7.423L3.172,225.438c-1.903,1.52-2.946,3.566-3.14,6.136
+			c-0.193,2.568,0.472,4.811,1.997,6.713l17.701,21.128c1.525,1.712,3.521,2.759,5.996,3.142c2.285,0.192,4.57-0.476,6.855-1.998
+			L230.149,95.817l197.57,164.741c1.526,1.328,3.521,1.991,5.996,1.991h0.858c2.471-0.376,4.463-1.43,5.996-3.138l17.703-21.125
+			c1.522-1.906,2.189-4.145,1.991-6.716C460.068,229.007,459.021,226.961,457.122,225.438z"/>
+
+<path fill="#D81036" d="M 457.122 225.438 L 251.849 54.417 L 251.849 54.417 C 245.765 49.468 238.531 46.994 230.155 46.994 C 221.78 46.994 214.547 49.468 208.457 54.417 L 3.172 225.438 C 1.269 226.958 0.226 229.004 0.032 231.574 C -0.161 234.142 0.504 236.385 2.029 238.287 L 19.73 259.415 C 21.255 261.127 23.251 262.174 25.726 262.557 C 28.011 262.749 30.296 262.081 32.581 260.559 L 230.149 95.817 L 427.719 260.558 C 429.245 261.886 431.24 262.549 433.715 262.549 H 434.573 C 437.044 262.173 439.036 261.119 440.569 259.411 L 458.272 238.286 C 459.794 236.38 460.461 234.141 460.263 231.57 C 460.068 229.007 459.021 226.961 457.122 225.438 Z"/>
+	</g>
+</g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/home.svg.d.ts b/sdnr/wt-odlux/odlux/framework/src/assets/images/home.svg.d.ts
new file mode 100644
index 0000000..7098d79
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/home.svg.d.ts
@@ -0,0 +1,20 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+ declare const home: string;
+ export default home;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/odluxLogo.gif b/sdnr/wt-odlux/odlux/framework/src/assets/images/odluxLogo.gif
new file mode 100644
index 0000000..ad188a8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/odluxLogo.gif
Binary files differ
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/odluxLogo.gif.d.ts b/sdnr/wt-odlux/odlux/framework/src/assets/images/odluxLogo.gif.d.ts
new file mode 100644
index 0000000..3613183
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/odluxLogo.gif.d.ts
@@ -0,0 +1,20 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+declare const odluxLogo: string;
+export default odluxLogo;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/onapLogo.gif b/sdnr/wt-odlux/odlux/framework/src/assets/images/onapLogo.gif
new file mode 100644
index 0000000..cd7eb8f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/onapLogo.gif
Binary files differ
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/images/onapLogo.gif.d.ts b/sdnr/wt-odlux/odlux/framework/src/assets/images/onapLogo.gif.d.ts
new file mode 100644
index 0000000..5bfb37a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/images/onapLogo.gif.d.ts
@@ -0,0 +1,20 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+ declare const onapLogo: string;
+ export default onapLogo;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/assets/version.json b/sdnr/wt-odlux/odlux/framework/src/assets/version.json
new file mode 100644
index 0000000..6d4eb0c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/assets/version.json
@@ -0,0 +1,4 @@
+{
+    "version":"56.139cd6d(20/07/08)",
+    "build":"2020-07-16T06:06:24Z"
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/common/event.ts b/sdnr/wt-odlux/odlux/framework/src/common/event.ts
new file mode 100644
index 0000000..9134879
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/common/event.ts
@@ -0,0 +1,81 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+/**
+  * Represents an event.
+  * Events enable a class or object to notify other classes or objects when something of interest occurs.
+  * The class that sends (or invokes) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.
+  * 
+  * Objects can create an instances of an Events and offer that Events for other objects to attach to.
+  * Objects who want to be informed about an Event can attach a function (an event handler) to the event which is then called when the event is fired.
+  * 
+  * @template TEventArg Type of the event argument. Use void if the event does not has an argument.
+  */
+export class Event<TEventArg> {
+
+  /**
+   * Creates a new instance of the Event class.
+   */
+  constructor() {
+    this.eventHandlers = new Array<(arg: TEventArg) => void>();
+  }
+
+  /**
+   * Adds an event handler to this event, so that when the event is fired the given event handler function is called.
+   * 
+   * @param eventHandler The event handler function to add to this event.
+   * @throws {Error} Thrown if the given event handler function has already been added to this event.
+   */
+  public addHandler = (eventHandler: (arg: TEventArg) => void): void => {
+    if (this.eventHandlers.indexOf(eventHandler) > -1) {
+      throw new Error("The given event handler is already added to this event.");
+    }
+
+    this.eventHandlers.push(eventHandler);
+  }
+
+  /**
+   * Removes an event handler from this event, so that the given event handler function will not be called anymore when the event is fired.
+   * 
+   * @param eventHandler: The event handler function to remove.
+   * @throws {Error} Thrown if the given event handler function has not been added to this event before.
+   */
+  public removeHandler = (eventHandler: (arg: TEventArg) => void): void => {
+    const index = this.eventHandlers.indexOf(eventHandler);
+    if (!(index > -1)) {
+      throw new Error("The given event handler has not been added to this event yet.");
+    }
+
+    this.eventHandlers.splice(index, 1);
+  }
+
+  /**
+   * Invokes the event and calls all event handler functions currently registered on the event.
+   * 
+   * @param argument The argument for the event. The argument will be passed to all registered event handler functions.
+   */
+  public invoke = (argument?: TEventArg): void => {
+    this.eventHandlers.forEach((eventHandler: (arg?: TEventArg) => void, index: number, array: Array<(arg: TEventArg) => void>): void => {
+      eventHandler(argument);
+    });
+  }
+
+  private eventHandlers: Array<(arg?: TEventArg) => void>;
+
+}
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/errorDisplay.tsx b/sdnr/wt-odlux/odlux/framework/src/components/errorDisplay.tsx
new file mode 100644
index 0000000..d41d826
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/errorDisplay.tsx
@@ -0,0 +1,131 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import  React from 'react';
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import Modal from '@mui/material/Modal';
+import Button from '@mui/material/Button';
+import Card from '@mui/material/Card';
+import CardActions from '@mui/material/CardActions';
+import CardContent from '@mui/material/CardContent';
+import Typography from '@mui/material/Typography';
+
+import { ClearErrorInfoAction, RemoveErrorInfoAction } from '../actions/errorActions';
+
+import { connect, Connect } from '../flux/connect';
+
+const styles = (theme: Theme) => createStyles({
+  modal: {
+    display: "flex",
+    alignItems: "center",
+    justifyContent: "center",
+  },
+  paper: {
+    width: theme.spacing(50),
+    backgroundColor: theme.palette.background.paper,
+    boxShadow: theme.shadows[5],
+    padding: theme.spacing(4),
+  },
+  card: {
+    minWidth: 275,
+  },
+  bullet: {
+    display: 'inline-block',
+    margin: '0 2px',
+    transform: 'scale(0.8)',
+  },
+  title: {
+    marginBottom: 16,
+    fontSize: 14,
+  },
+  pos: {
+    marginBottom: 12,
+  },
+});
+
+type ErrorDisplayProps = WithStyles<typeof styles> & Connect;
+
+// function getModalStyle() {
+//   const top = 50 + rand();
+//   const left = 50 + rand();
+
+//   return {
+//     top: `${ top }%`,
+//     left: `${ left }%`,
+//     transform: `translate(-${ top }%, -${ left }%)`,
+//   };
+// }
+
+/**
+ * Represents a component for formatting and displaying errors.
+ */
+class ErrorDisplayComponent extends React.Component<ErrorDisplayProps> {
+  constructor(props: ErrorDisplayProps) {
+    super(props);
+  }
+
+  render(): JSX.Element {
+    const { classes, state } = this.props;
+    const errorInfo = state.framework.applicationState.errors.length && state.framework.applicationState.errors[state.framework.applicationState.errors.length - 1];
+    
+    return (
+      <Modal className={classes.modal}
+        aria-labelledby="simple-modal-title"
+        aria-describedby="simple-modal-description"
+        open={state.framework.applicationState.errors && state.framework.applicationState.errors.length > 0}
+        onClose={() => this.props.dispatch(new ClearErrorInfoAction())}
+      >
+        {errorInfo &&
+          <div className={classes.paper}>
+            <Card className={classes.card}>
+              <CardContent>
+                <Typography className={classes.title} color="textSecondary">
+                  {errorInfo.title != null ? errorInfo.title : "Something went wrong."}
+                </Typography>
+                <Typography variant="h5" component="h2">
+                  {errorInfo.error && errorInfo.error.toString()}
+                </Typography>
+                <Typography className={classes.pos} color="textSecondary">
+                  {errorInfo.message && errorInfo.message.toString()}
+                </Typography>
+                <Typography component="p">
+                  {errorInfo.info && errorInfo.info.componentStack && errorInfo.info.componentStack.split('\n').map(line => {
+                    return [line, <br />];
+                  })}
+                  {errorInfo.info && errorInfo.info.extra && errorInfo.info.extra.split('\n').map(line => {
+                    return [line, <br />];
+                  })}
+                </Typography>
+              </CardContent>
+              <CardActions>
+                <Button color="inherit" size="small" onClick={() => this.props.dispatch(new RemoveErrorInfoAction(errorInfo))} >Close</Button>
+              </CardActions>
+            </Card>
+          </div> || <div></div>
+        }
+      </Modal>
+    );
+  }
+}
+
+export const ErrorDisplay = withStyles(styles)(connect()(ErrorDisplayComponent));
+export default ErrorDisplay;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/icons/menuIcon.tsx b/sdnr/wt-odlux/odlux/framework/src/components/icons/menuIcon.tsx
new file mode 100644
index 0000000..0d7d734
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/icons/menuIcon.tsx
@@ -0,0 +1,29 @@
+import React from 'react';
+
+type MenuIconPropsBase = {
+  className?: string;
+  size?: number | string;
+};
+
+type MenuIconPropsWithColor = MenuIconPropsBase & {
+  color: string;
+};
+
+type MenuIconProps = MenuIconPropsBase | MenuIconPropsWithColor;
+
+const MenuIcon = (props: MenuIconProps) => {
+  const { className, size = '30px' } = props;
+  const color = 'color' in props ? props.color : '#36A9E1';
+
+  return (
+    <svg className={className} width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
+      <path fill={color} d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z" />
+      <path fill={color} d="M28,14H4c-1.104,0-2,0.896-2,2  s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z" />
+      <path fill={color} d="M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2  S29.104,22,28,22z" />
+    </svg>
+  );
+};
+
+MenuIcon.defaultName = 'MenuIcon';
+
+export default MenuIcon;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/logo.tsx b/sdnr/wt-odlux/odlux/framework/src/components/logo.tsx
new file mode 100644
index 0000000..f2bb1f5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/logo.tsx
@@ -0,0 +1,103 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+/******************************************************************************
+ * Copyright 2018 highstreet technologies GmbH
+ * 
+ * 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.
+ *****************************************************************************/
+
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { Theme } from '@mui/material/styles'; // infra for styling
+
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+
+const defaultLogo = require('../assets/icons/ht.Connect.svg');
+
+const styles = (theme: Theme) => createStyles({
+  headerLogo: {
+    backgroundImage: "url(" + (theme.design && theme.design.url || defaultLogo) + ")",
+    backgroundColor: theme.palette.primary.main,
+    backgroundRepeat: "no-repeat",
+    backgroundSize: "auto " + (theme.design && theme.design.logoHeight || 70) + "px",
+    height: theme.design && theme.design.logoHeight || 70,
+    width: theme.design ? theme.design.width / theme.design.height * theme.design.logoHeight : 220
+  }
+});
+
+type LogoProps = RouteComponentProps<{ id: string }> & WithStyles<typeof styles>;
+interface ILogoState {
+  windowWidth: number
+}
+
+class LogoComponent extends React.Component<LogoProps, ILogoState> {
+
+  private hideLogoWhenWindowWidthIsLower: number = 800;
+
+  constructor(props: LogoProps) {
+    super(props);
+    this.state = {
+      windowWidth: 0
+    };
+    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
+  }
+
+  componentDidMount(): void {
+    this.updateWindowDimensions();
+    window.addEventListener('resize', this.updateWindowDimensions);
+  };
+  componentWillUnmount(): void {
+    window.removeEventListener('resize', this.updateWindowDimensions);
+  };
+  updateWindowDimensions(): void {
+    this.setState({ windowWidth: window.innerWidth });
+  }
+
+  render(): JSX.Element {
+    let div: JSX.Element = <div />;
+    if (this.state.windowWidth >= this.hideLogoWhenWindowWidthIsLower) {
+      div = <div className={this.props.classes.headerLogo} />;
+    } else {
+      console.info([
+        "Logo hidden, because browser window width (",
+        this.state.windowWidth,
+        "px) is lower threshold (",
+        this.hideLogoWhenWindowWidthIsLower,
+        "px)."].join(''));
+    }
+    return div;
+  }
+}
+
+export const Logo = withStyles(styles)(withRouter(LogoComponent));
+export default Logo;
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/columnModel.ts b/sdnr/wt-odlux/odlux/framework/src/components/material-table/columnModel.ts
new file mode 100644
index 0000000..3ed3134
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/columnModel.ts
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+
+export enum ColumnType {
+  text,
+  numeric,
+  boolean,
+  date,
+  custom
+}
+
+type CustomControl<TData> = {
+  className?: string;
+  style?: React.CSSProperties;
+  rowData: TData;
+}
+
+export type ColumnModel<TData> = {
+  title?: string;
+  disablePadding?: boolean;
+  width?: string | number ;
+  className?: string;
+  hide?: boolean;
+  style?: React.CSSProperties;
+  align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
+  disableSorting?: boolean;
+  disableFilter?: boolean;
+} & ({
+  property: string;
+  type: ColumnType.custom;
+  customControl: React.ComponentType<CustomControl<TData>>;
+} | {
+  property: keyof TData;
+  type: ColumnType.boolean;
+  labels?: { "true": string, "false": string };
+} | {
+    property: keyof TData;
+    type?: ColumnType.numeric | ColumnType.text | ColumnType.date;
+});
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/index.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-table/index.tsx
new file mode 100644
index 0000000..c1a5005
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/index.tsx
@@ -0,0 +1,707 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import Table from '@mui/material/Table';
+import TableBody from '@mui/material/TableBody';
+import TableCell from '@mui/material/TableCell';
+import TableContainer from '@mui/material/TableContainer';
+import TablePagination from '@mui/material/TablePagination';
+import TableRow from '@mui/material/TableRow';
+import Paper from '@mui/material/Paper';
+import Checkbox from '@mui/material/Checkbox';
+
+import { TableToolbar } from './tableToolbar';
+import { EnhancedTableHead } from './tableHead';
+import { EnhancedTableFilter } from './tableFilter';
+
+import { ColumnModel, ColumnType } from './columnModel';
+import { Menu, Typography } from '@mui/material';
+import { DistributiveOmit } from '@mui/types';
+
+import makeStyles from '@mui/styles/makeStyles';
+
+import { SvgIconProps } from '@mui/material/SvgIcon';
+
+import { DividerTypeMap } from '@mui/material/Divider';
+import { MenuItemProps } from '@mui/material/MenuItem';
+import { flexbox } from '@mui/system';
+import { RowDisabled } from './utilities';
+import { toAriaLabel } from '../../utilities/yangHelper';
+export { ColumnModel, ColumnType } from './columnModel';
+
+type propType = string | number | null | undefined | (string | number)[];
+type dataType = { [prop: string]: propType };
+type resultType<TData = dataType> = { page: number, total: number, rows: TData[] };
+
+export type DataCallback<TData = dataType> = (page?: number, rowsPerPage?: number, orderBy?: string | null, order?: 'asc' | 'desc' | null, filter?: { [property: string]: string }) => resultType<TData> | Promise<resultType<TData>>;
+
+function regExpEscape(s: string) {
+  return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
+}
+
+function wildcardCheck(input: string, pattern: string) {
+   if (!pattern) return true; 
+   const regex = new RegExp(
+     (!pattern.startsWith('*') ? '^' : '') + 
+     pattern.split(/\*+/).map(p => p.split(/\?+/).map(regExpEscape).join('.')).join('.*') + 
+     (!pattern.endsWith('*') ? '$' : '')
+   );
+   return input.match(regex) !== null && input.match(regex)!.length >= 1;
+}
+
+function desc(a: dataType, b: dataType, orderBy: string) {
+  if ((b[orderBy] || "") < (a[orderBy] || "")) {
+    return -1;
+  }
+  if ((b[orderBy] || "") > (a[orderBy] || "")) {
+    return 1;
+  }
+  return 0;
+}
+
+function stableSort(array: dataType[], cmp: (a: dataType, b: dataType) => number) {
+  const stabilizedThis = array.map((el, index) => [el, index]) as [dataType, number][];
+  stabilizedThis.sort((a, b) => {
+    const order = cmp(a[0], b[0]);
+    if (order !== 0) return order;
+    return a[1] - b[1];
+  });
+  return stabilizedThis.map(el => el[0]);
+}
+
+function getSorting(order: 'asc' | 'desc' | null, orderBy: string) {
+  return order === 'desc' ? (a: dataType, b: dataType) => desc(a, b, orderBy) : (a: dataType, b: dataType) => -desc(a, b, orderBy);
+}
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    width: '100%',
+    overflow: "hidden",
+    marginTop: theme.spacing(3),
+    position: "relative",
+    boxSizing: "border-box",
+    display: "flex",
+    flexDirection: "column",
+  },
+  container: {
+    flex: "1 1 100%"
+  },
+  pagination: {
+    overflow: "hidden",
+    minHeight: "52px"
+  }
+});
+
+const useTableRowExtStyles = makeStyles((theme: Theme) => createStyles({
+  disabled: {
+    color: "rgba(180, 180, 180, 0.7)",
+  },
+}));
+
+type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any;
+type TableRowExtProps = GetStatelessComponentProps<typeof TableRow> & { disabled: boolean };
+const TableRowExt : React.FC<TableRowExtProps> = (props) => {
+  const [disabled, setDisabled] = React.useState(true);
+  const classes = useTableRowExtStyles();
+  
+  const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
+      if (ev.button ===1){
+        setDisabled(!disabled);  
+        ev.preventDefault();
+        ev.stopPropagation();
+      } else if (props.disabled && disabled) {
+        ev.preventDefault();
+        ev.stopPropagation();
+      }
+  }; 
+
+  return (   
+    <TableRow {...{...props,  color: props.disabled && disabled ? '#a0a0a0' : undefined , className: props.disabled && disabled ? classes.disabled : '', onMouseDown, onContextMenu: props.disabled && disabled ? onMouseDown : props.onContextMenu } }  /> 
+  );
+};
+
+export type MaterialTableComponentState<TData = {}> = {
+  order: 'asc' | 'desc';
+  orderBy: string | null;
+  selected: any[] | null;
+  rows: TData[];
+  total: number;
+  page: number;
+  rowsPerPage: number;
+  loading: boolean;
+  showFilter: boolean;
+  hiddenColumns: string[];
+  filter: { [property: string]: string };
+};
+
+export type TableApi = { forceRefresh?: () => Promise<void> };
+
+type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles>  & {
+  className?: string;
+  columns: ColumnModel<TData>[];
+  idProperty: keyof TData | ((data: TData) => React.Key);
+  
+  //Note: used to save settings as well. Must be unique across apps. Null tableIds will not get saved to the settings
+  tableId: string | null;
+  isPopup?: boolean;
+  title?: string;
+  stickyHeader?: boolean;
+  allowHtmlHeader?: boolean;
+  defaultSortOrder?: 'asc' | 'desc';
+  defaultSortColumn?: keyof TData;
+  enableSelection?: boolean;
+  disableSorting?: boolean;
+  disableFilter?: boolean;
+  customActionButtons?: { icon: React.ComponentType<SvgIconProps>, tooltip?: string, ariaLabel: string, onClick: () => void, disabled?: boolean }[];
+  onHandleClick?(event: React.MouseEvent<HTMLTableRowElement>, rowData: TData): void;
+  createContextMenu?: (row: TData) => React.ReactElement<MenuItemProps | DividerTypeMap<{}, "hr">, React.ComponentType<MenuItemProps | DividerTypeMap<{}, "hr">>>[];
+};
+
+type MaterialTableComponentPropsWithRows<TData = {}> = MaterialTableComponentBaseProps<TData> & { rows: TData[]; asynchronus?: boolean; };
+type MaterialTableComponentPropsWithRequestData<TData = {}> = MaterialTableComponentBaseProps<TData> & { onRequestData: DataCallback; tableApi?: TableApi; };
+type MaterialTableComponentPropsWithExternalState<TData = {}> = MaterialTableComponentBaseProps<TData> & MaterialTableComponentState & {
+  onToggleFilter: () => void;
+  onFilterChanged: (property: string, filterTerm: string) => void;
+  onHandleChangePage: (page: number) => void;
+  onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
+  onHandleRequestSort: (property: string) => void;
+  onHideColumns : (columnNames: string[]) => void
+  onShowColumns:  (columnNames: string[]) => void
+};
+
+type MaterialTableComponentProps<TData = {}> =
+  MaterialTableComponentPropsWithRows<TData> |
+  MaterialTableComponentPropsWithRequestData<TData> |
+  MaterialTableComponentPropsWithExternalState<TData>;
+
+function isMaterialTableComponentPropsWithRows(props: MaterialTableComponentProps): props is MaterialTableComponentPropsWithRows {
+  return (props as MaterialTableComponentPropsWithRows).rows !== undefined && (props as MaterialTableComponentPropsWithRows).rows instanceof Array;
+}
+
+function isMaterialTableComponentPropsWithRequestData(props: MaterialTableComponentProps): props is MaterialTableComponentPropsWithRequestData {
+  return (props as MaterialTableComponentPropsWithRequestData).onRequestData !== undefined && (props as MaterialTableComponentPropsWithRequestData).onRequestData instanceof Function;
+}
+
+function isMaterialTableComponentPropsWithRowsAndRequestData(props: MaterialTableComponentProps): props is MaterialTableComponentPropsWithExternalState {
+  const propsWithExternalState = (props as MaterialTableComponentPropsWithExternalState)
+  return propsWithExternalState.onFilterChanged instanceof Function ||
+    propsWithExternalState.onHandleChangePage instanceof Function ||
+    propsWithExternalState.onHandleChangeRowsPerPage instanceof Function ||
+    propsWithExternalState.onToggleFilter instanceof Function ||
+    propsWithExternalState.onHideColumns instanceof Function ||
+    propsWithExternalState.onHandleRequestSort instanceof Function
+}
+
+// get settings in here!
+
+
+class MaterialTableComponent<TData extends {} = {}> extends React.Component<MaterialTableComponentProps, MaterialTableComponentState & { contextMenuInfo: { index: number; mouseX?: number; mouseY?: number }; }> {
+
+  constructor(props: MaterialTableComponentProps) {
+    super(props);
+    
+
+    const page = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.page : 0;
+    const rowsPerPage = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.rowsPerPage || 10 : 10;
+
+    this.state = {
+      contextMenuInfo: { index: -1 },
+      filter: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.filter || {} : {},
+      showFilter: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.showFilter : false,
+      loading: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.loading : false,
+      order: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.order : this.props.defaultSortOrder || 'asc',
+      orderBy: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.orderBy : this.props.defaultSortColumn || null,
+      selected: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.selected : null,
+      rows: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) || [],
+      total: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.length || 0,
+      hiddenColumns: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) && this.props.hiddenColumns || [],
+      page,
+      rowsPerPage,
+    };
+
+    if (isMaterialTableComponentPropsWithRequestData(this.props)) {
+      this.update();
+
+      if (this.props.tableApi) {
+        this.props.tableApi.forceRefresh = () => this.update();
+      }
+    }
+  }
+  render(): JSX.Element {
+    const { classes, columns, allowHtmlHeader } = this.props;
+    const { rows, total: rowCount, order, orderBy, selected, rowsPerPage, page, showFilter, filter } = this.state;
+    const emptyRows = rowsPerPage - Math.min(rowsPerPage, rowCount - page * rowsPerPage);
+    const getId = typeof this.props.idProperty !== "function" ? (data: TData) => ((data as { [key: string]: any })[this.props.idProperty as any as string] as string | number) : this.props.idProperty;
+    const toggleFilter = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onToggleFilter : () => { !this.props.disableFilter && this.setState({ showFilter: !showFilter }, this.update) }
+
+    const hideColumns = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onHideColumns : (data: string[]) => { const newArray = [...new Set([...this.state.hiddenColumns, ...data])]; this.setState({hiddenColumns:newArray}); }
+    const showColumns = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onShowColumns : (data: string[]) => { const newArray = this.state.hiddenColumns.filter(el=> !data.includes(el));   this.setState({hiddenColumns:newArray}); }
+
+    const allColumnsHidden = this.props.columns.length === this.state.hiddenColumns.length;
+    return (
+      <Paper className={this.props.className ? `${classes.root} ${this.props.className}` : classes.root}>
+        <TableContainer className={classes.container}>
+          <TableToolbar tableId={this.props.tableId} numSelected={selected && selected.length} title={this.props.title} customActionButtons={this.props.customActionButtons} onExportToCsv={this.exportToCsv}
+            onToggleFilter={toggleFilter}
+            columns={columns}
+            onHideColumns={hideColumns}
+            onShowColumns={showColumns} />
+          <Table padding="normal" aria-label={this.props.tableId ? this.props.tableId : 'tableTitle'} stickyHeader={this.props.stickyHeader || false} >
+            <EnhancedTableHead
+              allowHtmlHeader={allowHtmlHeader || false}
+              columns={columns}
+              numSelected={selected && selected.length}
+              order={order}
+              orderBy={orderBy}
+              onSelectAllClick={this.handleSelectAllClick}
+              onRequestSort={this.onHandleRequestSort}
+              rowCount={rows.length}
+              enableSelection={this.props.enableSelection}
+              hiddenColumns={this.state.hiddenColumns}
+            />
+            <TableBody>
+              {showFilter && <EnhancedTableFilter columns={columns} hiddenColumns={this.state.hiddenColumns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
+              
+              {allColumnsHidden ? <Typography variant="body1" textAlign="center">All columns of this table are hidden.</Typography> :
+              
+              rows // may need ordering here
+                .map((entry: TData & { [RowDisabled]?: boolean, [kex: string]: any }, index) => {
+                  const entryId = getId(entry);
+                  const contextMenu = (this.props.createContextMenu && this.state.contextMenuInfo.index === index && this.props.createContextMenu(entry)) || null;
+                  const isSelected = this.isSelected(entryId) || this.state.contextMenuInfo.index === index;
+                  return (
+                    <TableRowExt
+                      hover
+                      onClick={event => {
+                        if (this.props.createContextMenu) {
+                          this.setState({
+                            contextMenuInfo: {
+                              index: -1
+                            }
+                          });
+                        }
+                        this.handleClick(event, entry, entryId);
+                      }}
+                      onContextMenu={event => {
+                        if (this.props.createContextMenu) {
+                          event.preventDefault();
+                          event.stopPropagation();
+                          this.setState({ contextMenuInfo: { index, mouseX: event.clientX - 2, mouseY: event.clientY - 4 } });
+                        }
+                      }}
+                      role="checkbox"
+                      aria-checked={isSelected}
+                      aria-label="table-row"
+                      tabIndex={-1}
+                      key={entryId}
+                      selected={isSelected}
+                      disabled={entry[RowDisabled] || false}
+                    >
+                      {this.props.enableSelection
+                        ? <TableCell padding="checkbox" style={{ width: "50px", color:  entry[RowDisabled] || false ? "inherit" : undefined } }>
+                          <Checkbox color='secondary' checked={isSelected} />
+                        </TableCell>
+                        : null
+                      }
+                      {
+                        
+                        this.props.columns.map(
+                          col => {
+                            const style = col.width ? { width: col.width } : {};
+                            const tableCell = (
+
+                              <TableCell style={ entry[RowDisabled] || false ? { ...style, color: "inherit"  } : style } aria-label={col.title? toAriaLabel(col.title) : toAriaLabel(col.property)} key={col.property} align={col.type === ColumnType.numeric && !col.align ? "right" : col.align} >
+                                {col.type === ColumnType.custom && col.customControl
+                                  ? <col.customControl className={col.className} style={col.style} rowData={entry} />
+                                  : col.type === ColumnType.boolean
+                                    ? <span className={col.className} style={col.style}>{col.labels ? col.labels[entry[col.property] ? "true" : "false"] : String(entry[col.property])}</span>
+                                    : <span className={col.className} style={col.style}>{String(entry[col.property])}</span>
+                                }
+                              </TableCell>
+                            );
+                            
+                            //show column if...
+                            const showColumn = !this.state.hiddenColumns.includes(col.property);
+                            return showColumn && tableCell
+                          }
+                        )
+                      }
+                      {<Menu open={!!contextMenu} onClose={() => this.setState({ contextMenuInfo: { index: -1 } })} anchorReference="anchorPosition" keepMounted
+                        anchorPosition={this.state.contextMenuInfo.mouseY != null && this.state.contextMenuInfo.mouseX != null ? { top: this.state.contextMenuInfo.mouseY, left: this.state.contextMenuInfo.mouseX } : undefined}>
+                        {contextMenu}
+                      </Menu> || null}
+                    </TableRowExt>
+                  );
+                })}
+              {emptyRows > 0 && (
+                <TableRow style={{ height: 49 * emptyRows }}>
+                  <TableCell colSpan={this.props.columns.length} />
+                </TableRow>
+              )}
+            </TableBody>
+          </Table>
+        </TableContainer>
+        <TablePagination className={classes.pagination}
+          rowsPerPageOptions={[5, 10, 20, 50]}
+          component="div"
+          count={rowCount}
+          rowsPerPage={rowsPerPage}
+          page={page}
+          aria-label={this.props.isPopup ? "popup-table-pagination-footer" : "table-pagination-footer" }
+          backIconButtonProps={{
+            'aria-label': this.props.isPopup ? 'popup-previous-page' : 'previous-page',
+          }}
+          nextIconButtonProps={{
+            'aria-label': this.props.isPopup ? 'popup-next-page': 'next-page',
+          }}
+          onPageChange={this.onHandleChangePage}
+          onRowsPerPageChange={this.onHandleChangeRowsPerPage}
+        />
+      </Paper>
+    );
+  }
+
+  static getDerivedStateFromProps(props: MaterialTableComponentProps, state: MaterialTableComponentState & { _rawRows: {}[] }): MaterialTableComponentState & { _rawRows: {}[] } {
+   
+    if (isMaterialTableComponentPropsWithRowsAndRequestData(props)) {
+      return {
+        ...state,
+        rows: props.rows,
+        total: props.total,
+        orderBy: props.orderBy,
+        order: props.order,
+        filter: props.filter,
+        loading: props.loading,
+        showFilter: props.showFilter,
+        page: props.page,
+        hiddenColumns: props.hiddenColumns,
+        rowsPerPage: props.rowsPerPage
+      }
+    } else if (isMaterialTableComponentPropsWithRows(props) && props.asynchronus && state._rawRows !== props.rows) {
+      const newState = MaterialTableComponent.updateRows(props, state);
+      return {
+        ...state,
+        ...newState,
+        _rawRows: props.rows || []
+      };
+    }
+    return state;
+  }
+
+  private static updateRows(props: MaterialTableComponentPropsWithRows, state: MaterialTableComponentState): { rows: {}[], total: number, page: number } {
+
+    let data = [...(props.rows as dataType[] || [])];
+    const columns = props.columns;
+
+    const { page, rowsPerPage, order, orderBy, filter } = state;
+
+    try {
+      if (state.showFilter) {
+        Object.keys(filter).forEach(prop => {
+          const column = columns.find(c => c.property === prop);
+          const filterExpression = filter[prop];
+
+          if (!column) throw new Error("Filter for not existing column found.");
+
+          if (filterExpression != null) {
+            data = data.filter((val) => {
+              const dataValue = val[prop];
+
+              if (dataValue != null) {
+
+                if (column.type === ColumnType.boolean) {
+
+                  const boolDataValue = JSON.parse(String(dataValue).toLowerCase());
+                  const boolFilterExpression = JSON.parse(String(filterExpression).toLowerCase());
+                  return boolDataValue == boolFilterExpression;
+
+                } else if (column.type === ColumnType.text) {
+
+                  const valueAsString = String(dataValue);
+                  const filterExpressionAsString = String(filterExpression).trim();
+                  if (filterExpressionAsString.length === 0) return true;
+                  return wildcardCheck(valueAsString, filterExpressionAsString);
+
+                } else if (column.type === ColumnType.numeric){
+                  
+                  const valueAsNumber = Number(dataValue);
+                  const filterExpressionAsString = String(filterExpression).trim();
+                  if (filterExpressionAsString.length === 0 || isNaN(valueAsNumber)) return true;
+                  
+                  if (filterExpressionAsString.startsWith('>=')) {
+                    return valueAsNumber >= Number(filterExpressionAsString.substring(2).trim());
+                  } else if (filterExpressionAsString.startsWith('<=')) {
+                    return valueAsNumber <= Number(filterExpressionAsString.substring(2).trim());
+                  } else if (filterExpressionAsString.startsWith('>')) {
+                    return valueAsNumber > Number(filterExpressionAsString.substring(1).trim());
+                  } else if (filterExpressionAsString.startsWith('<')) {
+                    return valueAsNumber < Number(filterExpressionAsString.substring(1).trim());
+                  }
+                } else if (column.type === ColumnType.date){
+                   const valueAsString = String(dataValue);
+
+                   const convertToDate = (valueAsString: string) => {
+                    // time value needs to be padded   
+                    const hasTimeValue = /T\d{2,2}/.test(valueAsString);
+                    const indexCollon =  valueAsString.indexOf(':');
+                        if (hasTimeValue && (indexCollon === -1 || indexCollon >= valueAsString.length-2)) {
+                            valueAsString = indexCollon === -1 
+                            ? valueAsString + ":00"
+                            : indexCollon === valueAsString.length-1
+                                ? valueAsString + "00"
+                                : valueAsString += "0"
+                        }
+                     return new Date(Date.parse(valueAsString));   
+                   };
+                   
+                   // @ts-ignore
+                   const valueAsDate = new Date(Date.parse(dataValue));
+                   const filterExpressionAsString = String(filterExpression).trim();             
+
+                   if (filterExpressionAsString.startsWith('>=')) {
+                    return valueAsDate >= convertToDate(filterExpressionAsString.substring(2).trim());
+                  } else if (filterExpressionAsString.startsWith('<=')) {
+                    return valueAsDate <= convertToDate(filterExpressionAsString.substring(2).trim());
+                  } else if (filterExpressionAsString.startsWith('>')) {
+                    return valueAsDate > convertToDate(filterExpressionAsString.substring(1).trim());
+                  } else if (filterExpressionAsString.startsWith('<')) {
+                    return valueAsDate < convertToDate(filterExpressionAsString.substring(1).trim());
+                  }
+
+                  
+                  if (filterExpressionAsString.length === 0) return true;
+                  return wildcardCheck(valueAsString, filterExpressionAsString);
+
+                }
+              }
+
+              return (dataValue == filterExpression)
+            });
+          };
+        });
+      }
+
+      const rowCount = data.length;
+
+      if (page > 0 && rowsPerPage * page > rowCount) { //if result is smaller than the currently shown page, new search and repaginate
+        let newPage = Math.floor(rowCount / rowsPerPage);
+        return {
+          rows: data,
+          total: rowCount,
+          page: newPage
+        };
+      } else {
+        data = (orderBy && order
+          ? stableSort(data, getSorting(order, orderBy))
+          : data).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
+
+        return {
+          rows: data,
+          total: rowCount,
+          page: page
+        };
+      }
+
+
+    } catch (e) {
+      console.error(e);
+      return {
+        rows: [],
+        total: 0,
+        page: page
+      }
+    }
+  }
+
+  private async update() {
+    if (isMaterialTableComponentPropsWithRequestData(this.props)) {
+      const response = await Promise.resolve(
+        this.props.onRequestData(
+          this.state.page, this.state.rowsPerPage, this.state.orderBy, this.state.order, this.state.showFilter && this.state.filter || {})
+      );
+      this.setState(response);
+    } else {
+      let updateResult = MaterialTableComponent.updateRows(this.props, this.state);
+      this.setState(updateResult);
+    }
+  }
+
+  private onFilterChanged = (property: string, filterTerm: string) => {
+    if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+      this.props.onFilterChanged(property, filterTerm);
+      return;
+    }
+    if (this.props.disableFilter) return;
+    const colDefinition = this.props.columns && this.props.columns.find(col => col.property === property);
+    if (colDefinition && colDefinition.disableFilter) return;
+
+    const filter = { ...this.state.filter, [property]: filterTerm };
+    this.setState({
+      filter
+    }, this.update);
+  };
+
+  private onHandleRequestSort = (event: React.SyntheticEvent, property: string) => {
+    if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+      this.props.onHandleRequestSort(property);
+      return;
+    }
+    if (this.props.disableSorting) return;
+    const colDefinition = this.props.columns && this.props.columns.find(col => col.property === property);
+    if (colDefinition && colDefinition.disableSorting) return;
+
+    const orderBy = this.state.orderBy === property && this.state.order === 'desc' ? null : property;
+    const order = this.state.orderBy === property && this.state.order === 'asc' ? 'desc' : 'asc';
+    this.setState({
+      order,
+      orderBy
+    }, this.update);
+  };
+
+  handleSelectAllClick: () => {};
+
+  private onHandleChangePage = (event: any | null, page: number) => {
+    if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+      this.props.onHandleChangePage(page);
+      return;
+    }
+    this.setState({
+      page
+    }, this.update);
+  };
+
+  private onHandleChangeRowsPerPage = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
+    if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+      this.props.onHandleChangeRowsPerPage(+(event && event.target.value));
+      return;
+    }
+    const rowsPerPage = +(event && event.target.value);
+    if (rowsPerPage && rowsPerPage > 0) {
+      this.setState({
+        rowsPerPage
+      }, this.update);
+    }
+  };
+
+  private isSelected(id: string | number): boolean {
+    let selected = this.state.selected || [];
+    const selectedIndex = selected.indexOf(id);
+    return (selectedIndex > -1);
+  }
+
+  private handleClick(event: any, rowData: TData, id: string | number): void {
+    if (this.props.onHandleClick instanceof Function) {
+      this.props.onHandleClick(event, rowData);
+      return;
+    }
+    if (!this.props.enableSelection) {
+      return;
+    }
+    let selected = this.state.selected || [];
+    const selectedIndex = selected.indexOf(id);
+    if (selectedIndex > -1) {
+      selected = [
+        ...selected.slice(0, selectedIndex),
+        ...selected.slice(selectedIndex + 1)
+      ];
+    } else {
+      selected = [
+        ...selected,
+        id
+      ];
+    }
+    this.setState({
+      selected
+    });
+  }
+
+
+  private exportToCsv = async () => {
+    let file;
+    let data: dataType[] | null = null;
+    let csv: string[] = [];
+
+    if (isMaterialTableComponentPropsWithRequestData(this.props)) {
+      // table with extra request handler
+      this.setState({ loading: true });
+      const result = await Promise.resolve(
+        this.props.onRequestData(0, 1000, this.state.orderBy, this.state.order, this.state.showFilter && this.state.filter || {})
+      );
+      data = result.rows;
+      this.setState({ loading: true });
+    } else if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+      // table with generated handlers note: exports data shown on current page
+      data = this.props.rows;
+    }
+    else {
+      // table with local data
+      data = MaterialTableComponent.updateRows(this.props, this.state).rows;
+    }
+
+    if (data && data.length > 0) {
+      csv.push(this.props.columns.map(col => col.title || col.property).join(',') + "\r\n");
+      this.state.rows && this.state.rows.forEach((row: any) => {
+        csv.push(this.props.columns.map(col => row[col.property]).join(',') + "\r\n");
+      });
+      const properties = { type: "text/csv;charset=utf-8" }; // Specify the file's mime-type.
+      try {
+        // Specify the filename using the File constructor, but ...
+        file = new File(csv, "export.csv", properties);
+      } catch (e) {
+        // ... fall back to the Blob constructor if that isn't supported.
+        file = new Blob(csv, properties);
+      }
+    }
+    if (!file) return;
+    var reader = new FileReader();
+    reader.onload = function (e) {
+      const dataUri = reader.result as any;
+      const link = document.createElement("a");
+      if (typeof link.download === 'string') {
+        link.href = dataUri;
+        link.download = "export.csv";
+
+        //Firefox requires the link to be in the body
+        document.body.appendChild(link);
+
+        //simulate click
+        link.click();
+
+        //remove the link when done
+        document.body.removeChild(link);
+      } else {
+        window.open(dataUri);
+      }
+    }
+    reader.readAsDataURL(file);
+
+    // const url = URL.createObjectURL(file);
+    // window.location.replace(url);
+  }
+}
+
+export type MaterialTableCtorType<TData extends {} = {}> = new () => React.Component<DistributiveOmit<MaterialTableComponentProps<TData>, 'classes'>>;
+
+export const MaterialTable = withStyles(styles)(MaterialTableComponent);
+export default MaterialTable;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/showColumnDialog.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-table/showColumnDialog.tsx
new file mode 100644
index 0000000..ab0d465
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/showColumnDialog.tsx
@@ -0,0 +1,188 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2022 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { Button, FormControlLabel, Popover, Switch, Typography } from '@mui/material';
+import { connect, Connect, IDispatcher } from '../../flux/connect';
+
+import { ColumnModel } from './columnModel';
+import { IApplicationStoreState } from '../../store/applicationStore';
+import { TableSettingsColumn } from '../../models/settings';
+import { updateTableSettings } from '../../actions/settingsAction';
+
+const mapStateToProps = (state: IApplicationStoreState) => ({
+    settings: state.framework.applicationState.settings,
+    settingsDoneLoading: state.framework.applicationState.settings.isInitialLoadDone
+});
+
+const mapDispatchToProps = (dispatcher: IDispatcher) => ({
+    saveToSettings: (tableName: string, columns: TableSettingsColumn[]) => dispatcher.dispatch(updateTableSettings(tableName, columns))
+})
+
+type DialogProps = {
+    columns: ColumnModel<{}>[],
+    settingsName: string | null,
+    anchorEl: HTMLElement | null;
+    hideColumns: (columnNames: string[]) => void
+    showColumns: (columnNames: string[]) => void
+    onClose(): void
+
+} & Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
+
+        //TODO: figure out why everything gets triggered twice...
+
+const ShowColumnsDialog: React.FunctionComponent<DialogProps> = (props) => {
+
+    const savedSettings = props.settingsName && props.settings.tables[props.settingsName];
+
+    const [checkedColumns, setCheckedColumns] = React.useState<{ property: string, display: boolean, title: string | undefined }[]>([]);
+
+    const open = Boolean(props.anchorEl);
+    const allColumnNames = props.columns.map(e => e.property);
+
+    React.useEffect(() => {
+
+        createHideShowSelection();
+
+    }, []);
+
+    React.useEffect(() => {
+
+        createHideShowSelection();
+
+    }, [props.settings.isInitialLoadDone]);
+
+
+    const createHideShowSelection = () => {
+        let columns = props.columns.map(e => { return { property: e.property, display: !Boolean(e.hide), title: e.title } });
+
+
+        if (savedSettings) {
+
+            if (columns.length !== savedSettings.columns.length) {
+                console.error("saved column length does not match current column length. Maybe a settings entry got wrongly overridden?")
+            }
+
+            //overwrite column data with settings
+            savedSettings?.columns.forEach(el => {
+                let foundIndex = columns.findIndex(e => e.property == el.property);
+                if (columns[foundIndex] !== undefined)
+                    columns[foundIndex].display = el.displayed;
+            });
+
+        } else {
+            console.warn("No settingsName set, changes will not be saved.")
+        }
+
+        setCheckedColumns(columns);
+
+        const hideColumns = columns.filter(el => !el.display).map(e => e.property);
+        props.hideColumns(hideColumns);
+    }
+
+
+    const handleChange = (propertyName: string, checked: boolean) => {
+        if (!checked) {
+            props.hideColumns([propertyName]);
+        } else {
+            props.showColumns([propertyName])
+
+        }
+     
+        let updatedList = checkedColumns.map(item => {
+            if (item.property == propertyName) {
+                return { ...item, display: checked }; 
+            }
+            return item; 
+        });
+
+        setCheckedColumns(updatedList);
+    };
+
+    const onHideAll = () => {
+
+        switchCheckedColumns(false);
+        props.hideColumns(allColumnNames);
+    }
+
+    const onShowAll = () => {
+
+        switchCheckedColumns(true);
+        props.showColumns(allColumnNames);
+    }
+
+    const onClose = () => {
+
+        const tableColumns: TableSettingsColumn[] = checkedColumns.map(el => {
+            return {
+                property: el.property,
+                displayed: el.display
+            }
+        });
+
+        if (props.settingsName) {
+            props.saveToSettings(props.settingsName, tableColumns);
+        }
+        props.onClose();
+
+    }
+
+    const switchCheckedColumns = (changeToValue: boolean) => {
+        let updatedList = checkedColumns.map(item => {
+            return { ...item, display: changeToValue };
+        });
+
+        setCheckedColumns(updatedList);
+
+    }
+
+    return (<Popover open={open} onClose={onClose}
+        anchorEl={props.anchorEl}
+        anchorOrigin={{
+            vertical: 'top',
+            horizontal: 'left',
+        }} >
+        <div>
+            <Typography fontWeight={600} style={{ margin: 10 }} >Hide / Show Columns</Typography>
+        </div>
+        <div style={{ display: "flex", flexDirection: "column", margin: 10 }}>
+            {
+                checkedColumns?.map((el, i) => {
+
+                    return <>
+
+                        <FormControlLabel
+                            value="end"
+                            key={"hide-show-column-"+i}
+                            aria-label={"hide-or-show-column-button"}
+                            control={<Switch color="secondary" checked={el.display} onChange={e => handleChange(el.property, e.target.checked)} />}
+                            label={el.title || el.property}
+                            labelPlacement="end"
+                        />
+                    </>
+                })
+            }
+            <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between" }}>
+                <Button color="secondary" aria-label="hide-all-columns-button" onClick={(e) => onHideAll()}>Hide all</Button>
+                <Button color="secondary" aria-label="show-all-columns-button" onClick={(e) => onShowAll()}>Show all</Button>
+            </div>
+        </div>
+    </Popover>)
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ShowColumnsDialog);
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableFilter.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableFilter.tsx
new file mode 100644
index 0000000..1b91368
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableFilter.tsx
@@ -0,0 +1,113 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import { ColumnModel, ColumnType } from './columnModel';
+import { Theme } from '@mui/material/styles';
+
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+
+import TableCell from '@mui/material/TableCell';
+import TableRow from '@mui/material/TableRow';
+import Input from '@mui/material/Input';
+import { Select, FormControl, InputLabel, MenuItem, SelectChangeEvent } from '@mui/material';
+import { toAriaLabel } from '../../utilities/yangHelper';
+
+
+const styles = (theme: Theme) => createStyles({
+  container: {
+    display: 'flex',
+    flexWrap: 'wrap',
+  },
+  input: {
+    margin: theme.spacing(1),
+  },
+  numberInput: {
+    float: "right"
+  }
+});
+
+interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> {
+  onFilterChanged: (property: string, filterTerm: string) => void;
+  filter: { [property: string]: string };
+  columns: ColumnModel<{}>[];
+  hiddenColumns: string[];
+  enableSelection?: boolean;
+}
+
+class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterComponentProps> {
+  createSelectFilterHandler = (property: string) => (event: SelectChangeEvent<HTMLSelectElement | string>) => {
+    this.props.onFilterChanged && this.props.onFilterChanged(property, event.target.value as string);
+  };
+  createInputFilterHandler = (property: string) => (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
+    this.props.onFilterChanged && this.props.onFilterChanged(property, event.currentTarget.value);
+  };
+
+
+  render() {
+    const { columns, filter, classes } = this.props;
+    return (
+      <TableRow>
+        {this.props.enableSelection
+          ? <TableCell padding="checkbox" style={{ width: "50px" }}>
+          </TableCell>
+          : null
+        }
+        {columns.map((col, ind) => {
+          const style = col.width ? { width: col.width } : {};
+          const tableCell = (
+            <TableCell
+              className={col.type === ColumnType.numeric ? classes.numberInput : ''}
+              key={col.property}
+              padding={col.disablePadding ? 'none' : 'normal'}
+              style={style}
+            >
+              {col.disableFilter || (col.type === ColumnType.custom)
+                ? null
+                : (col.type === ColumnType.boolean)
+                  ? <Select variant="standard" className={classes.input} aria-label={col.title ? toAriaLabel(col.title as string) + '-filter' : `${ind + 1}-filter`}
+                    value={filter[col.property] !== undefined ? filter[col.property] : ''}
+                    onChange={this.createSelectFilterHandler(col.property)}
+                    inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} >
+                    <MenuItem value={undefined} aria-label="none-value" >
+                      <em>None</em>
+                    </MenuItem>
+                    <MenuItem aria-label="true-value" value={true as any as string}>{col.labels ? col.labels["true"] : "true"}</MenuItem>
+                    <MenuItem aria-label="false-value" value={false as any as string}>{col.labels ? col.labels["false"] : "false"}</MenuItem>
+                  </Select>
+                  : <Input className={classes.input}
+                    inputProps={{ 'aria-label': col.title ? toAriaLabel(col.title as string) + '-filter' : `${ind + 1}-filter` }}
+                    value={filter[col.property] || ''}
+                    onChange={this.createInputFilterHandler(col.property)} />}
+            </TableCell>
+          );
+
+          const showColumn = !this.props.hiddenColumns.includes(col.property);
+
+          return showColumn && tableCell;
+        }, this)}
+      </TableRow>
+    );
+  }
+}
+
+export const EnhancedTableFilter = withStyles(styles)(EnhancedTableFilterComponent);
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableHead.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableHead.tsx
new file mode 100644
index 0000000..d6f7b7d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableHead.tsx
@@ -0,0 +1,127 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import { ColumnModel, ColumnType } from './columnModel';
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import TableSortLabel from '@mui/material/TableSortLabel';
+import TableCell from '@mui/material/TableCell';
+import TableHead from '@mui/material/TableHead';
+import TableRow from '@mui/material/TableRow';
+import Checkbox from '@mui/material/Checkbox';
+import Tooltip from '@mui/material/Tooltip';
+
+const styles = (theme: Theme) => createStyles({
+  header: {
+    backgroundColor: "#fafafa",
+    position: "sticky",
+    top: 0
+  }
+});
+
+
+type styles_header = WithStyles<typeof styles>;
+
+interface IEnhancedTableHeadComponentProps extends styles_header {
+  numSelected: number | null;
+  onRequestSort: (event: React.SyntheticEvent, property: string) => void;
+  onSelectAllClick: () => void;
+  order: 'asc' | 'desc';
+  orderBy: string | null;
+  rowCount: number;
+  columns: ColumnModel<{}>[];
+  hiddenColumns: string[];
+  enableSelection?: boolean;
+  allowHtmlHeader?: boolean;
+}
+
+class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadComponentProps> {
+  createSortHandler = (property: string) => (event: React.SyntheticEvent) => {
+    this.props.onRequestSort(event, property);
+  };
+
+  render() {
+    const { onSelectAllClick, order, orderBy, numSelected, rowCount, columns } = this.props;
+    const {classes} = this.props;
+
+    return (
+      <TableHead>
+        <TableRow>
+          { this.props.enableSelection 
+           ? <TableCell padding="checkbox" style={ { width: "50px" } } className= {classes.header} >
+              <Checkbox
+                 indeterminate={ numSelected && numSelected > 0 && numSelected < rowCount || undefined }
+                 checked={ numSelected === rowCount }
+                 onChange={ onSelectAllClick }
+              />
+            </TableCell>
+          : null
+          }
+          { columns.map(col => {
+            const style = col.width ? { width: col.width } : {};
+            const tableCell = (
+              <TableCell className= {classes.header}
+                key={ col.property }
+                align={ col.type === ColumnType.numeric ? 'right' : 'left' } 
+                padding={ col.disablePadding ? 'none' : 'normal' }
+                sortDirection={ orderBy === (col.property) ? order : false }
+                style={ style }
+              >
+                { col.disableSorting || (col.type === ColumnType.custom)
+                  ? <TableSortLabel
+                    active={ false }
+                    direction={ undefined }
+                  >
+                    { col.title || col.property }
+                  </TableSortLabel>
+                  : <Tooltip disableInteractive
+                    title="Sort"
+                    placement={ col.type === ColumnType.numeric ? 'bottom-end' : 'bottom-start' }
+                    enterDelay={ 300 }
+                  >
+                    <TableSortLabel
+                      active={ orderBy === col.property }
+                      direction={ order || undefined }
+                      onClick={ this.createSortHandler(col.property) }
+                    >
+                      {
+                        this.props.allowHtmlHeader ? <div className="content" dangerouslySetInnerHTML={{__html: col.title || col.property}}></div>
+                       :  (col.title || col.property )
+                      }
+                    </TableSortLabel>
+                  </Tooltip> }
+              </TableCell>
+            );
+
+            //show column if...
+            const showColumn = !this.props.hiddenColumns.includes(col.property);
+
+            return showColumn && tableCell;
+          }, this) }
+        </TableRow>
+      </TableHead>
+    );
+  }
+}
+
+export const EnhancedTableHead = withStyles(styles)(EnhancedTableHeadComponent);
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableToolbar.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableToolbar.tsx
new file mode 100644
index 0000000..143b802
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/tableToolbar.tsx
@@ -0,0 +1,191 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { Theme, lighten } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import IconButton from '@mui/material/IconButton';
+import Tooltip from '@mui/material/Tooltip';
+import Toolbar from '@mui/material/Toolbar';
+import Typography from '@mui/material/Typography';
+import DeleteIcon from '@mui/icons-material/Delete';
+import MoreIcon from '@mui/icons-material/MoreVert';
+import FilterListIcon from '@mui/icons-material/FilterList';
+import MenuItem from '@mui/material/MenuItem';
+import Menu from '@mui/material/Menu';
+import { SvgIconProps } from '@mui/material/SvgIcon';
+import { Button } from '@mui/material';
+import { ColumnModel } from './columnModel';
+import  ShowColumnsDialog  from './showColumnDialog'
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    paddingRight: theme.spacing(1),
+  },
+  highlight:
+    theme.palette.mode === 'light'
+      ? {
+        color: theme.palette.secondary.main,
+        backgroundColor: lighten(theme.palette.secondary.light, 0.85),
+      }
+      : {
+        color: theme.palette.text.primary,
+        backgroundColor: theme.palette.secondary.dark,
+      },
+  spacer: {
+    flex: '1 1 100%',
+  },
+  actions: {
+    color: theme.palette.text.secondary,
+    display: "flex",
+    flex: "auto",
+    flexDirection: "row"
+  },
+  title: {
+    flex: '0 0 auto',
+  },
+  menuButton: {
+    marginLeft: -12,
+    marginRight: 20,
+  },
+});
+
+interface ITableToolbarComponentProps extends WithStyles<typeof styles> {
+  numSelected: number | null;
+  title?: string;
+  tableId: string | null;
+  customActionButtons?: { icon: React.ComponentType<SvgIconProps>, tooltip?: string, ariaLabel: string, onClick: () => void, disabled?: boolean }[];
+  columns: ColumnModel<{}>[];
+  onHideColumns: (columnNames: string[]) => void
+  onShowColumns: (columnNames: string[]) => void
+  onToggleFilter: () => void;
+  onExportToCsv: () => void;
+}
+
+class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, { anchorEl: EventTarget & HTMLElement | null, anchorElDialog: HTMLElement | null }> {
+
+  
+  constructor(props: ITableToolbarComponentProps) {
+    super(props);
+
+    this.state = {
+      anchorEl: null,
+      anchorElDialog: null
+    };
+  }
+
+  private handleMenu = (event: React.MouseEvent<HTMLElement>) => {
+    this.setState({ anchorEl: event.currentTarget });
+  };
+
+  private handleClose = () => {
+    this.setState({ anchorEl: null });
+  };
+
+  private showColumnsDialog = (event: React.MouseEvent<HTMLElement>) =>{
+    this.setState({ anchorElDialog: this.state.anchorEl });
+  }
+
+  private onCloseDialog = () =>{
+    this.setState({ anchorElDialog: null });
+
+  }
+
+  render() {
+    const { numSelected, classes } = this.props;
+    const open = !!this.state.anchorEl;
+    const buttonPrefix = this.props.tableId !== null ? this.props.tableId : 'table';
+    return (
+      <>
+      <Toolbar className={`${classes.root} ${numSelected && numSelected > 0 ? classes.highlight : ''} `} >
+        <div className={classes.title}>
+          {numSelected && numSelected > 0 ? (
+            <Typography color="inherit" variant="subtitle1">
+              {numSelected} selected
+          </Typography>
+          ) : (
+              <Typography variant="h5" id="tableTitle">
+                {this.props.title || null}
+              </Typography>
+            )}
+        </div>
+        <div className={classes.spacer} />
+        <div className={classes.actions}>
+          {this.props.customActionButtons
+            ? this.props.customActionButtons.map((action, ind) => (
+              <Tooltip disableInteractive key={`custom-action-${ind}`} title={action.tooltip || ''}>
+                <IconButton
+                  disabled={action.disabled}
+                  aria-label={`${buttonPrefix}-${action.ariaLabel}-button`}
+                  onClick={() => action.onClick()}
+                  size="large">
+                  <action.icon />
+                </IconButton>
+              </Tooltip>
+            ))
+            : null}
+          {numSelected && numSelected > 0 ? (
+            <Tooltip disableInteractive title="Delete">
+              <IconButton aria-label={`${buttonPrefix}-delete-button`} size="large">
+                <DeleteIcon />
+              </IconButton>
+            </Tooltip>
+          ) : (
+              <Tooltip disableInteractive title="Filter list">
+                <IconButton
+                  aria-label={`${buttonPrefix}-filter-list-button`}
+                  onClick={() => { this.props.onToggleFilter && this.props.onToggleFilter() }}
+                  size="large">
+                  <FilterListIcon />
+                </IconButton>
+              </Tooltip>
+            )}
+          <Tooltip disableInteractive title="Actions">
+            <IconButton
+              color="inherit"
+              aria-label={`${buttonPrefix}-additional-actions-button`}
+              aria-owns={open ? 'menu-appbar' : undefined}
+              aria-haspopup="true"
+              onClick={this.handleMenu}
+              size="large">
+              <MoreIcon />
+            </IconButton>
+          </Tooltip>
+          <Menu id="menu-appbar" anchorEl={this.state.anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
+            transformOrigin={{ vertical: 'top', horizontal: 'right' }} open={open} onClose={this.handleClose} >
+            <MenuItem aria-label="export-table-as-csv" onClick={(e) =>{ this.props.onExportToCsv(); this.handleClose()}}>Export as CSV</MenuItem>
+            <MenuItem aria-label="hide-show-table-columns" onClick={(e) =>{ this.showColumnsDialog(e); this.handleClose()}}>Hide/show columns</MenuItem>
+          </Menu>
+        </div>
+      </Toolbar>
+      <ShowColumnsDialog 
+        anchorEl={this.state.anchorElDialog} 
+        onClose={this.onCloseDialog}
+        settingsName={this.props.tableId} 
+        columns={this.props.columns} 
+        hideColumns={this.props.onHideColumns} 
+        showColumns={this.props.onShowColumns} />
+      </>
+    );
+  }
+}
+
+export const TableToolbar = withStyles(styles)(TableToolbarComponent);
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-table/utilities.ts b/sdnr/wt-odlux/odlux/framework/src/components/material-table/utilities.ts
new file mode 100644
index 0000000..e2fda76
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-table/utilities.ts
@@ -0,0 +1,357 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action, IActionHandler } from '../../flux/action';
+import { Dispatch } from '../../flux/store';
+
+import { AddErrorInfoAction } from '../../actions/errorActions';
+import { IApplicationStoreState } from '../../store/applicationStore';
+
+export const RowDisabled = Symbol("RowDisabled");
+import { DataCallback } from ".";
+
+export interface IExternalTableState<TData> {
+  order: 'asc' | 'desc';
+  orderBy: string | null;
+  selected: any[] | null;
+  hiddenColumns: string[]
+  rows: (TData & { [RowDisabled]?: boolean })[];
+  total: number;
+  page: number;
+  rowsPerPage: number;
+  loading: boolean;
+  showFilter: boolean;
+  filter: { [property: string]: string };
+  preFilter: { [property: string]: string };
+}
+
+export type ExternalMethodes<TData> = {
+  reloadAction: (dispatch: Dispatch, getAppState: () => IApplicationStoreState) => Promise<void | AddErrorInfoAction>;
+  createActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
+    onRefresh: () => void;
+    onHandleRequestSort: (orderBy: string) => void;
+    onHandleExplicitRequestSort: (property: string, sortOrder: "asc" | "desc") => void;
+    onToggleFilter: (refresh?: boolean | undefined) => void;
+    onFilterChanged: (property: string, filterTerm: string) => void;
+    onHandleChangePage: (page: number) => void;
+    onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
+    onHideColumns: (columnName: string[]) => void;
+    onShowColumns: (columnName: string[]) => void;
+    onClearFilters: () => void;
+  },
+ createPreActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
+  onPreFilterChanged: (preFilter: {
+      [key: string]: string;
+  }) => void;
+ };
+ createProperties: (state: IApplicationStoreState) => IExternalTableState<TData>;
+ actionHandler: IActionHandler<IExternalTableState<TData>, Action>;
+}
+
+
+/** Create an actionHandler and actions for external table states. */
+export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>) : ExternalMethodes<TData> ;
+export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>, disableRow: (data: TData) => boolean) : ExternalMethodes<TData>;
+export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>, disableRow?: (data: TData) => boolean) : ExternalMethodes<TData> {
+
+  //#region Actions
+  abstract class TableAction extends Action { }
+
+
+  class RequestSortAction extends TableAction {
+    constructor(public orderBy: string) {
+      super();
+    }
+  }
+
+  class RequestExplicitSortAction extends TableAction {
+    constructor(public propertyName: string, public sortOrder: "asc" | "desc") {
+      super();
+    }
+  }
+
+  class SetSelectedAction extends TableAction {
+    constructor(public selected: TData[] | null) {
+      super();
+    }
+  }
+
+  class SetPageAction extends TableAction {
+    constructor(public page: number) {
+      super();
+    }
+  }
+
+  class SetRowsPerPageAction extends TableAction {
+    constructor(public rowsPerPage: number) {
+      super();
+    }
+  }
+
+  class SetPreFilterChangedAction extends TableAction {
+    constructor(public preFilter: { [key: string]: string }) {
+      super();
+    }
+  }
+
+  class SetFilterChangedAction extends TableAction {
+    constructor(public filter: { [key: string]: string }) {
+      super();
+    }
+  }
+
+  class SetShowFilterAction extends TableAction {
+    constructor(public show: boolean) {
+      super();
+    }
+  }
+
+  class RefreshAction extends TableAction {
+    constructor() {
+      super();
+    }
+  }
+
+  class SetResultAction extends TableAction {
+    constructor(public result: { page: number, total: number, rows: TData[] }) {
+      super();
+    }
+  }
+
+  class HideColumnsAction extends TableAction{
+    constructor(public property: string[]){
+      super();
+    }
+  }
+
+  class ShowColumnsAction extends TableAction{
+    constructor(public property: string[]){
+      super();
+    }
+  }
+
+  // #endregion
+
+  //#region Action Handler
+  const externalTableStateInit: IExternalTableState<TData> = {
+    order: 'asc',
+    orderBy: null,
+    selected: null,
+    hiddenColumns:[],
+    rows: [],
+    total: 0,
+    page: 0,
+    rowsPerPage: 10,
+    loading: false,
+    showFilter: false,
+    filter: {},
+    preFilter: {}
+  };
+
+  const externalTableStateActionHandler: IActionHandler<IExternalTableState<TData>> = (state = externalTableStateInit, action) => {
+    if (!(action instanceof TableAction)) return state;
+    if (action instanceof RefreshAction) {
+      state = {
+        ...state,
+        loading: true
+      }
+    } else if (action instanceof SetResultAction) {
+      state = {
+        ...state,
+        loading: false,
+        rows: disableRow 
+          ? action.result.rows.map((row: TData) => ({...row, [RowDisabled]: disableRow(row) })) 
+          : action.result.rows,
+        total: action.result.total,
+        page: action.result.page,
+      }
+    } else if (action instanceof RequestSortAction) {
+      state = {
+        ...state,
+        loading: true,
+        orderBy: state.orderBy === action.orderBy && state.order === 'desc' ? null : action.orderBy,
+        order: state.orderBy === action.orderBy && state.order === 'asc' ? 'desc' : 'asc',
+      }
+    } else if (action instanceof RequestExplicitSortAction) {
+      state = {
+        ...state,
+        loading: true,
+        orderBy: action.propertyName,
+        order: action.sortOrder
+      }
+    }
+    else if (action instanceof SetShowFilterAction) {
+      state = {
+        ...state,
+        loading: true,
+        showFilter: action.show
+      }
+    } else if (action instanceof SetPreFilterChangedAction) {
+      state = {
+        ...state,
+        loading: true,
+        preFilter: action.preFilter
+      }
+    } else if (action instanceof SetFilterChangedAction) {
+      state = {
+        ...state,
+        loading: true,
+        filter: action.filter
+      }
+    } else if (action instanceof SetPageAction) {
+      state = {
+        ...state,
+        loading: true,
+        page: action.page
+      }
+    } else if (action instanceof SetRowsPerPageAction) {
+      state = {
+        ...state,
+        loading: true,
+        rowsPerPage: action.rowsPerPage
+      }
+    }
+    else if (action instanceof HideColumnsAction){
+      
+      //merge arrays, remove duplicates
+      const newArray = [...new Set([...state.hiddenColumns, ...action.property])]
+      state = {...state, hiddenColumns: newArray};
+    }
+    else if(action instanceof ShowColumnsAction){
+
+      const newArray = state.hiddenColumns.filter(el=> !action.property.includes(el));
+      state = {...state, hiddenColumns: newArray};
+    }
+
+    return state;
+  }
+
+  //const createTableAction(tableAction)
+
+  //#endregion
+  const reloadAction = (dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+    dispatch(new RefreshAction());
+    const ownState = selectState(getAppState());
+    const filter = { ...ownState.preFilter, ...(ownState.showFilter && ownState.filter || {}) };
+    return Promise.resolve(callback(ownState.page, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter)).then(result => {
+
+      if (ownState.page > 0 && ownState.rowsPerPage * ownState.page > result.total) { //if result is smaller than the currently shown page, new search and repaginate
+
+        let newPage = Math.floor(result.total / ownState.rowsPerPage);
+
+        Promise.resolve(callback(newPage, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter)).then(result1 => {
+          dispatch(new SetResultAction(result1));
+        });
+
+
+      } else {
+        dispatch(new SetResultAction(result));
+      }
+
+
+    }).catch(error => dispatch(new AddErrorInfoAction(error)));
+  };
+
+  const createPreActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
+    return {
+      onPreFilterChanged: (preFilter: { [key: string]: string }) => {
+        dispatch(new SetPreFilterChangedAction(preFilter));
+        (!skipRefresh) && dispatch(reloadAction);
+      }
+    };
+  }
+
+  const createActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
+    return {
+      onRefresh: () => {
+        dispatch(reloadAction);
+      },
+      onHandleRequestSort: (orderBy: string) => {
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new RequestSortAction(orderBy));
+          (!skipRefresh) && dispatch(reloadAction);
+        });
+      },
+      onHandleExplicitRequestSort: (property: string, sortOrder: "asc" | "desc") => {
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new RequestExplicitSortAction(property, sortOrder));
+          (!skipRefresh) && dispatch(reloadAction);
+        });
+      },
+      onToggleFilter: (refresh?: boolean) => {
+        dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+          const { showFilter } = selectState(getAppState());
+          dispatch(new SetShowFilterAction(!showFilter));
+          if (!skipRefresh && (refresh === undefined || refresh))
+            dispatch(reloadAction);
+        });
+      },
+      onFilterChanged: (property: string, filterTerm: string) => {
+        dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+          let { filter } = selectState(getAppState());
+          filter = { ...filter, [property]: filterTerm };
+          dispatch(new SetFilterChangedAction(filter));
+          (!skipRefresh) && dispatch(reloadAction);
+        });
+      },
+      onHandleChangePage: (page: number) => {
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new SetPageAction(page));
+          (!skipRefresh) && dispatch(reloadAction);
+        });
+      },
+      onHandleChangeRowsPerPage: (rowsPerPage: number | null) => {
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new SetRowsPerPageAction(rowsPerPage || 10));
+          (!skipRefresh) && dispatch(reloadAction);
+        });
+      },
+      onHideColumns: (columnName: string[]) =>{
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new HideColumnsAction(columnName));
+        })
+      },
+      onShowColumns: (columnName: string[]) =>{
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new ShowColumnsAction(columnName));
+        })
+      },
+      onClearFilters: () => {
+        dispatch((dispatch: Dispatch) => {
+          let filter = { };
+          dispatch(new SetFilterChangedAction(filter));
+        });
+      },
+      // selected:
+    };
+  };
+
+  const createProperties = (state: IApplicationStoreState) => {
+    return {
+      ...selectState(state)
+    }
+  }
+
+  return {
+    reloadAction: reloadAction,
+    createActions: createActions,
+    createProperties: createProperties,
+    createPreActions: createPreActions,
+    actionHandler: externalTableStateActionHandler,
+  }
+}
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/index.ts b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/index.ts
new file mode 100644
index 0000000..096e443
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/index.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { ListItemLink } from './listItemLink';
+export { Panel } from './panel';
+export { ToggleButton, ToggleButtonClassKey } from './toggleButton';
+export { TreeView, TreeItem,  TreeViewCtorType} from './treeView';
+export { Loader } from './loader';
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/listItemLink.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/listItemLink.tsx
new file mode 100644
index 0000000..626cb89
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/listItemLink.tsx
@@ -0,0 +1,83 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { NavLink, Link, Route } from 'react-router-dom';
+
+import ListItem from '@mui/material/ListItem';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+import { toAriaLabel } from '../../utilities/yangHelper';
+import { IconType } from '../../models/iconDefinition';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+const styles = (theme: Theme) => createStyles({
+  active: {
+    backgroundColor: theme.palette.action.selected
+  }
+});
+
+export interface IListItemLinkProps extends WithStyles<typeof styles> {
+  icon: IconType | null;
+  primary: string | React.ComponentType;
+  secondary?: React.ComponentType;
+  to: string;
+  exact?: boolean;
+  external?: boolean;
+}
+
+export const ListItemLink = withStyles(styles)((props: IListItemLinkProps) => {
+  const { icon, primary: Primary, secondary: Secondary, classes, to, exact = false, external=false } = props;
+  const renderLink = (itemProps: any): JSX.Element => (
+    props.external ? <a target="_blank" href={to} { ...itemProps }></a> :
+  <NavLink exact={ exact } to={ to } activeClassName={ classes.active } { ...itemProps } />);
+  
+  const customIconHeight = 22;
+  const ariaLabel = typeof Primary === 'string' ? toAriaLabel("link-to-"+Primary) : toAriaLabel("link-to-"+Primary.displayName);
+  
+  //create menu icon, either using an faIcon or a link to a custom svg icon
+  //moved to one place for easier usage
+  const listItemIcon = icon && ( typeof icon === 'string' ? <img height={customIconHeight} src={icon} /> : <FontAwesomeIcon icon={icon} /> );
+    
+  return (
+       <>
+        <ListItem button component={ renderLink } aria-label={ariaLabel}>
+          { icon
+            ? <ListItemIcon>{ listItemIcon }</ListItemIcon>
+            : null
+          }
+        { typeof Primary === 'string'
+          ? <ListItemText primary={ Primary } style={{ padding: 0 }} /> 
+          : <Primary />
+          }
+        </ListItem>
+        { Secondary 
+          ? <Route exact={ exact } path={ to } component={ Secondary } />
+          : null
+        }
+      </>
+    );
+  }
+);
+
+export default ListItemLink;
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/loader.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/loader.tsx
new file mode 100644
index 0000000..bd523e1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/loader.tsx
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+import * as React from "react";
+
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+const styles = (theme: Theme) => createStyles({
+  "@keyframes spin": {
+    "0%": { transform: "rotate(0deg)" },
+    "100%": { transform: "rotate(360deg)" },
+  },
+  loader: {
+    border: `16px solid ${theme.palette.grey.A200}`,
+    borderTop: `16px solid ${theme.palette.secondary.main}`,
+    borderRadius: "50%",
+    width: "120px",
+    height: "120px",
+    animation: "$spin 2s linear infinite",
+  }
+});
+
+const LoaderComponent: React.FC<WithStyles<typeof styles>> = (props) => {
+  return (
+    <div className={props.classes.loader} />
+  );
+};
+
+export const Loader = withStyles(styles)(LoaderComponent);
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/panel.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/panel.tsx
new file mode 100644
index 0000000..6d192d2
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/panel.tsx
@@ -0,0 +1,76 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import { Accordion, AccordionSummary, AccordionDetails, Typography, AccordionActions } from '@mui/material';
+
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import { SvgIconProps } from '@mui/material/SvgIcon';
+
+const styles = (theme: Theme) => createStyles({
+  accordion: {
+    // background: theme.palette.secondary.dark,
+    // color: theme.palette.primary.contrastText
+  },
+  detail: {
+    // background: theme.palette.background.paper,
+    // color: theme.palette.text.primary,
+    position: "relative",
+    flexDirection: 'column'
+  },
+  text: {
+    // color: theme.palette.common.white,
+    // fontSize: "1rem"
+  },
+});
+
+type PanalProps = WithStyles<typeof styles> & {
+  activePanel: string | null,
+  panelId: string,
+  title: string,
+  customActionButtons?: JSX.Element[];
+  onToggle: (panelId: string | null) => void;
+}
+
+const PanelComponent: React.SFC<PanalProps> = (props) => {
+  const { classes, activePanel, onToggle } = props;
+  return (
+    <Accordion className={classes.accordion} expanded={activePanel === props.panelId} onChange={() => onToggle(props.panelId)} >
+      <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+        <Typography className={classes.text} >{props.title}</Typography>
+      </AccordionSummary>
+      <AccordionDetails className={classes.detail}>
+        {props.children}
+      </AccordionDetails>
+      {props.customActionButtons
+        ? <AccordionActions>
+          {props.customActionButtons}
+        </AccordionActions>
+        : null}
+    </Accordion>
+  );
+};
+
+export const Panel = withStyles(styles)(PanelComponent);
+export default Panel;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/snackDisplay.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/snackDisplay.tsx
new file mode 100644
index 0000000..437784c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/snackDisplay.tsx
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { IApplicationStoreState } from '../../store/applicationStore';
+import { Connect, connect, IDispatcher } from '../../flux/connect';
+import { RemoveSnackbarNotification } from '../../actions/snackbarActions';
+
+import { WithSnackbarProps, withSnackbar } from 'notistack';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  notifications: state.framework.applicationState.snackBars
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  removeSnackbar: (key: number) => {
+    dispatcher.dispatch(new RemoveSnackbarNotification(key));
+   }
+});
+
+type DisplaySnackbarsComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithSnackbarProps;
+
+class DisplaySnackbarsComponent extends React.Component<DisplaySnackbarsComponentProps> {
+  private displayed: number[] = [];
+
+  private storeDisplayed = (id: number) => {
+    this.displayed = [...this.displayed, id];
+  };
+
+  public shouldComponentUpdate({ notifications: newSnacks = [] }: DisplaySnackbarsComponentProps) {
+    
+    const { notifications: currentSnacks } = this.props;
+    let notExists = false;
+    for (let i = 0; i < newSnacks.length; i++) {
+      if (notExists) continue;
+      notExists = notExists || !currentSnacks.filter(({ key }) => newSnacks[i].key === key).length;
+    }
+    return notExists;
+  }
+
+  componentDidUpdate() {
+    const { notifications = [] } = this.props;
+
+    notifications.forEach(notification => {
+      if (this.displayed.includes(notification.key)) return;
+      const options = notification.options || {};
+      this.props.enqueueSnackbar(notification.message, options);
+      this.storeDisplayed(notification.key);
+      this.props.removeSnackbar(notification.key);
+    });
+  }
+
+  render() {
+    return null;
+  }
+}
+
+const DisplayStackbars = withSnackbar(connect(mapProps, mapDispatch)(DisplaySnackbarsComponent));
+export default DisplayStackbars;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/toggleButton.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/toggleButton.tsx
new file mode 100644
index 0000000..54f14a7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/toggleButton.tsx
@@ -0,0 +1,181 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import classNames from 'classnames';
+import { Theme, alpha } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+import ButtonBase from '@mui/material/ButtonBase';
+
+
+export const styles = (theme: Theme) => createStyles({
+    /* Styles applied to the root element. */
+    root: {
+        ...theme.typography.button,
+        height: 32,
+        minWidth: 48,
+        margin: 0,
+        padding: `${theme.spacing(1 - 4)} ${theme.spacing(1.5)}`,
+        borderRadius: 2,
+        willChange: 'opacity',
+        color: alpha(theme.palette.action.active, 0.38),
+        '&:hover': {
+            textDecoration: 'none',
+            // Reset on mouse devices
+            backgroundColor: alpha(theme.palette.text.primary, 0.12),
+            '@media (hover: none)': {
+                backgroundColor: 'transparent',
+            },
+            '&.Mui-disabled': {
+                backgroundColor: 'transparent',
+            },
+        },
+        '&:not(:first-child)': {
+            borderTopLeftRadius: 0,
+            borderBottomLeftRadius: 0,
+        },
+        '&:not(:last-child)': {
+            borderTopRightRadius: 0,
+            borderBottomRightRadius: 0,
+        },
+    },
+    /* Styles applied to the root element if `disabled={true}`. */
+    disabled: {
+        color: alpha(theme.palette.action.disabled, 0.12),
+    },
+    /* Styles applied to the root element if `selected={true}`. */
+    selected: {
+        color: theme.palette.action.active,
+        '&:after': {
+            content: '""',
+            display: 'block',
+            position: 'absolute',
+            overflow: 'hidden',
+            borderRadius: 'inherit',
+            width: '100%',
+            height: '100%',
+            left: 0,
+            top: 0,
+            pointerEvents: 'none',
+            zIndex: 0,
+            backgroundColor: 'currentColor',
+            opacity: 0.38,
+        },
+        '& + &:before': {
+            content: '""',
+            display: 'block',
+            position: 'absolute',
+            overflow: 'hidden',
+            width: 1,
+            height: '100%',
+            left: 0,
+            top: 0,
+            pointerEvents: 'none',
+            zIndex: 0,
+            backgroundColor: 'currentColor',
+            opacity: 0.12,
+        },
+    },
+    /* Styles applied to the `label` wrapper element. */
+    label: {
+        width: '100%',
+        display: 'inherit',
+        alignItems: 'inherit',
+        justifyContent: 'inherit',
+    },
+});
+
+export type ToggleButtonClassKey = 'disabled' | 'root' | 'label' | 'selected';
+
+interface IToggleButtonProps extends WithStyles<typeof styles> {
+    className?: string;
+    component?: React.ReactType<IToggleButtonProps>;
+    disabled?: boolean;
+    disableFocusRipple?: boolean;
+    disableRipple?: boolean;
+    selected?: boolean;
+    type?: string;
+    value?: any;
+    onClick?: (event: React.FormEvent<HTMLElement>, value?: any) => void;
+    onChange?: (event: React.FormEvent<HTMLElement>, value?: any) => void;
+}
+
+class ToggleButtonComponent extends React.Component<IToggleButtonProps> {
+    handleChange = (event: React.FormEvent<HTMLElement>) => {
+        const { onChange, onClick, value } = this.props;
+
+        event.stopPropagation();
+        if (onClick) {
+            onClick(event, value);
+            if (event.isDefaultPrevented()) {
+                return;
+            }
+        }
+
+        if (onChange) {
+            onChange(event, value);
+        }
+        event.preventDefault();
+    };
+
+    render() {
+        const {
+            children,
+            className: classNameProp,
+            classes,
+            disableFocusRipple,
+            disabled,
+            selected,
+            ...other
+        } = this.props;
+
+        const className = classNames(
+            classes.root,
+            {
+                [classes.disabled]: disabled,
+                [classes.selected]: selected,
+            },
+            classNameProp,
+        );
+
+        return (
+            <ButtonBase
+                className={className}
+                disabled={disabled}
+                focusRipple={!disableFocusRipple}
+                onClick={this.handleChange}
+                href="#"
+                {...other}
+            >
+                <span className={classes.label}>{children}</span>
+            </ButtonBase>
+        );
+    }
+    public static defaultProps = {
+        disabled: false,
+        disableFocusRipple: false,
+        disableRipple: false,
+    };
+
+    public static muiName = 'ToggleButton';
+}
+
+export const ToggleButton = withStyles(styles, { name: 'MuiToggleButton' })(ToggleButtonComponent);
+export default ToggleButton;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx
new file mode 100644
index 0000000..bdabe0d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx
@@ -0,0 +1,40 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import classNames from 'classnames';
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+export const styles = (theme: Theme) => createStyles({
+  /* Styles applied to the root element. */
+  root: { 
+    transition: theme.transitions.create('background,box-shadow'),
+    background: 'transparent',
+    borderRadius: 2,
+    overflow: 'hidden',
+  },
+  /* Styles applied to the root element if `selected={true}` or `selected="auto" and `value` set. */
+  selected: {
+    background: theme.palette.background.paper,
+    boxShadow: theme.shadows[2],
+  },
+});
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/material-ui/treeView.tsx b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/treeView.tsx
new file mode 100644
index 0000000..5c23909
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/material-ui/treeView.tsx
@@ -0,0 +1,380 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { Theme } from '@mui/material/styles';
+
+import { makeStyles, WithStyles, WithTheme } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import { List, ListItem, TextField, ListItemText, ListItemIcon, Typography } from '@mui/material';
+import { DistributiveOmit } from '@mui/types';
+
+import withTheme from '@mui/styles/withTheme';
+
+import { SvgIconProps } from '@mui/material/SvgIcon';
+import FileIcon from '@mui/icons-material/InsertDriveFile';
+import CloseIcon from '@mui/icons-material/ExpandLess';
+import OpenIcon from '@mui/icons-material/ExpandMore';
+import FolderIcon from '@mui/icons-material/Folder';
+
+declare module '@mui/styles/defaultTheme' {
+  // eslint-disable-next-line @typescript-eslint/no-empty-interface (remove this line if you don't have the rule enabled)
+  interface DefaultTheme extends Theme {}
+}
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    padding: 0,
+    paddingBottom: 8,
+    paddingTop: 8,
+  },
+  search: {
+    padding: `0px ${theme.spacing(1)}`
+  }
+});
+
+export enum SearchMode {
+  OnKeyDown = 1,
+  OnEnter =2
+}
+
+export type TreeItem<TData = { }> = {
+  disabled?: boolean;
+  icon?: React.ComponentType<SvgIconProps>;
+  iconClass?: string;
+  content: string;
+  contentClass?: string;
+  children?: TreeItem<TData>[];
+  value?: TData;
+}
+
+export type ExternalTreeItem<TData = {}> = TreeItem<TData> & {
+  isMatch?: boolean;
+}
+
+
+type TreeViewComponentState<TData = { }> = {
+  /** All indices of all expanded Items */
+  expandedItems: ExternalTreeItem<TData>[];
+  /** The index of the active iten or undefined if no item is active. */
+  activeItem?: ExternalTreeItem<TData>;
+  /** The search term or undefined if search is currently not active. */
+  searchTerm?: string;
+  searchTermValue?: string;
+}
+
+type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styles> & {
+  className?: string;
+  items: TreeItem<TData>[];
+  useFolderIcons?: boolean;
+  enableSearchBar?: boolean;
+  autoExpandFolder?: boolean;
+  style?: React.CSSProperties;
+  itemHeight?: number;
+  depthOffset?: number;
+  searchMode?: SearchMode;
+
+}
+
+type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & {
+  initialSearchTerm? : string;
+  onItemClick?: (item: TreeItem<TData>) => void;
+  onFolderClick?: (item: TreeItem<TData>) => void;
+}
+
+type TreeViewComponentWithExternalSearchProps<TData = {}> = TreeViewComponentBaseProps<TData> & {
+  items: ExternalTreeItem<TData>[];
+  initialSearchTerm? : string;
+  searchTerm: string;
+  onSearch: (searchTerm: string) => void;
+  onItemClick?: (item: TreeItem<TData>) => void;
+  onFolderClick?: (item: TreeItem<TData>) => void;
+}
+
+type TreeViewComponentWithExternalStateProps<TData = {}> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+  items: ExternalTreeItem<TData>[];
+  initialSearchTerm? : string;
+  searchTerm: string;
+  onSearch: (searchTerm: string) => void;
+  onItemClick: (item: TreeItem<TData>) => void;
+  onFolderClick: (item: TreeItem<TData>) => void;
+}
+
+type TreeViewComponentProps<TData = { }> =
+  | TreeViewComponentWithInternalStateProps<TData>
+  | TreeViewComponentWithExternalSearchProps<TData>
+  | TreeViewComponentWithExternalStateProps<TData>;
+
+function isTreeViewComponentWithExternalSearchProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalSearchProps {
+  const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
+  return (
+    propsWithExternalState.onSearch instanceof Function &&
+    propsWithExternalState.onFolderClick === undefined &&
+    propsWithExternalState.expandedItems === undefined &&
+    propsWithExternalState.searchTerm !== undefined
+  );
+}
+
+function isTreeViewComponentWithExternalStateProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalStateProps {
+  const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
+  return (
+    propsWithExternalState.onSearch instanceof Function &&
+    propsWithExternalState.onFolderClick instanceof Function &&
+    propsWithExternalState.expandedItems !== undefined &&
+    propsWithExternalState.searchTerm !== undefined
+  );
+}
+
+class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentProps<TData>, TreeViewComponentState<TData>> {
+
+  /**
+    * Initializes a new instance.
+    */
+  constructor(props: TreeViewComponentProps<TData>) {
+    super(props);
+
+    this.state = {
+      expandedItems: [],
+      activeItem: undefined,
+      searchTerm: undefined,
+      searchTermValue: props.initialSearchTerm
+    };
+  }
+
+  render(): JSX.Element {
+    this.itemIndex = 0;
+    const { searchTerm , searchTermValue} = this.state;
+    const { children, items, enableSearchBar } = this.props;
+
+    return (
+      <div className={this.props.className ? `${this.props.classes.root} ${this.props.className}` : this.props.classes.root} style={this.props.style}>
+        {children}
+        {enableSearchBar && <TextField variant="standard" label={"Search"} inputProps={{'aria-label': 'treeview-searchfield'}} fullWidth={true} className={this.props.classes.search} value={searchTermValue} onKeyDown={this.onSearchKeyDown} onChange={this.onChangeSearchText} /> || null}
+        {enableSearchBar && (searchTerm === undefined || searchTerm.length===0 )&& <Typography style={{marginTop:'10px'}}>Please search for an inventory identifier or use *.</Typography>}
+        <List>
+          {this.renderItems(items, searchTerm && searchTerm.toLowerCase())}
+        </List>
+      </div>
+    );
+  }
+
+  private itemIndex: number = 0;
+  private renderItems = (items: TreeItem<TData>[], searchTerm: string | undefined, depth: number = 1, forceRender: boolean = true) => {
+
+    return items.reduce((acc, item) => {
+
+      const children = item.children; // this.props.childrenProperty && ((item as any)[this.props.childrenProperty] as TData[]);
+      const childrenJsx = children && this.renderItems(children, searchTerm, depth + 1, this.state.expandedItems.indexOf(item) > -1);
+
+      const expanded = !isTreeViewComponentWithExternalStateProps(this.props) && searchTerm
+        ? childrenJsx && childrenJsx.length > 0
+        : !children
+          ? false
+          : this.state.expandedItems.indexOf(item) > -1;
+      const isFolder = children !== undefined;
+
+      const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded || false, forceRender);
+      itemJsx && acc.push(itemJsx);
+
+      if (isFolder && expanded && childrenJsx) {
+        acc.push(...childrenJsx);
+      }
+      return acc;
+
+    }, [] as JSX.Element[]);
+  }
+  private renderItem = (item: ExternalTreeItem<TData> , searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean, forceRender: boolean): JSX.Element | null => {  
+    const styles = {
+      item: {
+        paddingLeft: (((this.props.depthOffset || 0) + depth) * Number(this.props.theme.spacing(3).replace("px", ''))),
+        backgroundColor: this.state.activeItem === item ? this.props.theme.palette.action.selected : undefined,
+        height: this.props.itemHeight || undefined,
+        cursor: item.disabled ? 'not-allowed' : 'pointer',
+        color: item.disabled ? this.props.theme.palette.text.disabled : this.props.theme.palette.text.primary,
+        overflow: 'hidden',
+        transform: 'translateZ(0)',
+      }
+    };
+
+    const text = item.content || ''; // need to keep track of search
+    const search_array = searchTerm?.split("*");
+    const index = search_array?.findIndex(function (_str: String) {
+      return _str.length > 0;
+    }) || 0;
+    const firstSearchSubString = search_array ? search_array[index] : "";
+    const matchIndex = firstSearchSubString ? text.toLowerCase().indexOf(firstSearchSubString) : -1;
+
+    const hasStarInSearch = search_array ? search_array.length > 1 : false;
+    const isSearchStringWithStar = hasStarInSearch && firstSearchSubString?.length > 0 || false;
+
+    const searchTermLength = firstSearchSubString && firstSearchSubString.length || 0;
+
+    const handleClickCreator = (isIcon: boolean) => (event: React.SyntheticEvent) => {
+      if (item.disabled) return;
+      event.preventDefault();
+      event.stopPropagation();
+      if (isFolder && (this.props.autoExpandFolder || isIcon)) {
+        this.props.onFolderClick ? this.props.onFolderClick(item) : this.onFolderClick(item);
+      } else {
+        this.props.onItemClick ? this.props.onItemClick(item) : this.onItemClick(item);
+      }
+    };
+
+    return ((searchTerm && (matchIndex > -1 || expanded || (!isTreeViewComponentWithExternalStateProps(this.props) && item.isMatch || depth === 1)) || !searchTerm || forceRender)
+      ? (
+        <ListItem key={`tree-list-${this.itemIndex++}`} aria-label="tree-view-item" style={styles.item} onClick={handleClickCreator(false)} button >
+
+          { // display the left icon
+            (this.props.useFolderIcons && <ListItemIcon>{isFolder ? <FolderIcon /> : <FileIcon />}</ListItemIcon>) ||
+            (item.icon && (<ListItemIcon className={ item.iconClass }><item.icon /></ListItemIcon>))}
+
+
+          { // highlight search result
+            isSearchStringWithStar && matchIndex > -1
+              ? <ListItemText className={item.contentClass} primary={(
+                <span
+                  style={{
+                    display: 'inline-block',
+                    backgroundColor: 'rgba(255,235,59,0.5)',
+                    padding: '3px',
+                  }}
+                >
+                  {text}
+                </span>)} />
+              : matchIndex > -1
+                ? <ListItemText className={item.contentClass} primary={(<span>
+                  {text.substring(0, matchIndex)}
+                  <span
+                    style={{
+                      display: 'inline-block',
+                      backgroundColor: 'rgba(255,235,59,0.5)',
+                      padding: '3px',
+                    }}
+                  >
+                    {text.substring(matchIndex, matchIndex + searchTermLength)}
+                  </span>
+                  {text.substring(matchIndex + searchTermLength)}
+                </span>)} />
+                : <ListItemText className={item.contentClass} primary={(
+                  <span style={item.isMatch ? {
+                    display: 'inline-block',
+                    padding: '3px',
+                  } : undefined}>
+                    {text} </span>
+                )} />
+          }
+
+          { // display the right icon, depending on the state
+            !isFolder ? null : expanded ? (<OpenIcon onClick={handleClickCreator(true)} />) : (<CloseIcon onClick={handleClickCreator(true)} />)}
+        </ListItem>
+      )
+      : null
+    );
+  }
+
+  private onFolderClick = (item: TreeItem<TData>) => {
+    // toggle items with children
+    if (this.state.searchTerm) return;
+    const indexOfItemToToggle = this.state.expandedItems.indexOf(item);
+    if (indexOfItemToToggle === -1) {
+      this.setState({
+        expandedItems: [...this.state.expandedItems, item],
+      });
+    } else {
+      this.setState({
+        expandedItems: [
+          ...this.state.expandedItems.slice(0, indexOfItemToToggle),
+          ...this.state.expandedItems.slice(indexOfItemToToggle + 1),
+        ]
+      });
+    }
+  };
+
+  private onItemClick = (item: TreeItem<TData>) => {
+    // activate items without children
+    this.setState({
+      activeItem: item,
+    });
+  };
+
+  private onSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
+    const enterMode = this.props.searchMode === SearchMode.OnEnter;
+
+    if (enterMode && event.keyCode === 13) {
+      event.preventDefault();
+      event.stopPropagation();
+
+      enterMode && this.setState({
+        searchTerm: this.state.searchTermValue
+      });
+
+      if (isTreeViewComponentWithExternalSearchProps(this.props) || isTreeViewComponentWithExternalStateProps(this.props)) {
+        this.props.onSearch(this.state.searchTermValue || "");
+      }
+    }
+  }
+
+  private onChangeSearchText = (event: React.ChangeEvent<HTMLInputElement>) => {
+    event.preventDefault();
+    event.stopPropagation();
+
+    const keyDownMode = (!this.props.searchMode || this.props.searchMode === SearchMode.OnKeyDown);
+
+    this.setState(keyDownMode
+      ? {
+        searchTerm: event.target.value,
+        searchTermValue: event.target.value,
+      } as any : {
+        searchTermValue: event.target.value,
+      }) as any;
+
+    if ((isTreeViewComponentWithExternalSearchProps(this.props) || isTreeViewComponentWithExternalStateProps(this.props)) && keyDownMode) {
+      this.props.onSearch(event.target.value);
+    }
+  };
+
+  static getDerivedStateFromProps(props: TreeViewComponentProps, state: TreeViewComponentState): TreeViewComponentState {
+    if (isTreeViewComponentWithExternalStateProps(props)) {
+      return {
+        ...state,
+        expandedItems: props.expandedItems || [],
+        activeItem: props.activeItem,
+        searchTerm: props.searchTerm
+      };
+    } else if (isTreeViewComponentWithExternalSearchProps(props)) {
+      return {
+        ...state,
+        searchTerm: props.searchTerm,
+      };
+    }
+    return state;
+  }
+
+  public static defaultProps = {
+    useFolderIcons: false,
+    enableSearchBar: false,
+    autoExpandFolder: false,
+    depthOffset: 0
+  }
+}
+
+export type TreeViewCtorType<TData = { }> = new () => React.Component<DistributiveOmit<TreeViewComponentProps<TData>, 'theme'|'classes'>>;
+
+export const TreeView = withTheme(withStyles(styles)(TreeViewComponent));
+export default TreeView;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt-odlux/odlux/framework/src/components/navigationMenu.tsx
new file mode 100644
index 0000000..bcc191a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/navigationMenu.tsx
@@ -0,0 +1,218 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { Theme } from '@mui/material/styles';
+import classNames from 'classnames';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import Drawer from '@mui/material/Drawer';
+import List from '@mui/material/List';
+
+import Divider from '@mui/material/Divider';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons';
+
+import ListItemLink from '../components/material-ui/listItemLink';
+
+import { connect, Connect } from '../flux/connect';
+import { MenuAction } from '../actions/menuAction';
+import { transportPCEUrl } from '../app';
+
+const aboutIcon = require('../assets/icons/About.svg');
+const homeIcon = require('../assets/icons/Home.svg');
+const loginIcon = require('../assets/icons/User.svg');
+const settingsIcon = require('../assets/icons/Tools.svg');
+
+const drawerWidth = 240;
+
+const extraLinks = (window as any)._odluxExtraLinks as [string, string][];
+
+const styles = (theme: Theme) => createStyles({
+  drawerPaper: {
+    position: 'relative',
+    width: drawerWidth,
+  },
+  toolbar: theme.mixins.toolbar as any,
+
+  drawerOpen: {
+    width: drawerWidth,
+    transition: theme.transitions.create('width', {
+      easing: theme.transitions.easing.sharp,
+      duration: theme.transitions.duration.enteringScreen,
+    }),
+  },
+  drawerClose: {
+    transition: theme.transitions.create('width', {
+      easing: theme.transitions.easing.sharp,
+      duration: theme.transitions.duration.leavingScreen,
+    }),
+    overflowX: 'hidden',
+    width: theme.spacing(7),
+    [theme.breakpoints.up('sm')]: {
+      width: theme.spacing(9),
+    },
+  },
+  drawer: {
+
+  },
+  menu: {
+    flex: "1 0 0%",
+  },
+  optLinks: {
+    borderTop: "2px solid #cfcfcf",
+    display: "flex",
+    flexDirection: "row",
+    flexWrap: "wrap",
+    justifyContent: "space-around"
+  },
+  link: {
+    margin: theme.spacing(1)+1,
+    fontSize: theme.typography.fontSize-2,
+  },
+});
+
+const tabletWidthBreakpoint = 768;
+
+export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, dispatch }: WithStyles<typeof styles> & Connect & Connect) => {
+  const { user } = state.framework.authenticationState;
+  const isOpen = state.framework.applicationState.isMenuOpen;
+  const closedByUser = state.framework.applicationState.isMenuClosedByUser;
+  const transportUrl = state.framework.applicationState.transportpceUrl;
+
+  const [responsive, setResponsive] = React.useState(false);
+
+  //collapse menu on mount if necessary
+  React.useEffect(()=>{
+
+    if(isOpen && window.innerWidth <= tabletWidthBreakpoint){
+
+      setResponsive(true);
+      dispatch(new MenuAction(false));
+    }
+
+  },[]);
+
+  React.useEffect(() => {
+
+    function handleResize() {
+      if (user && user.isValid) {
+        if (window.innerWidth < tabletWidthBreakpoint && !responsive) {
+          setResponsive(true);
+          if (!closedByUser) {
+            dispatch(new MenuAction(false));
+          }
+
+        } else if (window.innerWidth > tabletWidthBreakpoint && responsive) {
+          setResponsive(false);
+          if (!closedByUser) {
+            dispatch(new MenuAction(true));
+          }
+
+        }
+      }
+    }
+    window.addEventListener("resize", handleResize);
+
+
+    return () => {
+      window.removeEventListener("resize", handleResize);
+    }
+  })
+
+  React.useEffect(()=>{
+    // trigger a resize if menu changed in case elements have to re-arrange
+    window.dispatchEvent(new Event('menu-resized'));
+  }, [isOpen])
+
+  let menuItems = state.framework.applicationRegistration && Object.keys(state.framework.applicationRegistration).map(key => {
+    const reg = state.framework.applicationRegistration[key];
+    return reg && (
+      <ListItemLink
+        key={reg.name}
+        to={reg.path || `/${reg.name}`}
+        primary={reg.menuEntry || reg.name}
+        secondary={reg.subMenuEntry}
+        icon={reg.icon || null} />
+    ) || null;
+  }) || null;
+
+  if(transportUrl.length>0){
+
+    const transportPCELink = <ListItemLink
+      key={"transportPCE"}
+      to={transportUrl}
+      primary={"TransportPCE"}
+      icon={faProjectDiagram}
+      external />;
+
+    const linkFound = menuItems.find(obj => obj.key === "microwave");
+    
+    if (linkFound) {
+      const index = menuItems.indexOf(linkFound);
+      menuItems.splice(index + 1, 0, transportPCELink);
+    } else {
+      menuItems.push(transportPCELink);
+    }
+  }
+  
+
+  return (
+    <Drawer
+      variant="permanent"
+      className={
+        classNames(classes.drawer, {
+          [classes.drawerOpen]: isOpen,
+          [classes.drawerClose]: !isOpen
+        })
+      }
+      classes={{
+        paper: classes.drawerPaper,
+      }}
+    >
+      {user && user.isValid && <>
+        <div className={classes.toolbar} />
+        { /* https://fiffty.github.io/react-treeview-mui/ */}
+        <List className={classes.menu} component="nav">
+          <ListItemLink exact to="/" primary="Home" icon={homeIcon} />
+          <Divider />
+          {
+          menuItems
+          }
+          <Divider />
+          <ListItemLink to="/about" primary="About" icon={aboutIcon} />
+          {(false && process.env.NODE_ENV === "development")
+            ? <>
+              <Divider />
+              <ListItemLink to="/test" primary="Test" icon={settingsIcon} />
+            </>
+            : null
+          }
+        </List>
+        {isOpen && extraLinks && <div className={classes.optLinks}>
+          {extraLinks.map(linkInfo => (<a className={classes.link} href={linkInfo[1]}>{linkInfo[0]}</a>))}
+        </div> || null}
+      </> || null
+      }
+    </Drawer>)
+}));
+
+export default NavigationMenu;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/objectDump/index.tsx b/sdnr/wt-odlux/odlux/framework/src/components/objectDump/index.tsx
new file mode 100644
index 0000000..10a0547
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/objectDump/index.tsx
@@ -0,0 +1,205 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from "react";
+import makeStyles from '@mui/styles/makeStyles';
+
+export const getTypeName = (obj: any): string => {
+  if (obj == null) {
+    return obj === undefined ? "Undefined" : "Null";
+  }
+  return Object.prototype.toString.call(obj).slice(8, -1);
+};
+
+const isObjectLike = (obj: any) => {
+  return typeof obj === "object" && obj !== null;
+};
+
+const isBoolean = (obj: any) => {
+  return obj === true || obj === false ||
+    (isObjectLike(obj) && getTypeName(obj) === "Boolean");
+};
+
+const isNumber = (obj: any) => {
+  return typeof obj === "number" ||
+    (isObjectLike(obj) && getTypeName(obj) === "Number");
+};
+
+const isString = (obj: any) => {
+  return typeof obj === "string" ||
+    (isObjectLike(obj) && getTypeName(obj) === "String");
+};
+
+const isNull = (obj: any) => {
+  return obj === null;
+};
+
+const isDate = (obj: any): boolean => {
+  return isObjectLike(obj) && (obj instanceof Date);
+};
+
+const useSimpleTableStyles = makeStyles({
+  root: {
+  },
+  table: {
+    fontFamily: "verdana, arial, helvetica, sans-serif",
+    borderSpacing: "3px",
+    borderCollapse: "separate",
+    marginLeft: "30px"
+  },
+  label: {
+    cursor: "pointer",
+  },
+  th: {
+    textAlign: "left",
+    color: "white",
+    padding: "5px",
+    backgroundColor: "#cccccc",
+
+  },
+  td: {
+    verticalAlign: "top",
+    padding: "0.5rem 1rem",
+    border: "2px solid #DDD"
+  },
+  object: {
+  },
+  objectTh: {
+    backgroundColor: "#cccccc",
+  },
+  objectTd: {
+    padding: "0.5rem 1rem",
+    border: "2px solid #DDD"
+  },
+  chevron: {
+    '&:before': {
+      borderStyle: 'solid',
+      borderWidth: '0.25em 0.25em 0 0',
+      content: '\'\'',
+      display: 'inline-block',
+      height: '0.45em',
+      left: '0.15em',
+      position: 'relative',
+      top: '0.15em',
+      transform: 'rotate(-45deg)',
+      transition: 'all 0.3s',
+      verticalAlign: 'top',
+      width: '0.45em',
+    }
+
+  },
+    right: {
+    '&:before': {
+      left: '0',
+      transform: 'rotate(45deg)',
+    }
+  },
+  bottom: {
+    '&:before': {
+      left: '0',
+      transform: 'rotate(135deg)',
+    }
+  },
+});
+
+
+type SimpleTableProps = {
+  classNameTh?: string;
+  label?: JSX.Element | string | null;
+  cols?: number;
+  expand?: boolean;
+  ariaLabel?: string;
+}
+
+const SimpleTable: React.FC<SimpleTableProps> = (props) => {
+  const { label = '', cols = 2, expand = true, classNameTh, children } = props;
+  const [isExpanded, setIsExpanded] = React.useState(expand);
+
+  const classes = useSimpleTableStyles();
+
+  React.useEffect(() => {
+    setIsExpanded(expand);
+  }, [expand]);
+
+  const handleClick = () => {
+    setIsExpanded(!isExpanded);
+  };
+
+  return (
+    <table className={`${classes.root} ${classes.table}`} aria-label={props.ariaLabel? props.ariaLabel+'-table' : 'table'}>
+      {label && (<thead>
+        <tr aria-label={props.ariaLabel? props.ariaLabel+'-title-row' : 'title row'}>
+          <th className={`${classes.th} ${classes.label} ${classNameTh ? classNameTh : ''}`} colSpan={cols} onClick={handleClick}>
+            <span className={`${classes.chevron} ${isExpanded ? classes.bottom : classes.right }`}></span> { label }
+          </th>
+        </tr>
+      </thead>) || null
+      }
+      {isExpanded && <tbody >{children}</tbody> || null}
+    </table>
+  );
+};
+
+
+type ObjectRendererProps = {
+  className?: string;
+  label?: JSX.Element | string | null;
+  expand?: boolean;
+  object: { [key: string]: any };
+  ariaLabel?: string;
+};
+
+const ObjectRenderer: React.FC<ObjectRendererProps> = (props) => {
+  const { object, className, label = 'Object', expand = true } = props;
+  const classes = useSimpleTableStyles();
+
+  return (
+    <SimpleTable ariaLabel={props.ariaLabel} classNameTh={classes.objectTh} label={getTypeName(object) || label} expand={expand}>
+      {
+        Object.keys(object).map(key => {
+          return (
+            <tr key={String(key)} aria-label={props.ariaLabel? props.ariaLabel+'-row': 'row'}>
+              <td className={`${classes.td} ${classes.objectTd}`} aria-label="object-title">{String(key)} </td>
+              <td className={`${classes.td}`} aria-label="object-details">{renderObject(object[key], "sub-element")}</td>
+            </tr>
+          );
+        })
+      }
+    </SimpleTable>
+  );
+};
+
+
+type ArrayRendererProps = {
+  label?: JSX.Element | string | null;
+  extraRenderer?: { [label: string]: React.ComponentType<{ label?: JSX.Element | string | null; object: any; }> };
+  description?: string;
+  object: any;
+};
+
+const ArrayRenderer: React.FC<ArrayRendererProps> = (props) => {
+
+  return null;
+};
+
+export const renderObject = (object: any, ariaLabel?: string): JSX.Element | string => {
+  if (isString(object) || isNumber(object) || isBoolean(object)) {
+    return String(object);
+  }
+  return <ObjectRenderer object={object} ariaLabel={ariaLabel} />;
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/routing/appFrame.tsx b/sdnr/wt-odlux/odlux/framework/src/components/routing/appFrame.tsx
new file mode 100644
index 0000000..aa22f17
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/routing/appFrame.tsx
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+
+import { connect, Connect } from '../../flux/connect';
+
+import { SetTitleAction } from '../../actions/titleActions';
+import { AddErrorInfoAction } from '../../actions/errorActions';
+
+import { IconType } from '../../models/iconDefinition';
+
+export interface IAppFrameProps  {
+  title: string;
+  icon?: IconType;
+  appId?: string
+}
+
+/**
+ * Represents a component to wich will embed each single app providing the
+ * functionality to update the title and implement an exeprion border.
+ */
+export class AppFrame extends React.Component<IAppFrameProps & Connect> {
+
+  public render(): JSX.Element {
+    return (
+      <div style={{ flex: "1", overflow: "hidden", display: "flex", flexDirection: "column" }}>
+        { this.props.children }
+      </div>
+     )
+    }
+
+  public componentDidMount() {
+    this.props.dispatch(new SetTitleAction(this.props.title, this.props.icon, this.props.appId));
+  }
+  public componentDidCatch(error: Error | null, info: object) {
+    this.props.dispatch(new AddErrorInfoAction({ error, info }));
+  }
+}
+
+export default connect()(AppFrame);
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/settings/general.tsx b/sdnr/wt-odlux/odlux/framework/src/components/settings/general.tsx
new file mode 100644
index 0000000..ffd516b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/settings/general.tsx
@@ -0,0 +1,110 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import  React from 'react';
+import { Button, FormControlLabel, Switch, Typography } from '@mui/material';
+import makeStyles from '@mui/styles/makeStyles';
+import { SettingsComponentProps } from '../../models/settings';
+import { connect, Connect, IDispatcher } from '../../flux/connect';
+import { IApplicationStoreState } from '../../store/applicationStore';
+import { getGeneralSettingsAction, SetGeneralSettingsAction, updateGeneralSettingsAction } from '../../actions/settingsAction';
+import { sendMessage, SettingsMessage } from '../../services/broadcastService';
+
+
+type props = Connect<typeof mapProps, typeof mapDispatch> & SettingsComponentProps;
+
+const mapProps = (state: IApplicationStoreState) => ({
+    settings: state.framework.applicationState.settings,
+    user: state.framework.authenticationState.user?.user
+    
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+
+    updateSettings :(activateNotifications: boolean) => dispatcher.dispatch(updateGeneralSettingsAction(activateNotifications)),
+    getSettings: () =>dispatcher.dispatch(getGeneralSettingsAction()),
+  });
+
+const styles = makeStyles({
+    sectionMargin: {
+      marginTop: "30px",
+      marginBottom: "15px"
+    },
+    elementMargin: {
+      marginLeft: "10px"
+    },
+    buttonPosition:{
+      position: "absolute",
+      right: "32%"
+    }
+  });
+
+const General : React.FunctionComponent<props> = (props) =>{
+
+const classes = styles();
+
+const [areWebsocketsEnabled, setWebsocketsEnabled] = React.useState(props.settings.general.areNotificationsEnabled || false);
+
+React.useEffect(()=>{
+  props.getSettings();
+},[]);
+
+React.useEffect(()=>{
+  if(props.settings.general.areNotificationsEnabled!==null)
+    setWebsocketsEnabled(props.settings.general.areNotificationsEnabled)
+},[props.settings]);
+
+const onWebsocketsChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: boolean) =>{
+    setWebsocketsEnabled(newValue);
+  }
+
+const onSave = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) =>{
+
+    e.preventDefault();
+    const message: SettingsMessage = {key: 'general', enableNotifications: areWebsocketsEnabled, user: props.user!};
+    sendMessage(message, "odlux_settings");
+    props.updateSettings(areWebsocketsEnabled);
+    props.onClose();
+}
+
+const onCancel = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) =>{
+  e.preventDefault();
+  props.onClose();
+
+}
+
+
+    return <div>
+        <Typography className={classes.sectionMargin} variant="body1" style={{ fontWeight: "bold" }} gutterBottom>
+          Enable Notifications
+        </Typography>
+        <FormControlLabel style={{ padding:5}}
+        value="end"
+        control={<Switch color="secondary" aria-label="enable-notifications-button" aria-checked={areWebsocketsEnabled} checked={areWebsocketsEnabled} onChange={onWebsocketsChange} />}
+        label="Enable Notifications"
+        labelPlacement="end"
+      />
+      <div className={classes.buttonPosition}>
+       <Button aria-label="cancel-button" className={classes.elementMargin} variant="contained" color="primary" onClick={onCancel}>Cancel</Button>
+       <Button aria-label="save-button" className={classes.elementMargin} variant="contained" color="secondary" onClick={onSave}>Save</Button>
+    </div>
+    </div>
+}
+
+export const GeneralUserSettings = connect(mapProps, mapDispatch)(General);
+export default GeneralUserSettings;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/components/titleBar.tsx b/sdnr/wt-odlux/odlux/framework/src/components/titleBar.tsx
new file mode 100644
index 0000000..40c0fc7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/components/titleBar.tsx
@@ -0,0 +1,233 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+import AppBar from '@mui/material/AppBar';
+import Toolbar from '@mui/material/Toolbar';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import IconButton from '@mui/material/IconButton';
+import AccountCircle from '@mui/icons-material/AccountCircle';
+import MenuItem from '@mui/material/MenuItem';
+import Menu from '@mui/material/Menu';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faBan } from '@fortawesome/free-solid-svg-icons';
+import { faDotCircle } from '@fortawesome/free-solid-svg-icons';
+
+import { logoutUser } from '../actions/authentication';
+import { PushAction, ReplaceAction } from '../actions/navigationActions';
+
+import { connect, Connect, IDispatcher } from '../flux/connect';
+import { MenuAction, MenuClosedByUser } from '../actions/menuAction';
+
+import MenuIcon from './icons/menuIcon';
+import Logo from './logo';
+
+const styles = (theme: Theme) => createStyles({
+  appBar: {
+    zIndex: theme.zIndex.drawer + 1,
+  },
+  grow: {
+    flexGrow: 1,
+  },
+  menuButton: {
+    marginLeft: -12,
+    marginRight: 20,
+  },
+  icon: {
+    marginLeft: 16,
+    marginRight: 8,
+    marginBottom: -2,
+  },
+  connected: {
+    color: "green"
+  },
+  notConnected: {
+    color: "red"
+  },
+  notificationInfo: {
+    marginLeft: 5
+  }
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => {
+  return {
+    logout: () => {
+      dispatcher.dispatch(logoutUser());
+      dispatcher.dispatch(new ReplaceAction("/login"));
+    },
+    openSettings : () =>{
+      dispatcher.dispatch(new PushAction("/settings"));
+    },
+    toggleMainMenu: (value: boolean, value2: boolean) => {
+      dispatcher.dispatch(new MenuAction(value));
+      dispatcher.dispatch(new MenuClosedByUser(value2))
+    }
+  }
+};
+
+type TitleBarProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect<undefined, typeof mapDispatch>
+
+class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLElement | null }> {
+
+  constructor(props: TitleBarProps) {
+    super(props);
+    this.state = {
+      anchorEl: null
+    }
+
+  }
+  render(): JSX.Element {
+    const { classes, state, history, location } = this.props;
+    const open = !!this.state.anchorEl;
+    let toolbarElements: Array<JSX.Element>;
+    toolbarElements = [];
+
+    // create notificationInfo element
+    const notificationInfo = state.framework.applicationState.isWebsocketAvailable != undefined ?
+      (state.framework.applicationState.isWebsocketAvailable ?
+        <Typography aria-label="notifications-are-active" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.connected} icon={faDotCircle} />  |</Typography> : <Typography aria-label="notifications-are-inactive" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.notConnected} icon={faBan} /> |</Typography>)
+      : <Typography variant="body1" aria-label="notifications-are-not-available" className={classes.notificationInfo}>Notifications N/A |</Typography>;
+
+
+    // add notificationInfo element before help
+    if (state.framework.applicationRegistration) {
+      let isNotificationInfoAdded = false;
+      Object.keys(state.framework.applicationRegistration).map(key => {
+        const reg = state.framework.applicationRegistration[key];
+        if (reg && reg.statusBarElement) {
+          if (key === "help") {
+            isNotificationInfoAdded = true;
+            toolbarElements.push(notificationInfo);
+          }
+          toolbarElements.push(<reg.statusBarElement key={key} />);
+        }
+      });
+
+      // add notificationInfo in case help wasn't found
+      if (!isNotificationInfoAdded) {
+        toolbarElements.push(notificationInfo);
+      }
+    }
+
+    const stateIcon = state.framework.applicationState.icon;
+    const customIconHeight = 22; 
+    const icon = !stateIcon
+      ? null
+      : (typeof stateIcon === 'string'
+        ? <img className={classes.icon} height={customIconHeight} src={stateIcon} />
+        : <FontAwesomeIcon className={classes.icon} icon={stateIcon} />)
+    
+
+    return (
+      <AppBar enableColorOnDark position="absolute" className={classes.appBar}>
+        <Toolbar>
+          <IconButton
+            className={classes.menuButton}
+            color="inherit"
+            aria-label="Menu"
+            onClick={this.toggleMainMenu}
+            size="large">
+            <MenuIcon />
+          </IconButton>
+          <Logo />
+          <Typography variant="h6" color="inherit" >
+            {icon}
+            {state.framework.applicationState.title}
+          </Typography>
+          <div className={classes.grow}></div>
+          {
+            // render toolbar
+            toolbarElements.map((item) => {
+              return item
+            })
+          }
+
+          {state.framework.authenticationState.user
+            ? (<div>
+              <Button aria-label="current user menu button"
+                aria-owns={open ? 'menu-appbar' : undefined}
+                aria-haspopup="true"
+                onClick={this.openMenu}
+                color="inherit"
+              >
+                <AccountCircle />
+                {state.framework.authenticationState.user.user}
+              </Button>
+              <Menu
+                id="menu-appbar"
+                anchorEl={this.state.anchorEl}
+                anchorOrigin={{
+                  vertical: 'top',
+                  horizontal: 'right',
+                }}
+                transformOrigin={{
+                  vertical: 'top',
+                  horizontal: 'right',
+                }}
+                open={open}
+                onClose={this.closeMenu}
+              >
+                {/* <MenuItem onClick={ this.closeMenu }>Profile</MenuItem> */}
+                <MenuItem 
+                 aria-label="settings-button"
+                 onClick={ () =>{
+                    this.props.openSettings();
+                    this.closeMenu(); }}>Settings</MenuItem>
+                <MenuItem
+                aria-label="logout-button"
+                onClick={() => {
+                  this.props.logout();
+                  this.closeMenu();
+                }}>Logout</MenuItem>
+              </Menu>
+            </div>)
+            : (<Button onClick={() => { history.push('/login') }} color="inherit" disabled={location.pathname == "/login"}>Login</Button>)}
+        </Toolbar>
+      </AppBar>
+    );
+  };
+
+  private toggleMainMenu = (event: React.MouseEvent<HTMLElement>) => {
+    console.log(this.props);
+    if (this.props.state.framework.authenticationState.user && this.props.state.framework.authenticationState.user.isValid) {
+      const isMainMenuOpen = this.props.state.framework.applicationState.isMenuOpen
+      const isClosedByUser = this.props.state.framework.applicationState.isMenuClosedByUser
+      this.props.toggleMainMenu(!isMainMenuOpen, !isClosedByUser);
+    }
+  }
+
+  private openMenu = (event: React.MouseEvent<HTMLElement>) => {
+    this.setState({ anchorEl: event.currentTarget });
+  };
+
+  private closeMenu = () => {
+    this.setState({ anchorEl: null });
+  };
+}
+
+//todo: ggf. https://github.com/acdlite/recompose verwenden zur Vereinfachung
+
+export const TitleBar = withStyles(styles)(withRouter(connect(undefined, mapDispatch)(TitleBarComponent)));
+export default TitleBar;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/design/default.ts b/sdnr/wt-odlux/odlux/framework/src/design/default.ts
new file mode 100644
index 0000000..c4a8118
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/design/default.ts
@@ -0,0 +1,81 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+/******************************************************************************
+ * Copyright 2018 highstreet technologies GmbH
+ *
+ * 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.
+ *****************************************************************************/
+
+import { createTheme, adaptV4Theme } from '@mui/material/styles';
+import onapLogo from '../assets/images/onapLogo.gif'
+
+const theme = createTheme(adaptV4Theme({
+  design: {
+    id: "onap",
+    name: "Open Networking Automation Plattform (ONAP)",
+    url: onapLogo,
+    height: 49,
+    width: 229,
+    logoHeight: 32,
+  },
+  palette: {
+    primary: {
+      light: "#eeeeee",
+      main: "#ffffff",
+      dark: "#e0e0e0",
+      contrastText: "#07819B"
+    },
+    secondary: {
+      light: "rgba(7, 129, 155, 94)",
+      main: "rgba(7, 129, 155, 201)",
+      dark: "#07819B",
+      contrastText: "#ffffff"
+    },
+  },
+  overrides: { //temp fix for labels turning white after material new version (palette primary color)
+    MuiFormLabel: {
+      root: {
+        "&.Mui-focused": {
+          color: "rgba(143,143,143,1)"
+        }
+      },
+
+      focused: {}
+    },
+    MuiInput: {
+      underline: {
+
+        "&:after": {
+          borderBottom: "2px solid #444444"
+        }
+      }
+    }
+  },
+}));
+
+export default theme;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/favicon.ico b/sdnr/wt-odlux/odlux/framework/src/favicon.ico
new file mode 100644
index 0000000..a8a5d31
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/favicon.ico
Binary files differ
diff --git a/sdnr/wt-odlux/odlux/framework/src/flux/action.ts b/sdnr/wt-odlux/odlux/framework/src/flux/action.ts
new file mode 100644
index 0000000..7689025
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/flux/action.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+  * Represents an action in the odlux flux architecture.
+  */
+export abstract class Action { }
+
+export interface IActionHandler<TState, TAction extends Action = Action> {
+  (state: TState | undefined, action: TAction): TState;
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/flux/connect.tsx b/sdnr/wt-odlux/odlux/framework/src/flux/connect.tsx
new file mode 100644
index 0000000..09d30da
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/flux/connect.tsx
@@ -0,0 +1,213 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React, { FC, useContext, createContext, useState, useEffect, useRef } from 'react';
+
+import { Dispatch } from './store';
+
+import { ApplicationStore, IApplicationStoreState } from '../store/applicationStore';
+
+const LogLevel = +(localStorage.getItem('log.odlux.framework.flux.connect') || 0);
+
+interface IApplicationStoreContext {
+  applicationStore: ApplicationStore;
+}
+
+export interface IDispatcher {
+  dispatch: Dispatch;
+}
+
+interface IApplicationStoreProps {
+  state: IApplicationStoreState;
+}
+
+interface IDispatchProps {
+  dispatch: Dispatch;
+}
+
+type ComponentDecoratorInfer<TMergedProps> = {
+  <TProps>(wrappedComponent: React.ComponentType<TProps & TMergedProps>): React.ComponentClass<Omit<TProps & TMergedProps, keyof TMergedProps>>;
+};
+
+const ApplicationStoreContext = createContext<IApplicationStoreContext | undefined>(undefined);
+
+export type Connect<TMapProps extends ((...args: any) => any) | undefined = undefined, TMapDispatch extends ((...args: any) => any) | undefined = undefined> =
+  (TMapProps extends ((...args: any) => any) ? ReturnType<TMapProps> : IApplicationStoreProps) &
+  (TMapDispatch extends ((...args: any) => any) ? ReturnType<TMapDispatch> : IDispatchProps);
+
+export function connect(): ComponentDecoratorInfer<IApplicationStoreProps & IDispatchProps>;
+
+export function connect<TStateProps>(
+  mapStateToProps: (state: IApplicationStoreState) => TStateProps
+): ComponentDecoratorInfer<TStateProps & IDispatchProps>;
+
+export function connect<TStateProps, TDispatchProps>(
+  mapStateToProps: (state: IApplicationStoreState) => TStateProps,
+  mapDispatchToProps: (dispatcher: IDispatcher) => TDispatchProps
+): ComponentDecoratorInfer<TStateProps & TDispatchProps>;
+
+
+export function connect<TDispatchProps>(
+  mapStateToProps: undefined,
+  mapDispatchToProps: (dispatcher: IDispatcher) => TDispatchProps
+): ComponentDecoratorInfer<IApplicationStoreProps & TDispatchProps>;
+
+
+export function connect<TProps, TStateProps, TDispatchProps>(
+  mapStateToProps?: ((state: IApplicationStoreState) => TStateProps),
+  mapDispatchToProps?: ((dispatcher: IDispatcher) => TDispatchProps)
+):
+  ((WrappedComponent: React.ComponentType<TProps & (IApplicationStoreProps | TStateProps) & IDispatchProps>) => React.ComponentType<TProps>) {
+
+  const injectApplicationStore = (WrappedComponent: React.ComponentType<TProps & (IApplicationStoreProps | TStateProps) & IDispatchProps>): React.ComponentType<TProps> => {
+
+    class StoreAdapter extends React.Component<TProps, {}> {
+      
+      render(): JSX.Element {
+
+        if (isWrappedComponentIsVersion1(WrappedComponent)) {
+          const element = React.createElement(WrappedComponent, { ...(this.props as any), state: this.store.state, dispatch: this.store.dispatch.bind(this.store) });
+          return element;
+        } else if (mapStateToProps && isWrappedComponentIsVersion2(WrappedComponent)) {
+          const element = React.createElement(WrappedComponent, { ...(this.props as any), ...(mapStateToProps(this.store.state) as any), dispatch: this.store.dispatch.bind(this.store) });
+          return element;
+        } else if (mapStateToProps && mapDispatchToProps && isWrappedComponentIsVersion3(WrappedComponent)) {
+          const element = React.createElement(WrappedComponent, { ...(this.props as any), ...(mapStateToProps(this.store.state) as any), ...(mapDispatchToProps({ dispatch: this.store.dispatch.bind(this.store) }) as any) });
+          return element;
+        } else if (!mapStateToProps && mapDispatchToProps && isWrappedComponentIsVersion4(WrappedComponent)) {
+          const element = React.createElement(WrappedComponent, { ...(this.props as any), state: this.store.state, ...(mapDispatchToProps({ dispatch: this.store.dispatch.bind(this.store) }) as any) });
+          return element;
+        }
+        throw new Error("Invalid arguments in connect.");
+      }
+
+      componentDidMount(): void {
+        this.store && this.store.changed.addHandler(this.handleStoreChanged);
+      }
+
+      componentWillUnmount(): void {
+        this.store && this.store.changed.removeHandler(this.handleStoreChanged);
+      }
+
+      private get store(): ApplicationStore {
+        return this.context.applicationStore;
+      }
+
+      private handleStoreChanged = () => {
+        this.forceUpdate();
+      }
+    }
+    StoreAdapter.contextType = ApplicationStoreContext;
+    return StoreAdapter;
+  }
+
+
+  return injectApplicationStore;
+
+  /* inline methods */
+
+  function isWrappedComponentIsVersion1(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & IApplicationStoreProps & IDispatchProps> {
+    return !mapStateToProps && !mapDispatchToProps;
+  }
+
+  function isWrappedComponentIsVersion2(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & TStateProps & IDispatchProps> {
+    return !!mapStateToProps && !mapDispatchToProps;
+  }
+
+  function isWrappedComponentIsVersion3(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & TStateProps & TDispatchProps> {
+    return !!mapStateToProps && !!mapDispatchToProps;
+  }
+
+  function isWrappedComponentIsVersion4(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & TStateProps & TDispatchProps> {
+    return !mapStateToProps && !!mapDispatchToProps;
+  }
+}
+
+type ApplicationStoreProviderProps = {
+  applicationStore: ApplicationStore;
+}
+
+export const ApplicationStoreProvider: FC<ApplicationStoreProviderProps> = (props) => {
+  const { applicationStore, children } = props;
+
+  return (
+    <ApplicationStoreContext.Provider value={{ applicationStore }}>
+      {children}
+    </ApplicationStoreContext.Provider>
+  );
+};
+
+export const useApplicationStore = (): ApplicationStore => {
+  const context = useContext(ApplicationStoreContext);
+  if (context == null || context.applicationStore == null) {
+    throw new Error("Requires application store provider!")
+  }
+  return context.applicationStore
+};
+
+export const useSelectApplicationState = <TProp extends unknown >( selector: (state: IApplicationStoreState) => TProp, eqFunc = (a: TProp, b: TProp) => a === b ): TProp => {
+  const context = useContext(ApplicationStoreContext);
+  if (context == null || context.applicationStore == null) {
+    throw new Error("Requires application store provider!")
+  }
+  
+  const [propState, setPropState] = useState<TProp>(selector(context.applicationStore.state));
+  
+  const selectorRef = useRef(selector);
+  selectorRef.current = selector;
+
+  const propStateRef = useRef({propState});
+  propStateRef.current.propState = propState;
+
+  useEffect(() => {
+    if (context == null || context.applicationStore == null) {
+      throw new Error("Requires application store provider!")
+    }
+
+    const changedHandler = () => {
+      const newState = selectorRef.current(context.applicationStore.state);
+      if (!eqFunc(newState, propStateRef.current.propState)) {
+        setPropState(newState);
+      }
+    };
+
+    if (LogLevel > 3) {
+      console.log("useSelectApplicationState: adding handler", changedHandler);
+    }
+
+    context.applicationStore.changed.addHandler(changedHandler);
+
+    return () => {
+      if (LogLevel > 3) {
+        console.log("useSelectApplicationState: removing handler", changedHandler);
+      }
+
+      context.applicationStore.changed.removeHandler(changedHandler);
+    }
+  }, [context]);
+
+  return propState;
+  
+};
+
+export const useApplicationDispatch = (): Dispatch => {
+  const context = useContext(ApplicationStoreContext);
+  if (context == null || context.applicationStore == null) {
+    throw new Error("Requires application store provider!")
+  }
+  return context.applicationStore.dispatch;
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/flux/middleware.ts b/sdnr/wt-odlux/odlux/framework/src/flux/middleware.ts
new file mode 100644
index 0000000..de6505c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/flux/middleware.ts
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action, IActionHandler } from './action';
+import { Store, Dispatch, Enhancer } from './store';
+
+export interface MiddlewareArg<T> {
+  dispatch: Dispatch;
+  getState: () => T;
+}
+
+export interface Middleware<T> {
+  (obj: MiddlewareArg<T>): Function;
+}
+
+class InitialisationAction extends Action { };
+const initialisationAction = new InitialisationAction();
+
+export type ActionHandlerMapObject<S extends { [key: string]: any }, A extends Action = Action> = {
+  [K in keyof S]: IActionHandler<S[K], A>
+}
+
+export const combineActionHandler = <TState extends { [key: string]: any }, TAction extends Action = Action>(actionHandlers: ActionHandlerMapObject<TState, TAction>) : IActionHandler<TState, TAction> => {
+  const finalActionHandlers = {} as { [key: string]: any }; // https://github.com/microsoft/TypeScript/issues/31808
+  Object.keys(actionHandlers).forEach(actionHandlerKey => {
+    const handler = actionHandlers[actionHandlerKey];
+    if (typeof handler === 'function') {
+      finalActionHandlers[actionHandlerKey] = handler;
+    }
+  });
+
+  // ensure initialisation
+  Object.keys(finalActionHandlers).forEach(key => {
+    const actionHandler = finalActionHandlers[key];
+    const initialState = actionHandler(undefined, initialisationAction);
+    if (typeof initialState === 'undefined') {
+      const errorMessage = `Action handler ${ key } returned undefiend during initialization.`;
+      throw new Error(errorMessage);
+    }
+  });
+
+  return function combination<TAction extends Action>(state: TState = ({} as TState), action: TAction) {
+    let hasChanged = false;
+    const nextState = {} as { [key: string]: any }; // https://github.com/microsoft/TypeScript/issues/31808
+    Object.keys(finalActionHandlers).forEach(key => {
+      const actionHandler = finalActionHandlers[key];
+      const previousState = state[key];
+      const nextStateKey = actionHandler(previousState, action);
+      if (typeof nextStateKey === 'undefined') {
+        const errorMessage = `Given ${ action.constructor } and action handler ${ key } returned undefiend.`;
+        throw new Error(errorMessage);
+      }
+      nextState[key] = nextStateKey;
+      hasChanged = hasChanged || nextStateKey !== previousState;
+    });
+    return (hasChanged ? nextState : state) as TState;
+  };
+};
+
+export const chainMiddleware = <TStoreState>(...middlewares: Middleware<TStoreState>[]): Enhancer<TStoreState> => {
+  return (store: Store<TStoreState>) => {
+    const middlewareAPI = {
+      getState() { return store.state },
+      dispatch: <TAction extends Action>(action: TAction) => store.dispatch(action) // we want to use the combinded dispatch
+      // we should NOT use the flux dispatcher here, since the action would affect ALL stores
+    };
+    const chain = middlewares.map(middleware => middleware(middlewareAPI));
+    return compose(...chain)(store.dispatch) as Dispatch;
+  }
+};
+
+/**
+ * Composes single-argument functions from right to left. The rightmost
+ * function can take multiple arguments as it provides the signature for
+ * the resulting composite function.
+ *
+ * @param {...Function} funcs The functions to compose.
+ * @returns {Function} A function obtained by composing the argument functions
+ * from right to left. For example, compose(f, g, h) is identical to doing
+ * (...args) => f(g(h(...args))).
+ */
+const compose = (...funcs: Function[]) => {
+  if (funcs.length === 0) {
+    return (arg: any) => arg
+  }
+
+  if (funcs.length === 1) {
+    return funcs[0]
+  }
+
+  return funcs.reduce((a, b) => (...args: any[]) => a(b(...args)));
+};
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/flux/store.ts b/sdnr/wt-odlux/odlux/framework/src/flux/store.ts
new file mode 100644
index 0000000..347d295
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/flux/store.ts
@@ -0,0 +1,106 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Event } from "../common/event"
+
+import { Action } from './action';
+import { IActionHandler } from './action';
+
+const LogLevel = +(localStorage.getItem('log.odlux.framework.flux.store') || 0);
+
+export interface Dispatch {
+  <TAction extends Action>(action: TAction): TAction;
+}
+
+export interface Enhancer<TStoreState> {
+  (store: Store<TStoreState>): Dispatch;
+}
+
+class InitializationAction extends Action { };
+const initializationAction = new InitializationAction();
+
+export class Store<TStoreState> {
+
+  constructor(actionHandler: IActionHandler<TStoreState>, enhancer?: Enhancer<TStoreState>)
+  constructor(actionHandler: IActionHandler<TStoreState>, initialState: TStoreState, enhancer?: Enhancer<TStoreState>)
+  constructor(actionHandler: IActionHandler<TStoreState>, initialState?: TStoreState | Enhancer<TStoreState>, enhancer?: Enhancer<TStoreState>) {
+    if (typeof initialState === 'function') {
+      enhancer = initialState as Enhancer<TStoreState>;
+      initialState = undefined;
+    }
+
+    this._isDispatching = false;
+     
+    this.changed = new Event<void>();
+
+    this._actionHandler = actionHandler;
+    
+    this._state = initialState as TStoreState;
+    if (enhancer) this._dispatch = enhancer(this);
+
+    this._dispatch(initializationAction);
+  }
+
+  public changed: Event<void>;
+
+  private _dispatch: Dispatch = <TAction extends Action>(payload: TAction): TAction => {
+    if (LogLevel > 2) {
+      console.log('Store::Dispatch - ', payload);
+    }
+    if (payload == null || !(payload instanceof Action)) {
+      throw new Error(
+        'Actions must inherit from type Action. ' +
+        'Use a custom middleware for async actions.'
+      );
+    }
+    
+    if (this._isDispatching) {
+      throw new Error('ActionHandler may not dispatch actions.');
+    }
+
+    const oldState = this._state;
+    try {
+      this._isDispatching = true;
+      this._state = this._actionHandler(oldState, payload);
+    } finally {
+      this._isDispatching = false;
+    }
+
+    if (this._state !== oldState) {
+      if (LogLevel > 3) {
+        console.log('Store::Dispatch - state has changed', this._state);
+      }
+      this.changed.invoke();
+    }
+
+    return payload;
+  }
+
+  public get dispatch(): Dispatch {
+    return this._dispatch;
+  }
+
+  public get state() {
+    return this._state
+  }
+
+  private _state: TStoreState;
+  private _isDispatching: boolean;
+  private _actionHandler: IActionHandler<TStoreState>;
+
+}
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/handlers/applicationRegistryHandler.ts b/sdnr/wt-odlux/odlux/framework/src/handlers/applicationRegistryHandler.ts
new file mode 100644
index 0000000..ec7b0a0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/handlers/applicationRegistryHandler.ts
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+
+import { ApplicationInfo } from '../models/applicationInfo';
+import { applicationManager } from '../services/applicationManager';
+
+export interface IApplicationRegistration {
+  [name: string]: ApplicationInfo;
+}
+
+const applicationRegistrationInit: IApplicationRegistration = applicationManager.applications;
+
+export const applicationRegistryHandler: IActionHandler<IApplicationRegistration> = (state = applicationRegistrationInit, action) => {
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/handlers/applicationStateHandler.ts b/sdnr/wt-odlux/odlux/framework/src/handlers/applicationStateHandler.ts
new file mode 100644
index 0000000..d0a0724
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/handlers/applicationStateHandler.ts
@@ -0,0 +1,176 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+
+import { SetTitleAction } from '../actions/titleActions';
+import { SetExternalLoginProviderAction } from '../actions/loginProvider';
+import { AddSnackbarNotification, RemoveSnackbarNotification } from '../actions/snackbarActions';
+import { AddErrorInfoAction, RemoveErrorInfoAction, ClearErrorInfoAction } from '../actions/errorActions';
+import { MenuAction, MenuClosedByUser } from '../actions/menuAction'
+import { SetWebsocketAction } from '../actions/websocketAction';
+
+import { IconType } from '../models/iconDefinition';
+import { ErrorInfo } from '../models/errorInfo';
+import { SnackbarItem } from '../models/snackbarItem';
+import { ExternalLoginProvider } from '../models/externalLoginProvider';
+import { ApplicationConfig } from '../models/applicationConfig';
+import { IConnectAppStoreState } from '../../../apps/connectApp/src/handlers/connectAppRootHandler';
+import { IFaultAppStoreState } from '../../../apps/faultApp/src/handlers/faultAppRootHandler';
+import { GeneralSettings, Settings } from '../models/settings';
+import { LoadSettingsAction, SetGeneralSettingsAction, SetTableSettings, SettingsDoneLoadingAction } from '../actions/settingsAction';
+import { startWebsocketSession, suspendWebsocketSession } from '../services/notificationService';
+
+
+declare module '../store/applicationStore' {
+  interface IApplicationStoreState {
+    connect: IConnectAppStoreState;
+    fault: IFaultAppStoreState
+  }
+}
+export interface IApplicationState {
+  title: string;
+  appId?: string;
+  icon?: IconType;
+  isMenuOpen: boolean;
+  isMenuClosedByUser: boolean;
+  errors: ErrorInfo[];
+  snackBars: SnackbarItem[];
+  isWebsocketAvailable: boolean | null;
+  externalLoginProviders: ExternalLoginProvider[] | null;
+  authentication: "basic"|"oauth",  // basic 
+  enablePolicy: boolean,             // false 
+  transportpceUrl : string,
+  settings: Settings & { isInitialLoadDone: boolean }
+}
+
+const applicationStateInit: IApplicationState = {
+  title: "Loading ...",
+  errors: [],
+  snackBars: [],
+  isMenuOpen: true,
+  isMenuClosedByUser: false,
+  isWebsocketAvailable: null,
+  externalLoginProviders: null,
+  authentication: "basic",
+  enablePolicy: false,
+  transportpceUrl: "",
+  settings:{ 
+    general: { areNotificationsEnabled: null },
+    tables: {},
+    isInitialLoadDone: false
+  }
+};
+
+export const configureApplication = (config: ApplicationConfig) => {
+  applicationStateInit.authentication = config.authentication === "oauth" ? "oauth" : "basic";
+  applicationStateInit.enablePolicy = config.enablePolicy ? true : false;
+  applicationStateInit.transportpceUrl=config.transportpceUrl == undefined ? "" : config.transportpceUrl;
+}
+
+export const applicationStateHandler: IActionHandler<IApplicationState> = (state = applicationStateInit, action) => {
+  if (action instanceof SetTitleAction) {
+    state = {
+      ...state,
+      title: action.title,
+      icon: action.icon,
+      appId: action.appId,
+    };
+  } else if (action instanceof AddErrorInfoAction) {
+    state = {
+      ...state,
+      errors: [
+        ...state.errors,
+        action.errorInfo,
+      ]
+    };
+  } else if (action instanceof RemoveErrorInfoAction) {
+    const index = state.errors.indexOf(action.errorInfo);
+    if (index > -1) {
+      state = {
+        ...state,
+        errors: [
+          ...state.errors.slice(0, index),
+          ...state.errors.slice(index + 1),
+        ]
+      };
+    }
+  } else if (action instanceof ClearErrorInfoAction) {
+    if (state.errors && state.errors.length) {
+      state = {
+        ...state,
+        errors: [],
+      };
+    }
+  } else if (action instanceof AddSnackbarNotification) {
+    state = {
+      ...state,
+      snackBars: [
+        ...state.snackBars,
+        action.notification,
+      ]
+    };
+  } else if (action instanceof RemoveSnackbarNotification) {
+    state = {
+      ...state,
+      snackBars: state.snackBars.filter(s => s.key !== action.key),
+    };
+  } else if (action instanceof MenuAction) {
+    state = {
+      ...state,
+      isMenuOpen: action.isOpen,
+    }
+  } else if (action instanceof MenuClosedByUser) {
+    state = {
+      ...state,
+      isMenuClosedByUser: action.isClosed,
+    }
+  }
+  else if (action instanceof SetWebsocketAction) {
+    state = {
+      ...state,
+      isWebsocketAvailable: action.isConnected,
+    }
+  } else if (action instanceof SetExternalLoginProviderAction){
+    state = {
+      ...state,
+      externalLoginProviders: action.externalLoginProvders,
+    }
+  }else if(action instanceof SetGeneralSettingsAction){
+
+    state = {
+      ...state,
+      settings:{tables: state.settings.tables, isInitialLoadDone:state.settings.isInitialLoadDone, general:{areNotificationsEnabled: action.areNoticationsActive}}
+    }
+  }
+  else if(action instanceof SetTableSettings){
+
+    let tableUpdate = state.settings.tables;
+    tableUpdate[action.tableName] = {columns: action.updatedColumns};
+
+    state = {...state, settings:{general: state.settings.general, isInitialLoadDone:state.settings.isInitialLoadDone, tables: tableUpdate}}
+    
+  }else if(action instanceof LoadSettingsAction){
+    
+    state = {...state, settings:action.settings}
+  }
+  else if(action instanceof SettingsDoneLoadingAction){
+    state= {...state, settings: {...state.settings, isInitialLoadDone: true}}
+  }
+
+  return state;
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/handlers/authenticationHandler.ts b/sdnr/wt-odlux/odlux/framework/src/handlers/authenticationHandler.ts
new file mode 100644
index 0000000..3a4891c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/handlers/authenticationHandler.ts
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+import { UpdatePolicies, UpdateUser } from '../actions/authentication';
+
+import { AuthPolicy, User } from '../models/authentication';
+
+import { onLogin, onLogout } from '../services/applicationApi';
+import { startWebsocketSession, endWebsocketSession } from '../services/notificationService';
+import { startUserSession, endUserSession } from '../services/userSessionService';
+import { getUserData } from '../services/userdataService';
+
+export interface IAuthenticationState {
+  user?: User;
+  policies?: AuthPolicy[];
+}
+
+const authenticationStateInit: IAuthenticationState = {
+  user: undefined
+};
+
+export const authenticationStateHandler: IActionHandler<IAuthenticationState> = (state = authenticationStateInit, action) => {
+  if (action instanceof UpdateUser) {
+    const {user} = action;
+    
+    if (user) {
+      onLogin();
+    } else {
+      onLogout();
+    }
+
+    state = {
+      ...state,
+      user,
+    };
+  } else if (action instanceof UpdatePolicies) {
+     state = {
+       ...state,
+       policies: action.authPolicies,
+     };
+  }
+  return state;
+};
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/handlers/navigationStateHandler.ts b/sdnr/wt-odlux/odlux/framework/src/handlers/navigationStateHandler.ts
new file mode 100644
index 0000000..6ecdf2f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/handlers/navigationStateHandler.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+import { LocationChanged } from '../actions/navigationActions';
+
+
+export interface INavigationState {
+  pathname: string;
+  search: string;
+  hash: string;
+}
+
+const navigationStateInit: INavigationState = {
+  pathname: '/',
+  search: '',
+  hash: '',
+};
+
+
+export const navigationStateHandler: IActionHandler<INavigationState> = (state = navigationStateInit, action) => {
+  if (action instanceof LocationChanged) { 
+    state = {
+      ...state,
+      pathname: action.pathname,
+      search: action.search,
+      hash: action.hash
+    }
+  }
+  return state;
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/index.dev.html b/sdnr/wt-odlux/odlux/framework/src/index.dev.html
new file mode 100644
index 0000000..69c5f06
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/index.dev.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>O D L UX</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script >
+    //  window._odluxExtraLinks = [
+    //    ["imprint","https://some-url-to-imprint"],
+    //    ["privacy declaration", "https://some-url-to-privacy-declaration"]
+    //  ]
+  </script>
+  <script>
+    // run the application
+    require(["app" ,"connectApp","faultApp"/*,"inventoryApp","helpApp"*/], function (app,connectApp,faultApp,/*inventoryApp,helpApp*/) {
+      connectApp.register();
+      faultApp.register();
+      // inventoryApp.register();
+      // helpApp.register();
+      app("./app.tsx").configureApplication({ authentication:"basic",  enablePolicy:  false, transportpceUrl:"http://test.de"});
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/index.html b/sdnr/wt-odlux/odlux/framework/src/index.html
new file mode 100644
index 0000000..7196b5c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>O D L UX</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+<script>
+    // run the application
+    require(["run"], function (run) {
+      run.configureApplication({ authentication:"basic",  enablePolicy:  false,});
+      run.runApplication();
+    });
+
+    // don't change anything in here!!
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/middleware/api.ts b/sdnr/wt-odlux/odlux/framework/src/middleware/api.ts
new file mode 100644
index 0000000..8e9bc64
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/middleware/api.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action, IActionHandler } from '../flux/action';
+import { MiddlewareArg } from '../flux/middleware';
+import { Dispatch } from '../flux/store';
+
+import { IApplicationStoreState } from '../store/applicationStore';
+import { AddErrorInfoAction, ErrorInfo } from '../actions/errorActions';
+
+const baseUrl = `${ window.location.origin }${ window.location.pathname }`;
+
+export class ApiAction<TResult, TSuccessAction extends Action & { result: TResult }> extends Action {
+  constructor(public endpoint: string, public successAction: { new(result: TResult): TSuccessAction }, public authenticate: boolean = false) {
+    super();
+  }
+}
+
+export const apiMiddleware = (store: MiddlewareArg<IApplicationStoreState>) => (next: Dispatch) => <A extends Action>(action: A) => {
+
+  // So the middleware doesn't get applied to every single action
+  if (action instanceof ApiAction) {
+    const user = store && store.getState().framework.authenticationState.user;
+    const token = user && user.token || null;
+    let config = { headers: {} };
+
+    if (action.authenticate) {
+      if (token) {
+        config = {
+          ...config,
+          headers: {
+            ...config.headers,
+            // 'Authorization': `Bearer ${ token }`
+            authorization: "Basic YWRtaW46YWRtaW4="
+          }
+        }
+      } else {
+        return next(new AddErrorInfoAction({ message: 'Please login to continue.' }));
+      }
+    }
+
+    fetch(baseUrl + action.endpoint.replace(/\/{2,}/, '/'), config)
+      .then(response =>
+        response.json().then(data => ({ data, response }))
+      )
+      .then(result => {
+        next(new action.successAction(result.data));
+      })
+      .catch((error: any) => {
+        next(new AddErrorInfoAction((error instanceof Error) ? { error: error } : { message: error.toString() }));
+      });
+  }
+
+  // let all actions pass
+  return next(action);
+}
+
+export default apiMiddleware;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/middleware/logger.ts b/sdnr/wt-odlux/odlux/framework/src/middleware/logger.ts
new file mode 100644
index 0000000..fb0874f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/middleware/logger.ts
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { Dispatch } from '../flux/store';
+import { MiddlewareApi } from '../store/applicationStore';
+
+const LogLevel = +(localStorage.getItem('log.odlux.framework.middleware.logger') || 0);
+
+function createLoggerMiddleware() {
+  return function logger({ getState }: MiddlewareApi) {
+    return (next: Dispatch): Dispatch => action => {
+      if (LogLevel > 2) console.log('will dispatch', action);
+      const returnValue = next(action);
+      if (LogLevel > 2) console.log('state after dispatch', getState());
+      return returnValue;
+    };
+  };
+}
+
+export const logger = createLoggerMiddleware();
+export default logger;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/middleware/navigation.ts b/sdnr/wt-odlux/odlux/framework/src/middleware/navigation.ts
new file mode 100644
index 0000000..14ff09f
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/middleware/navigation.ts
@@ -0,0 +1,96 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as jwt from 'jsonwebtoken';
+import { History, createHashHistory } from 'history';
+
+import { User } from '../models/authentication';
+
+import { LocationChanged, NavigateToApplication } from '../actions/navigationActions';
+import { PushAction, ReplaceAction, GoAction, GoBackAction, GoForwardeAction } from '../actions/navigationActions';
+
+import { applicationManager } from '../services/applicationManager';
+import { loginUserAction, logoutUser } from '../actions/authentication';
+
+import { ApplicationStore } from '../store/applicationStore';
+import { Dispatch } from '../flux/store';
+
+export const history = createHashHistory();
+let applicationStore: ApplicationStore | null = null;
+
+const routerMiddlewareCreator = (historyParam: History) => () => (next: Dispatch): Dispatch => (action) => {
+
+  if (action instanceof NavigateToApplication) {
+    const application = applicationManager.applications && applicationManager.applications[action.applicationName];
+    if (application) {
+      const href = `/${application.path || application.name}${action.href ? '/' + action.href : ''}`.replace(/\/{2,}/i, '/');
+      if (action.replace) {
+        historyParam.replace(href, action.state);
+      } else {
+        historyParam.push(href, action.state);
+      }
+    }
+  } else if (action instanceof PushAction) {
+    historyParam.push(action.href, action.state);
+  } else if (action instanceof ReplaceAction) {
+    historyParam.replace(action.href, action.state);
+  } else if (action instanceof GoAction) {
+    historyParam.go(action.index);
+  } else if (action instanceof GoBackAction) {
+    historyParam.goBack();
+  } else if (action instanceof GoForwardeAction) {
+    historyParam.goForward();
+  } else if (action instanceof LocationChanged) {
+    // ensure user is logged in and token is valid
+    if (action.pathname.startsWith('/oauth') && (action.search.startsWith('?token='))) {
+      const ind =  action.search.lastIndexOf('token=');
+      const tokenStr = ind > -1 ? action.search.substring(ind + 6) : null;
+      const token = tokenStr && jwt.decode(tokenStr);
+      if (tokenStr && token) {
+        // @ts-ignore
+        const user = new User({ username: token.name, access_token: tokenStr, token_type: 'Bearer', expires: token.exp, issued: token.iat }) || undefined;
+        applicationStore?.dispatch(loginUserAction(user));
+      }
+    } if (!action.pathname.startsWith('/login') && applicationStore && (!applicationStore.state.framework.authenticationState.user || !applicationStore.state.framework.authenticationState.user.isValid)) {
+      historyParam.replace(`/login?returnTo=${action.pathname}`);
+      applicationStore.dispatch(logoutUser());
+    
+    } else if (action.pathname.startsWith('/login') && applicationStore && (applicationStore.state.framework.authenticationState.user && applicationStore.state.framework.authenticationState.user.isValid)) {
+      historyParam.replace('/');
+    } else {
+      return next(action);
+    }
+  } else {
+    return next(action);
+  }
+  return action;
+};
+
+const startListener = (historyParam: History, store: ApplicationStore) => {
+  store.dispatch(new LocationChanged(historyParam.location.pathname, historyParam.location.search, historyParam.location.hash));
+  historyParam.listen((location) => {
+    store.dispatch(new LocationChanged(location.pathname, location.search, location.hash));
+  });
+};
+
+export const startHistoryListener = (store: ApplicationStore) => {
+  applicationStore = store;
+  startListener(history, store);
+};
+
+export const routerMiddleware = routerMiddlewareCreator(history);
+export default routerMiddleware;
diff --git a/sdnr/wt-odlux/odlux/framework/src/middleware/policies.ts b/sdnr/wt-odlux/odlux/framework/src/middleware/policies.ts
new file mode 100644
index 0000000..662ecdd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/middleware/policies.ts
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import authenticationService from '../services/authenticationService';
+
+import { UpdateUser, UpdatePolicies } from '../actions/authentication';
+import { Dispatch } from '../flux/store';
+import { MiddlewareApi } from '../store/applicationStore';
+
+function updatePoliciesMiddleware() {
+  return ({ dispatch, getState }: MiddlewareApi) =>
+    (next : Dispatch) : Dispatch =>
+      action => {
+        const { framework: { applicationState: { enablePolicy } } } = getState() || { framework: { applicationState: { } } };
+        if (enablePolicy && action instanceof UpdateUser) {
+          next(action);
+          authenticationService.getAccessPolicies().then((policies) => dispatch(new UpdatePolicies(policies||undefined)));
+          return action;
+        }
+        if (enablePolicy === false) next(new UpdatePolicies());
+        return next(action);
+      };
+}
+
+export const updatePolicies = updatePoliciesMiddleware();
+export default updatePolicies;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/middleware/thunk.ts b/sdnr/wt-odlux/odlux/framework/src/middleware/thunk.ts
new file mode 100644
index 0000000..18f40c4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/middleware/thunk.ts
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Dispatch } from '../flux/store';
+import { MiddlewareApi } from '../store/applicationStore';
+
+function createThunkMiddleware() {
+  return ({ dispatch, getState }: MiddlewareApi) =>
+    (next : Dispatch) : Dispatch =>
+      action => {
+        if (typeof action === 'function') {
+          return action(dispatch, getState);
+        }
+
+        return next(action);
+      };
+}
+
+export const thunk = createThunkMiddleware();
+export default thunk;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/applicationConfig.ts b/sdnr/wt-odlux/odlux/framework/src/models/applicationConfig.ts
new file mode 100644
index 0000000..0ae9c26
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/applicationConfig.ts
@@ -0,0 +1,5 @@
+export type ApplicationConfig = { 
+    authentication: "basic"|"oauth",  // basic 
+    enablePolicy: false,               // false 
+    transportpceUrl? : string
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/applicationInfo.ts b/sdnr/wt-odlux/odlux/framework/src/models/applicationInfo.ts
new file mode 100644
index 0000000..ff07b7d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/applicationInfo.ts
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { ComponentType } from 'react';
+import { IconType } from './iconDefinition';
+
+import { IActionHandler } from '../flux/action';
+import { Middleware } from '../flux/middleware';
+import { SettingsComponentProps } from './settings';
+
+/** Represents the information needed about an application to integrate. */
+export class ApplicationInfo {
+  /** The name of the application. */
+  name: string;
+  /** Optional: The title of the application, if null ot undefined the name will be used. */
+  title?: string;
+  /** Optional: The icon of the application for the navigation and title bar. */
+  icon?: IconType;
+  /** Optional: The description of the application. */
+  description?: string;
+  /** The root component of the application. */
+  rootComponent: ComponentType;
+  /** Optional: The root action handler of the application. */
+  rootActionHandler?: IActionHandler<{ [key: string]: any }>;
+  /** Optional: Application speciffic middlewares. */
+  middlewares?: Middleware<{ [key: string]: any }>[];
+  /** Optional: A mapping object with the exported components. */
+  exportedComponents?: { [key: string]: ComponentType }
+  /** Optional: The entry to be shown in the menu. If undefiened the name will be used. */
+  menuEntry?: string | React.ComponentType;
+  /** Optional: A component to be shown in the menu when this app is active below the main entry. If undefiened the name will be used. */
+  subMenuEntry?: React.ComponentType;
+  /** Optional: A component to be shown in the applications status bar. If undefiened the name will be used. */
+  statusBarElement?: React.ComponentType;
+  /** Optional: A component to be shown in the dashboardview. If undefiened the name will be used. */
+  dashbaordElement?: React.ComponentType;
+  /** Optional: A component shown in the settings view */
+  settingsElement?: React.ComponentType<SettingsComponentProps>;
+  /** Optional: The pasth for this application. If undefined the name will be use as path. */
+  path?: string;
+}
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/authentication.ts b/sdnr/wt-odlux/odlux/framework/src/models/authentication.ts
new file mode 100644
index 0000000..f565381
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/authentication.ts
@@ -0,0 +1,94 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type AuthToken = {
+  username: string;
+  access_token: string;
+  token_type: string;
+  /***
+   * datetime the token should expire in unix timestamp 
+   * 
+   * must be in seconds
+   */
+  expires: number;
+  /***
+   * time the token was issued in unix timestamp
+   * 
+   * must be in seconds
+   * 
+   */
+  issued: number;
+}
+
+export type AuthPolicy = {
+  path: string;
+  methods: {
+    get?: boolean;
+    post?: boolean;
+    put?: boolean;
+    patch?: boolean;
+    delete?: boolean;
+  }
+}
+
+export class User {
+
+  constructor (private _bearerToken: AuthToken) {
+
+  }
+
+  public get user(): string | null {
+    return this._bearerToken && this._bearerToken.username;
+  };
+
+  public get token(): string | null {
+    return this._bearerToken && this._bearerToken.access_token;
+  }
+
+  public get tokenType(): string | null {
+    return this._bearerToken && this._bearerToken.token_type;
+  }
+
+  /***
+   * Time the user should be logged out, in unix timestamp in seconds
+   */
+  public get logoutAt(): number{
+    return this._bearerToken && this._bearerToken.expires;
+  }
+
+   /***
+   * Time the user logged in, in unix timestamp in seconds
+   */
+  public get loginAt(): number{
+    return this._bearerToken && this._bearerToken.issued;
+  }
+
+  public get isValid(): boolean {
+    return (this._bearerToken && (new Date().valueOf()) < this._bearerToken.expires*1000) || false;
+  }
+
+  public toString() {
+    return JSON.stringify(this._bearerToken);
+  }
+
+  public static fromString(data: string) {
+    return new User(JSON.parse(data));
+  }
+
+
+}
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/elasticSearch.ts b/sdnr/wt-odlux/odlux/framework/src/models/elasticSearch.ts
new file mode 100644
index 0000000..fc43836
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/elasticSearch.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type Result<TSource extends {}> = {
+  "data-provider:output": {
+    pagination?: {
+      size: number;
+      page: number;
+      total: number;
+    },
+    data: TSource[];
+  }
+}
+
+export type SingeResult<TSource extends {}> = {
+  "data-provider:output": TSource;
+}
+
+
+export type ResultTopology<TSource extends {}> = {
+  "output": {
+    pagination?: {
+      size: number;
+      page: number;
+      total: number;
+    },
+    data: TSource[];
+  }
+}
+
+export type HitEntry<TSource extends {}> = {
+  _index: string;
+  _type: string;
+  _id: string;
+  _score: number;
+  _source: TSource;
+}
+
+type ActionResponse ={
+  _index: string;
+  _type: string;
+  _id: string;
+  _shards: {
+    total: number,
+    successful: number,
+    failed: number
+    },
+
+}
+
+export type PostResponse = ActionResponse & {
+  created: boolean
+}
+
+export type DeleteResponse = ActionResponse & {
+  found: boolean
+}
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/errorInfo.ts b/sdnr/wt-odlux/odlux/framework/src/models/errorInfo.ts
new file mode 100644
index 0000000..21217a1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/errorInfo.ts
@@ -0,0 +1,29 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export type ErrorInfo = {
+  title?: string,
+  error?: Error | null,
+  url?: string,
+  line?: number,
+  col?: number,
+  info?: {
+    extra?: string,
+    componentStack?: string
+  },
+  message?: string
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/externalLoginProvider.ts b/sdnr/wt-odlux/odlux/framework/src/models/externalLoginProvider.ts
new file mode 100644
index 0000000..357feed
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/externalLoginProvider.ts
@@ -0,0 +1,23 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type ExternalLoginProvider = {
+    id: string;
+    title: string;
+    loginUrl: string;
+  }
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/iconDefinition.ts b/sdnr/wt-odlux/odlux/framework/src/models/iconDefinition.ts
new file mode 100644
index 0000000..ff50aa7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/iconDefinition.ts
@@ -0,0 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IconDefinition } from '@fortawesome/free-solid-svg-icons';
+
+export type IconType = IconDefinition | string;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/index.ts b/sdnr/wt-odlux/odlux/framework/src/models/index.ts
new file mode 100644
index 0000000..4b8dc20
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/index.ts
@@ -0,0 +1,18 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export * from './elasticSearch'; 
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/restService.ts b/sdnr/wt-odlux/odlux/framework/src/models/restService.ts
new file mode 100644
index 0000000..03f580b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/restService.ts
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+  * The PlainObject type is a JavaScript object containing zero or more key-value pairs.
+  */
+export interface PlainObject<T = any> {
+  [key: string]: T;
+}
+
+export interface AjaxParameter {
+  /**
+    * The HTTP method to use for the request (e.g. "POST", "GET", "PUT").
+    */
+  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH';
+  /**
+    * An object of additional header key/value pairs to send along with requests using the XMLHttpRequest
+    * transport. The header X-Requested-With: XMLHttpRequest is always added, but its default
+    * XMLHttpRequest value can be changed here. Values in the headers setting can also be overwritten from
+    * within the beforeSend function.
+    */
+  headers?: PlainObject<string | null | undefined>;
+  /**
+    * Data to be sent to the server. It is converted to a query string, if not already a string. It's
+    * appended to the url for GET-requests. See processData option to prevent this automatic processing.
+    * Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same
+    * key based on the value of the traditional setting (described below).
+    */
+  data?: PlainObject | string;
+}
+
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/settings.ts b/sdnr/wt-odlux/odlux/framework/src/models/settings.ts
new file mode 100644
index 0000000..1752d6a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/settings.ts
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type TableSettingsColumn = {
+  property: string;
+  displayed: boolean;
+};
+
+export type TableSettings = {
+  tables:{
+    [key: string]: {
+      columns: TableSettingsColumn[];
+            
+      //match prop names, hide them
+      //via property name! -> only those which are hidden!
+      //all others default false, oh yeah
+      //or maybe the other way around, gotta think about that
+    
+    };
+  };
+};
+
+export type GeneralSettings = {
+  general:{
+    areNotificationsEnabled: boolean | null;
+  };
+};
+
+export type Settings = TableSettings & GeneralSettings;
+
+export type SettingsComponentProps = {
+  onClose(): void;
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/models/snackbarItem.ts b/sdnr/wt-odlux/odlux/framework/src/models/snackbarItem.ts
new file mode 100644
index 0000000..c10d7ef
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/models/snackbarItem.ts
@@ -0,0 +1,20 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { OptionsObject } from "notistack";
+
+export type SnackbarItem = { key: number, message: string, options?: OptionsObject };
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/run.ts b/sdnr/wt-odlux/odlux/framework/src/run.ts
new file mode 100644
index 0000000..991b749
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/run.ts
@@ -0,0 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { configureApplication } from './handlers/applicationStateHandler';
+export { runApplication } from './app'; 
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts b/sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts
new file mode 100644
index 0000000..faa9984
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/applicationApi.ts
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Event } from '../common/event';
+import { ApplicationStore } from '../store/applicationStore';
+import { AuthMessage, sendMessage } from './broadcastService';
+
+let resolveApplicationStoreInitialized: (store: ApplicationStore) => void;
+let applicationStore: ApplicationStore | null = null;
+const applicationStoreInitialized: Promise<ApplicationStore> = new Promise((resolve) => resolveApplicationStoreInitialized = resolve);
+
+const loginEvent = new Event();
+const logoutEvent = new Event();
+
+const authChannelName = 'odlux_auth';
+
+export const onLogin = () => {
+
+  const message : AuthMessage = { key: 'login', data: {} };
+  sendMessage(message, authChannelName);
+  loginEvent.invoke();
+
+};
+
+export const onLogout = () => {
+  
+  document.cookie = 'JSESSIONID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
+
+  const message : AuthMessage = { key: 'logout', data: {} };
+  sendMessage(message, authChannelName);
+  logoutEvent.invoke();
+};
+
+export const setApplicationStore = (store: ApplicationStore) => {
+  if (!applicationStore && store) {
+    applicationStore = store;
+    resolveApplicationStoreInitialized(store);
+  }
+};
+
+export const applicationApi = {
+  get applicationStore(): ApplicationStore | null {
+    return applicationStore;
+  },
+
+  get applicationStoreInitialized(): Promise<ApplicationStore> {
+    return applicationStoreInitialized;
+  },
+
+  get loginEvent() {
+    return loginEvent;
+  },
+
+  get logoutEvent() {
+    return logoutEvent;
+  },
+};
+
+export default applicationApi;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts b/sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts
new file mode 100644
index 0000000..bd620a0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/applicationManager.ts
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { ApplicationInfo } from '../models/applicationInfo';
+import { Event } from '../common/event';
+
+import { applicationApi } from './applicationApi';
+
+/** Represents registry to manage all applications. */
+class ApplicationManager {
+    
+  /** Stores all registered applications.  */
+  private _applications: { [key: string]: ApplicationInfo }; 
+  
+  /** Initializes a new instance of this class. */
+  constructor() {
+    this._applications = {};
+    this.changed = new Event<void>(); 
+  }
+
+  /** The changed event will fire if the registration has changed. */
+  public changed: Event<void>;
+
+  /** Registers a new application. */
+  public registerApplication(applicationInfo: ApplicationInfo) {
+    this._applications[applicationInfo.name] = applicationInfo;
+    this.changed.invoke();
+    return applicationApi;
+  }
+
+  /** Gets all registered applications. */
+  public get applications() {
+    return this._applications;
+  }
+}
+
+/** A singleton instance of the application manager. */
+export const applicationManager = new ApplicationManager();
+export default applicationManager;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts b/sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts
new file mode 100644
index 0000000..b9c1a5a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/authenticationService.ts
@@ -0,0 +1,96 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { AuthPolicy, AuthToken } from "../models/authentication";
+import { ExternalLoginProvider } from "../models/externalLoginProvider";
+
+import { requestRest, formEncode, requestRestExt } from "./restService";
+
+type AuthTokenResponse = {
+  access_token: string;
+  token_type: string;
+  expires_at: number;
+  issued_at: number;
+}
+
+class AuthenticationService {
+  public async getAvaliableExteralProvider() {
+    const result = await requestRest<ExternalLoginProvider[]>(`oauth/providers`, {
+      method: "GET",
+      headers: {
+        'Content-Type': 'application/x-www-form-urlencoded'
+      },
+    }, false);
+    return result;
+  }
+
+  public async authenticateUserOAuth(email: string, password: string, scope: string): Promise<AuthToken | null> {
+    const result = await requestRest<AuthTokenResponse>(`oauth/login`, {
+      method: "POST",
+      headers: {
+        'Content-Type': 'application/x-www-form-urlencoded'
+      },
+      body: formEncode({
+        grant_type: "password",
+        username: email,
+        password: password,
+        scope: scope
+      })
+    }, false);
+
+   
+    return result && {
+      username: email,
+      access_token: result.access_token,
+      token_type: result.token_type,
+      expires: result.expires_at,
+      issued: result.issued_at
+    } || null;
+  }
+
+   public async authenticateUserBasicAuth(email: string, password: string, scope: string): Promise<AuthToken | null> {
+    const result = await requestRest<string>(`rests/data/network-topology:network-topology/topology=topology-netconf?fields=node(node-id)`, {
+      method: "GET",
+      headers: {
+        'Authorization':  "Basic " + btoa(email + ":" + password)
+      },
+    }, false);
+
+    if (result) {
+      return {
+          username: email,
+          access_token:  btoa(email + ":" + password),
+          token_type: "Basic",
+          expires: (new Date()).valueOf() / 1000 + 86400, // 1 day
+          issued: (new Date()).valueOf() / 1000
+      }
+    }
+    return null;
+  }
+
+  public async getAccessPolicies(){
+    return await requestRest<AuthPolicy[]>(`oauth/policies`, { method: "GET" }, true);
+  }
+
+  public async getServerReadyState(){
+    const result = await requestRestExt(`/ready`, { method: "GET" }, false);
+    return result.status == (200 || 304) ? true : false;
+  }
+}
+
+export const authenticationService = new AuthenticationService();
+export default authenticationService;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts b/sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts
new file mode 100644
index 0000000..202bf55
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/broadcastService.ts
@@ -0,0 +1,115 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { setGeneralSettingsAction } from '../actions/settingsAction';
+import { loginUserAction, logoutUser } from '../actions/authentication';
+import { ReplaceAction } from '../actions/navigationActions';
+import { User } from '../models/authentication';
+import { ApplicationStore } from '../store/applicationStore';
+
+type Broadcaster = {
+  channel: BroadcastChannel;
+  key: String;
+};
+
+type AuthTypes = 'login' | 'logout';
+export type AuthMessage = {
+  key: AuthTypes;
+  data: any;
+};
+
+type SettingsType = 'general';
+export type SettingsMessage = {
+  key: SettingsType;
+  enableNotifications: boolean;
+  user: string;
+};
+
+const channels: Broadcaster[] = [];
+let store: ApplicationStore | null = null;
+
+export const saveChannel = (channel: BroadcastChannel, channelName: string) => {
+  channels.push({ channel: channel, key: channelName });
+};
+
+const createSettingsBroadcastChannel = () => {
+
+  const name = 'odlux_settings';
+  const bc: BroadcastChannel = new BroadcastChannel(name);
+  channels.push({ channel: bc, key: name });
+
+  bc.onmessage = (eventMessage: MessageEvent<SettingsMessage>) => {
+    console.log(eventMessage);
+
+    if (eventMessage.data.key === 'general') {
+
+      if (store?.state.framework.authenticationState.user) {
+        const data = eventMessage.data;
+        if (store.state.framework.authenticationState.user.user === data.user) {
+          store?.dispatch(setGeneralSettingsAction(data.enableNotifications));
+        }
+      }
+    }
+  };
+};
+
+const createAuthBroadcastChannel = () => {
+  const name = 'odlux_auth';
+  const bc: BroadcastChannel = new BroadcastChannel(name);
+  channels.push({ channel: bc, key: name });
+
+  bc.onmessage = (eventMessage: MessageEvent<AuthMessage>) => {
+    console.log(eventMessage);
+
+    if (eventMessage.data.key === 'login') {
+      if (!store?.state.framework.authenticationState.user) {
+        const initialToken = localStorage.getItem('userToken');
+        if (initialToken) {
+          store?.dispatch(loginUserAction(User.fromString(initialToken)));
+          store?.dispatch(new ReplaceAction('/'));
+        }
+      }
+    } else if (eventMessage.data.key === 'logout') {
+
+      if (store?.state.framework.authenticationState.user) {
+        store?.dispatch(logoutUser());
+        store?.dispatch(new ReplaceAction('/login'));
+      }
+    }
+  };
+};
+
+export const startBroadcastChannel = (applicationStore: ApplicationStore) => {
+  store = applicationStore;
+
+  // might decide to use one general broadcast channel with more keys in the future
+  createAuthBroadcastChannel();
+  createSettingsBroadcastChannel();
+};
+
+export const getBroadcastChannel = (channelName: string) => {
+  const foundChannel = channels.find(s => s.key === channelName);
+  return foundChannel?.channel;
+};
+
+export const sendMessage = (data: any, channel: string) => {
+  const foundChannel = channels.find(s => s.key === channel);
+  if (foundChannel) {
+    foundChannel.channel.postMessage(data);
+  }
+};
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/index.ts b/sdnr/wt-odlux/odlux/framework/src/services/index.ts
new file mode 100644
index 0000000..2f64ba0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/index.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+export { applicationManager } from './applicationManager';
+export { subscribe, unsubscribe } from './notificationService';
+export { requestRest } from './restService';
+export { saveUserData as saveUserdata, getUserData as getUserdata } from './userdataService';
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts b/sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts
new file mode 100644
index 0000000..b2880b9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/notificationService.ts
@@ -0,0 +1,220 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { ApplicationStore } from '../store/applicationStore';
+import { SetWebsocketAction } from '../actions/websocketAction';
+
+const socketUrl = [location.protocol === 'https:' ? 'wss://' : 'ws://', location.hostname, ':', location.port, '/websocket'].join('');
+const subscriptions: { [scope: string]: SubscriptionCallback[] } = {};
+let socketReady: Promise<WebSocket>;
+let wasWebsocketConnectionEstablished: undefined | boolean;
+let applicationStore: ApplicationStore | null;
+
+let areWebsocketsStoppedViaSettings = false;
+
+
+export interface IFormatedMessage {
+    "event-time": string,
+    "data": {
+        "counter": number,
+        "attribute-name": string,
+        "time-stamp": string,
+        "object-id-ref": string,
+        "new-value": string
+    },
+    "node-id": string,
+    "type": {
+        "namespace": string,
+        "revision": string,
+        "type": string
+    }
+}
+
+export type SubscriptionCallback<TMessage extends IFormatedMessage = IFormatedMessage> = (msg: TMessage) => void;
+
+function setCurrentSubscriptions(notificationSocket: WebSocket) {
+  const scopesToSubscribe = Object.keys(subscriptions);
+  if (notificationSocket.readyState === notificationSocket.OPEN) {
+    const data = {
+      'data': 'scopes',
+      'scopes':[{
+        "schema":{
+            "namespace":"urn:opendaylight:params:xml:ns:yang:devicemanager",
+            "revision":"*",
+            "notification": scopesToSubscribe 
+         }
+      }]
+    };
+    notificationSocket.send(JSON.stringify(data));
+    return true;
+  };
+  return false;
+}
+
+function addScope<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>) {
+  const scopes = scope instanceof Array ? scope : [scope];
+
+    // send all new scopes to subscribe
+    const newScopesToSubscribe: string[] = scopes.reduce((acc: string[], cur: string) => {
+      const currentCallbacks = subscriptions[cur];
+      if (currentCallbacks) {
+        if (!currentCallbacks.some(c => c === callback)) {
+          currentCallbacks.push(callback);
+        }
+      } else {
+        subscriptions[cur] = [callback];
+        acc.push(cur);
+      }
+      return acc;
+    }, []);
+
+    if (newScopesToSubscribe.length === 0) {
+      return true;
+    }
+    return false;
+}
+
+function removeScope<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>) {
+  const scopes = scope instanceof Array ? scope : [scope];
+  scopes.forEach(s => {
+    const callbacks = subscriptions[s];
+    const index = callbacks && callbacks.indexOf(callback);
+    if (index > -1) {
+      callbacks.splice(index, 1);
+    }
+    if (callbacks.length === 0) {
+      subscriptions[s] === undefined;
+    }
+  });
+}
+
+export function subscribe<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>): Promise<boolean> {
+  addScope(scope, callback)
+  return socketReady && socketReady.then((notificationSocket) => {
+    // send a subscription to all active scopes
+    return setCurrentSubscriptions(notificationSocket);
+  }) || true;
+}
+
+export function unsubscribe<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>): Promise<boolean> {
+  removeScope(scope, callback);
+  return socketReady && socketReady.then((notificationSocket) => {
+    // send a subscription to all active scopes
+    return setCurrentSubscriptions(notificationSocket);
+  }) || true;
+}
+
+export const startNotificationService = (store: ApplicationStore) => {
+  applicationStore = store;
+}
+
+const connect = (): Promise<WebSocket> => {
+  return new Promise((resolve, reject) => {
+    const notificationSocket = new WebSocket(socketUrl);
+
+    notificationSocket.onmessage = (event: MessageEvent<string>) => {
+      // process received event
+      
+        if (event.data && typeof event.data === "string" ) {
+          const msg = JSON.parse(event.data) as IFormatedMessage;
+          const callbacks = msg?.type?.type && subscriptions[msg.type.type];
+          if (callbacks) {
+            callbacks.forEach(cb => {
+              // ensure all callbacks will be called
+              try {
+                return cb(msg);
+              } catch (reason) {
+                console.error(reason);
+              }
+            });
+          }
+        }
+       
+    };
+
+    notificationSocket.onerror = function (error) {
+      console.log("Socket error:");
+      console.log(error);
+      reject("Socket error: " + error);
+      if (applicationStore) {
+        applicationStore.dispatch(new SetWebsocketAction(false));
+      }
+    };
+
+    notificationSocket.onopen = function (event) {
+      if (applicationStore) {
+        applicationStore.dispatch(new SetWebsocketAction(true));
+      }
+      console.log("Socket connection opened.");
+      resolve(notificationSocket);
+
+      // send a subscription to all active scopes
+      setCurrentSubscriptions(notificationSocket);
+    };
+
+    notificationSocket.onclose = function (event) {
+      console.log("socket connection closed");
+      dispatchSocketClose();
+
+      const isUserLoggedIn = applicationStore?.state.framework.authenticationState.user && applicationStore?.state.framework.authenticationState.user?.isValid;
+
+      if (isUserLoggedIn && !areWebsocketsStoppedViaSettings) {
+        socketReady = connect();
+      }
+    };
+  });
+}
+
+
+export const startWebsocketSession = () => {
+  socketReady = connect();
+  areWebsocketsStoppedViaSettings = false;
+}
+
+export const suspendWebsocketSession = () =>{
+  areWebsocketsStoppedViaSettings = true;
+  closeSocket();
+}
+
+export const endWebsocketSession = () => {
+  closeSocket();
+}
+
+const closeSocket = () =>{
+  
+  if (socketReady) {
+    socketReady.then(websocket => {
+      websocket.close();
+    });
+  }else{
+    dispatchSocketClose();
+  }
+}
+
+const dispatchSocketClose = () =>{
+  const isUserLoggedIn = applicationStore?.state.framework.authenticationState.user && applicationStore?.state.framework.authenticationState.user?.isValid;
+
+  if(isUserLoggedIn){
+    applicationStore?.dispatch(new SetWebsocketAction(false));
+  }else{
+    applicationStore?.dispatch(new SetWebsocketAction(null));
+  }
+}
+
+
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts b/sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts
new file mode 100644
index 0000000..5ed4d7b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/restAccessorService.ts
@@ -0,0 +1,93 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as $ from 'jquery'; 
+import { Action, IActionHandler } from '../flux/action';
+import { MiddlewareArg } from '../flux/middleware';
+import { Dispatch } from '../flux/store';
+
+import { IApplicationStoreState } from '../store/applicationStore';
+import { AddErrorInfoAction, ErrorInfo } from '../actions/errorActions';
+import { PlainObject, AjaxParameter } from 'models/restService';
+
+export const absoluteUri = /^(https?:\/\/|blob:)/i;
+export const baseUrl = `${ window.location.origin }${ window.location.pathname }`;
+
+class RestBaseAction extends Action { }
+
+export const createRestApiAccessor = <TResult extends PlainObject>(urlOrPath: string, initialValue: TResult) => {
+  const isLocalRequest = !absoluteUri.test(urlOrPath);
+  const uri = isLocalRequest ? `${ baseUrl }/${ urlOrPath }`.replace(/\/{2,}/, '/') : urlOrPath ;
+ 
+  class RestRequestAction extends RestBaseAction { constructor(public settings?: AjaxParameter) { super(); } }
+
+  class RestResponseAction extends RestBaseAction { constructor(public result: TResult) { super(); } }
+
+  class RestErrorAction extends RestBaseAction { constructor(public error?: Error | string) { super(); } }
+  
+  type RestAction = RestRequestAction | RestResponseAction | RestErrorAction;
+
+  /** Represents our middleware to handle rest backend requests */
+  const restMiddleware = (api: MiddlewareArg<IApplicationStoreState>) =>
+    (next: Dispatch) => (action: RestAction): RestAction => {
+      
+      // pass all actions through by default
+      next(action);
+      // handle the RestRequestAction
+      if (action instanceof RestRequestAction) {
+        const state = api.getState();
+        const authHeader = isLocalRequest && state && state.framework.authenticationState.user && state.framework.authenticationState.user.token
+          ? { "Authentication": "Bearer " + state.framework.authenticationState.user.token } : { };
+        $.ajax({
+          url: uri,
+          method: (action.settings && action.settings.method) || "GET",
+          headers: { ...authHeader, ...(action.settings && action.settings.headers ? action.settings.headers : { }) },
+        }).then((data: TResult) => {
+           next(new RestResponseAction(data));
+        }).catch((err: any) => {
+          next(new RestErrorAction());
+          next(new AddErrorInfoAction((err instanceof Error) ? { error: err } : { message: err.toString() }));
+        });
+      }
+      // allways return action
+      return action;
+  };
+  
+  /** Represents our action handler to handle our actions */
+  const restActionHandler: IActionHandler<TResult> = (state = initialValue, action) => {
+    if (action instanceof RestRequestAction) {
+      return {
+        ...(state as any),
+        busy: true
+      };
+    } else if (action instanceof RestResponseAction) {
+      return action.result;
+    } else if (action instanceof RestErrorAction) {
+      return initialValue;
+    }
+    return state;
+  };
+
+  return {
+    requestAction: RestRequestAction,
+    actionHandler: restActionHandler,
+    middleware: restMiddleware,
+  };
+}
+
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/restService.ts b/sdnr/wt-odlux/odlux/framework/src/services/restService.ts
new file mode 100644
index 0000000..0be3dca
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/restService.ts
@@ -0,0 +1,168 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ReplaceAction } from '../actions/navigationActions';
+import { AddErrorInfoAction } from '../actions/errorActions';
+
+import { storeService } from './storeService';
+
+const baseUri = `${ window.location.origin }`;
+const absUrlPattern = /^https?:\/\//;
+
+export const formEncode = (params: { [key: string]: string | number }) => Object.keys(params).map((key) => {
+  return encodeURIComponent(key) + '=' + encodeURIComponent(params[key].toString());
+}).join('&');
+
+const wildcardToRegexp = (pattern: string) =>  {
+  return new RegExp('^' + pattern.split(/\*\*/).map((p) => p.split(/\*+/).map((i) => i.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')).join('^[/]')).join('.*') + '$');
+};
+
+export const getAccessPolicyByUrl = (url: string) => {
+  const result = {
+    GET : false,
+    POST: false,
+    PUT: false,
+    PATCH: false,
+    DELETE: false,
+  };
+  
+  if (!storeService.applicationStore) return result;
+
+  const { state: { framework: { applicationState: { enablePolicy }, authenticationState: { policies } } } } = storeService.applicationStore!;
+  
+  result.GET = true;
+  result.POST = true;
+  result.PUT = true;
+  result.PATCH = true;
+  result.DELETE = true; 
+
+  if (!enablePolicy || !policies || policies.length === 0) return result;
+
+  policies.forEach(p => {
+    const re = wildcardToRegexp(p.path);
+    if (re.test(url)) {
+      result.GET = p.methods.get != null ? p.methods.get : result.GET ;
+      result.POST = p.methods.post != null ? p.methods.post : result.POST ;
+      result.PUT = p.methods.put != null ? p.methods.put : result.PUT ;
+      result.PATCH = p.methods.patch != null ? p.methods.patch : result.PATCH ;
+      result.DELETE = p.methods.delete != null ? p.methods.delete : result.DELETE ;
+    }
+  }); 
+
+  return result;
+
+};
+
+/** Sends a rest request to the given path and reports the server state. 
+ *  @returns An object with the server state, a message and the data or undefined in case of a json parse error.
+ */
+export async function requestRestExt<TData>(path: string = '', initParam: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<{ status: number; message?: string; data: TData | null | undefined }> {
+  const result: { status: number; message?: string; data: TData | null } = {
+    status: -1,
+    data: null,
+  };
+  const isAbsUrl = absUrlPattern.test(path);
+  const uri = isAbsUrl ? path : isResource ? path.replace(/\/{2,}/i, '/') : (baseUri) + ('/' + path).replace(/\/{2,}/i, '/');
+  const init = {
+    'method': 'GET',
+    ...initParam,
+    headers: {
+      'Content-Type': 'application/json',
+      'Accept': 'application/json',
+      ...initParam.headers,
+    } as HeadersInit,
+  };
+  if (!isAbsUrl && authenticate && storeService.applicationStore) {
+    const { state: { framework: { authenticationState: { user } } } } = storeService.applicationStore;
+    // do not request if the user is not valid
+
+    if (!user || !user.isValid || !user.token || !user.tokenType)  {
+      return {
+        ...result,
+        message: 'User is not valid or not logged in.',
+      };
+    }
+    (init.headers = {
+      ...init.headers,
+      'Authorization': `${user.tokenType} ${user.token}`,
+      //'Authorization': 'Basic YWRtaW46YWRtaW4='
+    });
+  }
+
+  const fetchResult = await fetch(uri, init);
+  if (fetchResult.status === 309) {
+    const redirectUrl = fetchResult.headers.get('Location');
+    if (! redirectUrl) {
+      throw new Error('Status code 309 requires header "Location"');
+    }
+    localStorage.removeItem('userToken');
+    window.location.href = redirectUrl;
+    return {
+      ...result,
+      status: fetchResult.status,
+      message: 'Redirecting to new URL.',
+    };
+  } else if (fetchResult.status === 403) {
+    if (storeService.applicationStore) {
+      storeService.applicationStore.dispatch(new AddErrorInfoAction({ title: 'Forbidden', message:'Status: [403], access denied.' }));
+    }
+    return {
+      ...result,
+      status: 403,
+      message: 'Forbidden.',
+    };
+  } else if (fetchResult.status === 401) {
+    if (storeService.applicationStore) {
+      storeService.applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${storeService.applicationStore.state.framework.navigationState.pathname}`));
+    }
+    return {
+      ...result,
+      status: 401,
+      message: 'Authentication requested by server.',
+    };
+  }
+  const contentType = fetchResult.headers.get('Content-Type') || fetchResult.headers.get('content-type');
+  const isJson = contentType && (contentType.toLowerCase().startsWith('application/json') || contentType.toLowerCase().startsWith('application/yang-data+json'));
+  try {
+    const data = (isJson ? await fetchResult.json() : await fetchResult.text()) as TData;
+    return {
+      ...result,
+      status: fetchResult.status,
+      message: fetchResult.statusText,
+      data: data,
+    };
+  } catch (error) {
+    return {
+      ...result,
+      status: fetchResult.status,
+      message: error && error.message || String(error),
+      data: undefined,
+    };
+  }
+}
+
+/** Sends a rest request to the given path. 
+ * @returns The data, or null it there was any error
+ */
+export async function requestRest<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<TData | null | undefined> {
+  const res = await requestRestExt<TData>(path, init, authenticate, isResource);
+  if (res && res.status >= 200 && res.status < 300) {
+    return res.data;
+  }
+  return null;
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/snackbarService.ts b/sdnr/wt-odlux/odlux/framework/src/services/snackbarService.ts
new file mode 100644
index 0000000..50e279c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/snackbarService.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import { OptionsObject } from "notistack";
+
+export const snackbarService = {
+  enqueueSnackbar: (message: string, options?: OptionsObject) =>{ }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/storeService.ts b/sdnr/wt-odlux/odlux/framework/src/services/storeService.ts
new file mode 100644
index 0000000..cbb5987
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/storeService.ts
@@ -0,0 +1,11 @@
+import { ApplicationStore } from "../store/applicationStore";
+
+let applicationStore: ApplicationStore | null = null;
+
+export const startSoreService = (store: ApplicationStore) => {
+  applicationStore = store;
+};
+
+export const storeService = { 
+  get applicationStore() { return applicationStore; },
+ };
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts b/sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts
new file mode 100644
index 0000000..8d899c4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/userSessionService.ts
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ApplicationStore } from "../store/applicationStore";
+import { logoutUser } from "../actions/authentication";
+import { ReplaceAction } from "../actions/navigationActions";
+import { AuthMessage, getBroadcastChannel } from "./broadcastService";
+import { User } from "../models/authentication";
+
+let currentUser: User | null;
+let applicationStore: ApplicationStore | null = null;
+let timer : null | ReturnType<typeof setTimeout> = null;
+
+export const startUserSessionService = (store: ApplicationStore) =>{
+    applicationStore=store;
+}
+
+export const startUserSession = (user: User) => {
+    console.log("user session started...")
+
+    const currentTime = new Date();
+    //get time differnce between login time and now (eg after user refreshes page)
+    const timeDiffernce =(currentTime.valueOf()/1000 - user.loginAt);
+
+    currentUser = user;
+
+    if (process.env.NODE_ENV === "development") {
+        //console.warn("logout timer not started in development mode");
+
+        const expiresIn = (user.logoutAt - user.loginAt) - timeDiffernce;
+        console.log("user should be logged out in: "+expiresIn/60 +"minutes")
+        createForceLogoutInterval(expiresIn);
+    } else {
+        const expiresIn = (user.logoutAt - user.loginAt) - timeDiffernce;
+        console.log("user should be logged out in: "+expiresIn/60 +"minutes")
+        createForceLogoutInterval(expiresIn);
+    }
+};
+
+const createForceLogoutInterval = (intervalInSec: number) => {
+    console.log("logout timer running...");
+
+    if(timer!==null){
+        console.error("an old session was available");
+        clearTimeout(timer);
+    }
+   
+    timer = setTimeout(function () {
+        if (currentUser && applicationStore) {
+
+            applicationStore.dispatch(logoutUser());
+            applicationStore.dispatch(new ReplaceAction("/login"));
+
+        }
+
+    }, intervalInSec * 1000)
+}
+
+export const endUserSession = ()=>{
+
+    if(timer!==null){
+        clearTimeout(timer);
+        timer=null;
+    }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts b/sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts
new file mode 100644
index 0000000..53de8e1
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/services/userdataService.ts
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { requestRest } from './restService';
+
+const settingsPath = '/userdata';
+
+export const getUserData = <TData>(partialPath?: string) => requestRest<TData>(partialPath ? settingsPath + partialPath : settingsPath, { method: 'GET' });
+
+export const saveUserData = <TData>(partialPath: string, data: string) =>  requestRest<TData>(settingsPath + partialPath, { method: 'PUT', body: data });
+
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/store/applicationStore.ts b/sdnr/wt-odlux/odlux/framework/src/store/applicationStore.ts
new file mode 100644
index 0000000..cbe8c20
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/store/applicationStore.ts
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Store } from '../flux/store';
+import { combineActionHandler, MiddlewareArg, Middleware, chainMiddleware } from '../flux/middleware';
+
+import applicationService from '../services/applicationManager';
+
+import { applicationRegistryHandler, IApplicationRegistration } from '../handlers/applicationRegistryHandler';
+import { authenticationStateHandler, IAuthenticationState } from '../handlers/authenticationHandler';
+import { applicationStateHandler, IApplicationState } from '../handlers/applicationStateHandler';
+import { navigationStateHandler, INavigationState } from '../handlers/navigationStateHandler';
+
+import { setApplicationStore } from '../services/applicationApi';
+
+import apiMiddleware from '../middleware/api';
+import thunkMiddleware from '../middleware/thunk';
+import loggerMiddleware from '../middleware/logger';
+import routerMiddleware from '../middleware/navigation';
+import { updatePolicies } from '../middleware/policies';
+
+export type MiddlewareApi = MiddlewareArg<IApplicationStoreState>;
+
+export interface IFrameworkStoreState {
+  applicationRegistration: IApplicationRegistration;
+  applicationState: IApplicationState;
+  authenticationState: IAuthenticationState;
+  navigationState: INavigationState;
+}
+
+export interface IApplicationStoreState {
+  framework: IFrameworkStoreState;
+}
+
+const frameworkHandlers = combineActionHandler({
+  applicationRegistration: applicationRegistryHandler,
+  applicationState: applicationStateHandler,
+  authenticationState: authenticationStateHandler,
+  navigationState: navigationStateHandler
+});
+
+export class ApplicationStore extends Store<IApplicationStoreState> { }
+
+/** This function will create the application store considering the currently registered application ans their middlewares. */
+export const applicationStoreCreator = (): ApplicationStore => {
+  const middlewares: Middleware<IApplicationStoreState>[] = [];
+  const actionHandlers = Object.keys(applicationService.applications).reduce((acc, cur) => {
+    const reg = applicationService.applications[cur];
+    reg && typeof reg.rootActionHandler === 'function' && (acc[cur] = reg.rootActionHandler);
+    reg && reg.middlewares && Array.isArray(reg.middlewares) && middlewares.push(...(reg.middlewares as Middleware<IApplicationStoreState>[]));
+    return acc;
+  }, { framework: frameworkHandlers } as any);
+
+  const applicationStore = new ApplicationStore(combineActionHandler(actionHandlers), chainMiddleware(loggerMiddleware, thunkMiddleware, routerMiddleware, apiMiddleware, updatePolicies, ...middlewares));
+  setApplicationStore(applicationStore);
+  return applicationStore;
+}
+
+export default applicationStoreCreator;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/styles/att.ts b/sdnr/wt-odlux/odlux/framework/src/styles/att.ts
new file mode 100644
index 0000000..2d54590
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/styles/att.ts
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { createTheme, adaptV4Theme } from '@mui/material/styles';
+
+const theme = createTheme(adaptV4Theme({
+  design: {
+    id: "att",
+    name: "AT&T",
+    url: "https://pmcvariety.files.wordpress.com/2016/04/att_logo.jpg?w=1000&h=563&crop=1",
+    height: 70,
+    width: 150,
+    logoHeight: 60,
+  },
+  palette: {
+    primary: {
+      light: "#f2f2f29c",
+      main: "#f2f2f2",
+      dark: "#d5d5d5",
+      contrastText: "#0094d3"
+    },
+    secondary: {
+      light: "#f2f2f2",
+      main: "rgba(51, 171, 226, 1)",
+      dark: "rgba(41, 159, 213, 1)",
+      contrastText: "#0094d3"
+    }
+  },
+}));
+
+export default theme;
diff --git a/sdnr/wt-odlux/odlux/framework/src/utilities/elasticSearch.ts b/sdnr/wt-odlux/odlux/framework/src/utilities/elasticSearch.ts
new file mode 100644
index 0000000..e1d3752
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/utilities/elasticSearch.ts
@@ -0,0 +1,114 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Result, ResultTopology } from '../models';
+import { DataCallback } from '../components/material-table';
+
+import { requestRest } from '../services/restService';
+
+import { convertPropertyNames, convertPropertyValues, replaceUpperCase, replaceHyphen } from './yangHelper';
+
+type propType = string | number | null | undefined | (string | number)[];
+type dataType = { [prop: string]: propType };
+
+/** Represents a fabric for the searchDataHandler used by the internal data api.
+ *  @param typeName The name of the entry type to create a searchDataHandler for.
+ *  @param additionalFilters Filterproperties and their values to add permanently.
+ *  @returns The searchDataHandler callback to be used with the material table.
+*/
+export function createSearchDataHandler<TResult>(typeName: (() => string) | string, connectToTopologyServer?: boolean, additionalFilters?: {} | null | undefined): DataCallback<(TResult)> {
+  const fetchData: DataCallback<(TResult)> = async (pageIndex, rowsPerPage, orderBy, order, filter) => {
+
+    const topologyUrl = `/topology/network/read-${typeof typeName === "function" ? typeName() : typeName}-list`;
+    const dataProviderUrl = `/rests/operations/data-provider:read-${typeof typeName === "function" ? typeName() : typeName}-list`;
+
+    const url = connectToTopologyServer ? topologyUrl : dataProviderUrl;
+
+    filter = { ...filter, ...additionalFilters };
+
+    const filterKeys = filter && Object.keys(filter) || [];
+
+    const input = {
+      filter: filterKeys.filter(f => filter![f] != null && filter![f] !== "").map(property => ({ property, filtervalue: filter![property] })),
+      sortorder: orderBy ? [{ property: orderBy, sortorder: order === "desc" ? "descending" : "ascending" }] : [],
+      pagination: { size: rowsPerPage, page: (pageIndex != null && pageIndex > 0 && pageIndex || 0) + 1 }
+    }
+
+    if (url.includes('data-provider')) {
+      const query = {
+        "data-provider:input": input
+      };
+
+      const result = await requestRest<Result<TResult>>(url, {
+        method: "POST",       // *GET, POST, PUT, DELETE, etc.
+        mode: "same-origin",  // no-cors, cors, *same-origin
+        cache: "no-cache",    // *default, no-cache, reload, force-cache, only-if-cached
+        headers: {
+          "Content-Type": "application/json",
+          // "Content-Type": "application/x-www-form-urlencoded",
+        },
+        body: JSON.stringify(convertPropertyValues(query, replaceUpperCase)), // body data type must match "Content-Type" header
+      });
+      if (result) {
+        let rows: TResult[] = [];
+
+        if (result && result["data-provider:output"] && result["data-provider:output"].data) {
+          rows = result["data-provider:output"].data.map(obj => convertPropertyNames(obj, replaceHyphen)) || []
+        }
+
+        const data = {
+          page: +(result["data-provider:output"].pagination && result["data-provider:output"].pagination.page != null && result["data-provider:output"].pagination.page - 1 || 0), total: +(result["data-provider:output"].pagination && result["data-provider:output"].pagination.total || 0), rows: rows
+        };
+        return data;
+      }
+    } else if (url.includes('topology')) {
+
+      const queryTopology = {
+        "input": input
+      };
+
+      const resultTopology = await requestRest<ResultTopology<TResult>>(url, {
+        method: "POST",       // *GET, POST, PUT, DELETE, etc.
+        mode: "same-origin",  // no-cors, cors, *same-origin
+        cache: "no-cache",    // *default, no-cache, reload, force-cache, only-if-cached
+        headers: {
+          "Content-Type": "application/json",
+          // "Content-Type": "application/x-www-form-urlencoded",
+        },
+        body: JSON.stringify(queryTopology), // body data type must match "Content-Type" header
+      });
+      if (resultTopology) {
+        let rows: TResult[] = [];
+
+        if (resultTopology && resultTopology.output && resultTopology.output.data) {
+          rows = resultTopology.output.data.map(obj => obj) || []
+        }
+
+        const data = {
+          page: +(resultTopology.output.pagination && resultTopology.output.pagination.page != null && resultTopology.output.pagination.page - 1 || 0), total: +(resultTopology.output.pagination && resultTopology.output.pagination.total || 0), rows: rows
+        };
+        return data;
+      }
+    }
+
+    return { page: 1, total: 0, rows: [] };
+  };
+
+  return fetchData;
+}
+
diff --git a/sdnr/wt-odlux/odlux/framework/src/utilities/logLevel.ts b/sdnr/wt-odlux/odlux/framework/src/utilities/logLevel.ts
new file mode 100644
index 0000000..a198d98
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/utilities/logLevel.ts
@@ -0,0 +1,8 @@
+export enum LogLevel {
+  Always = 0,
+  Error = 1,
+  Warning = 2,
+  Info = 3,
+  Debug = 4,
+  Trace = 5,
+}
diff --git a/sdnr/wt-odlux/odlux/framework/src/utilities/withComponents.ts b/sdnr/wt-odlux/odlux/framework/src/utilities/withComponents.ts
new file mode 100644
index 0000000..8e460ad
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/utilities/withComponents.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import applicationService from '../services/applicationManager';
+export type WithComponents<T extends { [name: string]: string }> = {
+  components: { [prop in keyof T]: React.ComponentType }
+};
+
+export function withComponents<TProps,TMap extends { [name: string]: string }>(mapping: TMap) {
+  return (component: React.ComponentType<TProps & WithComponents<TMap>>): React.ComponentType<TProps> => {
+    const components = {} as any;
+    Object.keys(mapping).forEach(name => {
+      const [appKey, componentKey] = mapping[name].split('.');
+      const reg = applicationService.applications[appKey];
+      components[name] = reg && reg.exportedComponents && reg.exportedComponents[componentKey] || (() => null);
+    });
+    return (props: TProps) => (
+      React.createElement(component, Object.assign({ components }, props))
+    );
+  }
+}
+export default withComponents;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/utilities/yangHelper.ts b/sdnr/wt-odlux/odlux/framework/src/utilities/yangHelper.ts
new file mode 100644
index 0000000..7e77c05
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/utilities/yangHelper.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+export const replaceHyphen = (name: string) => name.replace(/-([a-z])/g, (g) => (g[1].toUpperCase()));
+export const replaceUpperCase = (name: string) => name.replace(/([a-z][A-Z])/g, (g) => g[0] + '-' + g[1].toLowerCase());
+
+/***
+ * Replaces whitespace with '-' and cast everything to lowercase
+ */
+export const toAriaLabel = (value: string) => value.replace(/\s/g, "-").toLowerCase();
+
+export const convertPropertyNames = <T extends { [prop: string]: any }>(obj: T, conv: (name: string) => string): T => {
+  return Object.keys(obj).reduce<{ [prop: string]: any }>((acc, cur) => {
+    acc[conv(cur)] = typeof obj[cur] === "object" ? convertPropertyNames(obj[cur], conv) : obj[cur];
+    return acc;
+  }, obj instanceof Array ? [] : {}) as T;
+}
+
+export const convertPropertyValues = <T extends { [prop: string]: any }>(obj: T, conv: (name: string) => string): T => {
+  return Object.keys(obj).reduce<{ [prop: string]: any }>((acc, cur) => {
+    acc[cur] = typeof obj[cur] === "object"
+      ? convertPropertyValues(obj[cur], conv)
+      : cur === "property"
+        ? conv(obj[cur])
+        : obj[cur];
+    return acc;
+  }, obj instanceof Array ? [] : {}) as T;
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/about.tsx b/sdnr/wt-odlux/odlux/framework/src/views/about.tsx
new file mode 100644
index 0000000..72358bf
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/about.tsx
@@ -0,0 +1,196 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React, { FC, useEffect, useState } from 'react';
+import * as marked from 'marked';
+import * as hljs from 'highlight.js';
+import { requestRestExt } from '../services/restService';
+import { Button, Typography } from '@mui/material';
+
+const defaultRenderer = new marked.Renderer();
+defaultRenderer.link = (href, title, text) => (
+  `<a target="_blank" rel="noopener noreferrer" href="${href}" title="${title}">${text}</a>`
+);
+
+type OdluxVersion= {version:string,build:string, framework: string, 
+  applications:{
+    configurationApp: string,
+    connectApp: string,
+    eventLogApp: string,
+    faultApp: string,
+    helpApp: string,
+    inventoryApp: string,
+    microwaveApp: string,
+    maintenanceApp: string,
+    mediatorApp: string,
+    networkMapApp: string,
+    permanceHistoryApp: string,
+    siteManagerApp: string,
+  }};
+
+type TopologyVersion = {version: string, buildTimestamp: string};
+
+const AboutComponent: FC = (props) => {
+  
+  const textareaRef = React.createRef<HTMLTextAreaElement>();
+  const [content, setContent] = useState<string | null>(null);
+  const [isCopiedSuccessfully, setCopySuccess] = useState(false);
+  const [isContetLoaded, setContentLoaded] = useState(false);
+
+  useEffect(()=>{
+    loadAboutContent();
+  },[]);
+
+  const getMarkOdluxVersionMarkdownTable = (data:OdluxVersion|null|undefined):string => {
+    if(!data) {
+      return "";
+    }else{
+      let applicationVersions= '';
+      if(data.applications){
+
+        applicationVersions = `| Framework | ${data.framework}|\n `+
+        `| ConnectApp | ${data.applications.connectApp}|\n `+
+        `| FaultApp | ${data.applications.faultApp}|\n `+
+        `| MaintenanceApp | ${data.applications.maintenanceApp}|\n `+
+        `| ConfigurationApp | ${data.applications.configurationApp}|\n `+
+        `| PerformanceHistoryApp | ${data.applications.permanceHistoryApp}|\n `+
+        `| InventoryApp | ${data.applications.inventoryApp}|\n `+
+        `| EventLogApp | ${data.applications.eventLogApp}|\n `+
+        `| MediatorApp | ${data.applications.mediatorApp}|\n `+
+        `| NetworkMapApp | ${data.applications.networkMapApp}|\n `+
+        `| MicrowaveApp | ${data.applications.microwaveApp}|\n `+
+        `| SiteManagerApp | ${data.applications.siteManagerApp}|\n `+
+        `| HelpApp | ${data.applications.helpApp}|\n `;
+      }
+    
+    return `| | |\n| --- | --- |\n| Version | ${data.version} |\n| Build timestamp | ${data.build}|\n`+
+    applicationVersions;
+    }
+  }
+
+  const getTopologyVersionMarkdownTable = (data: TopologyVersion|null|undefined) => { 
+    if(!data){
+      return "No version";
+    }
+    else
+    {
+      const topologyInfo = `| | |\n| --- | --- |\n| Version | ${data.version} |\n` +
+                           `| Build timestamp | ${data.buildTimestamp} |\n`;
+      return topologyInfo;
+    }
+  }
+
+  const loadAboutContent = (): void => {
+    const baseUri = window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/")+1);
+    const init = {
+      'method': 'GET',
+      headers: {
+        'Content-Type': 'application/json',
+        'Accept': 'text/markdown',
+      }
+    };
+    const p1 = requestRestExt<string>('/about',init);
+    const p2 = requestRestExt<OdluxVersion>(`${baseUri}version.json`);
+    const p3 = requestRestExt<any>(`/topology/info/version`);
+
+    Promise.all([p1,p2, p3]).then((responses) => {
+      const response = responses[0];
+      const response2 = responses[1]; 
+      const response3 = responses[2];   
+      const content = response.status == 200 ? response.data : `${response.status} ${response.message}` || "Server error";
+      const content2 = `\n## ODLUX Version Info\n`+(response2.status == 200 ? getMarkOdluxVersionMarkdownTable(response2.data) : `${response2.message}` || "ODLUX Server error");
+      const content3 =  `\n## Topology API Version Info\n`+(response3.status == 200 ? getTopologyVersionMarkdownTable(response3.data): `Topology API not available`);
+      const loadedSucessfully = response.status == 200 ? true : false;
+      setContent((content + content2 + content3 ) || null);
+      setContentLoaded(loadedSucessfully);
+    }).catch((error) => {
+      setContent(error);
+    });
+  }
+
+  const copyToClipboard = (e: React.MouseEvent<HTMLButtonElement>) =>{
+    e.preventDefault();
+
+    if(textareaRef.current!==null){
+      textareaRef.current.select();
+      document.execCommand('copy');
+      if(e.currentTarget != null){ // refocus on button, otherwhise the textarea would be focused
+        e.currentTarget.focus();
+      }
+      setCopySuccess(true);
+      window.setTimeout(()=>{ setCopySuccess(false);},2000);
+    }
+  }
+
+    const markedOptions: marked.MarkedOptions = {
+      gfm: true,
+      breaks: false,
+      pedantic: false,
+      sanitize: true,
+      smartLists: true,
+      smartypants: false,
+      langPrefix: 'hljs ',
+      ...({}),
+      highlight: (code, lang) => {
+        if (!!(lang && hljs.getLanguage(lang))) {
+          return hljs.highlight(lang, code).value;
+        }
+        return code;
+      }
+    };
+
+
+    const className = "about-table"
+    const style: React.CSSProperties = {};
+    const containerStyle = { overflow: "auto", paddingRight: "20px" }
+
+    const html = (marked(content || 'loading', { renderer: markedOptions && markedOptions.renderer || defaultRenderer }));
+
+    return (
+      <div style={containerStyle}>
+        { isContetLoaded &&
+        <div style={{float: "right", marginRight: "10px"}}>
+        <Button aria-label="copy-version-information-button" color="inherit" variant="contained" onClick={e => copyToClipboard(e)}>
+           Copy to clipboard
+        </Button>
+          {
+            isCopiedSuccessfully && 
+            <Typography variant="body1" style={{color: "green"}} align="center">
+             copied successfully
+            </Typography>
+          }
+        </div>
+      }
+       
+        <div
+          dangerouslySetInnerHTML={{ __html: html }}
+          className={className}
+          style={style}
+        />
+         <form>
+          <textarea
+           style={{opacity: ".01"}}
+            ref={textareaRef}
+            value={content || ''}
+          />
+        </form>
+      </div>
+    );
+};
+
+export const About = AboutComponent;
+export default About;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/frame.tsx b/sdnr/wt-odlux/odlux/framework/src/views/frame.tsx
new file mode 100644
index 0000000..2c9f8c0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/frame.tsx
@@ -0,0 +1,134 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React, { FC, memo } from 'react';
+import { Router, Route, Redirect, Switch } from 'react-router-dom';
+
+import { Theme } from '@mui/material/styles';
+import { makeStyles } from '@mui/styles';
+
+import { SnackbarProvider } from 'notistack';
+import { ConfirmProvider } from 'material-ui-confirm';
+
+import AppFrame from '../components/routing/appFrame';
+import TitleBar from '../components/titleBar';
+import Menu from '../components/navigationMenu';
+import ErrorDisplay from '../components/errorDisplay';
+import SnackDisplay from '../components/material-ui/snackDisplay';
+
+import Home from '../views/home';
+import Login from '../views/login';
+import About from '../views/about';
+import Test from '../views/test';
+import UserSettings from '../views/settings';
+
+import applicationService from '../services/applicationManager';
+
+import { history } from '../middleware/navigation';
+
+const aboutIcon = require('../assets/icons/About.svg');
+const homeIcon = require('../assets/icons/Home.svg');
+const loginIcon = require('../assets/icons/User.svg');
+const settingsIcon = require('../assets/icons/Tools.svg');
+
+
+const styles = makeStyles((theme: Theme) => {
+
+  return {
+  root: {
+    flexGrow: 1,
+    height: '100%',
+    zIndex: 1,
+    overflow: 'hidden',
+    position: 'relative',
+    display: 'flex',
+  },
+  content: {
+    flexGrow: 1,
+    display: "flex",
+    flexDirection: "column",
+    backgroundColor: '#fafafa',
+    padding: theme.spacing(3),
+    minWidth: 0, // So the Typography noWrap works
+  },
+  toolbar: theme.mixins.toolbar as any
+  };
+});
+
+const FrameComponent: FC = memo(() => {
+
+  const registrations = applicationService.applications;
+  const classes = styles();
+  return (
+    <ConfirmProvider>
+      <SnackbarProvider maxSnack={3}>
+        <Router history={history as any} >
+          <div className={classes.root}>
+            <SnackDisplay />
+            <ErrorDisplay />
+            <TitleBar />
+            <Menu />
+            <main className={classes.content}>
+              {
+                <div className={classes.toolbar} /> //needed for margins, don't remove!
+              }
+              <Switch>
+                <Route exact path="/" component={() => (
+                  <AppFrame title={"Home"} icon={homeIcon} >
+                    <Home />
+                  </AppFrame>
+                )} />
+                <Route path="/about" component={() => (
+                  <AppFrame title={"About"} icon={aboutIcon} >
+                    <About />
+                  </AppFrame>
+                )} />
+                <Route path="/settings" component={() => (
+                  <AppFrame title={"Settings"} icon={settingsIcon} >
+                    <UserSettings />
+                  </AppFrame>
+                )} />
+                {process.env.NODE_ENV === "development" ? <Route path="/test" component={() => (
+                  <AppFrame title={"Test"} icon={settingsIcon} >
+                    <Test />
+                  </AppFrame>
+                )} /> : null}
+                <Route path="/login" component={() => (
+                  <AppFrame title={"Login"} icon={loginIcon} >
+                    <Login />
+                  </AppFrame>
+                )} />
+                {Object.keys(registrations).map(p => {
+                  const application = registrations[p];
+                  return (<Route key={application.name} path={application.path || `/${application.name}`} component={() => (
+                    <AppFrame title={application.title || (typeof application.menuEntry === 'string' && application.menuEntry) || application.name} icon={application.icon} appId={application.name} >
+                      <application.rootComponent />
+                    </AppFrame>
+                  )} />)
+                })}
+                <Redirect to="/" />
+              </Switch>
+            </main>
+          </div>
+        </Router>
+      </SnackbarProvider>
+    </ConfirmProvider>
+  );
+});
+
+export const Frame = FrameComponent;
+export default Frame;
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/home.tsx b/sdnr/wt-odlux/odlux/framework/src/views/home.tsx
new file mode 100644
index 0000000..72c5059
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/home.tsx
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React, {FC, useState} from 'react';
+import applicationService from '../services/applicationManager';
+
+
+type DashboardElement = { name: string, element: JSX.Element };
+
+const DashboardView: FC = (props) => {
+
+  const registrations = applicationService.applications;
+
+  const [selectedIndex] = useState(0);
+
+  let dashboardArray: DashboardElement[] = [];
+
+  let dashboardElements: (DashboardElement)[] = Object.keys(registrations).map(p => {
+    const application = registrations[p];
+
+    if (application.dashbaordElement) {
+      const value: DashboardElement = { name: application.menuEntry?.toString()!, element: <application.dashbaordElement /> };
+      return value;
+
+    } else {
+      return null;
+    }
+  }).filter((x): x is DashboardElement => x !== null);
+
+  dashboardArray.push(...dashboardElements);
+
+  return <div>
+    <div>
+      <div>
+        {
+          dashboardArray[selectedIndex]?.element
+        }
+      </div>
+    </div>
+  </div>
+}
+
+
+export default DashboardView;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/login.tsx b/sdnr/wt-odlux/odlux/framework/src/views/login.tsx
new file mode 100644
index 0000000..46c0872
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/login.tsx
@@ -0,0 +1,250 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import React, { FC, useEffect, useState } from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import Alert from '@mui/material/Alert';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import CssBaseline from '@mui/material/CssBaseline';
+import FormControl from '@mui/material/FormControl';
+import Input from '@mui/material/Input';
+import InputLabel from '@mui/material/InputLabel';
+import Paper from '@mui/material/Paper';
+import { Theme } from '@mui/material/styles';
+import Typography from '@mui/material/Typography';
+
+import { makeStyles } from '@mui/styles';
+
+import { useApplicationDispatch, useSelectApplicationState } from '../flux/connect';
+import authenticationService from '../services/authenticationService';
+
+import { loginUserAction, UpdatePolicies } from '../actions/authentication';
+import { updateExternalLoginProviderAsyncActionCreator } from '../actions/loginProvider';
+
+import { AuthPolicy, AuthToken, User } from '../models/authentication';
+
+const loginIcon = require('../assets/icons/User.svg');
+
+const styles = makeStyles((theme: Theme) =>{
+  return{
+  layout: {
+    width: 'auto',
+    display: 'block', // Fix IE11 issue.
+    marginLeft: theme.spacing(3),
+    marginRight: theme.spacing(3),
+    [theme.breakpoints.up(400 + Number(theme.spacing(3).replace('px','')) * 2)]: {
+      width: 400,
+      marginLeft: 'auto',
+      marginRight: 'auto',
+    },
+  },
+  paper: {
+    marginTop: theme.spacing(8),
+    display: 'flex',
+    flexDirection: 'column',
+    alignItems: 'center',
+    padding: `${theme.spacing(2)} ${theme.spacing(3)} ${theme.spacing(3)}`,
+  },
+  avatar: {
+    margin: theme.spacing(1),
+    backgroundColor: theme.palette.secondary.main,
+  },
+  form: {
+    width: '100%', // Fix IE11 issue.
+    marginTop: theme.spacing(1),
+  },
+  submit: {
+    marginTop: theme.spacing(3),
+  },
+  lineContainer:{
+    width: '100%',
+    height: 10,
+    borderBottom: '1px solid grey',
+    textAlign: 'center',
+    marginTop:15,
+    marginBottom:5
+  },
+  thirdPartyDivider:{
+    fontSize: 15,
+     backgroundColor: 'white',
+     padding: '0 10px',
+     color: 'grey'
+  }
+};
+});
+
+
+type LoginProps = RouteComponentProps;
+
+// todo: ggf. redirect to einbauen
+const LoginComponent:  FC<LoginProps> = (props) => {
+
+  const search = useSelectApplicationState(state => state.framework.navigationState.search);
+  const authentication = useSelectApplicationState(state => state.framework.applicationState.authentication);
+  const externalLoginProviders = useSelectApplicationState(state => state.framework.applicationState.externalLoginProviders);
+  
+  const dispatch = useApplicationDispatch();
+  const updateExternalProviders = () => dispatch(updateExternalLoginProviderAsyncActionCreator());
+  const updateAuthentication = (token: AuthToken | null) => {
+    const user = token && new User(token) || undefined;
+    dispatch(loginUserAction(user));
+  }
+  const updatePolicies = (policies?: AuthPolicy[]) => {
+    return dispatch(new UpdatePolicies(policies));
+  }
+
+  const [isBusy, setBusy] = useState(false);
+  const [username, setUsername] = useState("");
+  const [password, setPassword] = useState("");
+  const [scope, setScope] = useState("sdn");
+  const [message, setMessage] = useState("");
+  const [isServerReady, setIsServerReady] = useState(false);
+
+  useEffect(()=>{
+     if (authentication === "oauth" && (externalLoginProviders == null || externalLoginProviders.length === 0)){
+       updateExternalProviders();
+     }
+
+    authenticationService.getServerReadyState().then(result =>{
+      setIsServerReady(result);
+    })
+  },[]);
+
+  const onSignIn = async (event: React.MouseEvent<HTMLButtonElement>) => {
+    event.preventDefault();
+  
+    setBusy(true);
+
+    const token = authentication === "oauth" 
+      ? await authenticationService.authenticateUserOAuth(username, password, scope)
+      : await authenticationService.authenticateUserBasicAuth(username, password, scope); 
+
+    updateAuthentication(token);
+    setBusy(false);
+
+    if (token) {
+      const query = search && search.replace(/^\?/, "").split('&').map(e => e.split("="));
+      const returnTo = query && query.find(e => e[0] === "returnTo");
+      props.history.replace(returnTo && returnTo[1] || "/");
+    }
+    else {
+
+      if(!isServerReady){
+        const ready = await authenticationService.getServerReadyState();
+        if(ready){
+          setIsServerReady(true);
+        }else{
+          setMessage("Login is currently not possible. Please re-try in a few minutes. If the problem persists, ask your administrator for assistance.");
+        }
+  
+      }else{
+        setMessage("Could not log in. Please check your credentials or ask your administrator for assistance.");
+        setPassword("");
+      }
+    }
+  }
+  
+  const classes = styles();
+  const areProvidersAvailable = externalLoginProviders && externalLoginProviders.length > 0;
+
+  return (
+    <>
+      <CssBaseline />
+      <main className={classes.layout}>
+        <Paper className={classes.paper}>
+          <Avatar className={classes.avatar}>
+            <img src={loginIcon} alt="loginIcon" />
+          </Avatar>
+          <Typography variant="caption">Sign in</Typography>
+          <form className={classes.form}>
+            {areProvidersAvailable &&
+              <>
+                {
+                  externalLoginProviders!.map((provider, index) => (
+                    <Button
+                      aria-controls="externalLogin"
+                      aria-label={"external-login-identity-provider-" + (index + 1)}
+                      aria-haspopup="true"
+                      fullWidth
+                      variant="contained"
+                      color="inherit"
+                      className={classes.submit} onClick={() => { window.location = provider.loginUrl as any; }}>
+                      {provider.title}
+                    </Button>))
+                }
+                <div className={classes.lineContainer}>
+                  <span className={classes.thirdPartyDivider}>
+                    OR
+                  </span>
+                </div>
+              </>
+            }
+            <FormControl variant="standard" margin="normal" required fullWidth>
+              <InputLabel htmlFor="username">Username</InputLabel>
+              <Input id="username" name="username" autoComplete="username" autoFocus
+                disabled={isBusy}
+                value={username}
+                onChange={event => { setUsername(event.target.value); }} />
+            </FormControl>
+            <FormControl variant="standard" margin="normal" required fullWidth>
+              <InputLabel htmlFor="password">Password</InputLabel>
+              <Input
+                name="password"
+                type="password"
+                id="password"
+                autoComplete="current-password"
+                disabled={isBusy}
+                value={password}
+                onChange={event => { setPassword(event.target.value); }}
+              />
+            </FormControl>
+            <FormControl variant="standard" margin="normal" required fullWidth>
+              <InputLabel htmlFor="password">Domain</InputLabel>
+              <Input
+                name="scope"
+                type="scope"
+                id="scope"
+                disabled={isBusy}
+                value={scope}
+                onChange={event => { setScope(event.target.value); }}
+              />
+            </FormControl>
+            <Button
+              aria-label="login-button"
+              type="submit"
+              fullWidth
+              variant="contained"
+              color="inherit"
+              disabled={isBusy}
+              className={classes.submit}
+              onClick={onSignIn}
+            >
+              Sign in
+            </Button>
+
+          </form>
+          {message && <Alert severity="error">{message}</Alert>}
+        </Paper>
+      </main>
+    </>
+  );
+}
+
+export const Login = withRouter(LoginComponent);
+export default Login;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/settings.tsx b/sdnr/wt-odlux/odlux/framework/src/views/settings.tsx
new file mode 100644
index 0000000..5973db9
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/settings.tsx
@@ -0,0 +1,115 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React, {FC, useState } from 'react';
+import { useApplicationDispatch } from "../flux/connect";
+
+import { Divider, List, ListItem, ListItemText, Paper } from '@mui/material';
+import { makeStyles } from '@mui/styles';
+import applicationService from '../services/applicationManager';
+
+import { GoBackAction } from '../actions/navigationActions';
+import { GeneralUserSettings } from '../components/settings/general';
+import { toAriaLabel } from '../utilities/yangHelper';
+
+type SettingsEntry = { name: string, element: JSX.Element };
+
+const styles = makeStyles({
+  sectionMargin: {
+    marginTop: "30px",
+    marginBottom: "15px"
+  },
+  elementMargin: {
+    marginLeft: "10px"
+  },
+  menu: {
+    flex: "1 0 0%",
+  }
+});
+
+const UserSettings: FC = (props) => {
+
+  const dispatch = useApplicationDispatch();
+  const goBack = () => dispatch(new GoBackAction());
+
+  const [selectedIndex, setSelectedIndex] = useState(0);
+
+  const registrations = applicationService.applications;
+
+  const navigateBack = () => {
+    goBack();
+  }
+
+  let settingsArray: SettingsEntry[] = [];
+
+  //add all framework specific settings
+  settingsArray.push({name:"General", element: <GeneralUserSettings onClose={navigateBack} />})
+
+  //get app settings
+  let settingsElements : (SettingsEntry) [] = Object.keys(registrations).map(p => {
+    const application = registrations[p];
+
+    if (application.settingsElement) {
+      const value: SettingsEntry = { name: application.menuEntry?.toString()!, element: <application.settingsElement onClose={navigateBack} /> };
+      return value;
+
+    } else {
+      return null;
+    }
+  }).filter((x): x is SettingsEntry => x !== null);
+
+
+  settingsArray.push(...settingsElements);
+
+  const onSelectElement = (e: any, newValue: number) => {
+    e.preventDefault();
+    setSelectedIndex(newValue);
+  }
+
+  const classes = styles();
+
+  return <div style={{ display: "flex", flexDirection: "row", height: "100%" }}>
+   <div style={{ display: "flex", flexDirection: "column", height: "100%", width: "15%" }}>
+      <Paper variant="outlined" style={{ height: "70%" }}>
+        <List className={classes.menu} component="nav">
+          {
+            settingsArray.map((el, index) => {
+              return (
+              <>
+                <ListItem key={"settings-key-"+index} selected={selectedIndex === index} button onClick={e => { onSelectElement(e, index) }} aria-label={toAriaLabel(el?.name+"-settings")}>
+                  <ListItemText primary={el?.name} style={{ padding: 0 }} />
+                </ListItem>
+                <Divider />
+              </>)
+            })
+          }
+        </List>
+      </Paper>
+    </div>
+    <div style={{ height: "100%", width: "80%", marginLeft: 15 }}>
+      <div style={{ height: "100%" }}>
+        {
+            settingsArray[selectedIndex]?.element
+        }
+      </div>
+    </div>
+  </div>
+}
+
+
+export default UserSettings;
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/test.tsx b/sdnr/wt-odlux/odlux/framework/src/views/test.tsx
new file mode 100644
index 0000000..72f8d2c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/test.tsx
@@ -0,0 +1,877 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withComponents, WithComponents } from '../utilities/withComponents';
+import { Theme } from '@mui/material/styles';
+
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
+import createStyles from '@mui/styles/createStyles';
+
+import Accordion from '@mui/material/Accordion';
+import AccordionSummary from '@mui/material/AccordionSummary';
+import AccordionDetails from '@mui/material/AccordionDetails';
+import Typography from '@mui/material/Typography';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+
+import { MaterialTable, MaterialTableCtorType, ColumnType } from '../components/material-table';
+import { TreeView, TreeItem, TreeViewCtorType } from '../components/material-ui/treeView';
+import { SvgIconProps } from '@mui/material/SvgIcon';
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    width: '100%',
+  },
+  heading: {
+    fontSize: theme.typography.pxToRem(15),
+    fontWeight: theme.typography.fontWeightRegular,
+  },
+});
+
+class SampleData {
+  _id: string;
+  index: number;
+  guid: string;
+  isActive: boolean;
+  balance: string;
+  age: number;
+  firstName: string;
+  lastName: string;
+  company: string;
+  email: string;
+  registered: string;
+  latitude: string;
+  longitude: string;
+}
+
+// https://next.json-generator.com/NJ5Bv-v1I
+const tableData: SampleData[] = [
+  {
+    "_id": "5c0e18399919a5c43636fdf2",
+    "index": 0,
+    "guid": "48728d8e-8300-4d0f-b967-e2166d023066",
+    "isActive": false,
+    "balance": "$3,480.16",
+    "age": 33,
+    "firstName": "Brooke",
+    "lastName": "Morris",
+    "company": "ZORROMOP",
+    "email": "brooke.morris@zorromop.de",
+    "registered": "Sunday, February 11, 2018 2:55 PM",
+    "latitude": "-69.109379",
+    "longitude": "113.735639"
+  },
+  {
+    "_id": "5c0e1839b61e3eeaf164259d",
+    "index": 1,
+    "guid": "28723570-1507-422e-b78c-924402371fb1",
+    "isActive": false,
+    "balance": "$1,305.01",
+    "age": 28,
+    "firstName": "Jolene",
+    "lastName": "Everett",
+    "company": "ZENCO",
+    "email": "jolene.everett@zenco.de",
+    "registered": "Saturday, December 8, 2018 5:17 PM",
+    "latitude": "13.683025",
+    "longitude": "85.101421"
+  },
+  {
+    "_id": "5c0e1839e81f57913c5d2147",
+    "index": 2,
+    "guid": "e914dc5d-91a3-405d-ac48-aee6f0cd391a",
+    "isActive": true,
+    "balance": "$1,418.37",
+    "age": 28,
+    "firstName": "Elva",
+    "lastName": "Travis",
+    "company": "ZYTREK",
+    "email": "elva.travis@zytrek.de",
+    "registered": "Thursday, March 10, 2016 5:13 PM",
+    "latitude": "53.75862",
+    "longitude": "-67.784532"
+  },
+  {
+    "_id": "5c0e1839bc9224a2b54c0f69",
+    "index": 3,
+    "guid": "88cbdce0-0bcc-4d16-83c3-3017690503c4",
+    "isActive": true,
+    "balance": "$1,709.60",
+    "age": 21,
+    "firstName": "Ellis",
+    "lastName": "Mcpherson",
+    "company": "DIGIPRINT",
+    "email": "ellis.mcpherson@digiprint.de",
+    "registered": "Sunday, December 21, 2014 5:25 AM",
+    "latitude": "46.486149",
+    "longitude": "-66.657067"
+  },
+  {
+    "_id": "5c0e183951b51475db0f35d1",
+    "index": 4,
+    "guid": "c887ac86-7ba1-4eb6-9b47-e88a1bcb3713",
+    "isActive": true,
+    "balance": "$3,578.54",
+    "age": 25,
+    "firstName": "Marcia",
+    "lastName": "Rocha",
+    "company": "ZAPPIX",
+    "email": "marcia.rocha@zappix.de",
+    "registered": "Tuesday, June 16, 2015 11:21 AM",
+    "latitude": "-39.905461",
+    "longitude": "150.873895"
+  },
+  {
+    "_id": "5c0e18398c5be8d362a578eb",
+    "index": 5,
+    "guid": "0d160697-9b5b-4941-9b5f-4ba3a7f97b49",
+    "isActive": true,
+    "balance": "$414.98",
+    "age": 32,
+    "firstName": "Lavonne",
+    "lastName": "Wilkins",
+    "company": "FARMAGE",
+    "email": "lavonne.wilkins@farmage.de",
+    "registered": "Monday, February 1, 2016 5:27 PM",
+    "latitude": "-16.839256",
+    "longitude": "-105.824746"
+  },
+  {
+    "_id": "5c0e18399804086c836d7d56",
+    "index": 6,
+    "guid": "715a5f63-35b6-4903-a46e-ba584b005e64",
+    "isActive": false,
+    "balance": "$1,755.78",
+    "age": 32,
+    "firstName": "Wise",
+    "lastName": "Berg",
+    "company": "ZIZZLE",
+    "email": "wise.berg@zizzle.de",
+    "registered": "Saturday, March 28, 2015 1:40 AM",
+    "latitude": "51.15269",
+    "longitude": "65.795093"
+  },
+  {
+    "_id": "5c0e18399c4d13538bcaf8c9",
+    "index": 7,
+    "guid": "7ee50269-23e8-499e-9a16-09f393d7600c",
+    "isActive": false,
+    "balance": "$342.52",
+    "age": 27,
+    "firstName": "Isabel",
+    "lastName": "Battle",
+    "company": "EZENTIA",
+    "email": "isabel.battle@ezentia.de",
+    "registered": "Thursday, June 7, 2018 12:16 AM",
+    "latitude": "-53.318152",
+    "longitude": "-153.516824"
+  },
+  {
+    "_id": "5c0e18398d7fb9a4eceeffa2",
+    "index": 8,
+    "guid": "1e30c9ac-2297-4f16-83e6-9559b1ebe92c",
+    "isActive": true,
+    "balance": "$3,184.71",
+    "age": 36,
+    "firstName": "Lenora",
+    "lastName": "Crawford",
+    "company": "KIDGREASE",
+    "email": "lenora.crawford@kidgrease.de",
+    "registered": "Saturday, January 7, 2017 6:17 PM",
+    "latitude": "-72.431496",
+    "longitude": "9.413359"
+  },
+  {
+    "_id": "5c0e18395837069ab6b79d00",
+    "index": 9,
+    "guid": "d04a02ed-5899-4729-a7e5-2d85b5d03973",
+    "isActive": true,
+    "balance": "$1,553.28",
+    "age": 35,
+    "firstName": "Sasha",
+    "lastName": "Bridges",
+    "company": "IDEALIS",
+    "email": "sasha.bridges@idealis.de",
+    "registered": "Sunday, February 4, 2018 7:02 PM",
+    "latitude": "8.095691",
+    "longitude": "-105.758195"
+  },
+  {
+    "_id": "5c0e18390be19bf65acad180",
+    "index": 10,
+    "guid": "3a1a77e6-ef15-4598-8274-c68ac3bb922a",
+    "isActive": false,
+    "balance": "$3,587.96",
+    "age": 20,
+    "firstName": "Wilkins",
+    "lastName": "Beasley",
+    "company": "DIGIFAD",
+    "email": "wilkins.beasley@digifad.de",
+    "registered": "Monday, March 5, 2018 1:27 PM",
+    "latitude": "-88.062704",
+    "longitude": "149.95661"
+  },
+  {
+    "_id": "5c0e1839ffbbad5c9954e49f",
+    "index": 11,
+    "guid": "97a56950-a08c-4e00-8002-ba2d5de4da5d",
+    "isActive": false,
+    "balance": "$1,997.80",
+    "age": 31,
+    "firstName": "Sullivan",
+    "lastName": "Mcclain",
+    "company": "EARTHMARK",
+    "email": "sullivan.mcclain@earthmark.de",
+    "registered": "Saturday, October 27, 2018 2:51 PM",
+    "latitude": "-81.86349",
+    "longitude": "-79.596991"
+  },
+  {
+    "_id": "5c0e183914bd464d55e7325f",
+    "index": 12,
+    "guid": "294f6485-d0f9-4b25-b998-325ae90fa769",
+    "isActive": true,
+    "balance": "$1,405.46",
+    "age": 24,
+    "firstName": "Herminia",
+    "lastName": "Fischer",
+    "company": "ECOLIGHT",
+    "email": "herminia.fischer@ecolight.de",
+    "registered": "Thursday, January 16, 2014 4:48 PM",
+    "latitude": "48.224363",
+    "longitude": "11.08339"
+  },
+  {
+    "_id": "5c0e183968ec2556d8f6566c",
+    "index": 13,
+    "guid": "16edfea4-7b37-4e54-868c-c369b413dd78",
+    "isActive": false,
+    "balance": "$3,440.67",
+    "age": 39,
+    "firstName": "Blanchard",
+    "lastName": "Blackwell",
+    "company": "GEOFORMA",
+    "email": "blanchard.blackwell@geoforma.de",
+    "registered": "Wednesday, July 30, 2014 4:07 AM",
+    "latitude": "-52.169297",
+    "longitude": "10.415879"
+  },
+  {
+    "_id": "5c0e183939a0fc955f2d94da",
+    "index": 14,
+    "guid": "4ed454e2-dde1-4ab5-a434-4a82205ced2d",
+    "isActive": true,
+    "balance": "$1,883.27",
+    "age": 35,
+    "firstName": "Gayle",
+    "lastName": "Little",
+    "company": "AQUAZURE",
+    "email": "gayle.little@aquazure.de",
+    "registered": "Tuesday, December 12, 2017 5:08 PM",
+    "latitude": "-58.473236",
+    "longitude": "38.022269"
+  },
+  {
+    "_id": "5c0e1839099f9221ccd968ac",
+    "index": 15,
+    "guid": "1d052fd4-7c54-45fb-b0db-7de1acc4262a",
+    "isActive": false,
+    "balance": "$2,601.94",
+    "age": 31,
+    "firstName": "Jocelyn",
+    "lastName": "Richards",
+    "company": "GINK",
+    "email": "jocelyn.richards@gink.de",
+    "registered": "Sunday, October 30, 2016 9:12 PM",
+    "latitude": "-43.489676",
+    "longitude": "2.557869"
+  },
+  {
+    "_id": "5c0e183970f320f377321c3f",
+    "index": 16,
+    "guid": "45bca125-8831-48c3-b22b-29ae318e7096",
+    "isActive": false,
+    "balance": "$3,441.74",
+    "age": 34,
+    "firstName": "Berta",
+    "lastName": "Valentine",
+    "company": "ISOSPHERE",
+    "email": "berta.valentine@isosphere.de",
+    "registered": "Sunday, March 19, 2017 8:22 PM",
+    "latitude": "-40.188039",
+    "longitude": "-170.085092"
+  },
+  {
+    "_id": "5c0e1839ab960bb0a9f4f392",
+    "index": 17,
+    "guid": "d7b5122a-94c9-423c-b799-1a8f8314b152",
+    "isActive": false,
+    "balance": "$56.39",
+    "age": 21,
+    "firstName": "Russell",
+    "lastName": "Powers",
+    "company": "TETAK",
+    "email": "russell.powers@tetak.de",
+    "registered": "Thursday, November 3, 2016 9:23 PM",
+    "latitude": "-51.610519",
+    "longitude": "-133.280363"
+  },
+  {
+    "_id": "5c0e183998f0195404b9aaa4",
+    "index": 18,
+    "guid": "a043ba97-ea7e-48ce-bb15-18ee09fb393d",
+    "isActive": true,
+    "balance": "$1,503.57",
+    "age": 37,
+    "firstName": "Rosario",
+    "lastName": "Brennan",
+    "company": "VIAGRAND",
+    "email": "rosario.brennan@viagrand.de",
+    "registered": "Saturday, March 17, 2018 10:32 PM",
+    "latitude": "-43.773365",
+    "longitude": "47.58682"
+  },
+  {
+    "_id": "5c0e1839bcb2a5cc567129ac",
+    "index": 19,
+    "guid": "de6d5d36-201e-4f87-9976-ed31f3160e42",
+    "isActive": false,
+    "balance": "$1,160.18",
+    "age": 29,
+    "firstName": "Anita",
+    "lastName": "Hodges",
+    "company": "TUBALUM",
+    "email": "anita.hodges@tubalum.de",
+    "registered": "Sunday, November 26, 2017 11:54 AM",
+    "latitude": "7.080244",
+    "longitude": "-9.970715"
+  },
+  {
+    "_id": "5c0e18394b37e854a1ef371c",
+    "index": 20,
+    "guid": "9407113b-896a-4699-ac1b-363bc3c6f8ad",
+    "isActive": false,
+    "balance": "$34.81",
+    "age": 31,
+    "firstName": "Barrett",
+    "lastName": "Weaver",
+    "company": "DUOFLEX",
+    "email": "barrett.weaver@duoflex.de",
+    "registered": "Tuesday, November 3, 2015 9:31 AM",
+    "latitude": "40.30558",
+    "longitude": "-69.986664"
+  },
+  {
+    "_id": "5c0e1839b5658f90e16a86e0",
+    "index": 21,
+    "guid": "81f894c4-c931-422d-a30e-593824d95bf9",
+    "isActive": true,
+    "balance": "$2,808.63",
+    "age": 26,
+    "firstName": "Baxter",
+    "lastName": "Chase",
+    "company": "BUNGA",
+    "email": "baxter.chase@bunga.de",
+    "registered": "Friday, October 28, 2016 7:10 AM",
+    "latitude": "-49.05652",
+    "longitude": "63.123535"
+  },
+  {
+    "_id": "5c0e1839cb9462c9ecbb59af",
+    "index": 22,
+    "guid": "92e67862-4fdf-43af-a3ef-ef3edb8d6706",
+    "isActive": true,
+    "balance": "$3,552.71",
+    "age": 29,
+    "firstName": "Olga",
+    "lastName": "Kemp",
+    "company": "OHMNET",
+    "email": "olga.kemp@ohmnet.de",
+    "registered": "Saturday, March 26, 2016 11:51 AM",
+    "latitude": "-17.450481",
+    "longitude": "-13.945794"
+  },
+  {
+    "_id": "5c0e18396f999c2b8ac731a9",
+    "index": 23,
+    "guid": "a682eaae-34f0-4973-b8a0-30972de0732b",
+    "isActive": false,
+    "balance": "$1,999.20",
+    "age": 21,
+    "firstName": "Ebony",
+    "lastName": "Le",
+    "company": "MULTRON",
+    "email": "ebony.le@multron.de",
+    "registered": "Friday, March 27, 2015 9:23 AM",
+    "latitude": "-70.380014",
+    "longitude": "173.20685"
+  },
+  {
+    "_id": "5c0e18391cfb28263eb42db7",
+    "index": 24,
+    "guid": "f1cddb5f-0b89-453e-b0c9-8193a56cc610",
+    "isActive": true,
+    "balance": "$2,950.91",
+    "age": 30,
+    "firstName": "Norman",
+    "lastName": "Price",
+    "company": "COMVEX",
+    "email": "norman.price@comvex.de",
+    "registered": "Tuesday, August 21, 2018 11:17 PM",
+    "latitude": "86.501469",
+    "longitude": "159.545352"
+  },
+  {
+    "_id": "5c0e18394a6be11128c7e5ca",
+    "index": 25,
+    "guid": "dadb738a-40fd-45b6-abac-023a803d95c2",
+    "isActive": true,
+    "balance": "$2,767.09",
+    "age": 25,
+    "firstName": "Sara",
+    "lastName": "Ruiz",
+    "company": "AUSTECH",
+    "email": "sara.ruiz@austech.de",
+    "registered": "Wednesday, June 20, 2018 6:34 AM",
+    "latitude": "86.784904",
+    "longitude": "-120.331325"
+  },
+  {
+    "_id": "5c0e183974631549eda97cea",
+    "index": 26,
+    "guid": "b5c43ee5-14ed-4ab5-b3db-b31a8bb65ceb",
+    "isActive": true,
+    "balance": "$3,235.42",
+    "age": 32,
+    "firstName": "Holly",
+    "lastName": "Santos",
+    "company": "LOVEPAD",
+    "email": "holly.santos@lovepad.de",
+    "registered": "Thursday, November 22, 2018 9:26 PM",
+    "latitude": "-19.640066",
+    "longitude": "50.410992"
+  },
+  {
+    "_id": "5c0e1839ab9b933881429d78",
+    "index": 27,
+    "guid": "94961092-65ca-41b9-bc69-3e40ce2cafc9",
+    "isActive": true,
+    "balance": "$2,106.34",
+    "age": 39,
+    "firstName": "Rachel",
+    "lastName": "Douglas",
+    "company": "DEMINIMUM",
+    "email": "rachel.douglas@deminimum.de",
+    "registered": "Sunday, April 9, 2017 3:55 AM",
+    "latitude": "31.395281",
+    "longitude": "-1.899514"
+  },
+  {
+    "_id": "5c0e183937f743155859c5a9",
+    "index": 28,
+    "guid": "07d7ef18-bcef-483d-999e-0b3da4a7098b",
+    "isActive": true,
+    "balance": "$2,260.65",
+    "age": 40,
+    "firstName": "Reed",
+    "lastName": "Workman",
+    "company": "BUZZMAKER",
+    "email": "reed.workman@buzzmaker.de",
+    "registered": "Wednesday, May 28, 2014 3:44 PM",
+    "latitude": "23.789646",
+    "longitude": "106.938375"
+  },
+  {
+    "_id": "5c0e1839f8f4b60beb28b7ed",
+    "index": 29,
+    "guid": "9b4952e5-aa0e-4919-9e17-7c357a297394",
+    "isActive": false,
+    "balance": "$702.99",
+    "age": 27,
+    "firstName": "Cochran",
+    "lastName": "Ware",
+    "company": "HIVEDOM",
+    "email": "cochran.ware@hivedom.de",
+    "registered": "Monday, October 16, 2017 5:51 AM",
+    "latitude": "85.953108",
+    "longitude": "124.590037"
+  },
+  {
+    "_id": "5c0e1839342fbd54a88269df",
+    "index": 30,
+    "guid": "30937d5b-9514-4ebd-b628-2cfb5017fe41",
+    "isActive": false,
+    "balance": "$385.88",
+    "age": 35,
+    "firstName": "Cote",
+    "lastName": "Hess",
+    "company": "TERAPRENE",
+    "email": "cote.hess@teraprene.de",
+    "registered": "Thursday, March 15, 2018 4:42 PM",
+    "latitude": "81.38211",
+    "longitude": "64.516797"
+  },
+  {
+    "_id": "5c0e18395b6dc85d73ce1fb3",
+    "index": 31,
+    "guid": "f34847da-7f96-4cd8-8d8a-b06c0eb0a8f2",
+    "isActive": true,
+    "balance": "$3,494.56",
+    "age": 27,
+    "firstName": "Daniels",
+    "lastName": "Ayala",
+    "company": "BESTO",
+    "email": "daniels.ayala@besto.de",
+    "registered": "Sunday, December 18, 2016 10:52 AM",
+    "latitude": "47.704227",
+    "longitude": "41.674767"
+  },
+  {
+    "_id": "5c0e183974587cdccf30b13f",
+    "index": 32,
+    "guid": "fdbb6d83-0e47-4453-b8a7-b47f44e4164b",
+    "isActive": false,
+    "balance": "$2,087.38",
+    "age": 26,
+    "firstName": "Powers",
+    "lastName": "Drake",
+    "company": "GENESYNK",
+    "email": "powers.drake@genesynk.de",
+    "registered": "Saturday, September 29, 2018 12:24 AM",
+    "latitude": "40.580432",
+    "longitude": "110.940759"
+  },
+  {
+    "_id": "5c0e18397b51245e971c58b8",
+    "index": 33,
+    "guid": "6adfe544-238b-4001-b2a6-f50ea3094da3",
+    "isActive": true,
+    "balance": "$3,566.22",
+    "age": 34,
+    "firstName": "Pacheco",
+    "lastName": "Ramsey",
+    "company": "ENVIRE",
+    "email": "pacheco.ramsey@envire.de",
+    "registered": "Friday, September 11, 2015 12:14 AM",
+    "latitude": "-30.691235",
+    "longitude": "69.343692"
+  },
+  {
+    "_id": "5c0e18391ede9c0996fd09e7",
+    "index": 34,
+    "guid": "d190b32f-d33b-4c17-a18a-bb2f57e79ba7",
+    "isActive": false,
+    "balance": "$1,671.63",
+    "age": 32,
+    "firstName": "Mcintyre",
+    "lastName": "Chan",
+    "company": "ORBAXTER",
+    "email": "mcintyre.chan@orbaxter.de",
+    "registered": "Wednesday, May 7, 2014 7:11 PM",
+    "latitude": "7.380435",
+    "longitude": "70.955103"
+  },
+  {
+    "_id": "5c0e1839fe48069c9c260fa9",
+    "index": 35,
+    "guid": "a41c064b-6bf4-4ba5-b229-9b657d286936",
+    "isActive": false,
+    "balance": "$24.02",
+    "age": 27,
+    "firstName": "Genevieve",
+    "lastName": "Sparks",
+    "company": "ZBOO",
+    "email": "genevieve.sparks@zboo.de",
+    "registered": "Saturday, December 16, 2017 2:51 PM",
+    "latitude": "-63.406337",
+    "longitude": "118.662621"
+  },
+  {
+    "_id": "5c0e1839a7e8e76accf0803e",
+    "index": 36,
+    "guid": "3e71864d-4be5-418e-ace8-346c3d7a9c5f",
+    "isActive": true,
+    "balance": "$3,261.01",
+    "age": 30,
+    "firstName": "Powell",
+    "lastName": "Patterson",
+    "company": "GAZAK",
+    "email": "powell.patterson@gazak.de",
+    "registered": "Thursday, May 18, 2017 10:10 AM",
+    "latitude": "-10.428548",
+    "longitude": "64.979192"
+  },
+  {
+    "_id": "5c0e183984b0320f1118a8b0",
+    "index": 37,
+    "guid": "ec5b292c-6efb-471b-9bf5-a47286e03515",
+    "isActive": false,
+    "balance": "$918.71",
+    "age": 37,
+    "firstName": "Tara",
+    "lastName": "Mcmillan",
+    "company": "GRAINSPOT",
+    "email": "tara.mcmillan@grainspot.de",
+    "registered": "Sunday, May 17, 2015 1:01 PM",
+    "latitude": "-13.519031",
+    "longitude": "67.931062"
+  },
+  {
+    "_id": "5c0e183965875876835ccd79",
+    "index": 38,
+    "guid": "b7e97ffb-439a-4454-90af-7f5ebd565ebc",
+    "isActive": true,
+    "balance": "$574.99",
+    "age": 28,
+    "firstName": "Pennington",
+    "lastName": "Gallegos",
+    "company": "CEDWARD",
+    "email": "pennington.gallegos@cedward.de",
+    "registered": "Wednesday, September 26, 2018 6:01 AM",
+    "latitude": "-63.693261",
+    "longitude": "-38.352153"
+  },
+  {
+    "_id": "5c0e183922505dd21be49009",
+    "index": 39,
+    "guid": "5187aa39-4357-462b-9508-3c537d26d70d",
+    "isActive": false,
+    "balance": "$2,447.08",
+    "age": 26,
+    "firstName": "Meagan",
+    "lastName": "Irwin",
+    "company": "SENTIA",
+    "email": "meagan.irwin@sentia.de",
+    "registered": "Saturday, April 2, 2016 4:39 PM",
+    "latitude": "1.051313",
+    "longitude": "-86.168315"
+  },
+  {
+    "_id": "5c0e183900a9f7f896e5b3b1",
+    "index": 40,
+    "guid": "31889843-79e7-4636-9ca1-4eb5cbcb0ae3",
+    "isActive": true,
+    "balance": "$1,992.25",
+    "age": 22,
+    "firstName": "Kelly",
+    "lastName": "Cobb",
+    "company": "BOVIS",
+    "email": "kelly.cobb@bovis.de",
+    "registered": "Tuesday, August 9, 2016 5:36 PM",
+    "latitude": "-85.547579",
+    "longitude": "-89.794104"
+  },
+  {
+    "_id": "5c0e18393b25b8552ff950e2",
+    "index": 41,
+    "guid": "0bf02edc-ca1b-4cfe-8356-b65881bdca11",
+    "isActive": true,
+    "balance": "$465.96",
+    "age": 27,
+    "firstName": "Angela",
+    "lastName": "Booker",
+    "company": "EQUICOM",
+    "email": "angela.booker@equicom.de",
+    "registered": "Thursday, July 30, 2015 1:39 AM",
+    "latitude": "-9.345395",
+    "longitude": "107.070665"
+  },
+  {
+    "_id": "5c0e183955d747ebbe25437b",
+    "index": 42,
+    "guid": "6405e559-5849-4d12-ae4e-520f13b4dffe",
+    "isActive": true,
+    "balance": "$15.63",
+    "age": 28,
+    "firstName": "Carrie",
+    "lastName": "Mclean",
+    "company": "BOINK",
+    "email": "carrie.mclean@boink.de",
+    "registered": "Wednesday, February 1, 2017 1:50 PM",
+    "latitude": "72.287519",
+    "longitude": "-135.436286"
+  },
+  {
+    "_id": "5c0e1839e9cfe1b28e31e7e6",
+    "index": 43,
+    "guid": "e49e7ca7-a6cc-4cdb-bebe-5a3b6ba931eb",
+    "isActive": true,
+    "balance": "$3,127.94",
+    "age": 33,
+    "firstName": "Callie",
+    "lastName": "Cooley",
+    "company": "MUSIX",
+    "email": "callie.cooley@musix.de",
+    "registered": "Wednesday, August 30, 2017 4:58 PM",
+    "latitude": "-38.954739",
+    "longitude": "-152.706424"
+  },
+  {
+    "_id": "5c0e18391bafa0750ff4f280",
+    "index": 44,
+    "guid": "c245ffd3-4924-4dce-ae4a-f4cabf057b54",
+    "isActive": false,
+    "balance": "$1,320.36",
+    "age": 35,
+    "firstName": "Terry",
+    "lastName": "Bennett",
+    "company": "EXOTECHNO",
+    "email": "terry.bennett@exotechno.de",
+    "registered": "Friday, June 17, 2016 11:54 PM",
+    "latitude": "-48.946183",
+    "longitude": "32.53167"
+  },
+  {
+    "_id": "5c0e1839e91b27fcce34b70f",
+    "index": 45,
+    "guid": "0860cb66-de4c-410e-8233-aeef5ee9d64e",
+    "isActive": false,
+    "balance": "$1,187.75",
+    "age": 30,
+    "firstName": "Phoebe",
+    "lastName": "Bartlett",
+    "company": "VORATAK",
+    "email": "phoebe.bartlett@voratak.de",
+    "registered": "Tuesday, July 25, 2017 2:57 AM",
+    "latitude": "-63.208957",
+    "longitude": "-91.209743"
+  },
+  {
+    "_id": "5c0e183987e8a4e98415c8dd",
+    "index": 46,
+    "guid": "49219833-172c-4659-9192-d1116a5ca833",
+    "isActive": false,
+    "balance": "$3,225.24",
+    "age": 38,
+    "firstName": "Jordan",
+    "lastName": "Evans",
+    "company": "PHARMACON",
+    "email": "jordan.evans@pharmacon.de",
+    "registered": "Sunday, April 23, 2017 6:27 PM",
+    "latitude": "-59.454678",
+    "longitude": "67.251185"
+  },
+  {
+    "_id": "5c0e183944979692cc1a3e48",
+    "index": 47,
+    "guid": "680c4d15-d539-4db9-8793-a2f6d3f354aa",
+    "isActive": false,
+    "balance": "$2,913.14",
+    "age": 28,
+    "firstName": "Goodman",
+    "lastName": "Cain",
+    "company": "CAXT",
+    "email": "goodman.cain@caxt.de",
+    "registered": "Tuesday, November 1, 2016 6:11 PM",
+    "latitude": "-30.187547",
+    "longitude": "-164.313273"
+  },
+  {
+    "_id": "5c0e1839ef5312ac08e3cbc3",
+    "index": 48,
+    "guid": "85f5fa5d-b6b3-47c6-ad1b-faee10a4e1bd",
+    "isActive": true,
+    "balance": "$544.97",
+    "age": 27,
+    "firstName": "Aisha",
+    "lastName": "Oliver",
+    "company": "MINGA",
+    "email": "aisha.oliver@minga.de",
+    "registered": "Sunday, July 3, 2016 8:18 AM",
+    "latitude": "-21.527536",
+    "longitude": "141.029691"
+  },
+  {
+    "_id": "5c0e1839c2e58f5da04f29fd",
+    "index": 49,
+    "guid": "e2ee9b25-5887-49a9-a1c6-17432154d266",
+    "isActive": true,
+    "balance": "$3,621.65",
+    "age": 31,
+    "firstName": "Erin",
+    "lastName": "Lester",
+    "company": "SLOFAST",
+    "email": "erin.lester@slofast.de",
+    "registered": "Saturday, February 20, 2016 5:13 AM",
+    "latitude": "-30.080798",
+    "longitude": "-1.291093"
+  }
+];
+
+const components = {
+  'counter': 'demoApp.counter'
+};
+
+type TreeDemoItem = TreeItem<string>;
+
+const treeData: TreeDemoItem[] = [
+  {
+    content: "Erste Ebene", children: [
+      {
+        content: "Zweite Ebene", children: [
+          { content: "Dritte Ebene" },
+        ]
+      },
+      { content: "Zweite Ebene 2" },
+    ]
+  },
+  { content: "Erste Ebene 3" },
+];
+
+const SampleDataMaterialTable = MaterialTable as MaterialTableCtorType<SampleData>;
+
+const SampleTree = TreeView as any as TreeViewCtorType<string>;
+
+const TestComponent = (props: WithComponents<typeof components> & WithStyles<typeof styles>) => {
+
+  return (
+    <div>
+      <h2>About</h2>
+      <Accordion>
+        <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+          <Typography className={props.classes.heading}>Client Side Table Demo</Typography>
+        </AccordionSummary>
+        <AccordionDetails>
+          <SampleDataMaterialTable rows={tableData} tableId={null} columns={
+            [
+              { property: "index", type: ColumnType.text, title: "Index", width: "80px", disableFilter: true, disableSorting: true },
+              { property: "firstName", type: ColumnType.text, title: "First Name" },
+              { property: "lastName", type: ColumnType.text, title: "Last Name" },
+              { property: "age", type: ColumnType.numeric, title: "Age", width: "60px" },
+              { property: "email", type: ColumnType.text, title: "eMail" },
+              { property: "actions", type: ColumnType.custom, title: "Actions", customControl: ({ rowData }) => (<div>Button</div>) },
+            ]
+          } idProperty={"_id"} title={"Customers 2018"} >
+          </SampleDataMaterialTable>
+        </AccordionDetails>
+      </Accordion>
+      <Accordion>
+        <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+          <Typography className={props.classes.heading}>Tree Demo</Typography>
+        </AccordionSummary>
+        <AccordionDetails>
+          <SampleTree items={treeData} useFolderIcons enableSearchBar />
+        </AccordionDetails>
+      </Accordion>
+    </div>
+  );
+};
+
+export const Test = withComponents(components)(withStyles(styles)(TestComponent));
+export default Test;
diff --git a/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json b/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json
new file mode 100644
index 0000000..1d9af90
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json
@@ -0,0 +1,19 @@
+{
+    "version":"##buildno##",
+    "build":"##build-timestamp##",
+    "framework":"##odlux.framework.buildno##",
+    "applications":{
+        "configurationApp":"##odlux.apps.configurationApp.buildno##",
+        "connectApp":"##odlux.apps.connectApp.buildno##",
+        "eventLogApp":"##odlux.apps.eventLogApp.buildno##",
+        "faultApp":"##odlux.apps.faultApp.buildno##",
+        "helpApp":"##odlux.apps.helpApp.buildno##",
+        "inventoryApp":"##odlux.apps.inventoryApp.buildno##",
+        "linkCalculationApp":"##odlux.apps.linkCalculationApp.buildno##",
+        "maintenanceApp":"##odlux.apps.maintenanceApp.buildno##",
+        "mediatorApp":"##odlux.apps.mediatorApp.buildno##",
+        "networkMapApp":"##odlux.apps.networkMapApp.buildno##",
+        "permanceHistoryApp":"##odlux.apps.permanceHistoryApp.buildno##"
+    
+    }
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/tsconfig.json b/sdnr/wt-odlux/odlux/framework/tsconfig.json
new file mode 100644
index 0000000..cb36bc8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/tsconfig.json
@@ -0,0 +1,39 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "node",
+      "prop-types",
+      "react",
+      "react-dom",
+      "jest"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/framework/webpack.config.js b/sdnr/wt-odlux/odlux/framework/webpack.config.js
new file mode 100644
index 0000000..b7bbacb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/webpack.config.js
@@ -0,0 +1,265 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const requirejsPlugin = require('requirejs-webpack-plugin');
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+  return [{
+    name: "Client",
+    mode: "none", //disable default behavior
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      app: [
+        "./run.ts",
+        "./app.tsx",
+        "./services",
+        "./components/objectDump",
+        "./components/material-table",
+        "./components/material-ui",
+        "./utilities/elasticSearch",
+        "./models"],
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      library: "[name]", // related to webpack.DllPlugin::name
+      libraryTarget: "umd2",
+      filename: "[name].js",
+      chunkFilename: "[name].js"
+    },
+
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }, 
+      {
+        //don't minify images
+        test: /\.(png|gif|jpg|svg)$/,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 10,
+            name: './images/[name].[ext]'
+          }
+        }]
+      }
+      ]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          mangle: {
+            reserved: ["./app.tsx"]
+          },
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      new CopyWebpackPlugin([{
+        from: '../../node_modules/requirejs/require.js',
+        to: '.'
+      }, {
+        from: './favicon.ico',
+        to: '.'
+      }, {
+        from: env === "release" ? './index.html' : 'index.dev.html',
+        to: './index.html'
+      }]),
+      new requirejsPlugin({
+        path: distPath,
+        filename: 'config.js',
+        baseUrl: '',
+        pathUrl: '',
+        processOutput: function (assets) {
+          let mainConfig =  JSON.stringify(assets, null, 2);
+          mainConfig = mainConfig.slice(0,-1); // remove closing bracket from string
+          const entireConfig = mainConfig.concat(", waitSeconds: 30}"); // add waitSeconds to config
+          return 'require.config(' + entireConfig + ')';
+        }
+      }),
+      // new HtmlWebpackPlugin({
+      //   filename: "index.html",
+      //   template: "./index.html",
+      //   inject: "head"
+      // }),
+      // new HtmlWebpackIncludeAssetsPlugin({
+      //    assets: ['vendor.js'],
+      //    append: false
+      // }),
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "src"),
+        manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+        sourceType: "umd2"
+      }),
+      new webpack.DllPlugin({
+        context: path.resolve(__dirname, "src"),
+        name: "[name]",
+        path: path.resolve(distPath, "[name]-manifest.json")
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        }),
+      ] : [
+          new webpack.HotModuleReplacementPlugin(),
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new webpack.WatchIgnorePlugin([
+            /css\.d\.ts$/,
+            /less\.d\.ts$/
+          ]),
+          new CopyWebpackPlugin([{
+            from: './assets/version.json',
+            to: './version.json'
+          }])
+        ])
+    ],
+
+    devServer: {
+      public: "http://localhost:3100",
+      contentBase: distPath,
+
+      compress: true,
+      headers: {
+        "Access-Control-Allow-Origin": "*"
+      },
+      host: "0.0.0.0",
+      port: 3100,
+      disableHostCheck: true,
+      historyApiFallback: true,
+      inline: true,
+      hot: false,
+      quiet: false,
+      stats: {
+        colors: true
+      },
+      proxy: {
+        "/about": {
+          // target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          secure: false
+        }, 
+        "/yang-schema/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },   
+        "/oauth/": {
+          // target: "https://10.20.35.188:30205",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/oauth2/": {
+          // target: "https://10.20.35.188:30205",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/database/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/help/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+         "/about/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/tree/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/websocket": {
+          target: "http://sdnr:8181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        },
+        "/apidoc": {
+          target: "http://sdnr:8181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+    }
+  }];
+}
+
+
diff --git a/sdnr/wt-odlux/odlux/framework/webpack.runner.js b/sdnr/wt-odlux/odlux/framework/webpack.runner.js
new file mode 100644
index 0000000..02bcf6b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/webpack.runner.js
@@ -0,0 +1,85 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+  return [{
+    name: "App",
+
+    mode: "none", //disable default behavior
+
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      run: ["./run.ts"]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      filename: "[name].js",
+      library: "[name]",
+      libraryTarget: "umd2",
+      chunkFilename: "[name].js"
+    },
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      }, {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      }]
+    },
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+    plugins: [
+      new webpack.DllReferencePlugin({
+        context: path.resolve(__dirname, "./src"),
+        manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+        sourceType: "umd2"
+      }),
+
+    ]
+  }
+  ];
+};
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/framework/webpack.vendor.js b/sdnr/wt-odlux/odlux/framework/webpack.vendor.js
new file mode 100644
index 0000000..2d618b7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/webpack.vendor.js
@@ -0,0 +1,127 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+
+const TerserPlugin = require('terser-webpack-plugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const extractCSS = new ExtractTextPlugin('vendor.css');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+  const distPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+  const frameworkPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+  return [{
+    name: "Vendor",
+    mode: "none", //disable default behavior
+    target: "web",
+
+    context: path.resolve(__dirname, "src"),
+
+    entry: {
+      vendor: [
+        "@babel/polyfill",
+        "@fortawesome/fontawesome-svg-core",
+        "@fortawesome/free-solid-svg-icons",
+        "@fortawesome/react-fontawesome",
+        "jquery",
+        "react",
+        "react-dom",
+        "react-router-dom",
+        "@mui/material"
+      ]
+    },
+
+    devtool: env === "release" ? false : "source-map",
+
+    resolve: {
+      extensions: [".ts", ".tsx", ".js", ".jsx"]
+    },
+
+    output: {
+      path: distPath,
+      library: "[name]", // related to webpack.DllPlugin::name
+      libraryTarget: "umd2",
+      filename: "[name].js",
+      chunkFilename: "[name].js"
+    },
+
+    module: {
+      rules: [{
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }, {
+          loader: "ts-loader"
+        }]
+      },
+      {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: [{
+          loader: "babel-loader"
+        }]
+      },
+      {
+        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
+        loader: 'url-loader?limit=100000&name=assets/[name].[ext]'
+      },  {
+        test: /\.json$/,
+        loader: 'json-loader'
+      },
+      ]
+    },
+
+    optimization: {
+      noEmitOnErrors: true,
+      namedModules: env !== "release",
+      minimize: env === "release",
+      minimizer: env !== "release" ? [] : [new TerserPlugin({
+        terserOptions: {
+          warnings: false, // false, true, "verbose"
+          compress: {
+            drop_console: true,
+            drop_debugger: true,
+          }
+        }
+      })],
+    },
+
+    plugins: [
+      extractCSS,
+      new webpack.DllPlugin({
+        context: path.resolve(__dirname, "src"),
+        name: "[name]",
+        path: path.resolve(distPath, "[name]-manifest.json")
+      }),
+      ...(env === "release" ? [
+        new webpack.DefinePlugin({
+          "process.env": {
+            NODE_ENV: "'production'",
+            VERSION: JSON.stringify(require("./package.json").version)
+          }
+        })
+      ] : [
+          new webpack.HotModuleReplacementPlugin(),
+          new webpack.DefinePlugin({
+            "process.env": {
+              NODE_ENV: "'development'",
+              VERSION: JSON.stringify(require("./package.json").version)
+            }
+          }),
+          new webpack.WatchIgnorePlugin([
+            /s?css\.d\.ts$/,
+            /less\.d\.ts$/
+          ])
+        ])
+    ]
+  }];
+}
diff --git a/sdnr/wt-odlux/odlux/installer/pom.xml b/sdnr/wt-odlux/odlux/installer/pom.xml
new file mode 100644
index 0000000..7342b03
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/installer/pom.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux-installer</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <application.name>sdnr-odlux-installer</application.name>
+        <include.transitive.dependencies>false</include.transitive.dependencies>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>maven-repo-zip</id>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                            <attach>true</attach>
+                            <finalName>stage/${application.name}-${project.version}</finalName>
+                            <descriptors>
+                                <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+                            </descriptors>
+                            <appendAssemblyId>true</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>unpack features</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <includes>odlux/**</includes>
+                            <outputDirectory>${project.build.directory}/assembly</outputDirectory>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-framework</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- connectApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-connectApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- eventLogApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-eventLogApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- helpApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-helpApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- maintenanceApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-maintenanceApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- minimumApp -->
+                                <!--<artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-minimumApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>-->
+                                <!-- configurationApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-configurationApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- demoApp -->
+                                <!--<artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-demoApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>-->
+                                <!-- faultApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-faultApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- inventoryApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-inventoryApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- performanceHistoryApp -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-app-performanceHistoryApp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                </artifactItem>
+                                <!-- helpserver resources -->
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sdnr-odlux-helpserver-provider</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>false</overWrite>
+                                    <includes>help/**</includes>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt-odlux/odlux/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 0000000..c5dc077
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,53 @@
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : ccsdk features
+  ~ ================================================================================
+  ~ Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+    <id>repo</id>
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <!--  we want "system" and related files right at the root level
+          as this file is suppose to be unzip on top of a karaf
+          distro. -->
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+      <fileSet>
+            <directory>apps/connectApp/dist</directory>
+            <outputDirectory>.</outputDirectory>
+            <excludes>
+            </excludes>
+        </fileSet>
+        <fileSet>
+            <directory>target/assembly/</directory>
+            <outputDirectory>.</outputDirectory>
+            <excludes>
+            </excludes>
+        </fileSet>
+    </fileSets>
+
+</assembly>
diff --git a/sdnr/wt-odlux/odlux/jest.json b/sdnr/wt-odlux/odlux/jest.json
new file mode 100644
index 0000000..5d6e748
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/jest.json
@@ -0,0 +1,18 @@
+{
+  "moduleFileExtensions": [
+    "ts",
+    "tsx",
+    "js",
+    "jsx"
+  ],
+  "moduleNameMapper": {
+    "^@odlux/framework$": "<rootDir>/framework/src",
+    "^@odlux/(.*)$": "<rootDir>/apps/$1/src"
+  },
+  "transform": {
+    "^.+\\.(ts|tsx)$": "ts-jest"
+  },
+  "testMatch": [
+    "**/*-test.(ts|tsx)"
+  ]
+}
\ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/lerna.json b/sdnr/wt-odlux/odlux/lerna.json
new file mode 100644
index 0000000..2ee1b49
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/lerna.json
@@ -0,0 +1,14 @@
+{
+  "version": "independent",
+  "command": {
+    "init": {
+      "exact": true
+    }
+  },
+  "npmClient": "yarn",
+  "useWorkspaces": true,
+  "packages": [
+    "framework",
+    "apps/*"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/lib/broadcast/mapChannel.ts b/sdnr/wt-odlux/odlux/lib/broadcast/mapChannel.ts
new file mode 100644
index 0000000..efd76eb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/lib/broadcast/mapChannel.ts
@@ -0,0 +1,29 @@
+
+const channel: BroadcastChannel = new BroadcastChannel("odlux_map");
+const listeners: { [key: string]: ((data: any) => void)[] } = {};
+
+channel.onmessage = (eventMessage: MessageEvent<any>) => {
+  const { key, data } = eventMessage.data;
+  if (listeners[key]) {
+    listeners[key].forEach(listener => listener(data));
+  }
+};
+
+export const sendMapMessage = (data: any, key: string) => {
+  channel.postMessage({ key, data });
+};
+
+export const addMapMessageListener = (key: string, listener: (data: any) => void) => {
+  if (!listeners[key]) {
+    listeners[key] = [];
+  }
+  
+  if (!listeners[key].find(l => l === listener)) {
+    listeners[key].push(listener);
+  }
+
+  return () => {
+    listeners[key] = listeners[key].filter(l => l !== listener);
+  }
+};
+
diff --git a/sdnr/wt-odlux/odlux/odlux.properties b/sdnr/wt-odlux/odlux/odlux.properties
new file mode 100644
index 0000000..c4424ac
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/odlux.properties
@@ -0,0 +1,14 @@
+odlux.framework.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.configurationApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.connectApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.eventLogApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.faultApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.helpApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.inventoryApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.linkCalculationApp.buildno=171.5e3c222(22/09/30)
+odlux.apps.maintenanceApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.mediatorApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.networkMapApp.buildno=172.b89e2c2b(23/10/04)
+odlux.apps.lineOfSightApp.buildno=168.38fd458(22/09/16)
+odlux.apps.permanceHistoryApp.buildno=81.1c38886(20/12/04)
+odlux.apps.siteManagerApp=164.e02f116(22/08/12)
diff --git a/sdnr/wt-odlux/odlux/package.json b/sdnr/wt-odlux/odlux/package.json
new file mode 100644
index 0000000..c90cf1d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/package.json
@@ -0,0 +1,101 @@
+{
+  "private": true,
+  "version": "0.1.0",
+  "workspaces": [
+    "framework",
+    "apps/*"
+  ],
+  "scripts": {
+    "init": "lerna bootstrap --hoist",
+    "build": "lerna build",
+    "test": "jest --no-cache --coverage --config jest.json"
+  },
+  "dependencies": {
+    "@emotion/react": "^11.7.0",
+    "@emotion/styled": "^11.6.0",
+    "@fortawesome/fontawesome-svg-core": "1.2.35",
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@fortawesome/react-fontawesome": "0.1.14",
+    "@mui/icons-material": "^5.2.0",
+    "@mui/lab": "^5.0.0-alpha.58",
+    "@mui/material": "^5.2.2",
+    "@mui/styles": "^5.2.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/glob-to-regexp": "0.4.0",
+    "@types/history": "^4.7.9",
+    "@types/jquery": "3.3.10",
+    "@types/jsonwebtoken": "7.2.8",
+    "@types/node": "^12.0.0",
+    "@types/react": "17.0.37",
+    "@types/react-dom": "17.0.11",
+    "@types/react-router-dom": "5.1.7",
+    "@types/react-transition-group": "2.0.15",
+    "classnames": "2.2.6",
+    "csstype": "2.6.8",
+    "history": "^4.9.0",
+    "jquery": "3.3.1",
+    "jsonwebtoken": "8.3.0",
+    "jss": "10.0.3",
+    "material-ui-confirm": "3.0.2",
+    "notistack": "2.0.3",
+    "prop-types": "15.7.2",
+    "react": "17.0.2",
+    "react-dom": "17.0.2",
+    "react-router-dom": "5.2.0",
+    "react-split-pane": "0.1.92",
+    "react-transition-group": "4.3.0"
+  },
+  "devDependencies": {
+    "@babel/core": "7.1.0",
+    "@babel/polyfill": "7.0.0",
+    "@babel/preset-env": "7.1.0",
+    "@babel/preset-react": "7.0.0",
+    "@octokit/core": "3.0.0",
+    "@types/jest": "23.3.12",
+    "@typescript-eslint/eslint-plugin": "5.42.0",
+    "@typescript-eslint/parser": "5.42.0",
+    "autoprefixer": "9.1.5",
+    "babel-loader": "8.0.4",
+    "copy-webpack-plugin": "4.5.2",
+    "css-loader": "1.0.0",
+    "eslint": "8.26.0",
+    "eslint-config-airbnb": "19.0.4",
+    "eslint-config-airbnb-typescript": "17.0.0",
+    "eslint-plugin-import": "2.26.0",
+    "eslint-plugin-jsx-a11y": "6.6.1",
+    "eslint-plugin-react": "7.31.10",
+    "eslint-plugin-react-hooks": "4.6.0",
+    "extract-text-webpack-plugin": "next",
+    "file-loader": "2.0.0",
+    "glob-to-regexp": "0.4.1",
+    "html-webpack-include-assets-plugin": "1.0.5",
+    "html-webpack-plugin": "3.2.0",
+    "jest": "23.6.0",
+    "lerna": "3.22.1",
+    "postcss-loader": "3.0.0",
+    "requirejs": "2.3.6",
+    "requirejs-webpack-plugin": "1.0.5",
+    "rimraf": "2.6.2",
+    "style-loader": "0.23.0",
+    "terser-webpack-plugin": "1.2.1",
+    "ts-jest": "23.10.5",
+    "ts-loader": "5.2.1",
+    "tslint": "5.12.1",
+    "tslint-config-airbnb": "5.11.1",
+    "tslint-config-airbnb-base": "0.2.0",
+    "tslint-config-prettier": "1.17.0",
+    "tslint-eslint-rules": "4.1.1",
+    "tslint-react": "3.6.0",
+    "tslint-react-recommended": "1.0.15",
+    "typescript": "4.1.4",
+    "typings-for-css-modules-loader": "1.7.0",
+    "url-loader": "1.1.2",
+    "webpack": "4.28.4",
+    "webpack-cli": "3.2.1",
+    "webpack-dev-server": "3.1.14"
+  },
+  "resolutions": {
+    "@types/react": "17.0.37"
+  }
+}
diff --git a/sdnr/wt-odlux/odlux/pom.xml b/sdnr/wt-odlux/odlux/pom.xml
new file mode 100644
index 0000000..c19c667
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : SDNR ODLUX
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>odlux-top</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>SDNR ODLUX :: ${project.artifactId}</name>
+
+    <modules>
+        <module>framework</module>
+        <module>apps/apiDemo</module>
+        <module>apps/connectApp</module>
+        <module>apps/demoApp</module>
+        <module>apps/faultApp</module>
+        <module>apps/helpApp</module>
+        <module>apps/inventoryApp</module>
+        <module>apps/maintenanceApp</module>
+        <module>apps/minimumApp</module>
+        <module>apps/performanceHistoryApp</module>
+        <module>apps/eventLogApp</module>
+        <module>apps/configurationApp</module>
+        <module>apps/app-installer</module>
+        <module>installer</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <executions>
+                    <execution><!-- Run our version calculation script -->
+                        <id>Clean node and node_modules</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <executable>rm</executable>
+                            <arguments>
+                                <argument>-r</argument>
+                                <argument>node_modules</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/proxy.conf.js b/sdnr/wt-odlux/odlux/proxy.conf.js
new file mode 100644
index 0000000..e5b91b6
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/proxy.conf.js
@@ -0,0 +1,106 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+module.exports = {
+  "/about": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/yang-schema/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/oauth/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/database/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/restconf/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/rests/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/userdata": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/userdata/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/help/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/about/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/tree/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/sitedoc/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+  "/topology/": {
+    target: "http://sdncweb:8080",
+    secure: false
+  },
+
+  "/websocket": {
+    target: "http://sdncweb:8080",
+    ws: true,
+    changeOrigin: true,
+    secure: false
+  },
+  "/apidoc": {
+    target: "http://sdncweb:8080",
+    ws: true,
+    changeOrigin: true,
+    secure: false
+  },
+  "/tiles/": {
+    target: "http://sdncweb:8080",
+    headers: {
+      "Connection": "keep-alive"
+    },
+    secure: false
+  },
+  "/swagger/": {
+    target: "http://swagger.t1.lab.osn-lab.com",
+    secure: false,
+    pathRewrite(pathname) {
+      return pathname.replace(/^\/swagger/, '/');
+    }
+  },
+  "/electromagnetic-field/": {
+    target: "http://sdncweb:8080",
+    ws: true,
+    changeOrigin: true,
+    secure: false
+  },
+}
+
diff --git a/sdnr/wt-odlux/odlux/test.txt b/sdnr/wt-odlux/odlux/test.txt
new file mode 100644
index 0000000..43cf1c8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/test.txt
Binary files differ
diff --git a/sdnr/wt-odlux/odlux/tsconfig.json b/sdnr/wt-odlux/odlux/tsconfig.json
new file mode 100644
index 0000000..c4cc6e0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/tsconfig.json
@@ -0,0 +1,39 @@
+{
+  "compilerOptions": {
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": true,
+    "allowUnreachableCode": false,
+    "allowUnusedLabels": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "noImplicitReturns": true,
+    "noImplicitThis": true,
+    "strictNullChecks": true,
+    "pretty": true,
+    "newLine": "LF",
+    "module": "es2015",
+    "target": "es2016",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "jsx": "preserve",
+    "lib": [
+      "dom",
+      "es2015",
+      "es2016"
+    ],
+    "types": [
+      "prop-types",
+      "react",
+      "react-dom"
+    ]
+  },
+  "exclude": [
+    "node_modules",
+    "apps/*/dist",
+    "apps/*/node_modules"
+  ],
+  "include": [
+    "apps/*/src"
+  ]
+}
diff --git a/sdnr/wt-odlux/odlux/yarn.lock b/sdnr/wt-odlux/odlux/yarn.lock
new file mode 100644
index 0000000..652947d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/yarn.lock
@@ -0,0 +1,12853 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35", "@babel/code-frame@^7.21.4":
+  version "7.21.4"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39"
+  integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==
+  dependencies:
+    "@babel/highlight" "^7.18.6"
+
+"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.0.tgz#bdceda7e6bcbe92475b497e35c868479635affe7"
+  integrity sha512-OgCMbbNCD/iA8cjMt+Zhp+nIC7XKaEaTG8zjvZPjGbhkppq1NIMWiZn7EaZRxUDHn4Ul265scRqg94N2WiFaGw==
+
+"@babel/core@7.1.0":
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.0.tgz#08958f1371179f62df6966d8a614003d11faeb04"
+  integrity sha512-9EWmD0cQAbcXSc+31RIoYgEHx3KQ2CCSMDBhnXrShWvo45TMw+3/55KVxlhkG53kw9tl87DqINgHDgFVhZJV/Q==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/generator" "^7.0.0"
+    "@babel/helpers" "^7.1.0"
+    "@babel/parser" "^7.1.0"
+    "@babel/template" "^7.1.0"
+    "@babel/traverse" "^7.1.0"
+    "@babel/types" "^7.0.0"
+    convert-source-map "^1.1.0"
+    debug "^3.1.0"
+    json5 "^0.5.0"
+    lodash "^4.17.10"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
+"@babel/generator@^7.0.0", "@babel/generator@^7.22.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.0.tgz#59241bf17ab7a9b0f7c339e16355366ef2a1a6e2"
+  integrity sha512-tyzR0OsH88AelgukhL2rbEUCLKBGmy2G9Th/5vpyOt0zf44Be61kvIQXjCwTSX8t+qJ/vMwZfhK6mPdrMLZXRg==
+  dependencies:
+    "@babel/types" "^7.22.0"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    "@jridgewell/trace-mapping" "^0.3.17"
+    jsesc "^2.5.1"
+
+"@babel/helper-annotate-as-pure@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
+  integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.0.tgz#9417d188b520074aa051d91661d65b7268cba3fb"
+  integrity sha512-65sHfBfgwY7VAzJscbxFoNSdqWul2+dMfSPihzmTKRd3QEKdcGmWEy7qRaVzMYsH7oJ91UIGFIAzW3xg7ER13w==
+  dependencies:
+    "@babel/types" "^7.22.0"
+
+"@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.7":
+  version "7.22.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz#bfcd6b7321ffebe33290d68550e2c9d7eb7c7a58"
+  integrity sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==
+  dependencies:
+    "@babel/compat-data" "^7.22.0"
+    "@babel/helper-validator-option" "^7.21.0"
+    browserslist "^4.21.3"
+    lru-cache "^5.1.1"
+    semver "^6.3.0"
+
+"@babel/helper-create-regexp-features-plugin@^7.18.6":
+  version "7.22.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.1.tgz#a7ed9a8488b45b467fca353cd1a44dc5f0cf5c70"
+  integrity sha512-WWjdnfR3LPIe+0EY8td7WmjhytxXtjKAEpnAxun/hkNiyOaPlvGK+NZaBFIdi9ndYV3Gav7BpFvtUwnaJlwi1w==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    regexpu-core "^5.3.1"
+    semver "^6.3.0"
+
+"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.22.1":
+  version "7.22.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz#ac3a56dbada59ed969d712cf527bd8271fe3eba8"
+  integrity sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==
+
+"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0":
+  version "7.21.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4"
+  integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==
+  dependencies:
+    "@babel/template" "^7.20.7"
+    "@babel/types" "^7.21.0"
+
+"@babel/helper-hoist-variables@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
+  integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-member-expression-to-functions@^7.22.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.0.tgz#73a47b2338b8c8708f85acb0d76cbb8760fe7616"
+  integrity sha512-nf2NhMw5E6vzxvUOPeqHnNxcCyTe7r8MJYIWzLaMosohfQTk6F2jepzprj4ux8ez0yTPjDyrDeboItaylgdaiw==
+  dependencies:
+    "@babel/types" "^7.22.0"
+
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6", "@babel/helper-module-imports@^7.21.4":
+  version "7.21.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af"
+  integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==
+  dependencies:
+    "@babel/types" "^7.21.4"
+
+"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.5", "@babel/helper-module-transforms@^7.22.0":
+  version "7.22.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz#e0cad47fedcf3cae83c11021696376e2d5a50c63"
+  integrity sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==
+  dependencies:
+    "@babel/helper-environment-visitor" "^7.22.1"
+    "@babel/helper-module-imports" "^7.21.4"
+    "@babel/helper-simple-access" "^7.21.5"
+    "@babel/helper-split-export-declaration" "^7.18.6"
+    "@babel/helper-validator-identifier" "^7.19.1"
+    "@babel/template" "^7.21.9"
+    "@babel/traverse" "^7.22.1"
+    "@babel/types" "^7.22.0"
+
+"@babel/helper-optimise-call-expression@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe"
+  integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.21.5", "@babel/helper-plugin-utils@^7.8.0":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz#345f2377d05a720a4e5ecfa39cbf4474a4daed56"
+  integrity sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==
+
+"@babel/helper-remap-async-to-generator@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519"
+  integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-wrap-function" "^7.18.9"
+    "@babel/types" "^7.18.9"
+
+"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7":
+  version "7.22.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.1.tgz#38cf6e56f7dc614af63a21b45565dd623f0fdc95"
+  integrity sha512-ut4qrkE4AuSfrwHSps51ekR1ZY/ygrP1tp0WFm8oVq6nzc/hvfV/22JylndIbsf2U2M9LOMwiSddr6y+78j+OQ==
+  dependencies:
+    "@babel/helper-environment-visitor" "^7.22.1"
+    "@babel/helper-member-expression-to-functions" "^7.22.0"
+    "@babel/helper-optimise-call-expression" "^7.18.6"
+    "@babel/template" "^7.21.9"
+    "@babel/traverse" "^7.22.1"
+    "@babel/types" "^7.22.0"
+
+"@babel/helper-simple-access@^7.21.5":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz#d697a7971a5c39eac32c7e63c0921c06c8a249ee"
+  integrity sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==
+  dependencies:
+    "@babel/types" "^7.21.5"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.20.0":
+  version "7.20.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684"
+  integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==
+  dependencies:
+    "@babel/types" "^7.20.0"
+
+"@babel/helper-split-export-declaration@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075"
+  integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-string-parser@^7.21.5":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd"
+  integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==
+
+"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
+  version "7.19.1"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
+  integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
+
+"@babel/helper-validator-option@^7.21.0":
+  version "7.21.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180"
+  integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==
+
+"@babel/helper-wrap-function@^7.18.9":
+  version "7.20.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3"
+  integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==
+  dependencies:
+    "@babel/helper-function-name" "^7.19.0"
+    "@babel/template" "^7.18.10"
+    "@babel/traverse" "^7.20.5"
+    "@babel/types" "^7.20.5"
+
+"@babel/helpers@^7.1.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.0.tgz#9971320554c691c7dfafa5c4ba35edf340df29a0"
+  integrity sha512-I/hZCYErxdjuUnJpJxHmCESB3AdcOAFjj+K6+of9JyWBeAhggR9NQoUHI481pRNH87cx77mbpx0cygzXlvGayA==
+  dependencies:
+    "@babel/template" "^7.21.9"
+    "@babel/traverse" "^7.22.0"
+    "@babel/types" "^7.22.0"
+
+"@babel/highlight@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf"
+  integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.18.6"
+    chalk "^2.0.0"
+    js-tokens "^4.0.0"
+
+"@babel/parser@^7.1.0", "@babel/parser@^7.21.9", "@babel/parser@^7.22.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.0.tgz#b23786d26c2fd2ee07ec7384a96a398c3e3866f9"
+  integrity sha512-DA65VCJRetcFmJnt9/hEmRvXNCwk0V86dxG6p6N13hzDazaLRjGdTGPGgjxZOtLuFgWzOSRX4grybmRXwQ9bSg==
+
+"@babel/plugin-proposal-async-generator-functions@^7.1.0":
+  version "7.20.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326"
+  integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==
+  dependencies:
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.20.2"
+    "@babel/helper-remap-async-to-generator" "^7.18.9"
+    "@babel/plugin-syntax-async-generators" "^7.8.4"
+
+"@babel/plugin-proposal-json-strings@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b"
+  integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/plugin-syntax-json-strings" "^7.8.3"
+
+"@babel/plugin-proposal-object-rest-spread@^7.0.0":
+  version "7.20.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a"
+  integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==
+  dependencies:
+    "@babel/compat-data" "^7.20.5"
+    "@babel/helper-compilation-targets" "^7.20.7"
+    "@babel/helper-plugin-utils" "^7.20.2"
+    "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+    "@babel/plugin-transform-parameters" "^7.20.7"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb"
+  integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"
+  integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-syntax-async-generators@^7.0.0", "@babel/plugin-syntax-async-generators@^7.8.4":
+  version "7.8.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+  integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-json-strings@^7.8.3":
+  version "7.8.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
+  integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-jsx@^7.21.4":
+  version "7.21.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz#f264ed7bf40ffc9ec239edabc17a50c4f5b6fea2"
+  integrity sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.20.2"
+
+"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3":
+  version "7.8.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+  integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.0.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+  version "7.8.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+  integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-transform-arrow-functions@^7.0.0":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz#9bb42a53de447936a57ba256fbf537fc312b6929"
+  integrity sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.21.5"
+
+"@babel/plugin-transform-async-to-generator@^7.1.0":
+  version "7.20.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354"
+  integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==
+  dependencies:
+    "@babel/helper-module-imports" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.20.2"
+    "@babel/helper-remap-async-to-generator" "^7.18.9"
+
+"@babel/plugin-transform-block-scoped-functions@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8"
+  integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-block-scoping@^7.0.0":
+  version "7.21.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz#e737b91037e5186ee16b76e7ae093358a5634f02"
+  integrity sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.20.2"
+
+"@babel/plugin-transform-classes@^7.1.0":
+  version "7.21.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz#f469d0b07a4c5a7dbb21afad9e27e57b47031665"
+  integrity sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-compilation-targets" "^7.20.7"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-function-name" "^7.21.0"
+    "@babel/helper-optimise-call-expression" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.20.2"
+    "@babel/helper-replace-supers" "^7.20.7"
+    "@babel/helper-split-export-declaration" "^7.18.6"
+    globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.0.0":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz#3a2d8bb771cd2ef1cd736435f6552fe502e11b44"
+  integrity sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.21.5"
+    "@babel/template" "^7.20.7"
+
+"@babel/plugin-transform-destructuring@^7.0.0":
+  version "7.21.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz#73b46d0fd11cd6ef57dea8a381b1215f4959d401"
+  integrity sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.20.2"
+
+"@babel/plugin-transform-dotall-regex@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8"
+  integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-duplicate-keys@^7.0.0":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e"
+  integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-exponentiation-operator@^7.1.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd"
+  integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==
+  dependencies:
+    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-for-of@^7.0.0":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz#e890032b535f5a2e237a18535f56a9fdaa7b83fc"
+  integrity sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.21.5"
+
+"@babel/plugin-transform-function-name@^7.1.0":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0"
+  integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==
+  dependencies:
+    "@babel/helper-compilation-targets" "^7.18.9"
+    "@babel/helper-function-name" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-literals@^7.0.0":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc"
+  integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-modules-amd@^7.1.0":
+  version "7.20.11"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a"
+  integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.20.11"
+    "@babel/helper-plugin-utils" "^7.20.2"
+
+"@babel/plugin-transform-modules-commonjs@^7.1.0":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz#d69fb947eed51af91de82e4708f676864e5e47bc"
+  integrity sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.21.5"
+    "@babel/helper-plugin-utils" "^7.21.5"
+    "@babel/helper-simple-access" "^7.21.5"
+
+"@babel/plugin-transform-modules-systemjs@^7.0.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.0.tgz#ffaad58d858f3efc1f9135cdd47f8ba1cc99a282"
+  integrity sha512-hSo/4vBjCjwsol3nLDJG3QRDuNzvzofnyhKyCiSXpzqEVmkos9SODFC3xzDvvuE3AUjHUMgTpTRpJq16i62heA==
+  dependencies:
+    "@babel/helper-hoist-variables" "^7.18.6"
+    "@babel/helper-module-transforms" "^7.22.0"
+    "@babel/helper-plugin-utils" "^7.21.5"
+    "@babel/helper-validator-identifier" "^7.19.1"
+
+"@babel/plugin-transform-modules-umd@^7.1.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9"
+  integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-new-target@^7.0.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.0.tgz#df29199eac6fe2faecd4a65b78b668bb83cbd317"
+  integrity sha512-IZH0e2Fm8XmnZTXRzoRsHBBJ7wFzfeU22iiEZCi6EumrAjKOG6AdHpsxtBezG4SCQhqRS8DojQM8+bqtOBTQqw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.21.5"
+
+"@babel/plugin-transform-object-super@^7.1.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c"
+  integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/helper-replace-supers" "^7.18.6"
+
+"@babel/plugin-transform-parameters@^7.1.0", "@babel/plugin-transform-parameters@^7.20.7":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.0.tgz#0c1941e4aab5137ae85a6e5ef86b3ba137ba165e"
+  integrity sha512-hlRM1lu7xeqW8EKKg9ByHwnCEIy0dNPd/fwffpwAck2H3C5mQCrWR9PdrjsywivsFuVAbyyAImU58vAR1cXrEw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.21.5"
+
+"@babel/plugin-transform-react-display-name@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415"
+  integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-react-jsx-self@^7.0.0":
+  version "7.21.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz#ec98d4a9baafc5a1eb398da4cf94afbb40254a54"
+  integrity sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.20.2"
+
+"@babel/plugin-transform-react-jsx-source@^7.0.0":
+  version "7.19.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz#88578ae8331e5887e8ce28e4c9dc83fb29da0b86"
+  integrity sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.19.0"
+
+"@babel/plugin-transform-react-jsx@^7.0.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.0.tgz#5b187d73d43f726a332823012711fd3f3391965c"
+  integrity sha512-Li7gdm7eGZJidME4KlXmzQdnuUwE4jhPnICgGpWN56W7GWhmCQ2LmDepyZX4zBsoSNWP9bqDcJo5wQFndcAd9Q==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-module-imports" "^7.21.4"
+    "@babel/helper-plugin-utils" "^7.21.5"
+    "@babel/plugin-syntax-jsx" "^7.21.4"
+    "@babel/types" "^7.22.0"
+
+"@babel/plugin-transform-regenerator@^7.0.0":
+  version "7.21.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz#576c62f9923f94bcb1c855adc53561fd7913724e"
+  integrity sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.21.5"
+    regenerator-transform "^0.15.1"
+
+"@babel/plugin-transform-shorthand-properties@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9"
+  integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-spread@^7.0.0":
+  version "7.20.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e"
+  integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.20.2"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
+
+"@babel/plugin-transform-sticky-regex@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc"
+  integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-template-literals@^7.0.0":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e"
+  integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-typeof-symbol@^7.0.0":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0"
+  integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-unicode-regex@^7.0.0":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca"
+  integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/polyfill@7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.0.0.tgz#c8ff65c9ec3be6a1ba10113ebd40e8750fb90bff"
+  integrity sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==
+  dependencies:
+    core-js "^2.5.7"
+    regenerator-runtime "^0.11.1"
+
+"@babel/polyfill@^7.0.0":
+  version "7.12.1"
+  resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96"
+  integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==
+  dependencies:
+    core-js "^2.6.5"
+    regenerator-runtime "^0.13.4"
+
+"@babel/preset-env@7.1.0":
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11"
+  integrity sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==
+  dependencies:
+    "@babel/helper-module-imports" "^7.0.0"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-proposal-async-generator-functions" "^7.1.0"
+    "@babel/plugin-proposal-json-strings" "^7.0.0"
+    "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
+    "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
+    "@babel/plugin-proposal-unicode-property-regex" "^7.0.0"
+    "@babel/plugin-syntax-async-generators" "^7.0.0"
+    "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
+    "@babel/plugin-transform-arrow-functions" "^7.0.0"
+    "@babel/plugin-transform-async-to-generator" "^7.1.0"
+    "@babel/plugin-transform-block-scoped-functions" "^7.0.0"
+    "@babel/plugin-transform-block-scoping" "^7.0.0"
+    "@babel/plugin-transform-classes" "^7.1.0"
+    "@babel/plugin-transform-computed-properties" "^7.0.0"
+    "@babel/plugin-transform-destructuring" "^7.0.0"
+    "@babel/plugin-transform-dotall-regex" "^7.0.0"
+    "@babel/plugin-transform-duplicate-keys" "^7.0.0"
+    "@babel/plugin-transform-exponentiation-operator" "^7.1.0"
+    "@babel/plugin-transform-for-of" "^7.0.0"
+    "@babel/plugin-transform-function-name" "^7.1.0"
+    "@babel/plugin-transform-literals" "^7.0.0"
+    "@babel/plugin-transform-modules-amd" "^7.1.0"
+    "@babel/plugin-transform-modules-commonjs" "^7.1.0"
+    "@babel/plugin-transform-modules-systemjs" "^7.0.0"
+    "@babel/plugin-transform-modules-umd" "^7.1.0"
+    "@babel/plugin-transform-new-target" "^7.0.0"
+    "@babel/plugin-transform-object-super" "^7.1.0"
+    "@babel/plugin-transform-parameters" "^7.1.0"
+    "@babel/plugin-transform-regenerator" "^7.0.0"
+    "@babel/plugin-transform-shorthand-properties" "^7.0.0"
+    "@babel/plugin-transform-spread" "^7.0.0"
+    "@babel/plugin-transform-sticky-regex" "^7.0.0"
+    "@babel/plugin-transform-template-literals" "^7.0.0"
+    "@babel/plugin-transform-typeof-symbol" "^7.0.0"
+    "@babel/plugin-transform-unicode-regex" "^7.0.0"
+    browserslist "^4.1.0"
+    invariant "^2.2.2"
+    js-levenshtein "^1.1.3"
+    semver "^5.3.0"
+
+"@babel/preset-react@7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0"
+  integrity sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-transform-react-display-name" "^7.0.0"
+    "@babel/plugin-transform-react-jsx" "^7.0.0"
+    "@babel/plugin-transform-react-jsx-self" "^7.0.0"
+    "@babel/plugin-transform-react-jsx-source" "^7.0.0"
+
+"@babel/regjsgen@^0.8.0":
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
+  integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
+
+"@babel/runtime-corejs3@^7.10.2":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.22.0.tgz#a5f773444360e0dabba36202ce37e436164813c8"
+  integrity sha512-H7/M8iVfk3gCcKBNQHFqHcUWt7ZVKGqC/IhsY7mfomQJJ6GXpSlNkGRiOvKwE5x18tDhIh7JopVbe1QeEu4udw==
+  dependencies:
+    core-js-pure "^3.30.2"
+    regenerator-runtime "^0.13.11"
+
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.21.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.0.tgz#b7ca53ae391c404037540724186038afd83e26f9"
+  integrity sha512-TT6NB0oszYQ4oxLNUdG+FNHIc3MohXVCKA2BeyQ4WeM2VCSC6wBZ6P0Yfkdzxv+87D8Xk0LJyHeCKlWMvpZt0g==
+  dependencies:
+    regenerator-runtime "^0.13.11"
+
+"@babel/template@^7.1.0", "@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.21.9":
+  version "7.21.9"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.21.9.tgz#bf8dad2859130ae46088a99c1f265394877446fb"
+  integrity sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==
+  dependencies:
+    "@babel/code-frame" "^7.21.4"
+    "@babel/parser" "^7.21.9"
+    "@babel/types" "^7.21.5"
+
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.20.5", "@babel/traverse@^7.22.0", "@babel/traverse@^7.22.1":
+  version "7.22.1"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.1.tgz#bd22c50b1439cfcfc2fa137b7fdf6c06787456e9"
+  integrity sha512-lAWkdCoUFnmwLBhIRLciFntGYsIIoC6vIbN8zrLPqBnJmPu7Z6nzqnKd7FsxQUNAvZfVZ0x6KdNvNp8zWIOHSQ==
+  dependencies:
+    "@babel/code-frame" "^7.21.4"
+    "@babel/generator" "^7.22.0"
+    "@babel/helper-environment-visitor" "^7.22.1"
+    "@babel/helper-function-name" "^7.21.0"
+    "@babel/helper-hoist-variables" "^7.18.6"
+    "@babel/helper-split-export-declaration" "^7.18.6"
+    "@babel/parser" "^7.22.0"
+    "@babel/types" "^7.22.0"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
+"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.5", "@babel/types@^7.21.0", "@babel/types@^7.21.4", "@babel/types@^7.21.5", "@babel/types@^7.22.0":
+  version "7.22.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.0.tgz#b7383f76a5fedf967c57c1f940066fb31ca3e97a"
+  integrity sha512-NtXlm3f6cNWIv003cETdlz9sss0VMNtplyatFohxWPz90AbwuhCbHbQopkGis6bG1vOunDLN0FF/4Uv5i8LFZQ==
+  dependencies:
+    "@babel/helper-string-parser" "^7.21.5"
+    "@babel/helper-validator-identifier" "^7.19.1"
+    to-fast-properties "^2.0.0"
+
+"@emotion/babel-plugin@^11.11.0":
+  version "11.11.0"
+  resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
+  integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==
+  dependencies:
+    "@babel/helper-module-imports" "^7.16.7"
+    "@babel/runtime" "^7.18.3"
+    "@emotion/hash" "^0.9.1"
+    "@emotion/memoize" "^0.8.1"
+    "@emotion/serialize" "^1.1.2"
+    babel-plugin-macros "^3.1.0"
+    convert-source-map "^1.5.0"
+    escape-string-regexp "^4.0.0"
+    find-root "^1.1.0"
+    source-map "^0.5.7"
+    stylis "4.2.0"
+
+"@emotion/cache@^11.11.0":
+  version "11.11.0"
+  resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff"
+  integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
+  dependencies:
+    "@emotion/memoize" "^0.8.1"
+    "@emotion/sheet" "^1.2.2"
+    "@emotion/utils" "^1.2.1"
+    "@emotion/weak-memoize" "^0.3.1"
+    stylis "4.2.0"
+
+"@emotion/hash@^0.9.1":
+  version "0.9.1"
+  resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
+  integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
+
+"@emotion/is-prop-valid@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc"
+  integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==
+  dependencies:
+    "@emotion/memoize" "^0.8.1"
+
+"@emotion/memoize@^0.8.1":
+  version "0.8.1"
+  resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
+  integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
+
+"@emotion/react@^11.7.0":
+  version "11.11.0"
+  resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02"
+  integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==
+  dependencies:
+    "@babel/runtime" "^7.18.3"
+    "@emotion/babel-plugin" "^11.11.0"
+    "@emotion/cache" "^11.11.0"
+    "@emotion/serialize" "^1.1.2"
+    "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
+    "@emotion/utils" "^1.2.1"
+    "@emotion/weak-memoize" "^0.3.1"
+    hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.1.2":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.2.tgz#017a6e4c9b8a803bd576ff3d52a0ea6fa5a62b51"
+  integrity sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==
+  dependencies:
+    "@emotion/hash" "^0.9.1"
+    "@emotion/memoize" "^0.8.1"
+    "@emotion/unitless" "^0.8.1"
+    "@emotion/utils" "^1.2.1"
+    csstype "^3.0.2"
+
+"@emotion/sheet@^1.2.2":
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
+  integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
+
+"@emotion/styled@^11.6.0":
+  version "11.11.0"
+  resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346"
+  integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==
+  dependencies:
+    "@babel/runtime" "^7.18.3"
+    "@emotion/babel-plugin" "^11.11.0"
+    "@emotion/is-prop-valid" "^1.2.1"
+    "@emotion/serialize" "^1.1.2"
+    "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
+    "@emotion/utils" "^1.2.1"
+
+"@emotion/unitless@^0.8.1":
+  version "0.8.1"
+  resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
+  integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963"
+  integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
+
+"@emotion/utils@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4"
+  integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==
+
+"@emotion/weak-memoize@^0.3.1":
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
+  integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
+
+"@eslint/eslintrc@^1.3.3":
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
+  integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==
+  dependencies:
+    ajv "^6.12.4"
+    debug "^4.3.2"
+    espree "^9.4.0"
+    globals "^13.19.0"
+    ignore "^5.2.0"
+    import-fresh "^3.2.1"
+    js-yaml "^4.1.0"
+    minimatch "^3.1.2"
+    strip-json-comments "^3.1.1"
+
+"@evocateur/libnpmaccess@^3.1.2":
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845"
+  integrity sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg==
+  dependencies:
+    "@evocateur/npm-registry-fetch" "^4.0.0"
+    aproba "^2.0.0"
+    figgy-pudding "^3.5.1"
+    get-stream "^4.0.0"
+    npm-package-arg "^6.1.0"
+
+"@evocateur/libnpmpublish@^1.2.2":
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz#55df09d2dca136afba9c88c759ca272198db9f1a"
+  integrity sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg==
+  dependencies:
+    "@evocateur/npm-registry-fetch" "^4.0.0"
+    aproba "^2.0.0"
+    figgy-pudding "^3.5.1"
+    get-stream "^4.0.0"
+    lodash.clonedeep "^4.5.0"
+    normalize-package-data "^2.4.0"
+    npm-package-arg "^6.1.0"
+    semver "^5.5.1"
+    ssri "^6.0.1"
+
+"@evocateur/npm-registry-fetch@^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz#8c4c38766d8d32d3200fcb0a83f064b57365ed66"
+  integrity sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g==
+  dependencies:
+    JSONStream "^1.3.4"
+    bluebird "^3.5.1"
+    figgy-pudding "^3.4.1"
+    lru-cache "^5.1.1"
+    make-fetch-happen "^5.0.0"
+    npm-package-arg "^6.1.0"
+    safe-buffer "^5.1.2"
+
+"@evocateur/pacote@^9.6.3":
+  version "9.6.5"
+  resolved "https://registry.yarnpkg.com/@evocateur/pacote/-/pacote-9.6.5.tgz#33de32ba210b6f17c20ebab4d497efc6755f4ae5"
+  integrity sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w==
+  dependencies:
+    "@evocateur/npm-registry-fetch" "^4.0.0"
+    bluebird "^3.5.3"
+    cacache "^12.0.3"
+    chownr "^1.1.2"
+    figgy-pudding "^3.5.1"
+    get-stream "^4.1.0"
+    glob "^7.1.4"
+    infer-owner "^1.0.4"
+    lru-cache "^5.1.1"
+    make-fetch-happen "^5.0.0"
+    minimatch "^3.0.4"
+    minipass "^2.3.5"
+    mississippi "^3.0.0"
+    mkdirp "^0.5.1"
+    normalize-package-data "^2.5.0"
+    npm-package-arg "^6.1.0"
+    npm-packlist "^1.4.4"
+    npm-pick-manifest "^3.0.0"
+    osenv "^0.1.5"
+    promise-inflight "^1.0.1"
+    promise-retry "^1.1.1"
+    protoduck "^5.0.1"
+    rimraf "^2.6.3"
+    safe-buffer "^5.2.0"
+    semver "^5.7.0"
+    ssri "^6.0.1"
+    tar "^4.4.10"
+    unique-filename "^1.1.1"
+    which "^1.3.1"
+
+"@fimbul/bifrost@^0.21.0":
+  version "0.21.0"
+  resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.21.0.tgz#d0fafa25938fda475657a6a1e407a21bbe02c74e"
+  integrity sha512-ou8VU+nTmOW1jeg+FT+sn+an/M0Xb9G16RucrfhjXGWv1Q97kCoM5CG9Qj7GYOSdu7km72k7nY83Eyr53Bkakg==
+  dependencies:
+    "@fimbul/ymir" "^0.21.0"
+    get-caller-file "^2.0.0"
+    tslib "^1.8.1"
+    tsutils "^3.5.0"
+
+"@fimbul/ymir@^0.21.0":
+  version "0.21.0"
+  resolved "https://registry.yarnpkg.com/@fimbul/ymir/-/ymir-0.21.0.tgz#8525726787aceeafd4e199472c0d795160b5d4a1"
+  integrity sha512-T/y7WqPsm4n3zhT08EpB5sfdm2Kvw3gurAxr2Lr5dQeLi8ZsMlNT/Jby+ZmuuAAd1PnXYzKp+2SXgIkQIIMCUg==
+  dependencies:
+    inversify "^5.0.0"
+    reflect-metadata "^0.1.12"
+    tslib "^1.8.1"
+
+"@fortawesome/fontawesome-common-types@^0.2.12", "@fortawesome/fontawesome-common-types@^0.2.35":
+  version "0.2.36"
+  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903"
+  integrity sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==
+
+"@fortawesome/fontawesome-svg-core@1.2.35":
+  version "1.2.35"
+  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz#85aea8c25645fcec88d35f2eb1045c38d3e65cff"
+  integrity sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg==
+  dependencies:
+    "@fortawesome/fontawesome-common-types" "^0.2.35"
+
+"@fortawesome/free-solid-svg-icons@5.6.3":
+  version "5.6.3"
+  resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.6.3.tgz#1d7f6669ccd6a1ea673699e41f7e32c81401a260"
+  integrity sha512-ld8Gfp1KrncOpFRheThUDlD6/Ro9ZJGqfCEMXlO/x1Cg7ltLc5iYDG7yxDowLcmFY2BGSmxIIU3ZMW5FVTrfwQ==
+  dependencies:
+    "@fortawesome/fontawesome-common-types" "^0.2.12"
+
+"@fortawesome/react-fontawesome@0.1.14":
+  version "0.1.14"
+  resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz#bf28875c3935b69ce2dc620e1060b217a47f64ca"
+  integrity sha512-4wqNb0gRLVaBm/h+lGe8UfPPivcbuJ6ecI4hIgW0LjI7kzpYB9FkN0L9apbVzg+lsBdcTf0AlBtODjcSX5mmKA==
+  dependencies:
+    prop-types "^15.7.2"
+
+"@humanwhocodes/config-array@^0.11.6":
+  version "0.11.8"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
+  integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==
+  dependencies:
+    "@humanwhocodes/object-schema" "^1.2.1"
+    debug "^4.1.1"
+    minimatch "^3.0.5"
+
+"@humanwhocodes/module-importer@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+  integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/object-schema@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+  integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
+
+"@jridgewell/gen-mapping@^0.3.2":
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
+  integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
+  dependencies:
+    "@jridgewell/set-array" "^1.0.1"
+    "@jridgewell/sourcemap-codec" "^1.4.10"
+    "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@3.1.0":
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
+  integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/set-array@^1.0.1":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+  integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/sourcemap-codec@1.4.14":
+  version "1.4.14"
+  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
+  integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+  version "1.4.15"
+  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+  integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
+  version "0.3.18"
+  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
+  integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
+  dependencies:
+    "@jridgewell/resolve-uri" "3.1.0"
+    "@jridgewell/sourcemap-codec" "1.4.14"
+
+"@lerna/add@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b"
+  integrity sha512-vhUXXF6SpufBE1EkNEXwz1VLW03f177G9uMOFMQkp6OJ30/PWg4Ekifuz9/3YfgB2/GH8Tu4Lk3O51P2Hskg/A==
+  dependencies:
+    "@evocateur/pacote" "^9.6.3"
+    "@lerna/bootstrap" "3.21.0"
+    "@lerna/command" "3.21.0"
+    "@lerna/filter-options" "3.20.0"
+    "@lerna/npm-conf" "3.16.0"
+    "@lerna/validation-error" "3.13.0"
+    dedent "^0.7.0"
+    npm-package-arg "^6.1.0"
+    p-map "^2.1.0"
+    semver "^6.2.0"
+
+"@lerna/bootstrap@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.21.0.tgz#bcd1b651be5b0970b20d8fae04c864548123aed6"
+  integrity sha512-mtNHlXpmvJn6JTu0KcuTTPl2jLsDNud0QacV/h++qsaKbhAaJr/FElNZ5s7MwZFUM3XaDmvWzHKaszeBMHIbBw==
+  dependencies:
+    "@lerna/command" "3.21.0"
+    "@lerna/filter-options" "3.20.0"
+    "@lerna/has-npm-version" "3.16.5"
+    "@lerna/npm-install" "3.16.5"
+    "@lerna/package-graph" "3.18.5"
+    "@lerna/pulse-till-done" "3.13.0"
+    "@lerna/rimraf-dir" "3.16.5"
+    "@lerna/run-lifecycle" "3.16.2"
+    "@lerna/run-topologically" "3.18.5"
+    "@lerna/symlink-binary" "3.17.0"
+    "@lerna/symlink-dependencies" "3.17.0"
+    "@lerna/validation-error" "3.13.0"
+    dedent "^0.7.0"
+    get-port "^4.2.0"
+    multimatch "^3.0.0"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+    p-finally "^1.0.0"
+    p-map "^2.1.0"
+    p-map-series "^1.0.0"
+    p-waterfall "^1.0.0"
+    read-package-tree "^5.1.6"
+    semver "^6.2.0"
+
+"@lerna/changed@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.21.0.tgz#108e15f679bfe077af500f58248c634f1044ea0b"
+  integrity sha512-hzqoyf8MSHVjZp0gfJ7G8jaz+++mgXYiNs9iViQGA8JlN/dnWLI5sWDptEH3/B30Izo+fdVz0S0s7ydVE3pWIw==
+  dependencies:
+    "@lerna/collect-updates" "3.20.0"
+    "@lerna/command" "3.21.0"
+    "@lerna/listable" "3.18.5"
+    "@lerna/output" "3.13.0"
+
+"@lerna/check-working-tree@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz#b4f8ae61bb4523561dfb9f8f8d874dd46bb44baa"
+  integrity sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ==
+  dependencies:
+    "@lerna/collect-uncommitted" "3.16.5"
+    "@lerna/describe-ref" "3.16.5"
+    "@lerna/validation-error" "3.13.0"
+
+"@lerna/child-process@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.16.5.tgz#38fa3c18064aa4ac0754ad80114776a7b36a69b2"
+  integrity sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg==
+  dependencies:
+    chalk "^2.3.1"
+    execa "^1.0.0"
+    strong-log-transformer "^2.0.0"
+
+"@lerna/clean@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.21.0.tgz#c0b46b5300cc3dae2cda3bec14b803082da3856d"
+  integrity sha512-b/L9l+MDgE/7oGbrav6rG8RTQvRiZLO1zTcG17zgJAAuhlsPxJExMlh2DFwJEVi2les70vMhHfST3Ue1IMMjpg==
+  dependencies:
+    "@lerna/command" "3.21.0"
+    "@lerna/filter-options" "3.20.0"
+    "@lerna/prompt" "3.18.5"
+    "@lerna/pulse-till-done" "3.13.0"
+    "@lerna/rimraf-dir" "3.16.5"
+    p-map "^2.1.0"
+    p-map-series "^1.0.0"
+    p-waterfall "^1.0.0"
+
+"@lerna/cli@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-3.18.5.tgz#c90c461542fcd35b6d5b015a290fb0dbfb41d242"
+  integrity sha512-erkbxkj9jfc89vVs/jBLY/fM0I80oLmJkFUV3Q3wk9J3miYhP14zgVEBsPZY68IZlEjT6T3Xlq2xO1AVaatHsA==
+  dependencies:
+    "@lerna/global-options" "3.13.0"
+    dedent "^0.7.0"
+    npmlog "^4.1.2"
+    yargs "^14.2.2"
+
+"@lerna/collect-uncommitted@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz#a494d61aac31cdc7aec4bbe52c96550274132e63"
+  integrity sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    chalk "^2.3.1"
+    figgy-pudding "^3.5.1"
+    npmlog "^4.1.2"
+
+"@lerna/collect-updates@3.20.0":
+  version "3.20.0"
+  resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.20.0.tgz#62f9d76ba21a25b7d9fbf31c02de88744a564bd1"
+  integrity sha512-qBTVT5g4fupVhBFuY4nI/3FSJtQVcDh7/gEPOpRxoXB/yCSnT38MFHXWl+y4einLciCjt/+0x6/4AG80fjay2Q==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/describe-ref" "3.16.5"
+    minimatch "^3.0.4"
+    npmlog "^4.1.2"
+    slash "^2.0.0"
+
+"@lerna/command@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.21.0.tgz#9a2383759dc7b700dacfa8a22b2f3a6e190121f7"
+  integrity sha512-T2bu6R8R3KkH5YoCKdutKv123iUgUbW8efVjdGCDnCMthAQzoentOJfDeodBwn0P2OqCl3ohsiNVtSn9h78fyQ==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/package-graph" "3.18.5"
+    "@lerna/project" "3.21.0"
+    "@lerna/validation-error" "3.13.0"
+    "@lerna/write-log-file" "3.13.0"
+    clone-deep "^4.0.1"
+    dedent "^0.7.0"
+    execa "^1.0.0"
+    is-ci "^2.0.0"
+    npmlog "^4.1.2"
+
+"@lerna/conventional-commits@3.22.0":
+  version "3.22.0"
+  resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.22.0.tgz#2798f4881ee2ef457bdae027ab7d0bf0af6f1e09"
+  integrity sha512-z4ZZk1e8Mhz7+IS8NxHr64wyklHctCJyWpJKEZZPJiLFJ8yKto/x38O80R10pIzC0rr8Sy/OsjSH4bl0TbbgqA==
+  dependencies:
+    "@lerna/validation-error" "3.13.0"
+    conventional-changelog-angular "^5.0.3"
+    conventional-changelog-core "^3.1.6"
+    conventional-recommended-bump "^5.0.0"
+    fs-extra "^8.1.0"
+    get-stream "^4.0.0"
+    lodash.template "^4.5.0"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+    pify "^4.0.1"
+    semver "^6.2.0"
+
+"@lerna/create-symlink@3.16.2":
+  version "3.16.2"
+  resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.16.2.tgz#412cb8e59a72f5a7d9463e4e4721ad2070149967"
+  integrity sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw==
+  dependencies:
+    "@zkochan/cmd-shim" "^3.1.0"
+    fs-extra "^8.1.0"
+    npmlog "^4.1.2"
+
+"@lerna/create@3.22.0":
+  version "3.22.0"
+  resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.22.0.tgz#d6bbd037c3dc5b425fe5f6d1b817057c278f7619"
+  integrity sha512-MdiQQzCcB4E9fBF1TyMOaAEz9lUjIHp1Ju9H7f3lXze5JK6Fl5NYkouAvsLgY6YSIhXMY8AHW2zzXeBDY4yWkw==
+  dependencies:
+    "@evocateur/pacote" "^9.6.3"
+    "@lerna/child-process" "3.16.5"
+    "@lerna/command" "3.21.0"
+    "@lerna/npm-conf" "3.16.0"
+    "@lerna/validation-error" "3.13.0"
+    camelcase "^5.0.0"
+    dedent "^0.7.0"
+    fs-extra "^8.1.0"
+    globby "^9.2.0"
+    init-package-json "^1.10.3"
+    npm-package-arg "^6.1.0"
+    p-reduce "^1.0.0"
+    pify "^4.0.1"
+    semver "^6.2.0"
+    slash "^2.0.0"
+    validate-npm-package-license "^3.0.3"
+    validate-npm-package-name "^3.0.0"
+    whatwg-url "^7.0.0"
+
+"@lerna/describe-ref@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.16.5.tgz#a338c25aaed837d3dc70b8a72c447c5c66346ac0"
+  integrity sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    npmlog "^4.1.2"
+
+"@lerna/diff@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.21.0.tgz#e6df0d8b9916167ff5a49fcb02ac06424280a68d"
+  integrity sha512-5viTR33QV3S7O+bjruo1SaR40m7F2aUHJaDAC7fL9Ca6xji+aw1KFkpCtVlISS0G8vikUREGMJh+c/VMSc8Usw==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/command" "3.21.0"
+    "@lerna/validation-error" "3.13.0"
+    npmlog "^4.1.2"
+
+"@lerna/exec@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.21.0.tgz#17f07533893cb918a17b41bcc566dc437016db26"
+  integrity sha512-iLvDBrIE6rpdd4GIKTY9mkXyhwsJ2RvQdB9ZU+/NhR3okXfqKc6py/24tV111jqpXTtZUW6HNydT4dMao2hi1Q==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/command" "3.21.0"
+    "@lerna/filter-options" "3.20.0"
+    "@lerna/profiler" "3.20.0"
+    "@lerna/run-topologically" "3.18.5"
+    "@lerna/validation-error" "3.13.0"
+    p-map "^2.1.0"
+
+"@lerna/filter-options@3.20.0":
+  version "3.20.0"
+  resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.20.0.tgz#0f0f5d5a4783856eece4204708cc902cbc8af59b"
+  integrity sha512-bmcHtvxn7SIl/R9gpiNMVG7yjx7WyT0HSGw34YVZ9B+3xF/83N3r5Rgtjh4hheLZ+Q91Or0Jyu5O3Nr+AwZe2g==
+  dependencies:
+    "@lerna/collect-updates" "3.20.0"
+    "@lerna/filter-packages" "3.18.0"
+    dedent "^0.7.0"
+    figgy-pudding "^3.5.1"
+    npmlog "^4.1.2"
+
+"@lerna/filter-packages@3.18.0":
+  version "3.18.0"
+  resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-3.18.0.tgz#6a7a376d285208db03a82958cfb8172e179b4e70"
+  integrity sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ==
+  dependencies:
+    "@lerna/validation-error" "3.13.0"
+    multimatch "^3.0.0"
+    npmlog "^4.1.2"
+
+"@lerna/get-npm-exec-opts@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz#d1b552cb0088199fc3e7e126f914e39a08df9ea5"
+  integrity sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==
+  dependencies:
+    npmlog "^4.1.2"
+
+"@lerna/get-packed@3.16.0":
+  version "3.16.0"
+  resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-3.16.0.tgz#1b316b706dcee86c7baa55e50b087959447852ff"
+  integrity sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw==
+  dependencies:
+    fs-extra "^8.1.0"
+    ssri "^6.0.1"
+    tar "^4.4.8"
+
+"@lerna/github-client@3.22.0":
+  version "3.22.0"
+  resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.22.0.tgz#5d816aa4f76747ed736ae64ff962b8f15c354d95"
+  integrity sha512-O/GwPW+Gzr3Eb5bk+nTzTJ3uv+jh5jGho9BOqKlajXaOkMYGBELEAqV5+uARNGWZFvYAiF4PgqHb6aCUu7XdXg==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@octokit/plugin-enterprise-rest" "^6.0.1"
+    "@octokit/rest" "^16.28.4"
+    git-url-parse "^11.1.2"
+    npmlog "^4.1.2"
+
+"@lerna/gitlab-client@3.15.0":
+  version "3.15.0"
+  resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz#91f4ec8c697b5ac57f7f25bd50fe659d24aa96a6"
+  integrity sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==
+  dependencies:
+    node-fetch "^2.5.0"
+    npmlog "^4.1.2"
+    whatwg-url "^7.0.0"
+
+"@lerna/global-options@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.13.0.tgz#217662290db06ad9cf2c49d8e3100ee28eaebae1"
+  integrity sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==
+
+"@lerna/has-npm-version@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz#ab83956f211d8923ea6afe9b979b38cc73b15326"
+  integrity sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    semver "^6.2.0"
+
+"@lerna/import@3.22.0":
+  version "3.22.0"
+  resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.22.0.tgz#1a5f0394f38e23c4f642a123e5e1517e70d068d2"
+  integrity sha512-uWOlexasM5XR6tXi4YehODtH9Y3OZrFht3mGUFFT3OIl2s+V85xIGFfqFGMTipMPAGb2oF1UBLL48kR43hRsOg==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/command" "3.21.0"
+    "@lerna/prompt" "3.18.5"
+    "@lerna/pulse-till-done" "3.13.0"
+    "@lerna/validation-error" "3.13.0"
+    dedent "^0.7.0"
+    fs-extra "^8.1.0"
+    p-map-series "^1.0.0"
+
+"@lerna/info@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/info/-/info-3.21.0.tgz#76696b676fdb0f35d48c83c63c1e32bb5e37814f"
+  integrity sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA==
+  dependencies:
+    "@lerna/command" "3.21.0"
+    "@lerna/output" "3.13.0"
+    envinfo "^7.3.1"
+
+"@lerna/init@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.21.0.tgz#1e810934dc8bf4e5386c031041881d3b4096aa5c"
+  integrity sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/command" "3.21.0"
+    fs-extra "^8.1.0"
+    p-map "^2.1.0"
+    write-json-file "^3.2.0"
+
+"@lerna/link@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.21.0.tgz#8be68ff0ccee104b174b5bbd606302c2f06e9d9b"
+  integrity sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ==
+  dependencies:
+    "@lerna/command" "3.21.0"
+    "@lerna/package-graph" "3.18.5"
+    "@lerna/symlink-dependencies" "3.17.0"
+    p-map "^2.1.0"
+    slash "^2.0.0"
+
+"@lerna/list@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.21.0.tgz#42f76fafa56dea13b691ec8cab13832691d61da2"
+  integrity sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg==
+  dependencies:
+    "@lerna/command" "3.21.0"
+    "@lerna/filter-options" "3.20.0"
+    "@lerna/listable" "3.18.5"
+    "@lerna/output" "3.13.0"
+
+"@lerna/listable@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-3.18.5.tgz#e82798405b5ed8fc51843c8ef1e7a0e497388a1a"
+  integrity sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg==
+  dependencies:
+    "@lerna/query-graph" "3.18.5"
+    chalk "^2.3.1"
+    columnify "^1.5.4"
+
+"@lerna/log-packed@3.16.0":
+  version "3.16.0"
+  resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-3.16.0.tgz#f83991041ee77b2495634e14470b42259fd2bc16"
+  integrity sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==
+  dependencies:
+    byte-size "^5.0.1"
+    columnify "^1.5.4"
+    has-unicode "^2.0.1"
+    npmlog "^4.1.2"
+
+"@lerna/npm-conf@3.16.0":
+  version "3.16.0"
+  resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.16.0.tgz#1c10a89ae2f6c2ee96962557738685300d376827"
+  integrity sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==
+  dependencies:
+    config-chain "^1.1.11"
+    pify "^4.0.1"
+
+"@lerna/npm-dist-tag@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz#9ef9abb7c104077b31f6fab22cc73b314d54ac55"
+  integrity sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ==
+  dependencies:
+    "@evocateur/npm-registry-fetch" "^4.0.0"
+    "@lerna/otplease" "3.18.5"
+    figgy-pudding "^3.5.1"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+
+"@lerna/npm-install@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.16.5.tgz#d6bfdc16f81285da66515ae47924d6e278d637d3"
+  integrity sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/get-npm-exec-opts" "3.13.0"
+    fs-extra "^8.1.0"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+    signal-exit "^3.0.2"
+    write-pkg "^3.1.0"
+
+"@lerna/npm-publish@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.18.5.tgz#240e4039959fd9816b49c5b07421e11b5cb000af"
+  integrity sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg==
+  dependencies:
+    "@evocateur/libnpmpublish" "^1.2.2"
+    "@lerna/otplease" "3.18.5"
+    "@lerna/run-lifecycle" "3.16.2"
+    figgy-pudding "^3.5.1"
+    fs-extra "^8.1.0"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+    pify "^4.0.1"
+    read-package-json "^2.0.13"
+
+"@lerna/npm-run-script@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz#9c2ec82453a26c0b46edc0bb7c15816c821f5c15"
+  integrity sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    "@lerna/get-npm-exec-opts" "3.13.0"
+    npmlog "^4.1.2"
+
+"@lerna/otplease@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-3.18.5.tgz#b77b8e760b40abad9f7658d988f3ea77d4fd0231"
+  integrity sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog==
+  dependencies:
+    "@lerna/prompt" "3.18.5"
+    figgy-pudding "^3.5.1"
+
+"@lerna/output@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/output/-/output-3.13.0.tgz#3ded7cc908b27a9872228a630d950aedae7a4989"
+  integrity sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==
+  dependencies:
+    npmlog "^4.1.2"
+
+"@lerna/pack-directory@3.16.4":
+  version "3.16.4"
+  resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.16.4.tgz#3eae5f91bdf5acfe0384510ed53faddc4c074693"
+  integrity sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==
+  dependencies:
+    "@lerna/get-packed" "3.16.0"
+    "@lerna/package" "3.16.0"
+    "@lerna/run-lifecycle" "3.16.2"
+    figgy-pudding "^3.5.1"
+    npm-packlist "^1.4.4"
+    npmlog "^4.1.2"
+    tar "^4.4.10"
+    temp-write "^3.4.0"
+
+"@lerna/package-graph@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.18.5.tgz#c740e2ea3578d059e551633e950690831b941f6b"
+  integrity sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA==
+  dependencies:
+    "@lerna/prerelease-id-from-version" "3.16.0"
+    "@lerna/validation-error" "3.13.0"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+    semver "^6.2.0"
+
+"@lerna/package@3.16.0":
+  version "3.16.0"
+  resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.16.0.tgz#7e0a46e4697ed8b8a9c14d59c7f890e0d38ba13c"
+  integrity sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==
+  dependencies:
+    load-json-file "^5.3.0"
+    npm-package-arg "^6.1.0"
+    write-pkg "^3.1.0"
+
+"@lerna/prerelease-id-from-version@3.16.0":
+  version "3.16.0"
+  resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz#b24bfa789f5e1baab914d7b08baae9b7bd7d83a1"
+  integrity sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==
+  dependencies:
+    semver "^6.2.0"
+
+"@lerna/profiler@3.20.0":
+  version "3.20.0"
+  resolved "https://registry.yarnpkg.com/@lerna/profiler/-/profiler-3.20.0.tgz#0f6dc236f4ea8f9ea5f358c6703305a4f32ad051"
+  integrity sha512-bh8hKxAlm6yu8WEOvbLENm42i2v9SsR4WbrCWSbsmOElx3foRnMlYk7NkGECa+U5c3K4C6GeBbwgqs54PP7Ljg==
+  dependencies:
+    figgy-pudding "^3.5.1"
+    fs-extra "^8.1.0"
+    npmlog "^4.1.2"
+    upath "^1.2.0"
+
+"@lerna/project@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.21.0.tgz#5d784d2d10c561a00f20320bcdb040997c10502d"
+  integrity sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A==
+  dependencies:
+    "@lerna/package" "3.16.0"
+    "@lerna/validation-error" "3.13.0"
+    cosmiconfig "^5.1.0"
+    dedent "^0.7.0"
+    dot-prop "^4.2.0"
+    glob-parent "^5.0.0"
+    globby "^9.2.0"
+    load-json-file "^5.3.0"
+    npmlog "^4.1.2"
+    p-map "^2.1.0"
+    resolve-from "^4.0.0"
+    write-json-file "^3.2.0"
+
+"@lerna/prompt@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-3.18.5.tgz#628cd545f225887d060491ab95df899cfc5218a1"
+  integrity sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ==
+  dependencies:
+    inquirer "^6.2.0"
+    npmlog "^4.1.2"
+
+"@lerna/publish@3.22.1":
+  version "3.22.1"
+  resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.22.1.tgz#b4f7ce3fba1e9afb28be4a1f3d88222269ba9519"
+  integrity sha512-PG9CM9HUYDreb1FbJwFg90TCBQooGjj+n/pb3gw/eH5mEDq0p8wKdLFe0qkiqUkm/Ub5C8DbVFertIo0Vd0zcw==
+  dependencies:
+    "@evocateur/libnpmaccess" "^3.1.2"
+    "@evocateur/npm-registry-fetch" "^4.0.0"
+    "@evocateur/pacote" "^9.6.3"
+    "@lerna/check-working-tree" "3.16.5"
+    "@lerna/child-process" "3.16.5"
+    "@lerna/collect-updates" "3.20.0"
+    "@lerna/command" "3.21.0"
+    "@lerna/describe-ref" "3.16.5"
+    "@lerna/log-packed" "3.16.0"
+    "@lerna/npm-conf" "3.16.0"
+    "@lerna/npm-dist-tag" "3.18.5"
+    "@lerna/npm-publish" "3.18.5"
+    "@lerna/otplease" "3.18.5"
+    "@lerna/output" "3.13.0"
+    "@lerna/pack-directory" "3.16.4"
+    "@lerna/prerelease-id-from-version" "3.16.0"
+    "@lerna/prompt" "3.18.5"
+    "@lerna/pulse-till-done" "3.13.0"
+    "@lerna/run-lifecycle" "3.16.2"
+    "@lerna/run-topologically" "3.18.5"
+    "@lerna/validation-error" "3.13.0"
+    "@lerna/version" "3.22.1"
+    figgy-pudding "^3.5.1"
+    fs-extra "^8.1.0"
+    npm-package-arg "^6.1.0"
+    npmlog "^4.1.2"
+    p-finally "^1.0.0"
+    p-map "^2.1.0"
+    p-pipe "^1.2.0"
+    semver "^6.2.0"
+
+"@lerna/pulse-till-done@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz#c8e9ce5bafaf10d930a67d7ed0ccb5d958fe0110"
+  integrity sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==
+  dependencies:
+    npmlog "^4.1.2"
+
+"@lerna/query-graph@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-3.18.5.tgz#df4830bb5155273003bf35e8dda1c32d0927bd86"
+  integrity sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA==
+  dependencies:
+    "@lerna/package-graph" "3.18.5"
+    figgy-pudding "^3.5.1"
+
+"@lerna/resolve-symlink@3.16.0":
+  version "3.16.0"
+  resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz#37fc7095fabdbcf317c26eb74e0d0bde8efd2386"
+  integrity sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==
+  dependencies:
+    fs-extra "^8.1.0"
+    npmlog "^4.1.2"
+    read-cmd-shim "^1.0.1"
+
+"@lerna/rimraf-dir@3.16.5":
+  version "3.16.5"
+  resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz#04316ab5ffd2909657aaf388ea502cb8c2f20a09"
+  integrity sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==
+  dependencies:
+    "@lerna/child-process" "3.16.5"
+    npmlog "^4.1.2"
+    path-exists "^3.0.0"
+    rimraf "^2.6.2"
+
+"@lerna/run-lifecycle@3.16.2":
+  version "3.16.2"
+  resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz#67b288f8ea964db9ea4fb1fbc7715d5bbb0bce00"
+  integrity sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==
+  dependencies:
+    "@lerna/npm-conf" "3.16.0"
+    figgy-pudding "^3.5.1"
+    npm-lifecycle "^3.1.2"
+    npmlog "^4.1.2"
+
+"@lerna/run-topologically@3.18.5":
+  version "3.18.5"
+  resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-3.18.5.tgz#3cd639da20e967d7672cb88db0f756b92f2fdfc3"
+  integrity sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg==
+  dependencies:
+    "@lerna/query-graph" "3.18.5"
+    figgy-pudding "^3.5.1"
+    p-queue "^4.0.0"
+
+"@lerna/run@3.21.0":
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.21.0.tgz#2a35ec84979e4d6e42474fe148d32e5de1cac891"
+  integrity sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q==
+  dependencies:
+    "@lerna/command" "3.21.0"
+    "@lerna/filter-options" "3.20.0"
+    "@lerna/npm-run-script" "3.16.5"
+    "@lerna/output" "3.13.0"
+    "@lerna/profiler" "3.20.0"
+    "@lerna/run-topologically" "3.18.5"
+    "@lerna/timer" "3.13.0"
+    "@lerna/validation-error" "3.13.0"
+    p-map "^2.1.0"
+
+"@lerna/symlink-binary@3.17.0":
+  version "3.17.0"
+  resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz#8f8031b309863814883d3f009877f82e38aef45a"
+  integrity sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==
+  dependencies:
+    "@lerna/create-symlink" "3.16.2"
+    "@lerna/package" "3.16.0"
+    fs-extra "^8.1.0"
+    p-map "^2.1.0"
+
+"@lerna/symlink-dependencies@3.17.0":
+  version "3.17.0"
+  resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz#48d6360e985865a0e56cd8b51b308a526308784a"
+  integrity sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==
+  dependencies:
+    "@lerna/create-symlink" "3.16.2"
+    "@lerna/resolve-symlink" "3.16.0"
+    "@lerna/symlink-binary" "3.17.0"
+    fs-extra "^8.1.0"
+    p-finally "^1.0.0"
+    p-map "^2.1.0"
+    p-map-series "^1.0.0"
+
+"@lerna/timer@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-3.13.0.tgz#bcd0904551db16e08364d6c18e5e2160fc870781"
+  integrity sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==
+
+"@lerna/validation-error@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-3.13.0.tgz#c86b8f07c5ab9539f775bd8a54976e926f3759c3"
+  integrity sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==
+  dependencies:
+    npmlog "^4.1.2"
+
+"@lerna/version@3.22.1":
+  version "3.22.1"
+  resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.22.1.tgz#9805a9247a47ee62d6b81bd9fa5fb728b24b59e2"
+  integrity sha512-PSGt/K1hVqreAFoi3zjD0VEDupQ2WZVlVIwesrE5GbrL2BjXowjCsTDPqblahDUPy0hp6h7E2kG855yLTp62+g==
+  dependencies:
+    "@lerna/check-working-tree" "3.16.5"
+    "@lerna/child-process" "3.16.5"
+    "@lerna/collect-updates" "3.20.0"
+    "@lerna/command" "3.21.0"
+    "@lerna/conventional-commits" "3.22.0"
+    "@lerna/github-client" "3.22.0"
+    "@lerna/gitlab-client" "3.15.0"
+    "@lerna/output" "3.13.0"
+    "@lerna/prerelease-id-from-version" "3.16.0"
+    "@lerna/prompt" "3.18.5"
+    "@lerna/run-lifecycle" "3.16.2"
+    "@lerna/run-topologically" "3.18.5"
+    "@lerna/validation-error" "3.13.0"
+    chalk "^2.3.1"
+    dedent "^0.7.0"
+    load-json-file "^5.3.0"
+    minimatch "^3.0.4"
+    npmlog "^4.1.2"
+    p-map "^2.1.0"
+    p-pipe "^1.2.0"
+    p-reduce "^1.0.0"
+    p-waterfall "^1.0.0"
+    semver "^6.2.0"
+    slash "^2.0.0"
+    temp-write "^3.4.0"
+    write-json-file "^3.2.0"
+
+"@lerna/write-log-file@3.13.0":
+  version "3.13.0"
+  resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-3.13.0.tgz#b78d9e4cfc1349a8be64d91324c4c8199e822a26"
+  integrity sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==
+  dependencies:
+    npmlog "^4.1.2"
+    write-file-atomic "^2.3.0"
+
+"@mrmlnc/readdir-enhanced@^2.2.1":
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
+  integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==
+  dependencies:
+    call-me-maybe "^1.0.1"
+    glob-to-regexp "^0.3.0"
+
+"@mui/base@5.0.0-beta.2":
+  version "5.0.0-beta.2"
+  resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.2.tgz#d7216897c8e523c4bd26d8d292cac1bcf156dc87"
+  integrity sha512-R9R+aqrl1QhZJaO05rhvooqxOaf7SKpQ+EjW80sbP3ticTVmLmrn4YBLQS7/ML+WXdrkrPtqSmKFdSE5Ik3gBQ==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@emotion/is-prop-valid" "^1.2.1"
+    "@mui/types" "^7.2.4"
+    "@mui/utils" "^5.13.1"
+    "@popperjs/core" "^2.11.7"
+    clsx "^1.2.1"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+
+"@mui/core-downloads-tracker@^5.13.2":
+  version "5.13.2"
+  resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.2.tgz#8802f8fa81fff46e37245a59e1e547c692e11c06"
+  integrity sha512-aOLCXMCySMFL2WmUhnz+DjF84AoFVu8rn35OsL759HXOZMz8zhEwVf5w/xxkWx7DycM2KXDTgAvYW48nTfqTLA==
+
+"@mui/icons-material@^5.2.0":
+  version "5.11.16"
+  resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.11.16.tgz#417fa773c56672e39d6ccfed9ac55591985f0d38"
+  integrity sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+
+"@mui/lab@^5.0.0-alpha.58":
+  version "5.0.0-alpha.131"
+  resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.131.tgz#adf523555a4bb97725de760ef3d55e9e17f42c13"
+  integrity sha512-NVC5ZqC0iJ1Cn6VMxyazB1EPhWKztLnKXXtFO0/nZaFuADu1BlLHg+0eTMKZwEXFbJybcAopCkA5hmuk/R7INA==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@mui/base" "5.0.0-beta.2"
+    "@mui/system" "^5.13.2"
+    "@mui/types" "^7.2.4"
+    "@mui/utils" "^5.13.1"
+    clsx "^1.2.1"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+
+"@mui/material@^5.2.2":
+  version "5.13.2"
+  resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.13.2.tgz#2cf36faf8a90a0971b3633cbf18b95c7c7ea555b"
+  integrity sha512-Pfke1l0GG2OJb/Nr10aVr8huoBFcBTdWKV5iFSTEHqf9c2C1ZlyYMISn7ui6X3Gix8vr+hP5kVqH1LAWwQSb6w==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@mui/base" "5.0.0-beta.2"
+    "@mui/core-downloads-tracker" "^5.13.2"
+    "@mui/system" "^5.13.2"
+    "@mui/types" "^7.2.4"
+    "@mui/utils" "^5.13.1"
+    "@types/react-transition-group" "^4.4.6"
+    clsx "^1.2.1"
+    csstype "^3.1.2"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+    react-transition-group "^4.4.5"
+
+"@mui/private-theming@^5.13.1":
+  version "5.13.1"
+  resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.13.1.tgz#c3e9a0b44f9c5a51b92cfcfb660536060cb61ed7"
+  integrity sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@mui/utils" "^5.13.1"
+    prop-types "^15.8.1"
+
+"@mui/styled-engine@^5.13.2":
+  version "5.13.2"
+  resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.13.2.tgz#c87bd61c0ab8086d34828b6defe97c02bcd642ef"
+  integrity sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@emotion/cache" "^11.11.0"
+    csstype "^3.1.2"
+    prop-types "^15.8.1"
+
+"@mui/styles@^5.2.2":
+  version "5.13.2"
+  resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.13.2.tgz#0d6c1b7c5437293cf4f0d98d1fd8c5cc02bb4138"
+  integrity sha512-gKNkVyk6azQ8wfCamh3yU/wLv1JscYrsQX9huQBwfwtE7kUTq2rgggdfJjRADjbcmT6IPX+oCHYjGfqqFgDIQQ==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@emotion/hash" "^0.9.1"
+    "@mui/private-theming" "^5.13.1"
+    "@mui/types" "^7.2.4"
+    "@mui/utils" "^5.13.1"
+    clsx "^1.2.1"
+    csstype "^3.1.2"
+    hoist-non-react-statics "^3.3.2"
+    jss "^10.10.0"
+    jss-plugin-camel-case "^10.10.0"
+    jss-plugin-default-unit "^10.10.0"
+    jss-plugin-global "^10.10.0"
+    jss-plugin-nested "^10.10.0"
+    jss-plugin-props-sort "^10.10.0"
+    jss-plugin-rule-value-function "^10.10.0"
+    jss-plugin-vendor-prefixer "^10.10.0"
+    prop-types "^15.8.1"
+
+"@mui/system@^5.13.2", "@mui/system@^5.2.2":
+  version "5.13.2"
+  resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.13.2.tgz#c9aa821049fc75d8ade1c0646dc4d2b67605b8fc"
+  integrity sha512-TPyWmRJPt0JPVxacZISI4o070xEJ7ftxpVtu6LWuYVOUOINlhoGOclam4iV8PDT3EMQEHuUrwU49po34UdWLlw==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@mui/private-theming" "^5.13.1"
+    "@mui/styled-engine" "^5.13.2"
+    "@mui/types" "^7.2.4"
+    "@mui/utils" "^5.13.1"
+    clsx "^1.2.1"
+    csstype "^3.1.2"
+    prop-types "^15.8.1"
+
+"@mui/types@^7.2.4":
+  version "7.2.4"
+  resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.4.tgz#b6fade19323b754c5c6de679a38f068fd50b9328"
+  integrity sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==
+
+"@mui/utils@^5.13.1":
+  version "5.13.1"
+  resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.13.1.tgz#86199e46014215f95da046a5ec803f4a39c96eee"
+  integrity sha512-6lXdWwmlUbEU2jUI8blw38Kt+3ly7xkmV9ljzY4Q20WhsJMWiNry9CX8M+TaP/HbtuyR8XKsdMgQW7h7MM3n3A==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@types/prop-types" "^15.7.5"
+    "@types/react-is" "^18.2.0"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+
+"@nodelib/fs.scandir@2.1.5":
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+  integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+  dependencies:
+    "@nodelib/fs.stat" "2.0.5"
+    run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+  integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.stat@^1.1.2":
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
+  integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+
+"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+  integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+  dependencies:
+    "@nodelib/fs.scandir" "2.1.5"
+    fastq "^1.6.0"
+
+"@octokit/auth-token@^2.4.0":
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36"
+  integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==
+  dependencies:
+    "@octokit/types" "^6.0.3"
+
+"@octokit/core@3.0.0":
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.0.0.tgz#4b7bf2a9e744a49abcbb3aca7b4dfc219513e4f9"
+  integrity sha512-FGUUqZbIwl5UPvuUTWq8ly2B12gJGWjYh1DviBzZLXp5LzHUgyzL+NDGsXeE4vszXoGsD/JfpZS+kjkLiD2T9w==
+  dependencies:
+    "@octokit/auth-token" "^2.4.0"
+    "@octokit/graphql" "^4.3.1"
+    "@octokit/request" "^5.4.0"
+    "@octokit/types" "^5.0.0"
+    before-after-hook "^2.1.0"
+    universal-user-agent "^5.0.0"
+
+"@octokit/endpoint@^6.0.1":
+  version "6.0.12"
+  resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658"
+  integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==
+  dependencies:
+    "@octokit/types" "^6.0.3"
+    is-plain-object "^5.0.0"
+    universal-user-agent "^6.0.0"
+
+"@octokit/graphql@^4.3.1":
+  version "4.8.0"
+  resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3"
+  integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==
+  dependencies:
+    "@octokit/request" "^5.6.0"
+    "@octokit/types" "^6.0.3"
+    universal-user-agent "^6.0.0"
+
+"@octokit/openapi-types@^12.11.0":
+  version "12.11.0"
+  resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0"
+  integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==
+
+"@octokit/plugin-enterprise-rest@^6.0.1":
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437"
+  integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==
+
+"@octokit/plugin-paginate-rest@^1.1.1":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc"
+  integrity sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==
+  dependencies:
+    "@octokit/types" "^2.0.1"
+
+"@octokit/plugin-request-log@^1.0.0":
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
+  integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
+
+"@octokit/plugin-rest-endpoint-methods@2.4.0":
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz#3288ecf5481f68c494dd0602fc15407a59faf61e"
+  integrity sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==
+  dependencies:
+    "@octokit/types" "^2.0.1"
+    deprecation "^2.3.1"
+
+"@octokit/request-error@^1.0.2":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801"
+  integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==
+  dependencies:
+    "@octokit/types" "^2.0.0"
+    deprecation "^2.0.0"
+    once "^1.4.0"
+
+"@octokit/request-error@^2.1.0":
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677"
+  integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==
+  dependencies:
+    "@octokit/types" "^6.0.3"
+    deprecation "^2.0.0"
+    once "^1.4.0"
+
+"@octokit/request@^5.2.0", "@octokit/request@^5.4.0", "@octokit/request@^5.6.0":
+  version "5.6.3"
+  resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0"
+  integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==
+  dependencies:
+    "@octokit/endpoint" "^6.0.1"
+    "@octokit/request-error" "^2.1.0"
+    "@octokit/types" "^6.16.1"
+    is-plain-object "^5.0.0"
+    node-fetch "^2.6.7"
+    universal-user-agent "^6.0.0"
+
+"@octokit/rest@^16.28.4":
+  version "16.43.2"
+  resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.2.tgz#c53426f1e1d1044dee967023e3279c50993dd91b"
+  integrity sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==
+  dependencies:
+    "@octokit/auth-token" "^2.4.0"
+    "@octokit/plugin-paginate-rest" "^1.1.1"
+    "@octokit/plugin-request-log" "^1.0.0"
+    "@octokit/plugin-rest-endpoint-methods" "2.4.0"
+    "@octokit/request" "^5.2.0"
+    "@octokit/request-error" "^1.0.2"
+    atob-lite "^2.0.0"
+    before-after-hook "^2.0.0"
+    btoa-lite "^1.0.0"
+    deprecation "^2.0.0"
+    lodash.get "^4.4.2"
+    lodash.set "^4.3.2"
+    lodash.uniq "^4.5.0"
+    octokit-pagination-methods "^1.1.0"
+    once "^1.4.0"
+    universal-user-agent "^4.0.0"
+
+"@octokit/types@^2.0.0", "@octokit/types@^2.0.1":
+  version "2.16.2"
+  resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2"
+  integrity sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==
+  dependencies:
+    "@types/node" ">= 8"
+
+"@octokit/types@^5.0.0":
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b"
+  integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==
+  dependencies:
+    "@types/node" ">= 8"
+
+"@octokit/types@^6.0.3", "@octokit/types@^6.16.1":
+  version "6.41.0"
+  resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04"
+  integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==
+  dependencies:
+    "@octokit/openapi-types" "^12.11.0"
+
+"@popperjs/core@^2.11.7":
+  version "2.11.7"
+  resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.7.tgz#ccab5c8f7dc557a52ca3288c10075c9ccd37fff7"
+  integrity sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==
+
+"@types/classnames@2.2.6":
+  version "2.2.6"
+  resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.6.tgz#dbe8a666156d556ed018e15a4c65f08937c3f628"
+  integrity sha512-XHcYvVdbtAxVstjKxuULYqYaWIzHR15yr1pZj4fnGChuBVJlIAp9StJna0ZJNSgxPh4Nac2FL4JM3M11Tm6fqQ==
+
+"@types/fbemitter@*":
+  version "2.0.32"
+  resolved "https://registry.yarnpkg.com/@types/fbemitter/-/fbemitter-2.0.32.tgz#8ed204da0f54e9c8eaec31b1eec91e25132d082c"
+  integrity sha512-Hwq28bBlbmfCgLnNJvjl5ssTrbZCTSblI4vqPpqZrbbEL8vn5l2UivxhlMYfUY7a4SR8UB6RKoLjOZfljqAa6g==
+
+"@types/flux@3.1.8":
+  version "3.1.8"
+  resolved "https://registry.yarnpkg.com/@types/flux/-/flux-3.1.8.tgz#987fbf0220d98aa23276c9635a8ef1e505f7c4a4"
+  integrity sha512-U7DS78cK1svrisTa920BM2AEsWnfgnxQmVn+1kju1XgjcDN/iU1Uiyy0pQNaG8s9P1X5Lj3pMaIfVuCjXAlSCA==
+  dependencies:
+    "@types/fbemitter" "*"
+    "@types/react" "*"
+
+"@types/glob-to-regexp@0.4.0":
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/@types/glob-to-regexp/-/glob-to-regexp-0.4.0.tgz#a295047724f4554be8192b4c779c5e44920a2fdc"
+  integrity sha512-unszpTzAknG612PxqtoNUkLM0T3rIAXT8oE9Dyhhbl4eew91jLqcgJZOu5j7GztHg09R8LWCMocRU1ohDFY7Pw==
+
+"@types/glob@^7.1.1":
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
+  integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==
+  dependencies:
+    "@types/minimatch" "*"
+    "@types/node" "*"
+
+"@types/highlight.js@9.12.3":
+  version "9.12.3"
+  resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"
+  integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==
+
+"@types/history@*":
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/@types/history/-/history-5.0.0.tgz#29f919f0c8e302763798118f45b19cab4a886f14"
+  integrity sha512-hy8b7Y1J8OGe6LbAjj3xniQrj3v6lsivCcrmf4TzSgPzLkhIeKgc5IZnT7ReIqmEuodjfO8EYAuoFvIrHi/+jQ==
+  dependencies:
+    history "*"
+
+"@types/history@^4.7.11", "@types/history@^4.7.9":
+  version "4.7.11"
+  resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
+  integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
+
+"@types/jest@23.3.12":
+  version "23.3.12"
+  resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.12.tgz#7e0ced251fa94c3bc2d1023d4b84b2992fa06376"
+  integrity sha512-/kQvbVzdEpOq4tEWT79yAHSM4nH4xMlhJv2GrLVQt4Qmo8yYsPdioBM1QpN/2GX1wkfMnyXvdoftvLUr0LBj7Q==
+
+"@types/jquery@3.3.10":
+  version "3.3.10"
+  resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.10.tgz#d0afaec7ee55f591992e74c607df5dc7cd9c76ab"
+  integrity sha512-W2bE8pGh9Tsg8mxh+B6BSH8lTG6ZV7K2ZMAlEwSTqKFU1wMI5HShyRKSp3DngnxCmDu35tW3RAC4mxBFYRsTuw==
+
+"@types/json-schema@^7.0.9":
+  version "7.0.12"
+  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
+  integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
+
+"@types/json5@^0.0.29":
+  version "0.0.29"
+  resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+  integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+
+"@types/jsonwebtoken@7.2.8":
+  version "7.2.8"
+  resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz#8d199dab4ddb5bba3234f8311b804d2027af2b3a"
+  integrity sha512-XENN3YzEB8D6TiUww0O8SRznzy1v+77lH7UmuN54xq/IHIsyWjWOzZuFFTtoiRuaE782uAoRwBe/wwow+vQXZw==
+  dependencies:
+    "@types/node" "*"
+
+"@types/marked@0.6.0":
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.6.0.tgz#e4ac316144a84afda5c2474488d7b9fef3ab9995"
+  integrity sha512-TxwhgR9VsIfRDJ3WwFokG8Xu+ea0nYGDRHdI783WJ983uffatz0ytIeUEIBOwPvRy241KRSNVyywQltuTqDh0w==
+
+"@types/minimatch@*":
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
+  integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
+
+"@types/minimist@^1.2.0":
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
+  integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
+
+"@types/node@*", "@types/node@>= 8":
+  version "20.2.4"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.4.tgz#e6c3345f7ed9c6df41fdc288a94e2633167bc15d"
+  integrity sha512-ni5f8Xlf4PwnT/Z3f0HURc3ZSw8UyrqMqmM3L5ysa7VjHu8c3FOmIo1nKCcLrV/OAmtf3N4kFna/aJqxsfEtnA==
+
+"@types/node@^12.0.0":
+  version "12.20.55"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
+  integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
+
+"@types/normalize-package-data@^2.4.0":
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
+  integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
+
+"@types/parse-json@^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
+  integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+
+"@types/prop-types@*", "@types/prop-types@^15.7.5":
+  version "15.7.5"
+  resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+  integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/react-dom@17.0.11":
+  version "17.0.11"
+  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.11.tgz#e1eadc3c5e86bdb5f7684e00274ae228e7bcc466"
+  integrity sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==
+  dependencies:
+    "@types/react" "*"
+
+"@types/react-is@^18.2.0":
+  version "18.2.0"
+  resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-18.2.0.tgz#2f5137853a46017b3d56447940fb3eb92bbf24a5"
+  integrity sha512-1vz2yObaQkLL7YFe/pme2cpvDsCwI1WXIfL+5eLz0MI9gFG24Re16RzUsI8t9XZn9ZWvgLNDrJBmrqXJO7GNQQ==
+  dependencies:
+    "@types/react" "*"
+
+"@types/react-router-dom@5.1.7":
+  version "5.1.7"
+  resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.7.tgz#a126d9ea76079ffbbdb0d9225073eb5797ab7271"
+  integrity sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==
+  dependencies:
+    "@types/history" "*"
+    "@types/react" "*"
+    "@types/react-router" "*"
+
+"@types/react-router@*":
+  version "5.1.20"
+  resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c"
+  integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==
+  dependencies:
+    "@types/history" "^4.7.11"
+    "@types/react" "*"
+
+"@types/react-transition-group@2.0.15":
+  version "2.0.15"
+  resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.15.tgz#e5ee3fe558832e141cc6041bdd54caea7b787af8"
+  integrity sha512-S0QnNzbHoWXDbKBl/xk5dxA4FT+BNlBcI3hku991cl8Cz3ytOkUMcCRtzdX11eb86E131bSsQqy5WrPCdJYblw==
+  dependencies:
+    "@types/react" "*"
+
+"@types/react-transition-group@^4.4.6":
+  version "4.4.6"
+  resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e"
+  integrity sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==
+  dependencies:
+    "@types/react" "*"
+
+"@types/react@*", "@types/react@17.0.37":
+  version "17.0.37"
+  resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.37.tgz#6884d0aa402605935c397ae689deed115caad959"
+  integrity sha512-2FS1oTqBGcH/s0E+CjrCCR9+JMpsu9b69RTFO+40ua43ZqP5MmQ4iUde/dMjWR909KxZwmOQIFq6AV6NjEG5xg==
+  dependencies:
+    "@types/prop-types" "*"
+    "@types/scheduler" "*"
+    csstype "^3.0.2"
+
+"@types/scheduler@*":
+  version "0.16.3"
+  resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5"
+  integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
+
+"@types/semver@^7.3.12":
+  version "7.5.0"
+  resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
+  integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==
+
+"@types/x2js@^3.1.0":
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@types/x2js/-/x2js-3.1.0.tgz#d809ef1ace1a8b55b3e8cb6a1a0b282af66475be"
+  integrity sha512-AWxcyKIXjJD/JXqrYwS6rOg30gTUpXEu98vr1MHEzAp4gLP6bYuhwVNoY+4d/z+wNYsGd4spX6DnjQCPCSwfJA==
+  dependencies:
+    x2js "*"
+
+"@typescript-eslint/eslint-plugin@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz#36a8c0c379870127059889a9cc7e05c260d2aaa5"
+  integrity sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==
+  dependencies:
+    "@typescript-eslint/scope-manager" "5.42.0"
+    "@typescript-eslint/type-utils" "5.42.0"
+    "@typescript-eslint/utils" "5.42.0"
+    debug "^4.3.4"
+    ignore "^5.2.0"
+    natural-compare-lite "^1.4.0"
+    regexpp "^3.2.0"
+    semver "^7.3.7"
+    tsutils "^3.21.0"
+
+"@typescript-eslint/parser@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.42.0.tgz#be0ffbe279e1320e3d15e2ef0ad19262f59e9240"
+  integrity sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==
+  dependencies:
+    "@typescript-eslint/scope-manager" "5.42.0"
+    "@typescript-eslint/types" "5.42.0"
+    "@typescript-eslint/typescript-estree" "5.42.0"
+    debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz#e1f2bb26d3b2a508421ee2e3ceea5396b192f5ef"
+  integrity sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==
+  dependencies:
+    "@typescript-eslint/types" "5.42.0"
+    "@typescript-eslint/visitor-keys" "5.42.0"
+
+"@typescript-eslint/type-utils@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz#4206d7192d4fe903ddf99d09b41d4ac31b0b7dca"
+  integrity sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==
+  dependencies:
+    "@typescript-eslint/typescript-estree" "5.42.0"
+    "@typescript-eslint/utils" "5.42.0"
+    debug "^4.3.4"
+    tsutils "^3.21.0"
+
+"@typescript-eslint/types@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.42.0.tgz#5aeff9b5eced48f27d5b8139339bf1ef805bad7a"
+  integrity sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==
+
+"@typescript-eslint/typescript-estree@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz#2592d24bb5f89bf54a63384ff3494870f95b3fd8"
+  integrity sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==
+  dependencies:
+    "@typescript-eslint/types" "5.42.0"
+    "@typescript-eslint/visitor-keys" "5.42.0"
+    debug "^4.3.4"
+    globby "^11.1.0"
+    is-glob "^4.0.3"
+    semver "^7.3.7"
+    tsutils "^3.21.0"
+
+"@typescript-eslint/utils@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.42.0.tgz#f06bd43b9a9a06ed8f29600273240e84a53f2f15"
+  integrity sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==
+  dependencies:
+    "@types/json-schema" "^7.0.9"
+    "@types/semver" "^7.3.12"
+    "@typescript-eslint/scope-manager" "5.42.0"
+    "@typescript-eslint/types" "5.42.0"
+    "@typescript-eslint/typescript-estree" "5.42.0"
+    eslint-scope "^5.1.1"
+    eslint-utils "^3.0.0"
+    semver "^7.3.7"
+
+"@typescript-eslint/visitor-keys@5.42.0":
+  version "5.42.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz#ee8d62d486f41cfe646632fab790fbf0c1db5bb0"
+  integrity sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==
+  dependencies:
+    "@typescript-eslint/types" "5.42.0"
+    eslint-visitor-keys "^3.3.0"
+
+"@webassemblyjs/ast@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace"
+  integrity sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==
+  dependencies:
+    "@webassemblyjs/helper-module-context" "1.7.11"
+    "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+    "@webassemblyjs/wast-parser" "1.7.11"
+
+"@webassemblyjs/floating-point-hex-parser@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz#a69f0af6502eb9a3c045555b1a6129d3d3f2e313"
+  integrity sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==
+
+"@webassemblyjs/helper-api-error@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz#c7b6bb8105f84039511a2b39ce494f193818a32a"
+  integrity sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==
+
+"@webassemblyjs/helper-buffer@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz#3122d48dcc6c9456ed982debe16c8f37101df39b"
+  integrity sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==
+
+"@webassemblyjs/helper-code-frame@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz#cf8f106e746662a0da29bdef635fcd3d1248364b"
+  integrity sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==
+  dependencies:
+    "@webassemblyjs/wast-printer" "1.7.11"
+
+"@webassemblyjs/helper-fsm@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz#df38882a624080d03f7503f93e3f17ac5ac01181"
+  integrity sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==
+
+"@webassemblyjs/helper-module-context@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz#d874d722e51e62ac202476935d649c802fa0e209"
+  integrity sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==
+
+"@webassemblyjs/helper-wasm-bytecode@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz#dd9a1e817f1c2eb105b4cf1013093cb9f3c9cb06"
+  integrity sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==
+
+"@webassemblyjs/helper-wasm-section@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz#9c9ac41ecf9fbcfffc96f6d2675e2de33811e68a"
+  integrity sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/helper-buffer" "1.7.11"
+    "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+    "@webassemblyjs/wasm-gen" "1.7.11"
+
+"@webassemblyjs/ieee754@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz#c95839eb63757a31880aaec7b6512d4191ac640b"
+  integrity sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==
+  dependencies:
+    "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.11.tgz#d7267a1ee9c4594fd3f7e37298818ec65687db63"
+  integrity sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==
+  dependencies:
+    "@xtuc/long" "4.2.1"
+
+"@webassemblyjs/utf8@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.11.tgz#06d7218ea9fdc94a6793aa92208160db3d26ee82"
+  integrity sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==
+
+"@webassemblyjs/wasm-edit@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz#8c74ca474d4f951d01dbae9bd70814ee22a82005"
+  integrity sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/helper-buffer" "1.7.11"
+    "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+    "@webassemblyjs/helper-wasm-section" "1.7.11"
+    "@webassemblyjs/wasm-gen" "1.7.11"
+    "@webassemblyjs/wasm-opt" "1.7.11"
+    "@webassemblyjs/wasm-parser" "1.7.11"
+    "@webassemblyjs/wast-printer" "1.7.11"
+
+"@webassemblyjs/wasm-gen@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz#9bbba942f22375686a6fb759afcd7ac9c45da1a8"
+  integrity sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+    "@webassemblyjs/ieee754" "1.7.11"
+    "@webassemblyjs/leb128" "1.7.11"
+    "@webassemblyjs/utf8" "1.7.11"
+
+"@webassemblyjs/wasm-opt@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz#b331e8e7cef8f8e2f007d42c3a36a0580a7d6ca7"
+  integrity sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/helper-buffer" "1.7.11"
+    "@webassemblyjs/wasm-gen" "1.7.11"
+    "@webassemblyjs/wasm-parser" "1.7.11"
+
+"@webassemblyjs/wasm-parser@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz#6e3d20fa6a3519f6b084ef9391ad58211efb0a1a"
+  integrity sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/helper-api-error" "1.7.11"
+    "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+    "@webassemblyjs/ieee754" "1.7.11"
+    "@webassemblyjs/leb128" "1.7.11"
+    "@webassemblyjs/utf8" "1.7.11"
+
+"@webassemblyjs/wast-parser@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz#25bd117562ca8c002720ff8116ef9072d9ca869c"
+  integrity sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/floating-point-hex-parser" "1.7.11"
+    "@webassemblyjs/helper-api-error" "1.7.11"
+    "@webassemblyjs/helper-code-frame" "1.7.11"
+    "@webassemblyjs/helper-fsm" "1.7.11"
+    "@xtuc/long" "4.2.1"
+
+"@webassemblyjs/wast-printer@1.7.11":
+  version "1.7.11"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz#c4245b6de242cb50a2cc950174fdbf65c78d7813"
+  integrity sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/wast-parser" "1.7.11"
+    "@xtuc/long" "4.2.1"
+
+"@xmldom/xmldom@^0.8.3":
+  version "0.8.7"
+  resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.7.tgz#8b1e39c547013941974d83ad5e9cf5042071a9a0"
+  integrity sha512-sI1Ly2cODlWStkINzqGrZ8K6n+MTSbAeQnAipGyL+KZCXuHaRlj2gyyy8B/9MvsFFqN7XHryQnB2QwhzvJXovg==
+
+"@xtuc/ieee754@^1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+  integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8"
+  integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==
+
+"@zkochan/cmd-shim@^3.1.0":
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e"
+  integrity sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==
+  dependencies:
+    is-windows "^1.0.0"
+    mkdirp-promise "^5.0.1"
+    mz "^2.5.0"
+
+JSONStream@^1.0.4, JSONStream@^1.3.4:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
+  integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
+  dependencies:
+    jsonparse "^1.2.0"
+    through ">=2.2.7 <3"
+
+abab@^2.0.0:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
+  integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
+
+abbrev@1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+  integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+
+accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
+  version "1.3.8"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
+  integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+  dependencies:
+    mime-types "~2.1.34"
+    negotiator "0.6.3"
+
+acorn-dynamic-import@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
+  integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==
+  dependencies:
+    acorn "^5.0.0"
+
+acorn-globals@^4.1.0:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
+  integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
+  dependencies:
+    acorn "^6.0.1"
+    acorn-walk "^6.0.1"
+
+acorn-jsx@^5.3.2:
+  version "5.3.2"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+  integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn-walk@^6.0.1:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
+  integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
+
+acorn@^5.0.0, acorn@^5.5.3, acorn@^5.6.2:
+  version "5.7.4"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
+  integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
+
+acorn@^6.0.1:
+  version "6.4.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
+  integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
+
+acorn@^8.8.0:
+  version "8.8.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
+  integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
+
+agent-base@4, agent-base@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+  integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+  dependencies:
+    es6-promisify "^5.0.0"
+
+agent-base@~4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
+  integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
+  dependencies:
+    es6-promisify "^5.0.0"
+
+agentkeepalive@^3.4.1:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67"
+  integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==
+  dependencies:
+    humanize-ms "^1.2.1"
+
+ajv-errors@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
+  integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
+
+ajv-keywords@^3.1.0:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+  integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4:
+  version "6.12.6"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+  integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
+ansi-colors@^3.0.0:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
+  integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
+
+ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
+  integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
+
+ansi-html@0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
+  integrity sha512-JoAxEa1DfP9m2xfB/y2r/aKcwXNlltr4+0QSBC4TrLfcxyvepX2Pv0t/xpgGV5bGsDzCYV8SzjWgyCW0T9yYbA==
+
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+  integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==
+
+ansi-regex@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
+  integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
+
+ansi-regex@^4.1.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
+  integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
+
+ansi-regex@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+  integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+  integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
+ansi-styles@^4.1.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+  integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+  dependencies:
+    color-convert "^2.0.1"
+
+any-promise@^1.0.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+  integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
+
+anymatch@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
+  integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
+  dependencies:
+    micromatch "^3.1.4"
+    normalize-path "^2.1.1"
+
+anymatch@~3.1.2:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+  integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+  dependencies:
+    normalize-path "^3.0.0"
+    picomatch "^2.0.4"
+
+append-transform@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+  integrity sha512-Yisb7ew0ZEyDtRYQ+b+26o9KbiYPFxwcsxKzbssigzRRMJ9LpExPVUg6Fos7eP7yP3q7///tzze4nm4lTptPBw==
+  dependencies:
+    default-require-extensions "^1.0.0"
+
+aproba@^1.0.3, aproba@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+  integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+
+aproba@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
+  integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
+
+are-we-there-yet@~1.1.2:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
+  integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==
+  dependencies:
+    delegates "^1.0.0"
+    readable-stream "^2.0.6"
+
+argparse@^1.0.7:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+  dependencies:
+    sprintf-js "~1.0.2"
+
+argparse@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+  integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-query@^4.2.2:
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
+  integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==
+  dependencies:
+    "@babel/runtime" "^7.10.2"
+    "@babel/runtime-corejs3" "^7.10.2"
+
+arr-diff@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+  integrity sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==
+  dependencies:
+    arr-flatten "^1.0.1"
+
+arr-diff@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
+  integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==
+
+arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+  integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
+
+arr-union@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
+  integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==
+
+array-buffer-byte-length@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead"
+  integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==
+  dependencies:
+    call-bind "^1.0.2"
+    is-array-buffer "^3.0.1"
+
+array-differ@^2.0.3:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1"
+  integrity sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==
+
+array-equal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
+  integrity sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==
+
+array-find-index@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+  integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==
+
+array-flatten@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+  integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
+
+array-flatten@^2.1.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
+  integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
+
+array-ify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
+  integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==
+
+array-includes@^3.1.4, array-includes@^3.1.5:
+  version "3.1.6"
+  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f"
+  integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+    get-intrinsic "^1.1.3"
+    is-string "^1.0.7"
+
+array-union@^1.0.1, array-union@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+  integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==
+  dependencies:
+    array-uniq "^1.0.1"
+
+array-union@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+  integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+array-uniq@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+  integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==
+
+array-unique@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+  integrity sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==
+
+array-unique@^0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
+  integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==
+
+array.prototype.flat@^1.2.5:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2"
+  integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+    es-shim-unscopables "^1.0.0"
+
+array.prototype.flatmap@^1.3.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
+  integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+    es-shim-unscopables "^1.0.0"
+
+array.prototype.reduce@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac"
+  integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+    es-array-method-boxes-properly "^1.0.0"
+    is-string "^1.0.7"
+
+arrify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+  integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==
+
+asap@^2.0.0:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+  integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
+
+asn1.js@^5.2.0:
+  version "5.4.1"
+  resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
+  integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==
+  dependencies:
+    bn.js "^4.0.0"
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+    safer-buffer "^2.1.0"
+
+asn1@~0.2.3:
+  version "0.2.6"
+  resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
+  integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
+  dependencies:
+    safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+  integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
+
+assert@^1.1.1:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
+  integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
+  dependencies:
+    object-assign "^4.1.1"
+    util "0.10.3"
+
+assign-symbols@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
+  integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==
+
+ast-types-flow@^0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
+  integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
+
+astral-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+  integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
+async-each@^1.0.1:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77"
+  integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==
+
+async-limiter@~1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+  integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+
+async@^2.1.4, async@^2.4.1, async@^2.6.4:
+  version "2.6.4"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
+  integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
+  dependencies:
+    lodash "^4.17.14"
+
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+  integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+atob-lite@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696"
+  integrity sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==
+
+atob@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+  integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
+autoprefixer@9.1.5:
+  version "9.1.5"
+  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.1.5.tgz#8675fd8d1c0d43069f3b19a2c316f3524e4f6671"
+  integrity sha512-kk4Zb6RUc58ld7gdosERHMF3DzIYJc2fp5sX46qEsGXQQy5bXsu8qyLjoxuY1NuQ/cJuCYnx99BfjwnRggrYIw==
+  dependencies:
+    browserslist "^4.1.0"
+    caniuse-lite "^1.0.30000884"
+    normalize-range "^0.1.2"
+    num2fraction "^1.2.2"
+    postcss "^7.0.2"
+    postcss-value-parser "^3.2.3"
+
+available-typed-arrays@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
+  integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
+
+aws-sign2@~0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+  integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==
+
+aws4@^1.8.0:
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
+  integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
+
+axe-core@^4.4.3:
+  version "4.7.2"
+  resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0"
+  integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
+
+axobject-query@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
+  integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
+
+babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+  integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==
+  dependencies:
+    chalk "^1.1.3"
+    esutils "^2.0.2"
+    js-tokens "^3.0.2"
+
+babel-core@^6.0.0, babel-core@^6.26.0:
+  version "6.26.3"
+  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
+  integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-generator "^6.26.0"
+    babel-helpers "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-register "^6.26.0"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    convert-source-map "^1.5.1"
+    debug "^2.6.9"
+    json5 "^0.5.1"
+    lodash "^4.17.4"
+    minimatch "^3.0.4"
+    path-is-absolute "^1.0.1"
+    private "^0.1.8"
+    slash "^1.0.0"
+    source-map "^0.5.7"
+
+babel-generator@^6.18.0, babel-generator@^6.26.0:
+  version "6.26.1"
+  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
+  integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
+  dependencies:
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    detect-indent "^4.0.0"
+    jsesc "^1.3.0"
+    lodash "^4.17.4"
+    source-map "^0.5.7"
+    trim-right "^1.0.1"
+
+babel-helpers@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
+  integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-jest@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
+  integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
+  dependencies:
+    babel-plugin-istanbul "^4.1.6"
+    babel-preset-jest "^23.2.0"
+
+babel-loader@8.0.4:
+  version "8.0.4"
+  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.4.tgz#7bbf20cbe4560629e2e41534147692d3fecbdce6"
+  integrity sha512-fhBhNkUToJcW9nV46v8w87AJOwAJDz84c1CL57n3Stj73FANM/b9TbCUK4YhdOwEyZ+OxhYpdeZDNzSI29Firw==
+  dependencies:
+    find-cache-dir "^1.0.0"
+    loader-utils "^1.0.2"
+    mkdirp "^0.5.1"
+    util.promisify "^1.0.0"
+
+babel-messages@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+  integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-istanbul@^4.1.6:
+  version "4.1.6"
+  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
+  integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
+  dependencies:
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+    find-up "^2.1.0"
+    istanbul-lib-instrument "^1.10.1"
+    test-exclude "^4.2.1"
+
+babel-plugin-jest-hoist@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
+  integrity sha512-N0MlMjZtahXK0yb0K3V9hWPrq5e7tThbghvDr0k3X75UuOOqwsWW6mk8XHD2QvEC0Ca9dLIfTgNU36TeJD6Hnw==
+
+babel-plugin-macros@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
+  integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+  dependencies:
+    "@babel/runtime" "^7.12.5"
+    cosmiconfig "^7.0.0"
+    resolve "^1.19.0"
+
+babel-plugin-syntax-object-rest-spread@^6.13.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
+  integrity sha512-C4Aq+GaAj83pRQ0EFgTvw5YO6T3Qz2KGrNRwIj9mSoNHVvdZY4KO2uA6HNtNXCw993iSZnckY1aLW8nOi8i4+w==
+
+babel-preset-jest@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
+  integrity sha512-AdfWwc0PYvDtwr009yyVNh72Ev68os7SsPmOFVX7zSA+STXuk5CV2iMVazZU01bEoHCSwTkgv4E4HOOcODPkPg==
+  dependencies:
+    babel-plugin-jest-hoist "^23.2.0"
+    babel-plugin-syntax-object-rest-spread "^6.13.0"
+
+babel-register@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
+  integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==
+  dependencies:
+    babel-core "^6.26.0"
+    babel-runtime "^6.26.0"
+    core-js "^2.5.0"
+    home-or-tmp "^2.0.0"
+    lodash "^4.17.4"
+    mkdirp "^0.5.1"
+    source-map-support "^0.4.15"
+
+babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+  integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    lodash "^4.17.4"
+
+babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+  integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    debug "^2.6.8"
+    globals "^9.18.0"
+    invariant "^2.2.2"
+    lodash "^4.17.4"
+
+babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+  integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==
+  dependencies:
+    babel-runtime "^6.26.0"
+    esutils "^2.0.2"
+    lodash "^4.17.4"
+    to-fast-properties "^1.0.3"
+
+babylon@^6.18.0:
+  version "6.18.0"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+  integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+
+balanced-match@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+  integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+base64-js@^1.0.2:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+  integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+base@^0.11.1:
+  version "0.11.2"
+  resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
+  integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
+  dependencies:
+    cache-base "^1.0.1"
+    class-utils "^0.3.5"
+    component-emitter "^1.2.1"
+    define-property "^1.0.0"
+    isobject "^3.0.1"
+    mixin-deep "^1.2.0"
+    pascalcase "^0.1.1"
+
+batch@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+  integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
+
+bcrypt-pbkdf@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+  integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==
+  dependencies:
+    tweetnacl "^0.14.3"
+
+before-after-hook@^2.0.0, before-after-hook@^2.1.0:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
+  integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==
+
+big.js@^3.1.3:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
+  integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==
+
+big.js@^5.2.2:
+  version "5.2.2"
+  resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+  integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+binary-extensions@^1.0.0:
+  version "1.13.1"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
+  integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
+
+binary-extensions@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+  integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+bindings@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
+  integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
+  dependencies:
+    file-uri-to-path "1.0.0"
+
+bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5:
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+  integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
+  version "4.12.0"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+  integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+
+bn.js@^5.0.0, bn.js@^5.1.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
+  integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
+
+body-parser@1.20.1:
+  version "1.20.1"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
+  integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
+  dependencies:
+    bytes "3.1.2"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "2.0.0"
+    destroy "1.2.0"
+    http-errors "2.0.0"
+    iconv-lite "0.4.24"
+    on-finished "2.4.1"
+    qs "6.11.0"
+    raw-body "2.5.1"
+    type-is "~1.6.18"
+    unpipe "1.0.0"
+
+bonjour@^3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
+  integrity sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==
+  dependencies:
+    array-flatten "^2.1.0"
+    deep-equal "^1.0.1"
+    dns-equal "^1.0.0"
+    dns-txt "^2.0.2"
+    multicast-dns "^6.0.1"
+    multicast-dns-service-types "^1.1.0"
+
+boolbase@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+  integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
+brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
+braces@^1.8.2:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+  integrity sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==
+  dependencies:
+    expand-range "^1.8.1"
+    preserve "^0.2.0"
+    repeat-element "^1.1.2"
+
+braces@^2.3.1, braces@^2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
+  integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
+  dependencies:
+    arr-flatten "^1.1.0"
+    array-unique "^0.3.2"
+    extend-shallow "^2.0.1"
+    fill-range "^4.0.0"
+    isobject "^3.0.1"
+    repeat-element "^1.1.2"
+    snapdragon "^0.8.1"
+    snapdragon-node "^2.0.1"
+    split-string "^3.0.2"
+    to-regex "^3.0.1"
+
+braces@^3.0.2, braces@~3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+  integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+  dependencies:
+    fill-range "^7.0.1"
+
+brorand@^1.0.1, brorand@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+  integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
+
+browser-process-hrtime@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
+  integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
+
+browser-resolve@^1.11.3:
+  version "1.11.3"
+  resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
+  integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==
+  dependencies:
+    resolve "1.1.7"
+
+browserify-aes@^1.0.0, browserify-aes@^1.0.4:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
+  integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
+  dependencies:
+    buffer-xor "^1.0.3"
+    cipher-base "^1.0.0"
+    create-hash "^1.1.0"
+    evp_bytestokey "^1.0.3"
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+browserify-cipher@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0"
+  integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==
+  dependencies:
+    browserify-aes "^1.0.4"
+    browserify-des "^1.0.0"
+    evp_bytestokey "^1.0.0"
+
+browserify-des@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c"
+  integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==
+  dependencies:
+    cipher-base "^1.0.1"
+    des.js "^1.0.0"
+    inherits "^2.0.1"
+    safe-buffer "^5.1.2"
+
+browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d"
+  integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==
+  dependencies:
+    bn.js "^5.0.0"
+    randombytes "^2.0.1"
+
+browserify-sign@^4.0.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
+  integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
+  dependencies:
+    bn.js "^5.1.1"
+    browserify-rsa "^4.0.1"
+    create-hash "^1.2.0"
+    create-hmac "^1.1.7"
+    elliptic "^6.5.3"
+    inherits "^2.0.4"
+    parse-asn1 "^5.1.5"
+    readable-stream "^3.6.0"
+    safe-buffer "^5.2.0"
+
+browserify-zlib@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
+  integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
+  dependencies:
+    pako "~1.0.5"
+
+browserslist@^4.1.0, browserslist@^4.21.3:
+  version "4.21.5"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
+  integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
+  dependencies:
+    caniuse-lite "^1.0.30001449"
+    electron-to-chromium "^1.4.284"
+    node-releases "^2.0.8"
+    update-browserslist-db "^1.0.10"
+
+bs-logger@0.x:
+  version "0.2.6"
+  resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
+  integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
+  dependencies:
+    fast-json-stable-stringify "2.x"
+
+bser@2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+  integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+  dependencies:
+    node-int64 "^0.4.0"
+
+btoa-lite@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
+  integrity sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==
+
+buffer-equal-constant-time@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
+  integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
+
+buffer-from@1.x, buffer-from@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+  integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+buffer-indexof@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
+  integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
+
+buffer-xor@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+  integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==
+
+buffer@^4.3.0:
+  version "4.9.2"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
+  integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==
+  dependencies:
+    base64-js "^1.0.2"
+    ieee754 "^1.1.4"
+    isarray "^1.0.0"
+
+builtin-modules@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+  integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==
+
+builtin-status-codes@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+  integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==
+
+builtins@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
+  integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==
+
+byline@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
+  integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==
+
+byte-size@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191"
+  integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==
+
+bytes@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+  integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
+
+bytes@3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
+  integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+
+cacache@^10.0.4:
+  version "10.0.4"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
+  integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==
+  dependencies:
+    bluebird "^3.5.1"
+    chownr "^1.0.1"
+    glob "^7.1.2"
+    graceful-fs "^4.1.11"
+    lru-cache "^4.1.1"
+    mississippi "^2.0.0"
+    mkdirp "^0.5.1"
+    move-concurrently "^1.0.1"
+    promise-inflight "^1.0.1"
+    rimraf "^2.6.2"
+    ssri "^5.2.4"
+    unique-filename "^1.1.0"
+    y18n "^4.0.0"
+
+cacache@^11.0.2:
+  version "11.3.3"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc"
+  integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==
+  dependencies:
+    bluebird "^3.5.5"
+    chownr "^1.1.1"
+    figgy-pudding "^3.5.1"
+    glob "^7.1.4"
+    graceful-fs "^4.1.15"
+    lru-cache "^5.1.1"
+    mississippi "^3.0.0"
+    mkdirp "^0.5.1"
+    move-concurrently "^1.0.1"
+    promise-inflight "^1.0.1"
+    rimraf "^2.6.3"
+    ssri "^6.0.1"
+    unique-filename "^1.1.1"
+    y18n "^4.0.0"
+
+cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3:
+  version "12.0.4"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c"
+  integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==
+  dependencies:
+    bluebird "^3.5.5"
+    chownr "^1.1.1"
+    figgy-pudding "^3.5.1"
+    glob "^7.1.4"
+    graceful-fs "^4.1.15"
+    infer-owner "^1.0.3"
+    lru-cache "^5.1.1"
+    mississippi "^3.0.0"
+    mkdirp "^0.5.1"
+    move-concurrently "^1.0.1"
+    promise-inflight "^1.0.1"
+    rimraf "^2.6.3"
+    ssri "^6.0.1"
+    unique-filename "^1.1.1"
+    y18n "^4.0.0"
+
+cache-base@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
+  integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
+  dependencies:
+    collection-visit "^1.0.0"
+    component-emitter "^1.2.1"
+    get-value "^2.0.6"
+    has-value "^1.0.0"
+    isobject "^3.0.1"
+    set-value "^2.0.0"
+    to-object-path "^0.3.0"
+    union-value "^1.0.0"
+    unset-value "^1.0.0"
+
+call-bind@^1.0.0, call-bind@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+  integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+  dependencies:
+    function-bind "^1.1.1"
+    get-intrinsic "^1.0.2"
+
+call-me-maybe@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa"
+  integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==
+
+caller-callsite@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
+  integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==
+  dependencies:
+    callsites "^2.0.0"
+
+caller-path@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
+  integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==
+  dependencies:
+    caller-callsite "^2.0.0"
+
+callsites@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
+  integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==
+
+callsites@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+  integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camel-case@3.0.x:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
+  integrity sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==
+  dependencies:
+    no-case "^2.2.0"
+    upper-case "^1.1.1"
+
+camelcase-keys@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+  integrity sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==
+  dependencies:
+    camelcase "^2.0.0"
+    map-obj "^1.0.0"
+
+camelcase-keys@^4.0.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77"
+  integrity sha512-Ej37YKYbFUI8QiYlvj9YHb6/Z60dZyPJW0Cs8sFilMbd2lP0bw3ylAq9yJkK4lcTA2dID5fG8LjmJYbO7kWb7Q==
+  dependencies:
+    camelcase "^4.1.0"
+    map-obj "^2.0.0"
+    quick-lru "^1.0.0"
+
+camelcase-keys@^6.2.2:
+  version "6.2.2"
+  resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0"
+  integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==
+  dependencies:
+    camelcase "^5.3.1"
+    map-obj "^4.0.0"
+    quick-lru "^4.0.1"
+
+camelcase@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+  integrity sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==
+
+camelcase@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+  integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==
+
+camelcase@^5.0.0, camelcase@^5.3.1:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+  integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+caniuse-lite@^1.0.30000884, caniuse-lite@^1.0.30001449:
+  version "1.0.30001489"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz#ca82ee2d4e4dbf2bd2589c9360d3fcc2c7ba3bd8"
+  integrity sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==
+
+capture-exit@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
+  integrity sha512-IS4lTgp57lUcpXzyCaiUQcRZBxZAkzl+jNXrMUXZjdnr2yujpKUMG9OYeYL29i6fL66ihypvVJ/MeX0B+9pWOg==
+  dependencies:
+    rsvp "^3.3.3"
+
+caseless@~0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+  integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
+
+chalk@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
+chalk@^4.0.0:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+  dependencies:
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
+
+chardet@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+  integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
+chart.js@2.8.0:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.8.0.tgz#b703b10d0f4ec5079eaefdcd6ca32dc8f826e0e9"
+  integrity sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==
+  dependencies:
+    chartjs-color "^2.1.0"
+    moment "^2.10.2"
+
+chart.js@^3.4.0:
+  version "3.9.1"
+  resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.9.1.tgz#3abf2c775169c4c71217a107163ac708515924b8"
+  integrity sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==
+
+chartjs-color-string@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
+  integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
+  dependencies:
+    color-name "^1.0.0"
+
+chartjs-color@^2.1.0:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0"
+  integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==
+  dependencies:
+    chartjs-color-string "^0.6.0"
+    color-convert "^1.9.3"
+
+chokidar@^2.0.0, chokidar@^2.1.8:
+  version "2.1.8"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
+  integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
+  dependencies:
+    anymatch "^2.0.0"
+    async-each "^1.0.1"
+    braces "^2.3.2"
+    glob-parent "^3.1.0"
+    inherits "^2.0.3"
+    is-binary-path "^1.0.0"
+    is-glob "^4.0.0"
+    normalize-path "^3.0.0"
+    path-is-absolute "^1.0.0"
+    readdirp "^2.2.1"
+    upath "^1.1.1"
+  optionalDependencies:
+    fsevents "^1.2.7"
+
+chokidar@^3.4.1:
+  version "3.5.3"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+  integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+  dependencies:
+    anymatch "~3.1.2"
+    braces "~3.0.2"
+    glob-parent "~5.1.2"
+    is-binary-path "~2.1.0"
+    is-glob "~4.0.1"
+    normalize-path "~3.0.0"
+    readdirp "~3.6.0"
+  optionalDependencies:
+    fsevents "~2.3.2"
+
+chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+  integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+
+chrome-trace-event@^1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+  integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+
+ci-info@^1.5.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+  integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
+ci-info@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+  integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
+cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+  integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+class-utils@^0.3.5:
+  version "0.3.6"
+  resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
+  integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
+  dependencies:
+    arr-union "^3.1.0"
+    define-property "^0.2.5"
+    isobject "^3.0.0"
+    static-extend "^0.1.1"
+
+classnames@2.2.6:
+  version "2.2.6"
+  resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
+  integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
+
+clean-css@4.2.x:
+  version "4.2.4"
+  resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178"
+  integrity sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==
+  dependencies:
+    source-map "~0.6.0"
+
+cli-cursor@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+  integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==
+  dependencies:
+    restore-cursor "^2.0.0"
+
+cli-width@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
+  integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
+
+cliui@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
+  integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
+  dependencies:
+    string-width "^2.1.1"
+    strip-ansi "^4.0.0"
+    wrap-ansi "^2.0.0"
+
+cliui@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
+  integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
+  dependencies:
+    string-width "^3.1.0"
+    strip-ansi "^5.2.0"
+    wrap-ansi "^5.1.0"
+
+clone-deep@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+  integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+  dependencies:
+    is-plain-object "^2.0.4"
+    kind-of "^6.0.2"
+    shallow-clone "^3.0.0"
+
+clone@^1.0.2:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+  integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
+
+clsx@^1.1.0, clsx@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
+  integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+  integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
+
+code-point-at@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+  integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==
+
+collection-visit@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
+  integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==
+  dependencies:
+    map-visit "^1.0.0"
+    object-visit "^1.0.0"
+
+color-convert@^1.9.0, color-convert@^1.9.3:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+  dependencies:
+    color-name "1.1.3"
+
+color-convert@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  dependencies:
+    color-name "~1.1.4"
+
+color-name@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+  integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+color-name@^1.0.0, color-name@~1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+colors@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
+  integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==
+
+colour@0.7.1:
+  version "0.7.1"
+  resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778"
+  integrity sha512-Rel466v0EnmKPcsxHo91L4kgPs/6XF7Pu2LJNszq9lXYwi5CFWEeIiRaTX5ym7PPMdj4udDHkLSVC1//JVkZQg==
+
+columnify@^1.5.4:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3"
+  integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==
+  dependencies:
+    strip-ansi "^6.0.1"
+    wcwidth "^1.0.0"
+
+combined-stream@^1.0.6, combined-stream@~1.0.6:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+  integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+  dependencies:
+    delayed-stream "~1.0.0"
+
+commander@2.17.x:
+  version "2.17.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+  integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
+
+commander@^2.12.1, commander@^2.19.0, commander@^2.20.0:
+  version "2.20.3"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+  integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@~2.19.0:
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+  integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
+commondir@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+  integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
+
+compare-func@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3"
+  integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==
+  dependencies:
+    array-ify "^1.0.0"
+    dot-prop "^5.1.0"
+
+component-emitter@^1.2.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
+  integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
+
+compressible@~2.0.16:
+  version "2.0.18"
+  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+  integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+  dependencies:
+    mime-db ">= 1.43.0 < 2"
+
+compression@^1.5.2:
+  version "1.7.4"
+  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+  integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
+  dependencies:
+    accepts "~1.3.5"
+    bytes "3.0.0"
+    compressible "~2.0.16"
+    debug "2.6.9"
+    on-headers "~1.0.2"
+    safe-buffer "5.1.2"
+    vary "~1.1.2"
+
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+  integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+concat-stream@^1.5.0:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+  integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+  dependencies:
+    buffer-from "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^2.2.2"
+    typedarray "^0.0.6"
+
+concat-stream@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
+  integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
+  dependencies:
+    buffer-from "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^3.0.2"
+    typedarray "^0.0.6"
+
+config-chain@^1.1.11:
+  version "1.1.13"
+  resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
+  integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
+  dependencies:
+    ini "^1.3.4"
+    proto-list "~1.2.1"
+
+confusing-browser-globals@^1.0.10:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
+  integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==
+
+connect-history-api-fallback@^1.3.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
+  integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
+
+console-browserify@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
+  integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+  integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
+
+constants-browserify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+  integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==
+
+content-disposition@0.5.4:
+  version "0.5.4"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
+  integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
+  dependencies:
+    safe-buffer "5.2.1"
+
+content-type@~1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
+  integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
+
+conventional-changelog-angular@^5.0.3:
+  version "5.0.13"
+  resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c"
+  integrity sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==
+  dependencies:
+    compare-func "^2.0.0"
+    q "^1.5.1"
+
+conventional-changelog-core@^3.1.6:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz#b31410856f431c847086a7dcb4d2ca184a7d88fb"
+  integrity sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==
+  dependencies:
+    conventional-changelog-writer "^4.0.6"
+    conventional-commits-parser "^3.0.3"
+    dateformat "^3.0.0"
+    get-pkg-repo "^1.0.0"
+    git-raw-commits "2.0.0"
+    git-remote-origin-url "^2.0.0"
+    git-semver-tags "^2.0.3"
+    lodash "^4.2.1"
+    normalize-package-data "^2.3.5"
+    q "^1.5.1"
+    read-pkg "^3.0.0"
+    read-pkg-up "^3.0.0"
+    through2 "^3.0.0"
+
+conventional-changelog-preset-loader@^2.1.1:
+  version "2.3.4"
+  resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c"
+  integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==
+
+conventional-changelog-writer@^4.0.6:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz#1ca7880b75aa28695ad33312a1f2366f4b12659f"
+  integrity sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw==
+  dependencies:
+    compare-func "^2.0.0"
+    conventional-commits-filter "^2.0.7"
+    dateformat "^3.0.0"
+    handlebars "^4.7.6"
+    json-stringify-safe "^5.0.1"
+    lodash "^4.17.15"
+    meow "^8.0.0"
+    semver "^6.0.0"
+    split "^1.0.0"
+    through2 "^4.0.0"
+
+conventional-commits-filter@^2.0.2, conventional-commits-filter@^2.0.7:
+  version "2.0.7"
+  resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3"
+  integrity sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==
+  dependencies:
+    lodash.ismatch "^4.4.0"
+    modify-values "^1.0.0"
+
+conventional-commits-parser@^3.0.3:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972"
+  integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==
+  dependencies:
+    JSONStream "^1.0.4"
+    is-text-path "^1.0.1"
+    lodash "^4.17.15"
+    meow "^8.0.0"
+    split2 "^3.0.0"
+    through2 "^4.0.0"
+
+conventional-recommended-bump@^5.0.0:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz#5af63903947b6e089e77767601cb592cabb106ba"
+  integrity sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ==
+  dependencies:
+    concat-stream "^2.0.0"
+    conventional-changelog-preset-loader "^2.1.1"
+    conventional-commits-filter "^2.0.2"
+    conventional-commits-parser "^3.0.3"
+    git-raw-commits "2.0.0"
+    git-semver-tags "^2.0.3"
+    meow "^4.0.0"
+    q "^1.5.1"
+
+convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
+  integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+
+cookie-signature@1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+  integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
+
+cookie@0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
+  integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+
+copy-concurrently@^1.0.0:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+  integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
+  dependencies:
+    aproba "^1.1.1"
+    fs-write-stream-atomic "^1.0.8"
+    iferr "^0.1.5"
+    mkdirp "^0.5.1"
+    rimraf "^2.5.4"
+    run-queue "^1.0.0"
+
+copy-descriptor@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
+  integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==
+
+copy-webpack-plugin@4.5.2:
+  version "4.5.2"
+  resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.5.2.tgz#d53444a8fea2912d806e78937390ddd7e632ee5c"
+  integrity sha512-zmC33E8FFSq3AbflTvqvPvBo621H36Afsxlui91d+QyZxPIuXghfnTsa1CuqiAaCPgJoSUWfTFbKJnadZpKEbQ==
+  dependencies:
+    cacache "^10.0.4"
+    find-cache-dir "^1.0.0"
+    globby "^7.1.1"
+    is-glob "^4.0.0"
+    loader-utils "^1.1.0"
+    minimatch "^3.0.4"
+    p-limit "^1.0.0"
+    serialize-javascript "^1.4.0"
+
+core-js-pure@^3.30.2:
+  version "3.30.2"
+  resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.30.2.tgz#005a82551f4af3250dcfb46ed360fad32ced114e"
+  integrity sha512-p/npFUJXXBkCCTIlEGBdghofn00jWG6ZOtdoIXSJmAu2QBvN0IqpZXWweOytcwE6cfx8ZvVUy1vw8zxhe4Y2vg==
+
+core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7, core-js@^2.6.5:
+  version "2.6.12"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
+  integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
+
+core-util-is@1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+  integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==
+
+core-util-is@~1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+  integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+
+corser@~2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87"
+  integrity sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==
+
+cosmiconfig@^5.0.0, cosmiconfig@^5.1.0:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
+  integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
+  dependencies:
+    import-fresh "^2.0.0"
+    is-directory "^0.3.1"
+    js-yaml "^3.13.1"
+    parse-json "^4.0.0"
+
+cosmiconfig@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6"
+  integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
+  dependencies:
+    "@types/parse-json" "^4.0.0"
+    import-fresh "^3.2.1"
+    parse-json "^5.0.0"
+    path-type "^4.0.0"
+    yaml "^1.10.0"
+
+create-ecdh@^4.0.0:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
+  integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==
+  dependencies:
+    bn.js "^4.1.0"
+    elliptic "^6.5.3"
+
+create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+  integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+  dependencies:
+    cipher-base "^1.0.1"
+    inherits "^2.0.1"
+    md5.js "^1.3.4"
+    ripemd160 "^2.0.1"
+    sha.js "^2.4.0"
+
+create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
+  integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
+  dependencies:
+    cipher-base "^1.0.3"
+    create-hash "^1.1.0"
+    inherits "^2.0.1"
+    ripemd160 "^2.0.0"
+    safe-buffer "^5.0.1"
+    sha.js "^2.4.8"
+
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+  integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+  dependencies:
+    nice-try "^1.0.4"
+    path-key "^2.0.1"
+    semver "^5.5.0"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
+cross-spawn@^7.0.2:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+  integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+  dependencies:
+    path-key "^3.1.0"
+    shebang-command "^2.0.0"
+    which "^2.0.1"
+
+crypto-browserify@^3.11.0:
+  version "3.12.0"
+  resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
+  integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
+  dependencies:
+    browserify-cipher "^1.0.0"
+    browserify-sign "^4.0.0"
+    create-ecdh "^4.0.0"
+    create-hash "^1.1.0"
+    create-hmac "^1.1.0"
+    diffie-hellman "^5.0.0"
+    inherits "^2.0.1"
+    pbkdf2 "^3.0.3"
+    public-encrypt "^4.0.0"
+    randombytes "^2.0.0"
+    randomfill "^1.0.3"
+
+css-loader@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56"
+  integrity sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==
+  dependencies:
+    babel-code-frame "^6.26.0"
+    css-selector-tokenizer "^0.7.0"
+    icss-utils "^2.1.0"
+    loader-utils "^1.0.2"
+    lodash.camelcase "^4.3.0"
+    postcss "^6.0.23"
+    postcss-modules-extract-imports "^1.2.0"
+    postcss-modules-local-by-default "^1.2.0"
+    postcss-modules-scope "^1.1.0"
+    postcss-modules-values "^1.3.0"
+    postcss-value-parser "^3.3.0"
+    source-list-map "^2.0.0"
+
+css-select@^4.1.3:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b"
+  integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==
+  dependencies:
+    boolbase "^1.0.0"
+    css-what "^6.0.1"
+    domhandler "^4.3.1"
+    domutils "^2.8.0"
+    nth-check "^2.0.1"
+
+css-selector-tokenizer@^0.7.0:
+  version "0.7.3"
+  resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1"
+  integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==
+  dependencies:
+    cssesc "^3.0.0"
+    fastparse "^1.1.2"
+
+css-vendor@^2.0.8:
+  version "2.0.8"
+  resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d"
+  integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==
+  dependencies:
+    "@babel/runtime" "^7.8.3"
+    is-in-browser "^1.0.2"
+
+css-what@^6.0.1:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
+  integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+
+cssesc@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+  integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
+  version "0.3.8"
+  resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+  integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^1.0.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
+  integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==
+  dependencies:
+    cssom "0.3.x"
+
+csstype@2.6.8:
+  version "2.6.8"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.8.tgz#0fb6fc2417ffd2816a418c9336da74d7f07db431"
+  integrity sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==
+
+csstype@^2.6.5:
+  version "2.6.21"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
+  integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
+
+csstype@^3.0.2, csstype@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
+  integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
+
+currently-unhandled@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+  integrity sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==
+  dependencies:
+    array-find-index "^1.0.1"
+
+cyclist@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
+  integrity sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==
+
+damerau-levenshtein@^1.0.8:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
+  integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+
+dargs@^4.0.1:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
+  integrity sha512-jyweV/k0rbv2WK4r9KLayuBrSh2Py0tNmV7LBoSMH4hMQyrG8OPyIOWB2VEx4DJKXWmK4lopYMVvORlDt2S8Aw==
+  dependencies:
+    number-is-nan "^1.0.0"
+
+dashdash@^1.12.0:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+  integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==
+  dependencies:
+    assert-plus "^1.0.0"
+
+data-urls@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
+  integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
+  dependencies:
+    abab "^2.0.0"
+    whatwg-mimetype "^2.2.0"
+    whatwg-url "^7.0.0"
+
+dateformat@^3.0.0:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
+  integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
+
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
+debug@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+  dependencies:
+    ms "2.0.0"
+
+debug@^3.1.0, debug@^3.2.5, debug@^3.2.7:
+  version "3.2.7"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+  integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+  dependencies:
+    ms "^2.1.1"
+
+debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+  integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+  dependencies:
+    ms "2.1.2"
+
+debuglog@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
+  integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==
+
+decamelize-keys@^1.0.0, decamelize-keys@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8"
+  integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==
+  dependencies:
+    decamelize "^1.1.0"
+    map-obj "^1.0.0"
+
+decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+  integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
+
+decamelize@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7"
+  integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==
+  dependencies:
+    xregexp "4.0.0"
+
+decode-uri-component@^0.2.0:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9"
+  integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==
+
+dedent@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+  integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
+
+deep-equal@^1.0.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
+  integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==
+  dependencies:
+    is-arguments "^1.0.4"
+    is-date-object "^1.0.1"
+    is-regex "^1.0.4"
+    object-is "^1.0.1"
+    object-keys "^1.1.1"
+    regexp.prototype.flags "^1.2.0"
+
+deep-is@^0.1.3, deep-is@~0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+  integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+default-gateway@^2.6.0:
+  version "2.7.2"
+  resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
+  integrity sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==
+  dependencies:
+    execa "^0.10.0"
+    ip-regex "^2.1.0"
+
+default-require-extensions@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+  integrity sha512-Dn2eAftOqXhNXs5f/Xjn7QTZ6kDYkx7u0EXQInN1oyYwsZysu11q7oTtaKcbzLxZRJiDHa8VmwpWmb4lY5FqgA==
+  dependencies:
+    strip-bom "^2.0.0"
+
+defaults@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
+  integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
+  dependencies:
+    clone "^1.0.2"
+
+define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
+  integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
+  dependencies:
+    has-property-descriptors "^1.0.0"
+    object-keys "^1.1.1"
+
+define-property@^0.2.5:
+  version "0.2.5"
+  resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
+  integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==
+  dependencies:
+    is-descriptor "^0.1.0"
+
+define-property@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
+  integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==
+  dependencies:
+    is-descriptor "^1.0.0"
+
+define-property@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
+  integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
+  dependencies:
+    is-descriptor "^1.0.2"
+    isobject "^3.0.1"
+
+del@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
+  integrity sha512-7yjqSoVSlJzA4t/VUwazuEagGeANEKB3f/aNI//06pfKgwoCb7f6Q1gETN1sZzYaj6chTQ0AhIwDiPdfOjko4A==
+  dependencies:
+    globby "^6.1.0"
+    is-path-cwd "^1.0.0"
+    is-path-in-cwd "^1.0.0"
+    p-map "^1.1.1"
+    pify "^3.0.0"
+    rimraf "^2.2.8"
+
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+  integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+delegates@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+  integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
+
+depd@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+  integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+depd@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+  integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
+
+deprecation@^2.0.0, deprecation@^2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
+  integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
+
+des.js@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
+  integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==
+  dependencies:
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+
+destroy@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+  integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
+
+detect-file@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
+  integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==
+
+detect-indent@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+  integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==
+  dependencies:
+    repeating "^2.0.0"
+
+detect-indent@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
+  integrity sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==
+
+detect-newline@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+  integrity sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==
+
+detect-node@^2.0.4:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
+  integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
+
+dezalgo@^1.0.0:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
+  integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==
+  dependencies:
+    asap "^2.0.0"
+    wrappy "1"
+
+diff@^3.2.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+
+diffie-hellman@^5.0.0:
+  version "5.0.3"
+  resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
+  integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==
+  dependencies:
+    bn.js "^4.1.0"
+    miller-rabin "^4.0.0"
+    randombytes "^2.0.0"
+
+dir-glob@^2.0.0, dir-glob@^2.2.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
+  integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==
+  dependencies:
+    path-type "^3.0.0"
+
+dir-glob@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+  integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+  dependencies:
+    path-type "^4.0.0"
+
+dns-equal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
+  integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==
+
+dns-packet@^1.3.1:
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f"
+  integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==
+  dependencies:
+    ip "^1.1.0"
+    safe-buffer "^5.0.1"
+
+dns-txt@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6"
+  integrity sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==
+  dependencies:
+    buffer-indexof "^1.0.0"
+
+doctrine@0.7.2, doctrine@^0.7.2:
+  version "0.7.2"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523"
+  integrity sha512-qiB/Rir6Un6Ad/TIgTRzsremsTGWzs8j7woXvp14jgq00676uBiBT5eUOi+FgRywZFVy5Us/c04ISRpZhRbS6w==
+  dependencies:
+    esutils "^1.1.6"
+    isarray "0.0.1"
+
+doctrine@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+  integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
+  dependencies:
+    esutils "^2.0.2"
+
+doctrine@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+  integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+  dependencies:
+    esutils "^2.0.2"
+
+dom-converter@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
+  integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==
+  dependencies:
+    utila "~0.4"
+
+dom-helpers@^5.0.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
+  integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
+  dependencies:
+    "@babel/runtime" "^7.8.7"
+    csstype "^3.0.2"
+
+dom-serializer@^1.0.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
+  integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
+  dependencies:
+    domelementtype "^2.0.1"
+    domhandler "^4.2.0"
+    entities "^2.0.0"
+
+domain-browser@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
+  integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
+
+domelementtype@^2.0.1, domelementtype@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
+  integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domexception@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
+  integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
+  dependencies:
+    webidl-conversions "^4.0.2"
+
+domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
+  version "4.3.1"
+  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
+  integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
+  dependencies:
+    domelementtype "^2.2.0"
+
+domutils@^2.5.2, domutils@^2.8.0:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
+  integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
+  dependencies:
+    dom-serializer "^1.0.1"
+    domelementtype "^2.2.0"
+    domhandler "^4.2.0"
+
+dot-prop@^4.2.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4"
+  integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==
+  dependencies:
+    is-obj "^1.0.0"
+
+dot-prop@^5.1.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
+  integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
+  dependencies:
+    is-obj "^2.0.0"
+
+duplexer@^0.1.1:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+  integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+
+duplexify@^3.4.2, duplexify@^3.6.0:
+  version "3.7.1"
+  resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
+  integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
+  dependencies:
+    end-of-stream "^1.0.0"
+    inherits "^2.0.1"
+    readable-stream "^2.0.0"
+    stream-shift "^1.0.0"
+
+ecc-jsbn@~0.1.1:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+  integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==
+  dependencies:
+    jsbn "~0.1.0"
+    safer-buffer "^2.1.0"
+
+ecdsa-sig-formatter@1.0.11:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
+  integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
+  dependencies:
+    safe-buffer "^5.0.1"
+
+ecstatic@^3.0.0:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.3.2.tgz#6d1dd49814d00594682c652adb66076a69d46c48"
+  integrity sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==
+  dependencies:
+    he "^1.1.1"
+    mime "^1.6.0"
+    minimist "^1.1.0"
+    url-join "^2.0.5"
+
+ee-first@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+  integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
+
+electron-to-chromium@^1.4.284:
+  version "1.4.408"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.408.tgz#73e657a24bd0b7481d68c943dded0d097b0d0a52"
+  integrity sha512-vjeaj0u/UYnzA/CIdGXzzcxRLCqRwREYc9YfaWInjIEr7/XPttZ6ShpyqapchEy0S2r6LpLjDBTnNj7ZxnxJKg==
+
+elliptic@^6.5.3:
+  version "6.5.4"
+  resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+  integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
+  dependencies:
+    bn.js "^4.11.9"
+    brorand "^1.1.0"
+    hash.js "^1.0.0"
+    hmac-drbg "^1.0.1"
+    inherits "^2.0.4"
+    minimalistic-assert "^1.0.1"
+    minimalistic-crypto-utils "^1.0.1"
+
+emoji-regex@^7.0.1:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
+  integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+
+emoji-regex@^8.0.0:
+  version "8.0.0"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+  integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emoji-regex@^9.2.2:
+  version "9.2.2"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+  integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
+emojis-list@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+  integrity sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng==
+
+emojis-list@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
+  integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+
+encodeurl@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+  integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
+
+encoding@^0.1.11:
+  version "0.1.13"
+  resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
+  integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
+  dependencies:
+    iconv-lite "^0.6.2"
+
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+  version "1.4.4"
+  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+  integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+  dependencies:
+    once "^1.4.0"
+
+enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
+  integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
+  dependencies:
+    graceful-fs "^4.1.2"
+    memory-fs "^0.5.0"
+    tapable "^1.0.0"
+
+entities@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
+  integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+
+env-paths@^2.2.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
+  integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
+
+envinfo@^7.3.1:
+  version "7.8.1"
+  resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
+  integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
+
+err-code@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960"
+  integrity sha512-CJAN+O0/yA1CKfRn9SXOGctSpEM7DCon/r/5r2eXFMY2zCCJBasFhcM5I+1kh3Ap11FsQCX+vGHceNPvpWKhoA==
+
+errno@^0.1.3, errno@~0.1.7:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
+  integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
+  dependencies:
+    prr "~1.0.1"
+
+error-ex@^1.2.0, error-ex@^1.3.1:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+  integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+  dependencies:
+    is-arrayish "^0.2.1"
+
+es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2:
+  version "1.21.2"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff"
+  integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==
+  dependencies:
+    array-buffer-byte-length "^1.0.0"
+    available-typed-arrays "^1.0.5"
+    call-bind "^1.0.2"
+    es-set-tostringtag "^2.0.1"
+    es-to-primitive "^1.2.1"
+    function.prototype.name "^1.1.5"
+    get-intrinsic "^1.2.0"
+    get-symbol-description "^1.0.0"
+    globalthis "^1.0.3"
+    gopd "^1.0.1"
+    has "^1.0.3"
+    has-property-descriptors "^1.0.0"
+    has-proto "^1.0.1"
+    has-symbols "^1.0.3"
+    internal-slot "^1.0.5"
+    is-array-buffer "^3.0.2"
+    is-callable "^1.2.7"
+    is-negative-zero "^2.0.2"
+    is-regex "^1.1.4"
+    is-shared-array-buffer "^1.0.2"
+    is-string "^1.0.7"
+    is-typed-array "^1.1.10"
+    is-weakref "^1.0.2"
+    object-inspect "^1.12.3"
+    object-keys "^1.1.1"
+    object.assign "^4.1.4"
+    regexp.prototype.flags "^1.4.3"
+    safe-regex-test "^1.0.0"
+    string.prototype.trim "^1.2.7"
+    string.prototype.trimend "^1.0.6"
+    string.prototype.trimstart "^1.0.6"
+    typed-array-length "^1.0.4"
+    unbox-primitive "^1.0.2"
+    which-typed-array "^1.1.9"
+
+es-array-method-boxes-properly@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
+  integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
+
+es-set-tostringtag@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
+  integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==
+  dependencies:
+    get-intrinsic "^1.1.3"
+    has "^1.0.3"
+    has-tostringtag "^1.0.0"
+
+es-shim-unscopables@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
+  integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+  dependencies:
+    has "^1.0.3"
+
+es-to-primitive@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+  integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+  dependencies:
+    is-callable "^1.1.4"
+    is-date-object "^1.0.1"
+    is-symbol "^1.0.2"
+
+es6-promise@^4.0.3:
+  version "4.2.8"
+  resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+  integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
+es6-promisify@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+  integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
+  dependencies:
+    es6-promise "^4.0.3"
+
+escalade@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+  integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escape-html@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+  integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+  integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+  integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
+escape-string-regexp@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+  integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+escodegen@^1.9.1:
+  version "1.14.3"
+  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
+  integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
+  dependencies:
+    esprima "^4.0.1"
+    estraverse "^4.2.0"
+    esutils "^2.0.2"
+    optionator "^0.8.1"
+  optionalDependencies:
+    source-map "~0.6.1"
+
+eslint-config-airbnb-base@^15.0.0:
+  version "15.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236"
+  integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==
+  dependencies:
+    confusing-browser-globals "^1.0.10"
+    object.assign "^4.1.2"
+    object.entries "^1.1.5"
+    semver "^6.3.0"
+
+eslint-config-airbnb-typescript@17.0.0:
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz#360dbcf810b26bbcf2ff716198465775f1c49a07"
+  integrity sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==
+  dependencies:
+    eslint-config-airbnb-base "^15.0.0"
+
+eslint-config-airbnb@19.0.4:
+  version "19.0.4"
+  resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3"
+  integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==
+  dependencies:
+    eslint-config-airbnb-base "^15.0.0"
+    object.assign "^4.1.2"
+    object.entries "^1.1.5"
+
+eslint-import-resolver-node@^0.3.6:
+  version "0.3.7"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
+  integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==
+  dependencies:
+    debug "^3.2.7"
+    is-core-module "^2.11.0"
+    resolve "^1.22.1"
+
+eslint-module-utils@^2.7.3:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
+  integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
+  dependencies:
+    debug "^3.2.7"
+
+eslint-plugin-import@2.26.0:
+  version "2.26.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
+  integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
+  dependencies:
+    array-includes "^3.1.4"
+    array.prototype.flat "^1.2.5"
+    debug "^2.6.9"
+    doctrine "^2.1.0"
+    eslint-import-resolver-node "^0.3.6"
+    eslint-module-utils "^2.7.3"
+    has "^1.0.3"
+    is-core-module "^2.8.1"
+    is-glob "^4.0.3"
+    minimatch "^3.1.2"
+    object.values "^1.1.5"
+    resolve "^1.22.0"
+    tsconfig-paths "^3.14.1"
+
+eslint-plugin-jsx-a11y@6.6.1:
+  version "6.6.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff"
+  integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==
+  dependencies:
+    "@babel/runtime" "^7.18.9"
+    aria-query "^4.2.2"
+    array-includes "^3.1.5"
+    ast-types-flow "^0.0.7"
+    axe-core "^4.4.3"
+    axobject-query "^2.2.0"
+    damerau-levenshtein "^1.0.8"
+    emoji-regex "^9.2.2"
+    has "^1.0.3"
+    jsx-ast-utils "^3.3.2"
+    language-tags "^1.0.5"
+    minimatch "^3.1.2"
+    semver "^6.3.0"
+
+eslint-plugin-react-hooks@4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
+  integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
+
+eslint-plugin-react@7.31.10:
+  version "7.31.10"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz#6782c2c7fe91c09e715d536067644bbb9491419a"
+  integrity sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==
+  dependencies:
+    array-includes "^3.1.5"
+    array.prototype.flatmap "^1.3.0"
+    doctrine "^2.1.0"
+    estraverse "^5.3.0"
+    jsx-ast-utils "^2.4.1 || ^3.0.0"
+    minimatch "^3.1.2"
+    object.entries "^1.1.5"
+    object.fromentries "^2.0.5"
+    object.hasown "^1.1.1"
+    object.values "^1.1.5"
+    prop-types "^15.8.1"
+    resolve "^2.0.0-next.3"
+    semver "^6.3.0"
+    string.prototype.matchall "^4.0.7"
+
+eslint-scope@^4.0.0:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
+  integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==
+  dependencies:
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-scope@^5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+  integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+  dependencies:
+    esrecurse "^4.3.0"
+    estraverse "^4.1.1"
+
+eslint-scope@^7.1.1:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b"
+  integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==
+  dependencies:
+    esrecurse "^4.3.0"
+    estraverse "^5.2.0"
+
+eslint-utils@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
+  integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+  dependencies:
+    eslint-visitor-keys "^2.0.0"
+
+eslint-visitor-keys@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
+  integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+
+eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
+  version "3.4.1"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
+  integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
+
+eslint@8.26.0:
+  version "8.26.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.26.0.tgz#2bcc8836e6c424c4ac26a5674a70d44d84f2181d"
+  integrity sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==
+  dependencies:
+    "@eslint/eslintrc" "^1.3.3"
+    "@humanwhocodes/config-array" "^0.11.6"
+    "@humanwhocodes/module-importer" "^1.0.1"
+    "@nodelib/fs.walk" "^1.2.8"
+    ajv "^6.10.0"
+    chalk "^4.0.0"
+    cross-spawn "^7.0.2"
+    debug "^4.3.2"
+    doctrine "^3.0.0"
+    escape-string-regexp "^4.0.0"
+    eslint-scope "^7.1.1"
+    eslint-utils "^3.0.0"
+    eslint-visitor-keys "^3.3.0"
+    espree "^9.4.0"
+    esquery "^1.4.0"
+    esutils "^2.0.2"
+    fast-deep-equal "^3.1.3"
+    file-entry-cache "^6.0.1"
+    find-up "^5.0.0"
+    glob-parent "^6.0.2"
+    globals "^13.15.0"
+    grapheme-splitter "^1.0.4"
+    ignore "^5.2.0"
+    import-fresh "^3.0.0"
+    imurmurhash "^0.1.4"
+    is-glob "^4.0.0"
+    is-path-inside "^3.0.3"
+    js-sdsl "^4.1.4"
+    js-yaml "^4.1.0"
+    json-stable-stringify-without-jsonify "^1.0.1"
+    levn "^0.4.1"
+    lodash.merge "^4.6.2"
+    minimatch "^3.1.2"
+    natural-compare "^1.4.0"
+    optionator "^0.9.1"
+    regexpp "^3.2.0"
+    strip-ansi "^6.0.1"
+    strip-json-comments "^3.1.0"
+    text-table "^0.2.0"
+
+espree@^9.4.0:
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b"
+  integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==
+  dependencies:
+    acorn "^8.8.0"
+    acorn-jsx "^5.3.2"
+    eslint-visitor-keys "^3.4.1"
+
+esprima@^4.0.0, esprima@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esquery@^1.4.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+  integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+  dependencies:
+    estraverse "^5.1.0"
+
+esrecurse@^4.1.0, esrecurse@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+  integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+  dependencies:
+    estraverse "^5.2.0"
+
+estraverse@^4.1.1, estraverse@^4.2.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+  integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+  integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+esutils@^1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375"
+  integrity sha512-RG1ZkUT7iFJG9LSHr7KDuuMSlujfeTtMNIcInURxKAxhMtwQhI3NrQhz26gZQYlsYZQKzsnwtpKrFKj9K9Qu1A==
+
+esutils@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+  integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+etag@~1.8.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+  integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+
+eventemitter3@^3.1.0:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
+  integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
+
+eventemitter3@^4.0.0:
+  version "4.0.7"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
+  integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+
+events@^3.0.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+  integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+eventsource@^1.0.7:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.2.tgz#bc75ae1c60209e7cb1541231980460343eaea7c2"
+  integrity sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==
+
+evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+  integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
+  dependencies:
+    md5.js "^1.3.4"
+    safe-buffer "^5.1.1"
+
+exec-sh@^0.2.0:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
+  integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
+  dependencies:
+    merge "^1.2.0"
+
+execa@^0.10.0:
+  version "0.10.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
+  integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
+  dependencies:
+    cross-spawn "^6.0.0"
+    get-stream "^3.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+execa@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+  integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+  dependencies:
+    cross-spawn "^6.0.0"
+    get-stream "^4.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+exit@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+  integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==
+
+expand-brackets@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+  integrity sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==
+  dependencies:
+    is-posix-bracket "^0.1.0"
+
+expand-brackets@^2.1.4:
+  version "2.1.4"
+  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
+  integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==
+  dependencies:
+    debug "^2.3.3"
+    define-property "^0.2.5"
+    extend-shallow "^2.0.1"
+    posix-character-classes "^0.1.0"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+expand-range@^1.8.1:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+  integrity sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==
+  dependencies:
+    fill-range "^2.1.0"
+
+expand-tilde@^2.0.0, expand-tilde@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
+  integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==
+  dependencies:
+    homedir-polyfill "^1.0.1"
+
+expect@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
+  integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
+  dependencies:
+    ansi-styles "^3.2.0"
+    jest-diff "^23.6.0"
+    jest-get-type "^22.1.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+
+express@^4.16.2:
+  version "4.18.2"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
+  integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
+  dependencies:
+    accepts "~1.3.8"
+    array-flatten "1.1.1"
+    body-parser "1.20.1"
+    content-disposition "0.5.4"
+    content-type "~1.0.4"
+    cookie "0.5.0"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "2.0.0"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "1.2.0"
+    fresh "0.5.2"
+    http-errors "2.0.0"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "2.4.1"
+    parseurl "~1.3.3"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.7"
+    qs "6.11.0"
+    range-parser "~1.2.1"
+    safe-buffer "5.2.1"
+    send "0.18.0"
+    serve-static "1.15.0"
+    setprototypeof "1.2.0"
+    statuses "2.0.1"
+    type-is "~1.6.18"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
+
+extend-shallow@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
+  integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==
+  dependencies:
+    is-extendable "^0.1.0"
+
+extend-shallow@^3.0.0, extend-shallow@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
+  integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==
+  dependencies:
+    assign-symbols "^1.0.0"
+    is-extendable "^1.0.1"
+
+extend@~3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+  integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+external-editor@^3.0.3:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
+  integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
+  dependencies:
+    chardet "^0.7.0"
+    iconv-lite "^0.4.24"
+    tmp "^0.0.33"
+
+extglob@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+  integrity sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==
+  dependencies:
+    is-extglob "^1.0.0"
+
+extglob@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
+  integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
+  dependencies:
+    array-unique "^0.3.2"
+    define-property "^1.0.0"
+    expand-brackets "^2.1.4"
+    extend-shallow "^2.0.1"
+    fragment-cache "^0.2.1"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+extract-text-webpack-plugin@next:
+  version "4.0.0-beta.0"
+  resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz#f7361d7ff430b42961f8d1321ba8c1757b5d4c42"
+  integrity sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==
+  dependencies:
+    async "^2.4.1"
+    loader-utils "^1.1.0"
+    schema-utils "^0.4.5"
+    webpack-sources "^1.1.0"
+
+extsprintf@1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+  integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==
+
+extsprintf@^1.2.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
+  integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^2.2.6:
+  version "2.2.7"
+  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
+  integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==
+  dependencies:
+    "@mrmlnc/readdir-enhanced" "^2.2.1"
+    "@nodelib/fs.stat" "^1.1.2"
+    glob-parent "^3.1.0"
+    is-glob "^4.0.0"
+    merge2 "^1.2.3"
+    micromatch "^3.1.10"
+
+fast-glob@^3.2.9:
+  version "3.2.12"
+  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+  integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+  dependencies:
+    "@nodelib/fs.stat" "^2.0.2"
+    "@nodelib/fs.walk" "^1.2.3"
+    glob-parent "^5.1.2"
+    merge2 "^1.3.0"
+    micromatch "^4.0.4"
+
+fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+  integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+  integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+fastparse@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
+  integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
+
+fastq@^1.6.0:
+  version "1.15.0"
+  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+  integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+  dependencies:
+    reusify "^1.0.4"
+
+faye-websocket@^0.10.0:
+  version "0.10.0"
+  resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
+  integrity sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==
+  dependencies:
+    websocket-driver ">=0.5.1"
+
+faye-websocket@~0.11.1:
+  version "0.11.4"
+  resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da"
+  integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==
+  dependencies:
+    websocket-driver ">=0.5.1"
+
+fb-watchman@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c"
+  integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==
+  dependencies:
+    bser "2.1.1"
+
+figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
+  integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
+
+figures@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+  integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==
+  dependencies:
+    escape-string-regexp "^1.0.5"
+
+file-entry-cache@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+  integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+  dependencies:
+    flat-cache "^3.0.4"
+
+file-loader@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-2.0.0.tgz#39749c82f020b9e85901dcff98e8004e6401cfde"
+  integrity sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==
+  dependencies:
+    loader-utils "^1.0.2"
+    schema-utils "^1.0.0"
+
+file-uri-to-path@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
+  integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
+
+filename-regex@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
+  integrity sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==
+
+fileset@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+  integrity sha512-UxowFKnAFIwtmSxgKjWAVgjE3Fk7MQJT0ZIyl0NwIFZTrx4913rLaonGJ84V+x/2+w/pe4ULHRns+GZPs1TVuw==
+  dependencies:
+    glob "^7.0.3"
+    minimatch "^3.0.3"
+
+fill-range@^2.1.0:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
+  integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
+  dependencies:
+    is-number "^2.1.0"
+    isobject "^2.0.0"
+    randomatic "^3.0.0"
+    repeat-element "^1.1.2"
+    repeat-string "^1.5.2"
+
+fill-range@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
+  integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==
+  dependencies:
+    extend-shallow "^2.0.1"
+    is-number "^3.0.0"
+    repeat-string "^1.6.1"
+    to-regex-range "^2.1.0"
+
+fill-range@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+  integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+  dependencies:
+    to-regex-range "^5.0.1"
+
+filter-obj@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
+  integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
+
+finalhandler@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
+  integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    on-finished "2.4.1"
+    parseurl "~1.3.3"
+    statuses "2.0.1"
+    unpipe "~1.0.0"
+
+find-cache-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
+  integrity sha512-46TFiBOzX7xq/PcSWfFwkyjpemdRnMe31UQF+os0y+1W3k95f6R4SEt02Hj4p3X0Mir9gfrkmOtshFidS0VPUg==
+  dependencies:
+    commondir "^1.0.1"
+    make-dir "^1.0.0"
+    pkg-dir "^2.0.0"
+
+find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
+  integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
+  dependencies:
+    commondir "^1.0.1"
+    make-dir "^2.0.0"
+    pkg-dir "^3.0.0"
+
+find-root@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
+  integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
+
+find-up@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==
+  dependencies:
+    path-exists "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+find-up@^2.0.0, find-up@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+  integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==
+  dependencies:
+    locate-path "^2.0.0"
+
+find-up@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+  integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+  dependencies:
+    locate-path "^3.0.0"
+
+find-up@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+  integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+  dependencies:
+    locate-path "^5.0.0"
+    path-exists "^4.0.0"
+
+find-up@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+  integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+  dependencies:
+    locate-path "^6.0.0"
+    path-exists "^4.0.0"
+
+findup-sync@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
+  integrity sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==
+  dependencies:
+    detect-file "^1.0.0"
+    is-glob "^3.1.0"
+    micromatch "^3.0.4"
+    resolve-dir "^1.0.1"
+
+flat-cache@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+  integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+  dependencies:
+    flatted "^3.1.0"
+    rimraf "^3.0.2"
+
+flatted@^3.1.0:
+  version "3.2.7"
+  resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
+  integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
+
+flush-write-stream@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
+  integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==
+  dependencies:
+    inherits "^2.0.3"
+    readable-stream "^2.3.6"
+
+follow-redirects@^1.0.0:
+  version "1.15.2"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
+  integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+
+for-each@^0.3.3:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
+  integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
+  dependencies:
+    is-callable "^1.1.3"
+
+for-in@^1.0.1, for-in@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+  integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==
+
+for-own@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
+  integrity sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==
+  dependencies:
+    for-in "^1.0.1"
+
+forever-agent@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+  integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==
+
+form-data@~2.3.2:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+  integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.6"
+    mime-types "^2.1.12"
+
+forwarded@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
+  integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
+
+fragment-cache@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
+  integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==
+  dependencies:
+    map-cache "^0.2.2"
+
+fresh@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+  integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
+
+from2@^2.1.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+  integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==
+  dependencies:
+    inherits "^2.0.1"
+    readable-stream "^2.0.0"
+
+fs-extra@^8.1.0:
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
+  integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
+  dependencies:
+    graceful-fs "^4.2.0"
+    jsonfile "^4.0.0"
+    universalify "^0.1.0"
+
+fs-minipass@^1.2.7:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
+  integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
+  dependencies:
+    minipass "^2.6.0"
+
+fs-write-stream-atomic@^1.0.8:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
+  integrity sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==
+  dependencies:
+    graceful-fs "^4.1.2"
+    iferr "^0.1.5"
+    imurmurhash "^0.1.4"
+    readable-stream "1 || 2"
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+  integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@^1.2.3, fsevents@^1.2.7:
+  version "1.2.13"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
+  integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==
+  dependencies:
+    bindings "^1.5.0"
+    nan "^2.12.1"
+
+fsevents@~2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+  integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+function.prototype.name@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+  integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.3"
+    es-abstract "^1.19.0"
+    functions-have-names "^1.2.2"
+
+functions-have-names@^1.2.2, functions-have-names@^1.2.3:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+  integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+gauge@~2.7.3:
+  version "2.7.4"
+  resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+  integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==
+  dependencies:
+    aproba "^1.0.3"
+    console-control-strings "^1.0.0"
+    has-unicode "^2.0.0"
+    object-assign "^4.1.0"
+    signal-exit "^3.0.0"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wide-align "^1.1.0"
+
+genfun@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537"
+  integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==
+
+get-caller-file@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+  integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+
+get-caller-file@^2.0.0, get-caller-file@^2.0.1:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+  integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
+  integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
+  dependencies:
+    function-bind "^1.1.1"
+    has "^1.0.3"
+    has-proto "^1.0.1"
+    has-symbols "^1.0.3"
+
+get-pkg-repo@^1.0.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d"
+  integrity sha512-xPCyvcEOxCJDxhBfXDNH+zA7mIRGb2aY1gIUJWsZkpJbp1BLHl+/Sycg26Dv+ZbZAJkO61tzbBtqHUi30NGBvg==
+  dependencies:
+    hosted-git-info "^2.1.4"
+    meow "^3.3.0"
+    normalize-package-data "^2.3.0"
+    parse-github-repo-url "^1.3.0"
+    through2 "^2.0.0"
+
+get-port@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119"
+  integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==
+
+get-stdin@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+  integrity sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==
+
+get-stream@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+  integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
+
+get-stream@^4.0.0, get-stream@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+  integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+  dependencies:
+    pump "^3.0.0"
+
+get-symbol-description@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
+  integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+  dependencies:
+    call-bind "^1.0.2"
+    get-intrinsic "^1.1.1"
+
+get-value@^2.0.3, get-value@^2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
+  integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==
+
+getpass@^0.1.1:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+  integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==
+  dependencies:
+    assert-plus "^1.0.0"
+
+git-raw-commits@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5"
+  integrity sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==
+  dependencies:
+    dargs "^4.0.1"
+    lodash.template "^4.0.2"
+    meow "^4.0.0"
+    split2 "^2.0.0"
+    through2 "^2.0.0"
+
+git-remote-origin-url@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f"
+  integrity sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==
+  dependencies:
+    gitconfiglocal "^1.0.0"
+    pify "^2.3.0"
+
+git-semver-tags@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-2.0.3.tgz#48988a718acf593800f99622a952a77c405bfa34"
+  integrity sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==
+  dependencies:
+    meow "^4.0.0"
+    semver "^6.0.0"
+
+git-up@^4.0.0:
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.5.tgz#e7bb70981a37ea2fb8fe049669800a1f9a01d759"
+  integrity sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==
+  dependencies:
+    is-ssh "^1.3.0"
+    parse-url "^6.0.0"
+
+git-url-parse@^11.1.2:
+  version "11.6.0"
+  resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.6.0.tgz#c634b8de7faa66498a2b88932df31702c67df605"
+  integrity sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==
+  dependencies:
+    git-up "^4.0.0"
+
+gitconfiglocal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b"
+  integrity sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==
+  dependencies:
+    ini "^1.3.2"
+
+github-markdown-css@2.10.0:
+  version "2.10.0"
+  resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-2.10.0.tgz#0612fed22816b33b282f37ef8def7a4ecabfe993"
+  integrity sha512-RX5VUC54uX6Lvrm226M9kMzsNeOa81MnKyxb3J0G5KLjyoOySOZgwyKFkUpv6iUhooiUZdogk+OTwQPJ4WttYg==
+
+glob-base@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+  integrity sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==
+  dependencies:
+    glob-parent "^2.0.0"
+    is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+  integrity sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==
+  dependencies:
+    is-glob "^2.0.0"
+
+glob-parent@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
+  integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==
+  dependencies:
+    is-glob "^3.1.0"
+    path-dirname "^1.0.0"
+
+glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+  dependencies:
+    is-glob "^4.0.1"
+
+glob-parent@^6.0.2:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+  integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+  dependencies:
+    is-glob "^4.0.3"
+
+glob-to-regexp@0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+  integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+glob-to-regexp@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
+  integrity sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==
+
+glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
+  version "7.2.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+  integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.1.1"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+global-modules-path@^2.3.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.1.tgz#e541f4c800a1a8514a990477b267ac67525b9931"
+  integrity sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==
+
+global-modules@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
+  integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
+  dependencies:
+    global-prefix "^1.0.1"
+    is-windows "^1.0.1"
+    resolve-dir "^1.0.0"
+
+global-prefix@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
+  integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==
+  dependencies:
+    expand-tilde "^2.0.2"
+    homedir-polyfill "^1.0.1"
+    ini "^1.3.4"
+    is-windows "^1.0.1"
+    which "^1.2.14"
+
+globals@^11.1.0:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+  integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globals@^13.15.0, globals@^13.19.0:
+  version "13.20.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
+  integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
+  dependencies:
+    type-fest "^0.20.2"
+
+globals@^9.18.0:
+  version "9.18.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+  integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
+
+globalthis@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
+  integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+  dependencies:
+    define-properties "^1.1.3"
+
+globby@^11.1.0:
+  version "11.1.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+  integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+  dependencies:
+    array-union "^2.1.0"
+    dir-glob "^3.0.1"
+    fast-glob "^3.2.9"
+    ignore "^5.2.0"
+    merge2 "^1.4.1"
+    slash "^3.0.0"
+
+globby@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
+  integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==
+  dependencies:
+    array-union "^1.0.1"
+    glob "^7.0.3"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+globby@^7.1.1:
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680"
+  integrity sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==
+  dependencies:
+    array-union "^1.0.1"
+    dir-glob "^2.0.0"
+    glob "^7.1.2"
+    ignore "^3.3.5"
+    pify "^3.0.0"
+    slash "^1.0.0"
+
+globby@^9.2.0:
+  version "9.2.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d"
+  integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==
+  dependencies:
+    "@types/glob" "^7.1.1"
+    array-union "^1.0.2"
+    dir-glob "^2.2.2"
+    fast-glob "^2.2.6"
+    glob "^7.1.3"
+    ignore "^4.0.3"
+    pify "^4.0.1"
+    slash "^2.0.0"
+
+gopd@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
+  integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
+  dependencies:
+    get-intrinsic "^1.1.3"
+
+graceful-fs@4.1.4:
+  version "4.1.4"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.4.tgz#ef089d2880f033b011823ce5c8fae798da775dbd"
+  integrity sha512-FJvXqYOJo21W86xfBsnT3Ev1hpRWRNdFfNEYSi/uVq+QmNADuhjwzoLtWc/p6lcqLA+l/g9GucxSHQrmOyJJEg==
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2:
+  version "4.2.11"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+  integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+grapheme-splitter@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
+  integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
+growly@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+  integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==
+
+handle-thing@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
+  integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
+
+handlebars@^4.0.3, handlebars@^4.7.6:
+  version "4.7.7"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
+  integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
+  dependencies:
+    minimist "^1.2.5"
+    neo-async "^2.6.0"
+    source-map "^0.6.1"
+    wordwrap "^1.0.0"
+  optionalDependencies:
+    uglify-js "^3.1.4"
+
+har-schema@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+  integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==
+
+har-validator@~5.1.3:
+  version "5.1.5"
+  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
+  integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
+  dependencies:
+    ajv "^6.12.3"
+    har-schema "^2.0.0"
+
+hard-rejection@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
+  integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
+  dependencies:
+    ansi-regex "^2.0.0"
+
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+  integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+  integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==
+
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+  integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-flag@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+  integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+  integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+  dependencies:
+    get-intrinsic "^1.1.1"
+
+has-proto@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
+  integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+
+has-symbols@^1.0.2, has-symbols@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+  integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+  integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+  dependencies:
+    has-symbols "^1.0.2"
+
+has-unicode@^2.0.0, has-unicode@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+  integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
+
+has-value@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
+  integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==
+  dependencies:
+    get-value "^2.0.3"
+    has-values "^0.1.4"
+    isobject "^2.0.0"
+
+has-value@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
+  integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==
+  dependencies:
+    get-value "^2.0.6"
+    has-values "^1.0.0"
+    isobject "^3.0.0"
+
+has-values@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
+  integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==
+
+has-values@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
+  integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==
+  dependencies:
+    is-number "^3.0.0"
+    kind-of "^4.0.0"
+
+has@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+  dependencies:
+    function-bind "^1.1.1"
+
+hash-base@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
+  integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
+  dependencies:
+    inherits "^2.0.4"
+    readable-stream "^3.6.0"
+    safe-buffer "^5.2.0"
+
+hash.js@^1.0.0, hash.js@^1.0.3:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+  integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+  dependencies:
+    inherits "^2.0.3"
+    minimalistic-assert "^1.0.1"
+
+he@1.2.x, he@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+  integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+
+highlight.js@9.13.1:
+  version "9.13.1"
+  resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
+  integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
+
+history@*:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
+  integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==
+  dependencies:
+    "@babel/runtime" "^7.7.6"
+
+history@^4.9.0:
+  version "4.10.1"
+  resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
+  integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
+  dependencies:
+    "@babel/runtime" "^7.1.2"
+    loose-envify "^1.2.0"
+    resolve-pathname "^3.0.0"
+    tiny-invariant "^1.0.2"
+    tiny-warning "^1.0.0"
+    value-equal "^1.0.1"
+
+hmac-drbg@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+  integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==
+  dependencies:
+    hash.js "^1.0.3"
+    minimalistic-assert "^1.0.0"
+    minimalistic-crypto-utils "^1.0.1"
+
+hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+  integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+  dependencies:
+    react-is "^16.7.0"
+
+home-or-tmp@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
+  integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==
+  dependencies:
+    os-homedir "^1.0.0"
+    os-tmpdir "^1.0.1"
+
+homedir-polyfill@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
+  integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
+  dependencies:
+    parse-passwd "^1.0.0"
+
+hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
+  version "2.8.9"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+  integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+
+hosted-git-info@^4.0.1:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
+  integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==
+  dependencies:
+    lru-cache "^6.0.0"
+
+hpack.js@^2.1.6:
+  version "2.1.6"
+  resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+  integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==
+  dependencies:
+    inherits "^2.0.1"
+    obuf "^1.0.0"
+    readable-stream "^2.0.1"
+    wbuf "^1.1.0"
+
+html-encoding-sniffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
+  integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
+  dependencies:
+    whatwg-encoding "^1.0.1"
+
+html-entities@^1.2.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc"
+  integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==
+
+html-minifier@^3.2.3:
+  version "3.5.21"
+  resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c"
+  integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==
+  dependencies:
+    camel-case "3.0.x"
+    clean-css "4.2.x"
+    commander "2.17.x"
+    he "1.2.x"
+    param-case "2.1.x"
+    relateurl "0.2.x"
+    uglify-js "3.4.x"
+
+html-webpack-include-assets-plugin@1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/html-webpack-include-assets-plugin/-/html-webpack-include-assets-plugin-1.0.5.tgz#12770c227290451633351b5ed72dda8ce8c0642e"
+  integrity sha512-YkkzE+QfYAuEq8/yEnfTcpCeSLyJ8XmB2LlQzY1GV7/ovDxavcCIKSMF4kIMRrWmFMPU8qog/zvBaQ1RJFFw/g==
+  dependencies:
+    glob "^7.1.3"
+    minimatch "^3.0.4"
+    slash "^2.0.0"
+
+html-webpack-plugin@3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b"
+  integrity sha512-Br4ifmjQojUP4EmHnRBoUIYcZ9J7M4bTMcm7u6xoIAIuq2Nte4TzXX0533owvkQKQD1WeMTTTyD4Ni4QKxS0Bg==
+  dependencies:
+    html-minifier "^3.2.3"
+    loader-utils "^0.2.16"
+    lodash "^4.17.3"
+    pretty-error "^2.0.2"
+    tapable "^1.0.0"
+    toposort "^1.0.0"
+    util.promisify "1.0.0"
+
+htmlparser2@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
+  integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
+  dependencies:
+    domelementtype "^2.0.1"
+    domhandler "^4.0.0"
+    domutils "^2.5.2"
+    entities "^2.0.0"
+
+http-cache-semantics@^3.8.1:
+  version "3.8.1"
+  resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
+  integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
+
+http-deceiver@^1.2.7:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+  integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==
+
+http-errors@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+  integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+  dependencies:
+    depd "2.0.0"
+    inherits "2.0.4"
+    setprototypeof "1.2.0"
+    statuses "2.0.1"
+    toidentifier "1.0.1"
+
+http-errors@~1.6.2:
+  version "1.6.3"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+  integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==
+  dependencies:
+    depd "~1.1.2"
+    inherits "2.0.3"
+    setprototypeof "1.1.0"
+    statuses ">= 1.4.0 < 2"
+
+http-parser-js@>=0.5.1:
+  version "0.5.8"
+  resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3"
+  integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==
+
+http-proxy-agent@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
+  integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
+  dependencies:
+    agent-base "4"
+    debug "3.1.0"
+
+http-proxy-middleware@~0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab"
+  integrity sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==
+  dependencies:
+    http-proxy "^1.16.2"
+    is-glob "^4.0.0"
+    lodash "^4.17.5"
+    micromatch "^3.1.9"
+
+http-proxy@^1.16.2, http-proxy@^1.8.1:
+  version "1.18.1"
+  resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
+  integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
+  dependencies:
+    eventemitter3 "^4.0.0"
+    follow-redirects "^1.0.0"
+    requires-port "^1.0.0"
+
+http-server@^0.11.1:
+  version "0.11.2"
+  resolved "https://registry.yarnpkg.com/http-server/-/http-server-0.11.2.tgz#cebd05b4fd42e2ecc2d571125e73b970f2b368d3"
+  integrity sha512-Gp1ka7W4MLjFz8CLhFmUWa+uIf7cq93O4DZv8X0ZmNS1L4P2dbMkmlBeYhb0hGaI3M0Y1xM4waWgnIf/5Hp7dQ==
+  dependencies:
+    colors "1.0.3"
+    corser "~2.0.0"
+    ecstatic "^3.0.0"
+    http-proxy "^1.8.1"
+    opener "~1.4.0"
+    optimist "0.6.x"
+    portfinder "^1.0.13"
+    union "^0.5.0"
+
+http-signature@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+  integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==
+  dependencies:
+    assert-plus "^1.0.0"
+    jsprim "^1.2.2"
+    sshpk "^1.7.0"
+
+https-browserify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
+  integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==
+
+https-proxy-agent@^2.2.3:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
+  integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+  dependencies:
+    agent-base "^4.3.0"
+    debug "^3.1.0"
+
+humanize-ms@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
+  integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
+  dependencies:
+    ms "^2.0.0"
+
+hyphenate-style-name@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
+  integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
+
+iconv-lite@0.4.24, iconv-lite@^0.4.24:
+  version "0.4.24"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
+iconv-lite@^0.6.2:
+  version "0.6.3"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
+  integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3.0.0"
+
+icss-replace-symbols@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
+  integrity sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==
+
+icss-utils@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962"
+  integrity sha512-bsVoyn/1V4R1kYYjLcWLedozAM4FClZUdjE9nIr8uWY7xs78y9DATgwz2wGU7M+7z55KenmmTkN2DVJ7bqzjAA==
+  dependencies:
+    postcss "^6.0.1"
+
+ieee754@^1.1.4:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+  integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+iferr@^0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
+  integrity sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==
+
+ignore-walk@^3.0.1:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335"
+  integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==
+  dependencies:
+    minimatch "^3.0.4"
+
+ignore@^3.3.5:
+  version "3.3.10"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
+  integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
+
+ignore@^4.0.3:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+  integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
+
+ignore@^5.2.0:
+  version "5.2.4"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
+  integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
+
+import-cwd@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
+  integrity sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==
+  dependencies:
+    import-from "^2.1.0"
+
+import-fresh@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
+  integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==
+  dependencies:
+    caller-path "^2.0.0"
+    resolve-from "^3.0.0"
+
+import-fresh@^3.0.0, import-fresh@^3.2.1:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+  integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+  dependencies:
+    parent-module "^1.0.0"
+    resolve-from "^4.0.0"
+
+import-from@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
+  integrity sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==
+  dependencies:
+    resolve-from "^3.0.0"
+
+import-local@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
+  integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
+  dependencies:
+    pkg-dir "^2.0.0"
+    resolve-cwd "^2.0.0"
+
+import-local@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
+  integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
+  dependencies:
+    pkg-dir "^3.0.0"
+    resolve-cwd "^2.0.0"
+
+imurmurhash@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+  integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+indent-string@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+  integrity sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==
+  dependencies:
+    repeating "^2.0.0"
+
+indent-string@^3.0.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
+  integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==
+
+indent-string@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+  integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+infer-owner@^1.0.3, infer-owner@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
+  integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+inherits@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+  integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==
+
+inherits@2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+  integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+
+ini@^1.3.2, ini@^1.3.4:
+  version "1.3.8"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+  integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
+init-package-json@^1.10.3:
+  version "1.10.3"
+  resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe"
+  integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==
+  dependencies:
+    glob "^7.1.1"
+    npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0"
+    promzard "^0.3.0"
+    read "~1.0.1"
+    read-package-json "1 || 2"
+    semver "2.x || 3.x || 4 || 5"
+    validate-npm-package-license "^3.0.1"
+    validate-npm-package-name "^3.0.0"
+
+inquirer@^6.2.0:
+  version "6.5.2"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
+  integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==
+  dependencies:
+    ansi-escapes "^3.2.0"
+    chalk "^2.4.2"
+    cli-cursor "^2.1.0"
+    cli-width "^2.0.0"
+    external-editor "^3.0.3"
+    figures "^2.0.0"
+    lodash "^4.17.12"
+    mute-stream "0.0.7"
+    run-async "^2.2.0"
+    rxjs "^6.4.0"
+    string-width "^2.1.0"
+    strip-ansi "^5.1.0"
+    through "^2.3.6"
+
+internal-ip@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27"
+  integrity sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==
+  dependencies:
+    default-gateway "^2.6.0"
+    ipaddr.js "^1.5.2"
+
+internal-slot@^1.0.3, internal-slot@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
+  integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
+  dependencies:
+    get-intrinsic "^1.2.0"
+    has "^1.0.3"
+    side-channel "^1.0.4"
+
+interpret@^1.1.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
+  integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
+
+invariant@^2.2.2, invariant@^2.2.4:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+  integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+  dependencies:
+    loose-envify "^1.0.0"
+
+inversify@^5.0.0:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.1.1.tgz#6fbd668c591337404e005a1946bfe0d802c08730"
+  integrity sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==
+
+invert-kv@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+  integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+
+ip-regex@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+  integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==
+
+ip@1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+  integrity sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==
+
+ip@^1.1.0, ip@^1.1.5:
+  version "1.1.8"
+  resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48"
+  integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==
+
+ipaddr.js@1.9.1, ipaddr.js@^1.5.2:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+  integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+is-accessor-descriptor@^0.1.6:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
+  integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==
+  dependencies:
+    kind-of "^3.0.2"
+
+is-accessor-descriptor@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
+  integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
+  dependencies:
+    kind-of "^6.0.0"
+
+is-arguments@^1.0.4:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
+  integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
+  dependencies:
+    call-bind "^1.0.2"
+    has-tostringtag "^1.0.0"
+
+is-array-buffer@^3.0.1, is-array-buffer@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe"
+  integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==
+  dependencies:
+    call-bind "^1.0.2"
+    get-intrinsic "^1.2.0"
+    is-typed-array "^1.1.10"
+
+is-arrayish@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+  integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-bigint@^1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
+  integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+  dependencies:
+    has-bigints "^1.0.1"
+
+is-binary-path@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+  integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==
+  dependencies:
+    binary-extensions "^1.0.0"
+
+is-binary-path@~2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+  integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+  dependencies:
+    binary-extensions "^2.0.0"
+
+is-boolean-object@^1.1.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
+  integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+  dependencies:
+    call-bind "^1.0.2"
+    has-tostringtag "^1.0.0"
+
+is-buffer@^1.1.5:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+  integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+
+is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+  integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
+is-ci@^1.0.10:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
+  integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+  dependencies:
+    ci-info "^1.5.0"
+
+is-ci@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+  integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+  dependencies:
+    ci-info "^2.0.0"
+
+is-core-module@^2.11.0, is-core-module@^2.5.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
+  version "2.12.1"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
+  integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
+  dependencies:
+    has "^1.0.3"
+
+is-data-descriptor@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
+  integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==
+  dependencies:
+    kind-of "^3.0.2"
+
+is-data-descriptor@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
+  integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
+  dependencies:
+    kind-of "^6.0.0"
+
+is-date-object@^1.0.1:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
+  integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+  dependencies:
+    has-tostringtag "^1.0.0"
+
+is-descriptor@^0.1.0:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
+  integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
+  dependencies:
+    is-accessor-descriptor "^0.1.6"
+    is-data-descriptor "^0.1.4"
+    kind-of "^5.0.0"
+
+is-descriptor@^1.0.0, is-descriptor@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
+  integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
+  dependencies:
+    is-accessor-descriptor "^1.0.0"
+    is-data-descriptor "^1.0.0"
+    kind-of "^6.0.2"
+
+is-directory@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
+  integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==
+
+is-dotfile@^1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
+  integrity sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==
+
+is-equal-shallow@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+  integrity sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==
+  dependencies:
+    is-primitive "^2.0.0"
+
+is-extendable@^0.1.0, is-extendable@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+  integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==
+
+is-extendable@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
+  integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
+  dependencies:
+    is-plain-object "^2.0.4"
+
+is-extglob@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+  integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==
+
+is-extglob@^2.1.0, is-extglob@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+  integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-finite@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
+  integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
+
+is-fullwidth-code-point@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+  integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==
+
+is-fullwidth-code-point@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+  integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-generator-fn@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
+  integrity sha512-95jJZX6O/gdekidH2usRBr9WdRw4LU56CttPstXFxvG0r3QUE9eaIdz2p2Y7zrm6jxz7SjByAo1AtzwGlRvfOg==
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+  integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==
+  dependencies:
+    is-extglob "^1.0.0"
+
+is-glob@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
+  integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==
+  dependencies:
+    is-extglob "^2.1.0"
+
+is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+  integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+  dependencies:
+    is-extglob "^2.1.1"
+
+is-in-browser@^1.0.2, is-in-browser@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
+  integrity sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==
+
+is-negative-zero@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
+  integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+
+is-number-object@^1.0.4:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
+  integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
+  dependencies:
+    has-tostringtag "^1.0.0"
+
+is-number@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+  integrity sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==
+  dependencies:
+    kind-of "^3.0.2"
+
+is-number@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+  integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==
+  dependencies:
+    kind-of "^3.0.2"
+
+is-number@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
+  integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
+
+is-number@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-obj@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+  integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==
+
+is-obj@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
+  integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
+
+is-path-cwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+  integrity sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==
+
+is-path-in-cwd@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+  integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
+  dependencies:
+    is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+  integrity sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==
+  dependencies:
+    path-is-inside "^1.0.1"
+
+is-path-inside@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+  integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
+is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+  integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
+
+is-plain-object@^2.0.3, is-plain-object@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+  integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+  dependencies:
+    isobject "^3.0.1"
+
+is-plain-object@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
+  integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+
+is-posix-bracket@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+  integrity sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==
+
+is-primitive@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+  integrity sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==
+
+is-regex@^1.0.4, is-regex@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+  integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+  dependencies:
+    call-bind "^1.0.2"
+    has-tostringtag "^1.0.0"
+
+is-shared-array-buffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
+  integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+  dependencies:
+    call-bind "^1.0.2"
+
+is-ssh@^1.3.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.4.0.tgz#4f8220601d2839d8fa624b3106f8e8884f01b8b2"
+  integrity sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==
+  dependencies:
+    protocols "^2.0.1"
+
+is-stream@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+  integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
+
+is-string@^1.0.5, is-string@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+  integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+  dependencies:
+    has-tostringtag "^1.0.0"
+
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
+  integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
+  dependencies:
+    has-symbols "^1.0.2"
+
+is-text-path@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e"
+  integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==
+  dependencies:
+    text-extensions "^1.0.0"
+
+is-typed-array@^1.1.10, is-typed-array@^1.1.9:
+  version "1.1.10"
+  resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
+  integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
+  dependencies:
+    available-typed-arrays "^1.0.5"
+    call-bind "^1.0.2"
+    for-each "^0.3.3"
+    gopd "^1.0.1"
+    has-tostringtag "^1.0.0"
+
+is-typedarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+  integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
+
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+  integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==
+
+is-weakref@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
+  integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+  dependencies:
+    call-bind "^1.0.2"
+
+is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
+  integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
+
+is-wsl@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+  integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==
+
+isarray@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+  integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
+
+isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+  integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
+
+isarray@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
+  integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
+
+isexe@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+  integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isobject@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+  integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==
+  dependencies:
+    isarray "1.0.0"
+
+isobject@^3.0.0, isobject@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+  integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+
+isstream@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+  integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
+
+istanbul-api@^1.3.1:
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
+  integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
+  dependencies:
+    async "^2.1.4"
+    fileset "^2.0.2"
+    istanbul-lib-coverage "^1.2.1"
+    istanbul-lib-hook "^1.2.2"
+    istanbul-lib-instrument "^1.10.2"
+    istanbul-lib-report "^1.1.5"
+    istanbul-lib-source-maps "^1.2.6"
+    istanbul-reports "^1.5.1"
+    js-yaml "^3.7.0"
+    mkdirp "^0.5.1"
+    once "^1.4.0"
+
+istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
+  integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
+
+istanbul-lib-hook@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
+  integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
+  dependencies:
+    append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
+  integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
+  dependencies:
+    babel-generator "^6.18.0"
+    babel-template "^6.16.0"
+    babel-traverse "^6.18.0"
+    babel-types "^6.18.0"
+    babylon "^6.18.0"
+    istanbul-lib-coverage "^1.2.1"
+    semver "^5.3.0"
+
+istanbul-lib-report@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
+  integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
+  dependencies:
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    path-parse "^1.0.5"
+    supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
+  integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
+  dependencies:
+    debug "^3.1.0"
+    istanbul-lib-coverage "^1.2.1"
+    mkdirp "^0.5.1"
+    rimraf "^2.6.1"
+    source-map "^0.5.3"
+
+istanbul-reports@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
+  integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
+  dependencies:
+    handlebars "^4.0.3"
+
+jest-changed-files@^23.4.2:
+  version "23.4.2"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
+  integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
+  dependencies:
+    throat "^4.0.0"
+
+jest-cli@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
+  integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    glob "^7.1.2"
+    graceful-fs "^4.1.11"
+    import-local "^1.0.0"
+    is-ci "^1.0.10"
+    istanbul-api "^1.3.1"
+    istanbul-lib-coverage "^1.2.0"
+    istanbul-lib-instrument "^1.10.1"
+    istanbul-lib-source-maps "^1.2.4"
+    jest-changed-files "^23.4.2"
+    jest-config "^23.6.0"
+    jest-environment-jsdom "^23.4.0"
+    jest-get-type "^22.1.0"
+    jest-haste-map "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve-dependencies "^23.6.0"
+    jest-runner "^23.6.0"
+    jest-runtime "^23.6.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    jest-watcher "^23.4.0"
+    jest-worker "^23.2.0"
+    micromatch "^2.3.11"
+    node-notifier "^5.2.1"
+    prompts "^0.1.9"
+    realpath-native "^1.0.0"
+    rimraf "^2.5.4"
+    slash "^1.0.0"
+    string-length "^2.0.0"
+    strip-ansi "^4.0.0"
+    which "^1.2.12"
+    yargs "^11.0.0"
+
+jest-config@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
+  integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
+  dependencies:
+    babel-core "^6.0.0"
+    babel-jest "^23.6.0"
+    chalk "^2.0.1"
+    glob "^7.1.1"
+    jest-environment-jsdom "^23.4.0"
+    jest-environment-node "^23.4.0"
+    jest-get-type "^22.1.0"
+    jest-jasmine2 "^23.6.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    micromatch "^2.3.11"
+    pretty-format "^23.6.0"
+
+jest-diff@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
+  integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
+  dependencies:
+    chalk "^2.0.1"
+    diff "^3.2.0"
+    jest-get-type "^22.1.0"
+    pretty-format "^23.6.0"
+
+jest-docblock@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
+  integrity sha512-CB8MdScYLkzQ0Q/I4FYlt2UBkG9tFzi+ngSPVhSBB70nifaC+5iWz6GEfa/lB4T2KCqGy+DLzi1v34r9R1XzuA==
+  dependencies:
+    detect-newline "^2.1.0"
+
+jest-each@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
+  integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
+  dependencies:
+    chalk "^2.0.1"
+    pretty-format "^23.6.0"
+
+jest-environment-jsdom@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
+  integrity sha512-UIXe32cMl/+DtyNHC15X+aFZMh04wx7PjWFBfz+nwoLgsIN2loKoNiKGSzUhMW/fVwbHrk8Qopglb7V4XB4EfQ==
+  dependencies:
+    jest-mock "^23.2.0"
+    jest-util "^23.4.0"
+    jsdom "^11.5.1"
+
+jest-environment-node@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
+  integrity sha512-bk8qScgIfkb+EdwJ0JZ9xGvN7N3m6Qok73G8hi6tzvNadpe4kOxxuGmK2cJzAM3tPC/HBulzrOeNHEvaThQFrQ==
+  dependencies:
+    jest-mock "^23.2.0"
+    jest-util "^23.4.0"
+
+jest-get-type@^22.1.0:
+  version "22.4.3"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
+  integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
+
+jest-haste-map@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
+  integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
+  dependencies:
+    fb-watchman "^2.0.0"
+    graceful-fs "^4.1.11"
+    invariant "^2.2.4"
+    jest-docblock "^23.2.0"
+    jest-serializer "^23.0.1"
+    jest-worker "^23.2.0"
+    micromatch "^2.3.11"
+    sane "^2.0.0"
+
+jest-jasmine2@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
+  integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
+  dependencies:
+    babel-traverse "^6.0.0"
+    chalk "^2.0.1"
+    co "^4.6.0"
+    expect "^23.6.0"
+    is-generator-fn "^1.0.0"
+    jest-diff "^23.6.0"
+    jest-each "^23.6.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    pretty-format "^23.6.0"
+
+jest-leak-detector@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
+  integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
+  dependencies:
+    pretty-format "^23.6.0"
+
+jest-matcher-utils@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
+  integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+  dependencies:
+    chalk "^2.0.1"
+    jest-get-type "^22.1.0"
+    pretty-format "^23.6.0"
+
+jest-message-util@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
+  integrity sha512-Tjqy7T8jHhPgV4Gsi+pKMMfaz3uP5DPtMGnm8RWNWUHIk2igqxQ3/9rud3JkINCvZDGqlpJVuFGIDXbltG4xLA==
+  dependencies:
+    "@babel/code-frame" "^7.0.0-beta.35"
+    chalk "^2.0.1"
+    micromatch "^2.3.11"
+    slash "^1.0.0"
+    stack-utils "^1.0.1"
+
+jest-mock@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
+  integrity sha512-lz+Rf6dwRNDVowuGCXm93ib8hMyPntl1GGVt9PuZfBAmTjP5yKYgK14IASiEjs7XoMo4i/R7+dkrJY3eESwTJg==
+
+jest-regex-util@^23.3.0:
+  version "23.3.0"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
+  integrity sha512-pNilf1tXhv5z0qjJy2Hl6Ar6dsi+XX2zpCAuzxRs4qoputI0Bm9rU7pa2ErrFTfiHYe8VboTR7WATPZXqzpQ/g==
+
+jest-resolve-dependencies@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
+  integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
+  dependencies:
+    jest-regex-util "^23.3.0"
+    jest-snapshot "^23.6.0"
+
+jest-resolve@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
+  integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
+  dependencies:
+    browser-resolve "^1.11.3"
+    chalk "^2.0.1"
+    realpath-native "^1.0.0"
+
+jest-runner@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
+  integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
+  dependencies:
+    exit "^0.1.2"
+    graceful-fs "^4.1.11"
+    jest-config "^23.6.0"
+    jest-docblock "^23.2.0"
+    jest-haste-map "^23.6.0"
+    jest-jasmine2 "^23.6.0"
+    jest-leak-detector "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-runtime "^23.6.0"
+    jest-util "^23.4.0"
+    jest-worker "^23.2.0"
+    source-map-support "^0.5.6"
+    throat "^4.0.0"
+
+jest-runtime@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
+  integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
+  dependencies:
+    babel-core "^6.0.0"
+    babel-plugin-istanbul "^4.1.6"
+    chalk "^2.0.1"
+    convert-source-map "^1.4.0"
+    exit "^0.1.2"
+    fast-json-stable-stringify "^2.0.0"
+    graceful-fs "^4.1.11"
+    jest-config "^23.6.0"
+    jest-haste-map "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-regex-util "^23.3.0"
+    jest-resolve "^23.6.0"
+    jest-snapshot "^23.6.0"
+    jest-util "^23.4.0"
+    jest-validate "^23.6.0"
+    micromatch "^2.3.11"
+    realpath-native "^1.0.0"
+    slash "^1.0.0"
+    strip-bom "3.0.0"
+    write-file-atomic "^2.1.0"
+    yargs "^11.0.0"
+
+jest-serializer@^23.0.1:
+  version "23.0.1"
+  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
+  integrity sha512-l6cPuiGEQI72H4+qMePF62E+URkZscnAqdHBYHkMrhKJOwU08AHvGmftXdosUzfCGhh/Ih4Xk1VgxnJSwrvQvQ==
+
+jest-snapshot@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
+  integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
+  dependencies:
+    babel-types "^6.0.0"
+    chalk "^2.0.1"
+    jest-diff "^23.6.0"
+    jest-matcher-utils "^23.6.0"
+    jest-message-util "^23.4.0"
+    jest-resolve "^23.6.0"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    pretty-format "^23.6.0"
+    semver "^5.5.0"
+
+jest-util@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
+  integrity sha512-OS1/0QSbbMF9N93MxF1hUmK93EF3NGQGbbaTBZZk95aytWtWmzxsFWwt/UXIIkfHbPCK1fXTrPklbL+ohuFFOA==
+  dependencies:
+    callsites "^2.0.0"
+    chalk "^2.0.1"
+    graceful-fs "^4.1.11"
+    is-ci "^1.0.10"
+    jest-message-util "^23.4.0"
+    mkdirp "^0.5.1"
+    slash "^1.0.0"
+    source-map "^0.6.0"
+
+jest-validate@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
+  integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
+  dependencies:
+    chalk "^2.0.1"
+    jest-get-type "^22.1.0"
+    leven "^2.1.0"
+    pretty-format "^23.6.0"
+
+jest-watcher@^23.4.0:
+  version "23.4.0"
+  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
+  integrity sha512-BZGZYXnte/vazfnmkD4ERByi2O2mW+C++W8Sb7dvOnwcSccvCKNQgmcz1L+9hxVD7HWtqymPctIY7v5ZbQGNyg==
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    string-length "^2.0.0"
+
+jest-worker@^23.2.0:
+  version "23.2.0"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
+  integrity sha512-zx0uwPCDxToGfYyQiSHh7T/sKIxQFnQqT6Uug7Y/L7PzEkFITPaufjQe6yaf1OXSnGvKC5Fwol1hIym0zDzyvw==
+  dependencies:
+    merge-stream "^1.0.1"
+
+jest@23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
+  integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
+  dependencies:
+    import-local "^1.0.0"
+    jest-cli "^23.6.0"
+
+jquery@3.3.1:
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
+  integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
+
+js-levenshtein@^1.1.3:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
+  integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
+
+js-sdsl@^4.1.4:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
+  integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-tokens@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+  integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==
+
+js-yaml@^3.13.1, js-yaml@^3.7.0:
+  version "3.14.1"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+  integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
+js-yaml@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+  integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+  dependencies:
+    argparse "^2.0.1"
+
+jsbn@~0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+  integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
+
+jsdom@^11.5.1:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
+  integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==
+  dependencies:
+    abab "^2.0.0"
+    acorn "^5.5.3"
+    acorn-globals "^4.1.0"
+    array-equal "^1.0.0"
+    cssom ">= 0.3.2 < 0.4.0"
+    cssstyle "^1.0.0"
+    data-urls "^1.0.0"
+    domexception "^1.0.1"
+    escodegen "^1.9.1"
+    html-encoding-sniffer "^1.0.2"
+    left-pad "^1.3.0"
+    nwsapi "^2.0.7"
+    parse5 "4.0.0"
+    pn "^1.1.0"
+    request "^2.87.0"
+    request-promise-native "^1.0.5"
+    sax "^1.2.4"
+    symbol-tree "^3.2.2"
+    tough-cookie "^2.3.4"
+    w3c-hr-time "^1.0.1"
+    webidl-conversions "^4.0.2"
+    whatwg-encoding "^1.0.3"
+    whatwg-mimetype "^2.1.0"
+    whatwg-url "^6.4.1"
+    ws "^5.2.0"
+    xml-name-validator "^3.0.0"
+
+jsesc@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+  integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==
+
+jsesc@^2.5.1:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+  integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+jsesc@~0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+  integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+
+json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+  integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+json-parse-even-better-errors@^2.3.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+  integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+  integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-schema@0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
+  integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+  integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+  integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
+
+json3@^3.3.2:
+  version "3.3.3"
+  resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
+  integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==
+
+json5@2.x:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+  integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+json5@^0.5.0, json5@^0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+  integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==
+
+json5@^1.0.1, json5@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
+  integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
+  dependencies:
+    minimist "^1.2.0"
+
+jsonfile@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+  integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
+jsonparse@^1.2.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
+  integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
+
+jsonwebtoken@8.3.0:
+  version "8.3.0"
+  resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz#056c90eee9a65ed6e6c72ddb0a1d325109aaf643"
+  integrity sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==
+  dependencies:
+    jws "^3.1.5"
+    lodash.includes "^4.3.0"
+    lodash.isboolean "^3.0.3"
+    lodash.isinteger "^4.0.4"
+    lodash.isnumber "^3.0.3"
+    lodash.isplainobject "^4.0.6"
+    lodash.isstring "^4.0.1"
+    lodash.once "^4.0.0"
+    ms "^2.1.1"
+
+jsprim@^1.2.2:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
+  integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==
+  dependencies:
+    assert-plus "1.0.0"
+    extsprintf "1.3.0"
+    json-schema "0.4.0"
+    verror "1.10.0"
+
+jss-plugin-camel-case@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz#27ea159bab67eb4837fa0260204eb7925d4daa1c"
+  integrity sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    hyphenate-style-name "^1.0.3"
+    jss "10.10.0"
+
+jss-plugin-default-unit@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz#db3925cf6a07f8e1dd459549d9c8aadff9804293"
+  integrity sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.10.0"
+
+jss-plugin-global@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz#1c55d3c35821fab67a538a38918292fc9c567efd"
+  integrity sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.10.0"
+
+jss-plugin-nested@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz#db872ed8925688806e77f1fc87f6e62264513219"
+  integrity sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.10.0"
+    tiny-warning "^1.0.2"
+
+jss-plugin-props-sort@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz#67f4dd4c70830c126f4ec49b4b37ccddb680a5d7"
+  integrity sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.10.0"
+
+jss-plugin-rule-value-function@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz#7d99e3229e78a3712f78ba50ab342e881d26a24b"
+  integrity sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.10.0"
+    tiny-warning "^1.0.2"
+
+jss-plugin-vendor-prefixer@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz#c01428ef5a89f2b128ec0af87a314d0c767931c7"
+  integrity sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    css-vendor "^2.0.8"
+    jss "10.10.0"
+
+jss@10.0.3:
+  version "10.0.3"
+  resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.3.tgz#5c160f96aa8ce8b9f851ee0b33505dcd37f490a4"
+  integrity sha512-AcDvFdOk16If9qvC9KN3oFXsrkHWM9+TaPMpVB9orm3z+nq1Xw3ofHyflRe/mkSucRZnaQtlhZs1hdP3DR9uRw==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    csstype "^2.6.5"
+    is-in-browser "^1.1.3"
+    tiny-warning "^1.0.2"
+
+jss@10.10.0, jss@^10.10.0:
+  version "10.10.0"
+  resolved "https://registry.yarnpkg.com/jss/-/jss-10.10.0.tgz#a75cc85b0108c7ac8c7b7d296c520a3e4fbc6ccc"
+  integrity sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    csstype "^3.0.2"
+    is-in-browser "^1.1.3"
+    tiny-warning "^1.0.2"
+
+"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.2:
+  version "3.3.3"
+  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
+  integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
+  dependencies:
+    array-includes "^3.1.5"
+    object.assign "^4.1.3"
+
+jwa@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
+  integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
+  dependencies:
+    buffer-equal-constant-time "1.0.1"
+    ecdsa-sig-formatter "1.0.11"
+    safe-buffer "^5.0.1"
+
+jws@^3.1.5:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
+  integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
+  dependencies:
+    jwa "^1.4.1"
+    safe-buffer "^5.0.1"
+
+killable@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
+  integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==
+
+kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+  integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==
+  dependencies:
+    is-buffer "^1.1.5"
+
+kind-of@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+  integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==
+  dependencies:
+    is-buffer "^1.1.5"
+
+kind-of@^5.0.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
+  integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
+
+kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
+  version "6.0.3"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+  integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+kleur@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
+  integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
+
+language-subtag-registry@^0.3.20:
+  version "0.3.22"
+  resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
+  integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
+
+language-tags@^1.0.5:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.8.tgz#042b4bdb0d4e771a9f8cc2fdc9bb26a52a367312"
+  integrity sha512-aWAZwgPLS8hJ20lNPm9HNVs4inexz6S2sQa3wx/+ycuutMNE5/IfYxiWYBbi+9UWCQVaXYCOPUl6gFrPR7+jGg==
+  dependencies:
+    language-subtag-registry "^0.3.20"
+
+lcid@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+  integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
+  dependencies:
+    invert-kv "^2.0.0"
+
+left-pad@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
+  integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
+
+lerna@3.22.1:
+  version "3.22.1"
+  resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.22.1.tgz#82027ac3da9c627fd8bf02ccfeff806a98e65b62"
+  integrity sha512-vk1lfVRFm+UuEFA7wkLKeSF7Iz13W+N/vFd48aW2yuS7Kv0RbNm2/qcDPV863056LMfkRlsEe+QYOw3palj5Lg==
+  dependencies:
+    "@lerna/add" "3.21.0"
+    "@lerna/bootstrap" "3.21.0"
+    "@lerna/changed" "3.21.0"
+    "@lerna/clean" "3.21.0"
+    "@lerna/cli" "3.18.5"
+    "@lerna/create" "3.22.0"
+    "@lerna/diff" "3.21.0"
+    "@lerna/exec" "3.21.0"
+    "@lerna/import" "3.22.0"
+    "@lerna/info" "3.21.0"
+    "@lerna/init" "3.21.0"
+    "@lerna/link" "3.21.0"
+    "@lerna/list" "3.21.0"
+    "@lerna/publish" "3.22.1"
+    "@lerna/run" "3.21.0"
+    "@lerna/version" "3.22.1"
+    import-local "^2.0.0"
+    npmlog "^4.1.2"
+
+leven@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
+  integrity sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==
+
+levn@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+  integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+  dependencies:
+    prelude-ls "^1.2.1"
+    type-check "~0.4.0"
+
+levn@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+  integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==
+  dependencies:
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+
+lightercollective@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.1.0.tgz#70df102c530dcb8d0ccabfe6175a8d00d5f61300"
+  integrity sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==
+
+lines-and-columns@^1.1.6:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+  integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+load-json-file@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    strip-bom "^2.0.0"
+
+load-json-file@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+  integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^4.0.0"
+    pify "^3.0.0"
+    strip-bom "^3.0.0"
+
+load-json-file@^5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3"
+  integrity sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==
+  dependencies:
+    graceful-fs "^4.1.15"
+    parse-json "^4.0.0"
+    pify "^4.0.1"
+    strip-bom "^3.0.0"
+    type-fest "^0.3.0"
+
+loader-runner@^2.3.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
+  integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
+
+loader-utils@0.2.16:
+  version "0.2.16"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d"
+  integrity sha512-dd4/ZWk+/kNr/GHdKCOGamC6WTfmi6yFjWTJ+l1nTNHut+y4RxGWuWtOzWWXEmmvunTBspjvTsp8RsjhasOxDA==
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
+loader-utils@^0.2.16:
+  version "0.2.17"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+  integrity sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug==
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
+loader-utils@^1.0.2, loader-utils@^1.1.0:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
+  integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==
+  dependencies:
+    big.js "^5.2.2"
+    emojis-list "^3.0.0"
+    json5 "^1.0.1"
+
+locate-path@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+  integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==
+  dependencies:
+    p-locate "^2.0.0"
+    path-exists "^3.0.0"
+
+locate-path@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+  integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+  dependencies:
+    p-locate "^3.0.0"
+    path-exists "^3.0.0"
+
+locate-path@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+  integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+  dependencies:
+    p-locate "^4.1.0"
+
+locate-path@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+  integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+  dependencies:
+    p-locate "^5.0.0"
+
+lodash._reinterpolate@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
+  integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==
+
+lodash.camelcase@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+  integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
+
+lodash.clonedeep@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+  integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
+
+lodash.get@^4.4.2:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+  integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
+
+lodash.includes@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
+  integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==
+
+lodash.isboolean@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+  integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
+
+lodash.isinteger@^4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
+  integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==
+
+lodash.ismatch@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
+  integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==
+
+lodash.isnumber@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
+  integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==
+
+lodash.isplainobject@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+  integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
+lodash.isstring@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+  integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
+
+lodash.merge@^4.6.2:
+  version "4.6.2"
+  resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+  integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+lodash.once@^4.0.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+  integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
+
+lodash.set@^4.3.2:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
+  integrity sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==
+
+lodash.sortby@^4.7.0:
+  version "4.7.0"
+  resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+  integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
+
+lodash.template@^4.0.2, lodash.template@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
+  integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
+  dependencies:
+    lodash._reinterpolate "^3.0.0"
+    lodash.templatesettings "^4.0.0"
+
+lodash.templatesettings@^4.0.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
+  integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
+  dependencies:
+    lodash._reinterpolate "^3.0.0"
+
+lodash.uniq@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+  integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
+
+lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
+  version "4.17.21"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+loglevel@^1.4.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4"
+  integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==
+
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+  integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+  dependencies:
+    js-tokens "^3.0.0 || ^4.0.0"
+
+loud-rejection@^1.0.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+  integrity sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==
+  dependencies:
+    currently-unhandled "^0.4.1"
+    signal-exit "^3.0.0"
+
+lower-case@^1.1.1:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
+  integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==
+
+lru-cache@^4.1.1:
+  version "4.1.5"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+  dependencies:
+    pseudomap "^1.0.2"
+    yallist "^2.1.2"
+
+lru-cache@^5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+  integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+  dependencies:
+    yallist "^3.0.2"
+
+lru-cache@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+  integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+  dependencies:
+    yallist "^4.0.0"
+
+macos-release@^2.2.0:
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.1.tgz#bccac4a8f7b93163a8d163b8ebf385b3c5f55bf9"
+  integrity sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==
+
+make-dir@^1.0.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
+  integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
+  dependencies:
+    pify "^3.0.0"
+
+make-dir@^2.0.0, make-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+  dependencies:
+    pify "^4.0.1"
+    semver "^5.6.0"
+
+make-error@1.x:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+  integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
+make-fetch-happen@^5.0.0:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd"
+  integrity sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==
+  dependencies:
+    agentkeepalive "^3.4.1"
+    cacache "^12.0.0"
+    http-cache-semantics "^3.8.1"
+    http-proxy-agent "^2.1.0"
+    https-proxy-agent "^2.2.3"
+    lru-cache "^5.1.1"
+    mississippi "^3.0.0"
+    node-fetch-npm "^2.0.2"
+    promise-retry "^1.1.1"
+    socks-proxy-agent "^4.0.0"
+    ssri "^6.0.0"
+
+makeerror@1.0.12:
+  version "1.0.12"
+  resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
+  integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
+  dependencies:
+    tmpl "1.0.5"
+
+map-age-cleaner@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+  integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+  dependencies:
+    p-defer "^1.0.0"
+
+map-cache@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
+  integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+  integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==
+
+map-obj@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
+  integrity sha512-TzQSV2DiMYgoF5RycneKVUzIa9bQsj/B3tTgsE3dOGqlzHnGIDaC7XBE7grnA+8kZPnfqSGFe95VHc2oc0VFUQ==
+
+map-obj@^4.0.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
+  integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
+
+map-visit@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
+  integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==
+  dependencies:
+    object-visit "^1.0.0"
+
+marked@0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.0.tgz#a18d01cfdcf8d15c3c455b71c8329e5e0f01faa1"
+  integrity sha512-HduzIW2xApSXKXJSpCipSxKyvMbwRRa/TwMbepmlZziKdH8548WSoDP4SxzulEKjlo8BE39l+2fwJZuRKOln6g==
+
+material-ui-confirm@3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/material-ui-confirm/-/material-ui-confirm-3.0.2.tgz#c1871fa3b1de504722bad0f20e51c71890a38f90"
+  integrity sha512-DMs9uNF7vmqHr2rZkfrJqla7r+7mjOj2Jroih7Nsxs5rrsRbTLPn6PzhQzMa8pBcPszPGtMAJ+Gf4rt4SFUmIQ==
+
+math-random@^1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
+  integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
+
+md5.js@^1.3.4:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
+  integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+    safe-buffer "^5.1.2"
+
+media-typer@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+  integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
+
+mem@^4.0.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+  integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
+  dependencies:
+    map-age-cleaner "^0.1.1"
+    mimic-fn "^2.0.0"
+    p-is-promise "^2.0.0"
+
+memory-fs@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
+  integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+memory-fs@~0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
+  integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+meow@^3.3.0:
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+  integrity sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==
+  dependencies:
+    camelcase-keys "^2.0.0"
+    decamelize "^1.1.2"
+    loud-rejection "^1.0.0"
+    map-obj "^1.0.1"
+    minimist "^1.1.3"
+    normalize-package-data "^2.3.4"
+    object-assign "^4.0.1"
+    read-pkg-up "^1.0.1"
+    redent "^1.0.0"
+    trim-newlines "^1.0.0"
+
+meow@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975"
+  integrity sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==
+  dependencies:
+    camelcase-keys "^4.0.0"
+    decamelize-keys "^1.0.0"
+    loud-rejection "^1.0.0"
+    minimist "^1.1.3"
+    minimist-options "^3.0.1"
+    normalize-package-data "^2.3.4"
+    read-pkg-up "^3.0.0"
+    redent "^2.0.0"
+    trim-newlines "^2.0.0"
+
+meow@^8.0.0:
+  version "8.1.2"
+  resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
+  integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==
+  dependencies:
+    "@types/minimist" "^1.2.0"
+    camelcase-keys "^6.2.2"
+    decamelize-keys "^1.1.0"
+    hard-rejection "^2.1.0"
+    minimist-options "4.1.0"
+    normalize-package-data "^3.0.0"
+    read-pkg-up "^7.0.1"
+    redent "^3.0.0"
+    trim-newlines "^3.0.0"
+    type-fest "^0.18.0"
+    yargs-parser "^20.2.3"
+
+merge-descriptors@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+  integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
+
+merge-stream@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
+  integrity sha512-e6RM36aegd4f+r8BZCcYXlO2P3H6xbUM6ktL2Xmf45GAOit9bI4z6/3VU7JwllVO1L7u0UDSg/EhzQ5lmMLolA==
+  dependencies:
+    readable-stream "^2.0.1"
+
+merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+  integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+merge@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
+  integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
+
+methods@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+  integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
+
+micromatch@^2.3.11:
+  version "2.3.11"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+  integrity sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==
+  dependencies:
+    arr-diff "^2.0.0"
+    array-unique "^0.2.1"
+    braces "^1.8.2"
+    expand-brackets "^0.1.4"
+    extglob "^0.3.1"
+    filename-regex "^2.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.1"
+    kind-of "^3.0.2"
+    normalize-path "^2.0.1"
+    object.omit "^2.0.0"
+    parse-glob "^3.0.4"
+    regex-cache "^0.4.2"
+
+micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9:
+  version "3.1.10"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
+  integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
+  dependencies:
+    arr-diff "^4.0.0"
+    array-unique "^0.3.2"
+    braces "^2.3.1"
+    define-property "^2.0.2"
+    extend-shallow "^3.0.2"
+    extglob "^2.0.4"
+    fragment-cache "^0.2.1"
+    kind-of "^6.0.2"
+    nanomatch "^1.2.9"
+    object.pick "^1.3.0"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.2"
+
+micromatch@^4.0.4:
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+  integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+  dependencies:
+    braces "^3.0.2"
+    picomatch "^2.3.1"
+
+miller-rabin@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
+  integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
+  dependencies:
+    bn.js "^4.0.0"
+    brorand "^1.0.1"
+
+mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
+  version "1.52.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+  integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34:
+  version "2.1.35"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+  integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+  dependencies:
+    mime-db "1.52.0"
+
+mime@1.6.0, mime@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+mime@^2.0.3, mime@^2.3.1:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
+  integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
+
+mimic-fn@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+  integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+mimic-fn@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+  integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+min-indent@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+  integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
+mini-create-react-context@^0.4.0:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e"
+  integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==
+  dependencies:
+    "@babel/runtime" "^7.12.1"
+    tiny-warning "^1.0.3"
+
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+  integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimalistic-crypto-utils@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+  integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
+
+minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+  integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+  dependencies:
+    brace-expansion "^1.1.7"
+
+minimist-options@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
+  integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
+  dependencies:
+    arrify "^1.0.1"
+    is-plain-obj "^1.1.0"
+    kind-of "^6.0.3"
+
+minimist-options@^3.0.1:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954"
+  integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==
+  dependencies:
+    arrify "^1.0.1"
+    is-plain-obj "^1.1.0"
+
+minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+  integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+minimist@~0.0.1:
+  version "0.0.10"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+  integrity sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==
+
+minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
+  integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
+  dependencies:
+    safe-buffer "^5.1.2"
+    yallist "^3.0.0"
+
+minizlib@^1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
+  integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
+  dependencies:
+    minipass "^2.9.0"
+
+mississippi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
+  integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==
+  dependencies:
+    concat-stream "^1.5.0"
+    duplexify "^3.4.2"
+    end-of-stream "^1.1.0"
+    flush-write-stream "^1.0.0"
+    from2 "^2.1.0"
+    parallel-transform "^1.1.0"
+    pump "^2.0.1"
+    pumpify "^1.3.3"
+    stream-each "^1.1.0"
+    through2 "^2.0.0"
+
+mississippi@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
+  integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==
+  dependencies:
+    concat-stream "^1.5.0"
+    duplexify "^3.4.2"
+    end-of-stream "^1.1.0"
+    flush-write-stream "^1.0.0"
+    from2 "^2.1.0"
+    parallel-transform "^1.1.0"
+    pump "^3.0.0"
+    pumpify "^1.3.3"
+    stream-each "^1.1.0"
+    through2 "^2.0.0"
+
+mixin-deep@^1.2.0:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
+  integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
+  dependencies:
+    for-in "^1.0.2"
+    is-extendable "^1.0.1"
+
+mkdirp-promise@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1"
+  integrity sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w==
+  dependencies:
+    mkdirp "*"
+
+mkdirp@*:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
+  integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
+
+mkdirp@0.x, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@^0.5.6, mkdirp@~0.5.0:
+  version "0.5.6"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+  integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+  dependencies:
+    minimist "^1.2.6"
+
+modify-values@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
+  integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
+
+moment@^2.10.2:
+  version "2.29.4"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
+  integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
+
+move-concurrently@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
+  integrity sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==
+  dependencies:
+    aproba "^1.1.1"
+    copy-concurrently "^1.0.0"
+    fs-write-stream-atomic "^1.0.8"
+    mkdirp "^0.5.1"
+    rimraf "^2.5.4"
+    run-queue "^1.0.3"
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+  integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+
+ms@2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
+  version "2.1.3"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+multicast-dns-service-types@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
+  integrity sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==
+
+multicast-dns@^6.0.1:
+  version "6.2.3"
+  resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229"
+  integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==
+  dependencies:
+    dns-packet "^1.3.1"
+    thunky "^1.0.2"
+
+multimatch@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b"
+  integrity sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==
+  dependencies:
+    array-differ "^2.0.3"
+    array-union "^1.0.2"
+    arrify "^1.0.1"
+    minimatch "^3.0.4"
+
+mute-stream@0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+  integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==
+
+mute-stream@~0.0.4:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
+  integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+
+mz@^2.5.0:
+  version "2.7.0"
+  resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+  integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
+  dependencies:
+    any-promise "^1.0.0"
+    object-assign "^4.0.1"
+    thenify-all "^1.0.0"
+
+nan@^2.12.1:
+  version "2.17.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
+  integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
+
+nanomatch@^1.2.9:
+  version "1.2.13"
+  resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
+  integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
+  dependencies:
+    arr-diff "^4.0.0"
+    array-unique "^0.3.2"
+    define-property "^2.0.2"
+    extend-shallow "^3.0.2"
+    fragment-cache "^0.2.1"
+    is-windows "^1.0.2"
+    kind-of "^6.0.2"
+    object.pick "^1.3.0"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+natural-compare-lite@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
+  integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
+
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+  integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+negotiator@0.6.3:
+  version "0.6.3"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+  integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
+neo-async@^2.5.0, neo-async@^2.6.0:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+  integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+nice-try@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+  integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+no-case@^2.2.0:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
+  integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
+  dependencies:
+    lower-case "^1.1.1"
+
+node-fetch-npm@^2.0.2:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4"
+  integrity sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==
+  dependencies:
+    encoding "^0.1.11"
+    json-parse-better-errors "^1.0.0"
+    safe-buffer "^5.1.1"
+
+node-fetch@^2.5.0, node-fetch@^2.6.7:
+  version "2.6.11"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25"
+  integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==
+  dependencies:
+    whatwg-url "^5.0.0"
+
+node-forge@^0.10.0:
+  version "0.10.0"
+  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
+  integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
+
+node-gyp@^5.0.2:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
+  integrity sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==
+  dependencies:
+    env-paths "^2.2.0"
+    glob "^7.1.4"
+    graceful-fs "^4.2.2"
+    mkdirp "^0.5.1"
+    nopt "^4.0.1"
+    npmlog "^4.1.2"
+    request "^2.88.0"
+    rimraf "^2.6.3"
+    semver "^5.7.1"
+    tar "^4.4.12"
+    which "^1.3.1"
+
+node-int64@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+  integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
+
+node-libs-browser@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
+  integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==
+  dependencies:
+    assert "^1.1.1"
+    browserify-zlib "^0.2.0"
+    buffer "^4.3.0"
+    console-browserify "^1.1.0"
+    constants-browserify "^1.0.0"
+    crypto-browserify "^3.11.0"
+    domain-browser "^1.1.1"
+    events "^3.0.0"
+    https-browserify "^1.0.0"
+    os-browserify "^0.3.0"
+    path-browserify "0.0.1"
+    process "^0.11.10"
+    punycode "^1.2.4"
+    querystring-es3 "^0.2.0"
+    readable-stream "^2.3.3"
+    stream-browserify "^2.0.1"
+    stream-http "^2.7.2"
+    string_decoder "^1.0.0"
+    timers-browserify "^2.0.4"
+    tty-browserify "0.0.0"
+    url "^0.11.0"
+    util "^0.11.0"
+    vm-browserify "^1.0.1"
+
+node-notifier@^5.2.1:
+  version "5.4.5"
+  resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.5.tgz#0cbc1a2b0f658493b4025775a13ad938e96091ef"
+  integrity sha512-tVbHs7DyTLtzOiN78izLA85zRqB9NvEXkAf014Vx3jtSvn/xBl6bR8ZYifj+dFcFrKI21huSQgJZ6ZtL3B4HfQ==
+  dependencies:
+    growly "^1.3.0"
+    is-wsl "^1.1.0"
+    semver "^5.5.0"
+    shellwords "^0.1.1"
+    which "^1.3.0"
+
+node-releases@^2.0.8:
+  version "2.0.12"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039"
+  integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==
+
+nopt@^4.0.1:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
+  integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
+  dependencies:
+    abbrev "1"
+    osenv "^0.1.4"
+
+normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+  integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+  dependencies:
+    hosted-git-info "^2.1.4"
+    resolve "^1.10.0"
+    semver "2 || 3 || 4 || 5"
+    validate-npm-package-license "^3.0.1"
+
+normalize-package-data@^3.0.0:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e"
+  integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==
+  dependencies:
+    hosted-git-info "^4.0.1"
+    is-core-module "^2.5.0"
+    semver "^7.3.4"
+    validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.1, normalize-path@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+  integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==
+  dependencies:
+    remove-trailing-separator "^1.0.1"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+  integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+  integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+normalize-url@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
+  integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
+
+notistack@2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/notistack/-/notistack-2.0.3.tgz#9007550e5cbc14df84d1d54e7a55ac0948eb59e8"
+  integrity sha512-krmVFtTO9kEY1Pa4NrbyexrjiRcV6TqBM2xLx8nuDea1g96Z/OZfkvVLmYKkTvoSJ3jyQntWK16z86ssW5kt4A==
+  dependencies:
+    clsx "^1.1.0"
+    hoist-non-react-statics "^3.3.0"
+
+npm-bundled@^1.0.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1"
+  integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==
+  dependencies:
+    npm-normalize-package-bin "^1.0.1"
+
+npm-lifecycle@^3.1.2:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz#9882d3642b8c82c815782a12e6a1bfeed0026309"
+  integrity sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==
+  dependencies:
+    byline "^5.0.0"
+    graceful-fs "^4.1.15"
+    node-gyp "^5.0.2"
+    resolve-from "^4.0.0"
+    slide "^1.1.6"
+    uid-number "0.0.6"
+    umask "^1.1.0"
+    which "^1.3.1"
+
+npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
+  integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
+
+"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7"
+  integrity sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==
+  dependencies:
+    hosted-git-info "^2.7.1"
+    osenv "^0.1.5"
+    semver "^5.6.0"
+    validate-npm-package-name "^3.0.0"
+
+npm-packlist@^1.4.4:
+  version "1.4.8"
+  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
+  integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
+  dependencies:
+    ignore-walk "^3.0.1"
+    npm-bundled "^1.0.1"
+    npm-normalize-package-bin "^1.0.1"
+
+npm-pick-manifest@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7"
+  integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==
+  dependencies:
+    figgy-pudding "^3.5.1"
+    npm-package-arg "^6.0.0"
+    semver "^5.4.1"
+
+npm-run-path@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+  integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
+  dependencies:
+    path-key "^2.0.0"
+
+npmlog@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+  integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
+  dependencies:
+    are-we-there-yet "~1.1.2"
+    console-control-strings "~1.1.0"
+    gauge "~2.7.3"
+    set-blocking "~2.0.0"
+
+nth-check@^2.0.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+  integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+  dependencies:
+    boolbase "^1.0.0"
+
+num2fraction@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+  integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==
+
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+  integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
+
+nwsapi@^2.0.7:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.4.tgz#fd59d5e904e8e1f03c25a7d5a15cfa16c714a1e5"
+  integrity sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==
+
+oauth-sign@~0.9.0:
+  version "0.9.0"
+  resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+  integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
+
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+  integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-copy@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
+  integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==
+  dependencies:
+    copy-descriptor "^0.1.0"
+    define-property "^0.2.5"
+    kind-of "^3.0.3"
+
+object-inspect@^1.12.3, object-inspect@^1.9.0:
+  version "1.12.3"
+  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
+  integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+
+object-is@^1.0.1:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
+  integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.3"
+
+object-keys@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+  integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object-visit@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
+  integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==
+  dependencies:
+    isobject "^3.0.0"
+
+object.assign@^4.1.2, object.assign@^4.1.3, object.assign@^4.1.4:
+  version "4.1.4"
+  resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
+  integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    has-symbols "^1.0.3"
+    object-keys "^1.1.1"
+
+object.entries@^1.1.5:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23"
+  integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+object.fromentries@^2.0.5:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73"
+  integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.6:
+  version "2.1.6"
+  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312"
+  integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==
+  dependencies:
+    array.prototype.reduce "^1.0.5"
+    call-bind "^1.0.2"
+    define-properties "^1.2.0"
+    es-abstract "^1.21.2"
+    safe-array-concat "^1.0.0"
+
+object.hasown@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92"
+  integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==
+  dependencies:
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+object.omit@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+  integrity sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==
+  dependencies:
+    for-own "^0.1.4"
+    is-extendable "^0.1.1"
+
+object.pick@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
+  integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==
+  dependencies:
+    isobject "^3.0.1"
+
+object.values@^1.1.5:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d"
+  integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+obuf@^1.0.0, obuf@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+  integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+
+octokit-pagination-methods@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"
+  integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==
+
+on-finished@2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
+  integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
+  dependencies:
+    ee-first "1.1.1"
+
+on-headers@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+  integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+  dependencies:
+    wrappy "1"
+
+onetime@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+  integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==
+  dependencies:
+    mimic-fn "^1.0.0"
+
+opener@~1.4.0:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
+  integrity sha512-4Im9TrPJcjAYyGR5gBe3yZnBzw5n3Bfh1ceHHGNOpMurINKc6RdSIPXMyon4BZacJbJc36lLkhipioGbWh5pwg==
+
+opn@^5.1.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
+  integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
+  dependencies:
+    is-wsl "^1.1.0"
+
+optimist@0.6.x:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+  integrity sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==
+  dependencies:
+    minimist "~0.0.1"
+    wordwrap "~0.0.2"
+
+optionator@^0.8.1:
+  version "0.8.3"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+  integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~2.0.6"
+    levn "~0.3.0"
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+    word-wrap "~1.2.3"
+
+optionator@^0.9.1:
+  version "0.9.1"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+  integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+  dependencies:
+    deep-is "^0.1.3"
+    fast-levenshtein "^2.0.6"
+    levn "^0.4.1"
+    prelude-ls "^1.2.1"
+    type-check "^0.4.0"
+    word-wrap "^1.2.3"
+
+os-browserify@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
+  integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==
+
+os-homedir@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+  integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==
+
+os-locale@^3.0.0, os-locale@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+  integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
+  dependencies:
+    execa "^1.0.0"
+    lcid "^2.0.0"
+    mem "^4.0.0"
+
+os-name@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801"
+  integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==
+  dependencies:
+    macos-release "^2.2.0"
+    windows-release "^3.1.0"
+
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+  integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
+
+osenv@^0.1.4, osenv@^0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+  integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
+  dependencies:
+    os-homedir "^1.0.0"
+    os-tmpdir "^1.0.0"
+
+p-defer@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+  integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==
+
+p-finally@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+  integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
+
+p-is-promise@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+  integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+
+p-limit@^1.0.0, p-limit@^1.1.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
+  integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
+  dependencies:
+    p-try "^1.0.0"
+
+p-limit@^2.0.0, p-limit@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+  integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+  dependencies:
+    p-try "^2.0.0"
+
+p-limit@^3.0.2:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+  integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+  dependencies:
+    yocto-queue "^0.1.0"
+
+p-locate@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+  integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==
+  dependencies:
+    p-limit "^1.1.0"
+
+p-locate@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+  integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+  dependencies:
+    p-limit "^2.0.0"
+
+p-locate@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+  integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+  dependencies:
+    p-limit "^2.2.0"
+
+p-locate@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+  integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+  dependencies:
+    p-limit "^3.0.2"
+
+p-map-series@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca"
+  integrity sha512-4k9LlvY6Bo/1FcIdV33wqZQES0Py+iKISU9Uc8p8AjWoZPnFKMpVIVD3s0EYn4jzLh1I+WeUZkJ0Yoa4Qfw3Kg==
+  dependencies:
+    p-reduce "^1.0.0"
+
+p-map@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
+  integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
+
+p-map@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
+  integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
+
+p-pipe@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9"
+  integrity sha512-IA8SqjIGA8l9qOksXJvsvkeQ+VGb0TAzNCzvKvz9wt5wWLqfWbV6fXy43gpR2L4Te8sOq3S+Ql9biAaMKPdbtw==
+
+p-queue@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-4.0.0.tgz#ed0eee8798927ed6f2c2f5f5b77fdb2061a5d346"
+  integrity sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==
+  dependencies:
+    eventemitter3 "^3.1.0"
+
+p-reduce@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
+  integrity sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==
+
+p-try@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+  integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
+
+p-try@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+  integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+p-waterfall@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-1.0.0.tgz#7ed94b3ceb3332782353af6aae11aa9fc235bb00"
+  integrity sha512-KeXddIp6jBT8qzyxfQGOGzNYc/7ftxKtRc5Uggre02yvbZrSBHE2M2C842/WizMBFD4s0Ngwz3QFOit2A+Ezrg==
+  dependencies:
+    p-reduce "^1.0.0"
+
+pako@~1.0.5:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+  integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
+parallel-transform@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc"
+  integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==
+  dependencies:
+    cyclist "^1.0.1"
+    inherits "^2.0.3"
+    readable-stream "^2.1.5"
+
+param-case@2.1.x:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
+  integrity sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==
+  dependencies:
+    no-case "^2.2.0"
+
+parent-module@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+  integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+  dependencies:
+    callsites "^3.0.0"
+
+parse-asn1@^5.0.0, parse-asn1@^5.1.5:
+  version "5.1.6"
+  resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4"
+  integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==
+  dependencies:
+    asn1.js "^5.2.0"
+    browserify-aes "^1.0.0"
+    evp_bytestokey "^1.0.0"
+    pbkdf2 "^3.0.3"
+    safe-buffer "^5.1.1"
+
+parse-github-repo-url@^1.3.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50"
+  integrity sha512-bSWyzBKqcSL4RrncTpGsEKoJ7H8a4L3++ifTAbTFeMHyq2wRV+42DGmQcHIrJIvdcacjIOxEuKH/w4tthF17gg==
+
+parse-glob@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+  integrity sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==
+  dependencies:
+    glob-base "^0.3.0"
+    is-dotfile "^1.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.0"
+
+parse-json@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==
+  dependencies:
+    error-ex "^1.2.0"
+
+parse-json@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+  integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==
+  dependencies:
+    error-ex "^1.3.1"
+    json-parse-better-errors "^1.0.1"
+
+parse-json@^5.0.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+  integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    error-ex "^1.3.1"
+    json-parse-even-better-errors "^2.3.0"
+    lines-and-columns "^1.1.6"
+
+parse-passwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
+  integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==
+
+parse-path@^4.0.0:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.4.tgz#4bf424e6b743fb080831f03b536af9fc43f0ffea"
+  integrity sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==
+  dependencies:
+    is-ssh "^1.3.0"
+    protocols "^1.4.0"
+    qs "^6.9.4"
+    query-string "^6.13.8"
+
+parse-url@^6.0.0:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.5.tgz#4acab8982cef1846a0f8675fa686cef24b2f6f9b"
+  integrity sha512-e35AeLTSIlkw/5GFq70IN7po8fmDUjpDPY1rIK+VubRfsUvBonjQ+PBZG+vWMACnQSmNlvl524IucoDmcioMxA==
+  dependencies:
+    is-ssh "^1.3.0"
+    normalize-url "^6.1.0"
+    parse-path "^4.0.0"
+    protocols "^1.4.0"
+
+parse5@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
+  integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
+
+parseurl@~1.3.2, parseurl@~1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+pascalcase@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
+  integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==
+
+path-browserify@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
+  integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
+
+path-dirname@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
+  integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==
+
+path-exists@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==
+  dependencies:
+    pinkie-promise "^2.0.0"
+
+path-exists@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+  integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
+
+path-exists@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+  integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+  integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-is-inside@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+  integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==
+
+path-key@^2.0.0, path-key@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+  integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
+
+path-key@^3.1.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+  integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.5, path-parse@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+  integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-to-regexp@0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+  integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
+
+path-to-regexp@^1.7.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
+  integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
+  dependencies:
+    isarray "0.0.1"
+
+path-type@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==
+  dependencies:
+    graceful-fs "^4.1.2"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+path-type@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+  integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+  dependencies:
+    pify "^3.0.0"
+
+path-type@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+  integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+pbkdf2@^3.0.3:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
+  integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==
+  dependencies:
+    create-hash "^1.1.2"
+    create-hmac "^1.1.4"
+    ripemd160 "^2.0.1"
+    safe-buffer "^5.0.1"
+    sha.js "^2.4.8"
+
+performance-now@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+  integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
+
+picocolors@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
+  integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+
+picocolors@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+  integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+  integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pify@^2.0.0, pify@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+  integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pify@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+  integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==
+
+pify@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+  integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==
+
+pkg-dir@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
+  integrity sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==
+  dependencies:
+    find-up "^2.1.0"
+
+pkg-dir@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+  integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+  dependencies:
+    find-up "^3.0.0"
+
+pn@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
+  integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
+
+portfinder@^1.0.13, portfinder@^1.0.9:
+  version "1.0.32"
+  resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81"
+  integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==
+  dependencies:
+    async "^2.6.4"
+    debug "^3.2.7"
+    mkdirp "^0.5.6"
+
+posix-character-classes@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
+  integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==
+
+postcss-load-config@^2.0.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a"
+  integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==
+  dependencies:
+    cosmiconfig "^5.0.0"
+    import-cwd "^2.0.0"
+
+postcss-loader@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d"
+  integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==
+  dependencies:
+    loader-utils "^1.1.0"
+    postcss "^7.0.0"
+    postcss-load-config "^2.0.0"
+    schema-utils "^1.0.0"
+
+postcss-modules-extract-imports@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a"
+  integrity sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==
+  dependencies:
+    postcss "^6.0.1"
+
+postcss-modules-local-by-default@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
+  integrity sha512-X4cquUPIaAd86raVrBwO8fwRfkIdbwFu7CTfEOjiZQHVQwlHRSkTgH5NLDmMm5+1hQO8u6dZ+TOOJDbay1hYpA==
+  dependencies:
+    css-selector-tokenizer "^0.7.0"
+    postcss "^6.0.1"
+
+postcss-modules-scope@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
+  integrity sha512-LTYwnA4C1He1BKZXIx1CYiHixdSe9LWYVKadq9lK5aCCMkoOkFyZ7aigt+srfjlRplJY3gIol6KUNefdMQJdlw==
+  dependencies:
+    css-selector-tokenizer "^0.7.0"
+    postcss "^6.0.1"
+
+postcss-modules-values@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
+  integrity sha512-i7IFaR9hlQ6/0UgFuqM6YWaCfA1Ej8WMg8A5DggnH1UGKJvTV/ugqq/KaULixzzOi3T/tF6ClBXcHGCzdd5unA==
+  dependencies:
+    icss-replace-symbols "^1.1.0"
+    postcss "^6.0.1"
+
+postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
+  integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
+
+postcss@^6.0.1, postcss@^6.0.23:
+  version "6.0.23"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
+  integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
+  dependencies:
+    chalk "^2.4.1"
+    source-map "^0.6.1"
+    supports-color "^5.4.0"
+
+postcss@^7.0.0, postcss@^7.0.2:
+  version "7.0.39"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
+  integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
+  dependencies:
+    picocolors "^0.2.1"
+    source-map "^0.6.1"
+
+prelude-ls@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+  integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+  integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
+
+preserve@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+  integrity sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==
+
+pretty-error@^2.0.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6"
+  integrity sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==
+  dependencies:
+    lodash "^4.17.20"
+    renderkid "^2.0.4"
+
+pretty-format@^23.6.0:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
+  integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
+  dependencies:
+    ansi-regex "^3.0.0"
+    ansi-styles "^3.2.0"
+
+private@^0.1.8:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
+  integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
+
+process-nextick-args@~2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+  integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+process@^0.11.10:
+  version "0.11.10"
+  resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+  integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
+
+promise-inflight@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
+  integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==
+
+promise-retry@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d"
+  integrity sha512-StEy2osPr28o17bIW776GtwO6+Q+M9zPiZkYfosciUUMYqjhU/ffwRAH0zN2+uvGyUsn8/YICIHRzLbPacpZGw==
+  dependencies:
+    err-code "^1.0.0"
+    retry "^0.10.0"
+
+prompts@^0.1.9:
+  version "0.1.14"
+  resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
+  integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
+  dependencies:
+    kleur "^2.0.1"
+    sisteransi "^0.1.1"
+
+promzard@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee"
+  integrity sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw==
+  dependencies:
+    read "1"
+
+prop-types@15.7.2:
+  version "15.7.2"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+  integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+  dependencies:
+    loose-envify "^1.4.0"
+    object-assign "^4.1.1"
+    react-is "^16.8.1"
+
+prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
+  version "15.8.1"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+  integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+  dependencies:
+    loose-envify "^1.4.0"
+    object-assign "^4.1.1"
+    react-is "^16.13.1"
+
+proto-list@~1.2.1:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+  integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
+
+protocols@^1.4.0:
+  version "1.4.8"
+  resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
+  integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==
+
+protocols@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86"
+  integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==
+
+protoduck@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f"
+  integrity sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==
+  dependencies:
+    genfun "^5.0.0"
+
+proxy-addr@~2.0.7:
+  version "2.0.7"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
+  integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
+  dependencies:
+    forwarded "0.2.0"
+    ipaddr.js "1.9.1"
+
+prr@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+  integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
+
+pseudomap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+  integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==
+
+psl@^1.1.28:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
+  integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
+
+public-encrypt@^4.0.0:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
+  integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==
+  dependencies:
+    bn.js "^4.1.0"
+    browserify-rsa "^4.0.0"
+    create-hash "^1.1.0"
+    parse-asn1 "^5.0.0"
+    randombytes "^2.0.1"
+    safe-buffer "^5.1.2"
+
+pump@^2.0.0, pump@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
+  integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
+  dependencies:
+    end-of-stream "^1.1.0"
+    once "^1.3.1"
+
+pump@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+  integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+  dependencies:
+    end-of-stream "^1.1.0"
+    once "^1.3.1"
+
+pumpify@^1.3.3:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
+  integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
+  dependencies:
+    duplexify "^3.6.0"
+    inherits "^2.0.3"
+    pump "^2.0.0"
+
+punycode@1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+  integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==
+
+punycode@^1.2.4:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+  integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
+
+punycode@^2.1.0, punycode@^2.1.1:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
+  integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
+
+q@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+  integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
+
+qs@6.11.0:
+  version "6.11.0"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
+  integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
+  dependencies:
+    side-channel "^1.0.4"
+
+qs@^6.4.0, qs@^6.9.4:
+  version "6.11.2"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
+  integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
+  dependencies:
+    side-channel "^1.0.4"
+
+qs@~6.5.2:
+  version "6.5.3"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
+  integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
+
+query-string@^6.13.8:
+  version "6.14.1"
+  resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.14.1.tgz#7ac2dca46da7f309449ba0f86b1fd28255b0c86a"
+  integrity sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==
+  dependencies:
+    decode-uri-component "^0.2.0"
+    filter-obj "^1.1.0"
+    split-on-first "^1.0.0"
+    strict-uri-encode "^2.0.0"
+
+querystring-es3@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+  integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==
+
+querystring@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+  integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==
+
+querystringify@^2.1.1:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
+  integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
+
+queue-microtask@^1.2.2:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+  integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+quick-lru@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
+  integrity sha512-tRS7sTgyxMXtLum8L65daJnHUhfDUgboRdcWW2bR9vBfrj2+O5HSMbQOJfJJjIVSPFqbBCF37FpwWXGitDc5tA==
+
+quick-lru@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
+  integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
+
+randomatic@^3.0.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
+  integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
+  dependencies:
+    is-number "^4.0.0"
+    kind-of "^6.0.0"
+    math-random "^1.0.1"
+
+randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+  integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+  dependencies:
+    safe-buffer "^5.1.0"
+
+randomfill@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
+  integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==
+  dependencies:
+    randombytes "^2.0.5"
+    safe-buffer "^5.1.0"
+
+range-parser@^1.0.3, range-parser@~1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+  integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.5.1:
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
+  integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+  dependencies:
+    bytes "3.1.2"
+    http-errors "2.0.0"
+    iconv-lite "0.4.24"
+    unpipe "1.0.0"
+
+react-chartjs-2@2.7.6:
+  version "2.7.6"
+  resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-2.7.6.tgz#b8cd29bed00bf55b9e8172b06466b4ecf2b86bfb"
+  integrity sha512-xDr0jhgt/o26atftXxTVsepz+QYZI2GNKBYpxtLvYgwffLUm18a9n562reUJAHvuwKsy2v+qMlK5HyjFtSW0mg==
+  dependencies:
+    lodash "^4.17.4"
+    prop-types "^15.5.8"
+
+react-chartjs-2@^3.0.3:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-3.3.0.tgz#3f62681645acccc1ab27a9186c70f79d6d417f73"
+  integrity sha512-4Mt0SR2aiUbWi/4762odRBYSnbNKSs4HWc0o3IW43py5bMfmfpeZU95w6mbvtuLZH/M3GsPJMU8DvDc+5U9blQ==
+
+react-dom@17.0.2:
+  version "17.0.2"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
+  integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    scheduler "^0.20.2"
+
+react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
+  version "16.13.1"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+  integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-is@^18.2.0:
+  version "18.2.0"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+  integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
+react-lifecycles-compat@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
+  integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+
+react-router-dom@5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
+  integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==
+  dependencies:
+    "@babel/runtime" "^7.1.2"
+    history "^4.9.0"
+    loose-envify "^1.3.1"
+    prop-types "^15.6.2"
+    react-router "5.2.0"
+    tiny-invariant "^1.0.2"
+    tiny-warning "^1.0.0"
+
+react-router@5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293"
+  integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
+  dependencies:
+    "@babel/runtime" "^7.1.2"
+    history "^4.9.0"
+    hoist-non-react-statics "^3.1.0"
+    loose-envify "^1.3.1"
+    mini-create-react-context "^0.4.0"
+    path-to-regexp "^1.7.0"
+    prop-types "^15.6.2"
+    react-is "^16.6.0"
+    tiny-invariant "^1.0.2"
+    tiny-warning "^1.0.0"
+
+react-split-pane@0.1.92:
+  version "0.1.92"
+  resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.92.tgz#68242f72138aed95dd5910eeb9d99822c4fc3a41"
+  integrity sha512-GfXP1xSzLMcLJI5BM36Vh7GgZBpy+U/X0no+VM3fxayv+p1Jly5HpMofZJraeaMl73b3hvlr+N9zJKvLB/uz9w==
+  dependencies:
+    prop-types "^15.7.2"
+    react-lifecycles-compat "^3.0.4"
+    react-style-proptype "^3.2.2"
+
+react-style-proptype@^3.2.2:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/react-style-proptype/-/react-style-proptype-3.2.2.tgz#d8e998e62ce79ec35b087252b90f19f1c33968a0"
+  integrity sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ==
+  dependencies:
+    prop-types "^15.5.4"
+
+react-transition-group@4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683"
+  integrity sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==
+  dependencies:
+    "@babel/runtime" "^7.5.5"
+    dom-helpers "^5.0.1"
+    loose-envify "^1.4.0"
+    prop-types "^15.6.2"
+
+react-transition-group@^4.4.5:
+  version "4.4.5"
+  resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
+  integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+  dependencies:
+    "@babel/runtime" "^7.5.5"
+    dom-helpers "^5.0.1"
+    loose-envify "^1.4.0"
+    prop-types "^15.6.2"
+
+react@17.0.2:
+  version "17.0.2"
+  resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
+  integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+
+read-cmd-shim@^1.0.1:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"
+  integrity sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==
+  dependencies:
+    graceful-fs "^4.1.2"
+
+"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a"
+  integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==
+  dependencies:
+    glob "^7.1.1"
+    json-parse-even-better-errors "^2.3.0"
+    normalize-package-data "^2.0.0"
+    npm-normalize-package-bin "^1.0.0"
+
+read-package-tree@^5.1.6:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636"
+  integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==
+  dependencies:
+    read-package-json "^2.0.0"
+    readdir-scoped-modules "^1.0.0"
+    util-promisify "^2.1.0"
+
+read-pkg-up@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==
+  dependencies:
+    find-up "^1.0.0"
+    read-pkg "^1.0.0"
+
+read-pkg-up@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
+  integrity sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==
+  dependencies:
+    find-up "^2.0.0"
+    read-pkg "^3.0.0"
+
+read-pkg-up@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
+  integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
+  dependencies:
+    find-up "^4.1.0"
+    read-pkg "^5.2.0"
+    type-fest "^0.8.1"
+
+read-pkg@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==
+  dependencies:
+    load-json-file "^1.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^1.0.0"
+
+read-pkg@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+  integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==
+  dependencies:
+    load-json-file "^4.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^3.0.0"
+
+read-pkg@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
+  integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
+  dependencies:
+    "@types/normalize-package-data" "^2.4.0"
+    normalize-package-data "^2.5.0"
+    parse-json "^5.0.0"
+    type-fest "^0.6.0"
+
+read@1, read@~1.0.1:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
+  integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==
+  dependencies:
+    mute-stream "~0.0.4"
+
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+  integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
+"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.6.0:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
+readdir-scoped-modules@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
+  integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==
+  dependencies:
+    debuglog "^1.0.1"
+    dezalgo "^1.0.0"
+    graceful-fs "^4.1.2"
+    once "^1.3.0"
+
+readdirp@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
+  integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==
+  dependencies:
+    graceful-fs "^4.1.11"
+    micromatch "^3.1.10"
+    readable-stream "^2.0.2"
+
+readdirp@~3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+  integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+  dependencies:
+    picomatch "^2.2.1"
+
+realpath-native@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
+  integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
+  dependencies:
+    util.promisify "^1.0.0"
+
+redent@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+  integrity sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==
+  dependencies:
+    indent-string "^2.1.0"
+    strip-indent "^1.0.1"
+
+redent@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
+  integrity sha512-XNwrTx77JQCEMXTeb8movBKuK75MgH0RZkujNuDKCezemx/voapl9i2gCSi8WWm8+ox5ycJi1gxF22fR7c0Ciw==
+  dependencies:
+    indent-string "^3.0.0"
+    strip-indent "^2.0.0"
+
+redent@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+  integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+  dependencies:
+    indent-string "^4.0.0"
+    strip-indent "^3.0.0"
+
+reflect-metadata@^0.1.12:
+  version "0.1.13"
+  resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
+  integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
+
+regenerate-unicode-properties@^10.1.0:
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
+  integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==
+  dependencies:
+    regenerate "^1.4.2"
+
+regenerate@^1.4.2:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
+  integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+
+regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+  integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
+regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.4:
+  version "0.13.11"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+  integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
+regenerator-transform@^0.15.1:
+  version "0.15.1"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"
+  integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==
+  dependencies:
+    "@babel/runtime" "^7.8.4"
+
+regex-cache@^0.4.2:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
+  integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
+  dependencies:
+    is-equal-shallow "^0.1.3"
+
+regex-not@^1.0.0, regex-not@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
+  integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
+  dependencies:
+    extend-shallow "^3.0.2"
+    safe-regex "^1.1.0"
+
+regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
+  integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.2.0"
+    functions-have-names "^1.2.3"
+
+regexpp@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
+  integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
+
+regexpu-core@^5.3.1:
+  version "5.3.2"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b"
+  integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==
+  dependencies:
+    "@babel/regjsgen" "^0.8.0"
+    regenerate "^1.4.2"
+    regenerate-unicode-properties "^10.1.0"
+    regjsparser "^0.9.1"
+    unicode-match-property-ecmascript "^2.0.0"
+    unicode-match-property-value-ecmascript "^2.1.0"
+
+regjsparser@^0.9.1:
+  version "0.9.1"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709"
+  integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==
+  dependencies:
+    jsesc "~0.5.0"
+
+relateurl@0.2.x:
+  version "0.2.7"
+  resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
+  integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
+
+remove-trailing-separator@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+  integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==
+
+renderkid@^2.0.4:
+  version "2.0.7"
+  resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.7.tgz#464f276a6bdcee606f4a15993f9b29fc74ca8609"
+  integrity sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==
+  dependencies:
+    css-select "^4.1.3"
+    dom-converter "^0.2.0"
+    htmlparser2 "^6.1.0"
+    lodash "^4.17.21"
+    strip-ansi "^3.0.1"
+
+repeat-element@^1.1.2:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9"
+  integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
+
+repeat-string@^1.5.2, repeat-string@^1.6.1:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+  integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
+
+repeating@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+  integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==
+  dependencies:
+    is-finite "^1.0.0"
+
+request-promise-core@1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
+  integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
+  dependencies:
+    lodash "^4.17.19"
+
+request-promise-native@^1.0.5:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
+  integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
+  dependencies:
+    request-promise-core "1.1.4"
+    stealthy-require "^1.1.1"
+    tough-cookie "^2.3.3"
+
+request@^2.87.0, request@^2.88.0:
+  version "2.88.2"
+  resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
+  integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
+  dependencies:
+    aws-sign2 "~0.7.0"
+    aws4 "^1.8.0"
+    caseless "~0.12.0"
+    combined-stream "~1.0.6"
+    extend "~3.0.2"
+    forever-agent "~0.6.1"
+    form-data "~2.3.2"
+    har-validator "~5.1.3"
+    http-signature "~1.2.0"
+    is-typedarray "~1.0.0"
+    isstream "~0.1.2"
+    json-stringify-safe "~5.0.1"
+    mime-types "~2.1.19"
+    oauth-sign "~0.9.0"
+    performance-now "^2.1.0"
+    qs "~6.5.2"
+    safe-buffer "^5.1.2"
+    tough-cookie "~2.5.0"
+    tunnel-agent "^0.6.0"
+    uuid "^3.3.2"
+
+require-directory@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+  integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+require-main-filename@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+  integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==
+
+require-main-filename@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+  integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+requirejs-webpack-plugin@1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/requirejs-webpack-plugin/-/requirejs-webpack-plugin-1.0.5.tgz#3bded42b2a9809898579019d6570732670416259"
+  integrity sha512-bpbdDFqOs+hKSeCVGwMU6724WoZUf/qh+wH56o+g1YX+ZHmlonv1lCOMjXrRG4kGY4Pc5iQvJFkWU9CoEgH4WA==
+  dependencies:
+    mkdirp "^0.5.1"
+
+requirejs@2.3.6:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
+  integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
+
+requires-port@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+  integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
+
+resolve-cwd@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
+  integrity sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==
+  dependencies:
+    resolve-from "^3.0.0"
+
+resolve-dir@^1.0.0, resolve-dir@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
+  integrity sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==
+  dependencies:
+    expand-tilde "^2.0.0"
+    global-modules "^1.0.0"
+
+resolve-from@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
+  integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==
+
+resolve-from@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+  integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve-pathname@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
+  integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
+
+resolve-url@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+  integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==
+
+resolve@1.1.7:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+  integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==
+
+resolve@1.x, resolve@^1.10.0, resolve@^1.19.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2:
+  version "1.22.2"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+  integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
+  dependencies:
+    is-core-module "^2.11.0"
+    path-parse "^1.0.7"
+    supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^2.0.0-next.3:
+  version "2.0.0-next.4"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
+  integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==
+  dependencies:
+    is-core-module "^2.9.0"
+    path-parse "^1.0.7"
+    supports-preserve-symlinks-flag "^1.0.0"
+
+restore-cursor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+  integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==
+  dependencies:
+    onetime "^2.0.0"
+    signal-exit "^3.0.2"
+
+ret@~0.1.10:
+  version "0.1.15"
+  resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
+  integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
+
+retry@^0.10.0:
+  version "0.10.1"
+  resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
+  integrity sha512-ZXUSQYTHdl3uS7IuCehYfMzKyIDBNoAuUblvy5oGO5UJSUTmStUUVPXbA9Qxd173Bgre53yCQczQuHgRWAdvJQ==
+
+reusify@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+  integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@2.6.2:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+  integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
+  dependencies:
+    glob "^7.0.5"
+
+rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+  integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+  dependencies:
+    glob "^7.1.3"
+
+rimraf@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+  integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+  dependencies:
+    glob "^7.1.3"
+
+ripemd160@^2.0.0, ripemd160@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
+  integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+
+rsvp@^3.3.3:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
+  integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+
+run-async@^2.2.0:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
+  integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
+
+run-parallel@^1.1.9:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+  integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+  dependencies:
+    queue-microtask "^1.2.2"
+
+run-queue@^1.0.0, run-queue@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
+  integrity sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==
+  dependencies:
+    aproba "^1.1.1"
+
+rxjs@^6.4.0:
+  version "6.6.7"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+  integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+  dependencies:
+    tslib "^1.9.0"
+
+safe-array-concat@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060"
+  integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==
+  dependencies:
+    call-bind "^1.0.2"
+    get-intrinsic "^1.2.0"
+    has-symbols "^1.0.3"
+    isarray "^2.0.5"
+
+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-regex-test@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
+  integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==
+  dependencies:
+    call-bind "^1.0.2"
+    get-intrinsic "^1.1.3"
+    is-regex "^1.1.4"
+
+safe-regex@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
+  integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==
+  dependencies:
+    ret "~0.1.10"
+
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sane@^2.0.0:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
+  integrity sha512-OuZwD1QJ2R9Dbnhd7Ur8zzD8l+oADp9npyxK63Q9nZ4AjhB2QwDQcQlD8iuUsGm5AZZqtEuCaJvK1rxGRxyQ1Q==
+  dependencies:
+    anymatch "^2.0.0"
+    capture-exit "^1.2.0"
+    exec-sh "^0.2.0"
+    fb-watchman "^2.0.0"
+    micromatch "^3.1.4"
+    minimist "^1.1.1"
+    walker "~1.0.5"
+    watch "~0.18.0"
+  optionalDependencies:
+    fsevents "^1.2.3"
+
+sax@^1.2.4:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+  integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+scheduler@^0.20.2:
+  version "0.20.2"
+  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+  integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+
+schema-utils@^0.4.4, schema-utils@^0.4.5:
+  version "0.4.7"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
+  integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==
+  dependencies:
+    ajv "^6.1.0"
+    ajv-keywords "^3.1.0"
+
+schema-utils@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
+  integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==
+  dependencies:
+    ajv "^6.1.0"
+    ajv-errors "^1.0.0"
+    ajv-keywords "^3.1.0"
+
+select-hose@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+  integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==
+
+selfsigned@^1.9.1:
+  version "1.10.14"
+  resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.14.tgz#ee51d84d9dcecc61e07e4aba34f229ab525c1574"
+  integrity sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==
+  dependencies:
+    node-forge "^0.10.0"
+
+"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+  integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@^7.3.4, semver@^7.3.7:
+  version "7.5.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec"
+  integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==
+  dependencies:
+    lru-cache "^6.0.0"
+
+send@0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+  integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
+  dependencies:
+    debug "2.6.9"
+    depd "2.0.0"
+    destroy "1.2.0"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    fresh "0.5.2"
+    http-errors "2.0.0"
+    mime "1.6.0"
+    ms "2.1.3"
+    on-finished "2.4.1"
+    range-parser "~1.2.1"
+    statuses "2.0.1"
+
+serialize-javascript@^1.4.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb"
+  integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==
+
+serialize-javascript@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
+  integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
+  dependencies:
+    randombytes "^2.1.0"
+
+serve-index@^1.7.2:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+  integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==
+  dependencies:
+    accepts "~1.3.4"
+    batch "0.6.1"
+    debug "2.6.9"
+    escape-html "~1.0.3"
+    http-errors "~1.6.2"
+    mime-types "~2.1.17"
+    parseurl "~1.3.2"
+
+serve-static@1.15.0:
+  version "1.15.0"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
+  integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
+  dependencies:
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    parseurl "~1.3.3"
+    send "0.18.0"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+  integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
+
+set-value@^2.0.0, set-value@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
+  integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
+  dependencies:
+    extend-shallow "^2.0.1"
+    is-extendable "^0.1.1"
+    is-plain-object "^2.0.3"
+    split-string "^3.0.1"
+
+setimmediate@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+  integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
+
+setprototypeof@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+  integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+
+setprototypeof@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+  integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+sha.js@^2.4.0, sha.js@^2.4.8:
+  version "2.4.11"
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
+  integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+shallow-clone@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+  integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+  dependencies:
+    kind-of "^6.0.2"
+
+shebang-command@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+  integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
+  dependencies:
+    shebang-regex "^1.0.0"
+
+shebang-command@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+  integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+  dependencies:
+    shebang-regex "^3.0.0"
+
+shebang-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+  integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
+
+shebang-regex@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+  integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+shellwords@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
+  integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
+
+side-channel@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+  integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+  dependencies:
+    call-bind "^1.0.0"
+    get-intrinsic "^1.0.2"
+    object-inspect "^1.9.0"
+
+signal-exit@^3.0.0, signal-exit@^3.0.2:
+  version "3.0.7"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+  integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+sisteransi@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
+  integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
+
+slash@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+  integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==
+
+slash@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+  integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
+slash@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+  integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slide@^1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+  integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==
+
+smart-buffer@^4.1.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
+  integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
+
+snapdragon-node@^2.0.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
+  integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
+  dependencies:
+    define-property "^1.0.0"
+    isobject "^3.0.0"
+    snapdragon-util "^3.0.1"
+
+snapdragon-util@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
+  integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
+  dependencies:
+    kind-of "^3.2.0"
+
+snapdragon@^0.8.1:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
+  integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
+  dependencies:
+    base "^0.11.1"
+    debug "^2.2.0"
+    define-property "^0.2.5"
+    extend-shallow "^2.0.1"
+    map-cache "^0.2.2"
+    source-map "^0.5.6"
+    source-map-resolve "^0.5.0"
+    use "^3.1.0"
+
+sockjs-client@1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177"
+  integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==
+  dependencies:
+    debug "^3.2.5"
+    eventsource "^1.0.7"
+    faye-websocket "~0.11.1"
+    inherits "^2.0.3"
+    json3 "^3.3.2"
+    url-parse "^1.4.3"
+
+sockjs@0.3.19:
+  version "0.3.19"
+  resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d"
+  integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==
+  dependencies:
+    faye-websocket "^0.10.0"
+    uuid "^3.0.1"
+
+socks-proxy-agent@^4.0.0:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
+  integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==
+  dependencies:
+    agent-base "~4.2.1"
+    socks "~2.3.2"
+
+socks@~2.3.2:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3"
+  integrity sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==
+  dependencies:
+    ip "1.1.5"
+    smart-buffer "^4.1.0"
+
+sort-keys@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
+  integrity sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==
+  dependencies:
+    is-plain-obj "^1.0.0"
+
+source-list-map@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+  integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+
+source-map-resolve@^0.5.0:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
+  integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
+  dependencies:
+    atob "^2.1.2"
+    decode-uri-component "^0.2.0"
+    resolve-url "^0.2.1"
+    source-map-url "^0.4.0"
+    urix "^0.1.0"
+
+source-map-support@^0.4.15:
+  version "0.4.18"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+  integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
+  dependencies:
+    source-map "^0.5.6"
+
+source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12:
+  version "0.5.21"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+  integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
+source-map-url@^0.4.0:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
+  integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
+
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
+  version "0.5.7"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+  integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+spdx-correct@^3.0.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
+  integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==
+  dependencies:
+    spdx-expression-parse "^3.0.0"
+    spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+  integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+
+spdx-expression-parse@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+  integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+  dependencies:
+    spdx-exceptions "^2.1.0"
+    spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+  version "3.0.13"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5"
+  integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==
+
+spdy-transport@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
+  integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
+  dependencies:
+    debug "^4.1.0"
+    detect-node "^2.0.4"
+    hpack.js "^2.1.6"
+    obuf "^1.1.2"
+    readable-stream "^3.0.6"
+    wbuf "^1.7.3"
+
+spdy@^4.0.0:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
+  integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
+  dependencies:
+    debug "^4.1.0"
+    handle-thing "^2.0.0"
+    http-deceiver "^1.2.7"
+    select-hose "^2.0.0"
+    spdy-transport "^3.0.0"
+
+split-on-first@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+  integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
+split-string@^3.0.1, split-string@^3.0.2:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
+  integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
+  dependencies:
+    extend-shallow "^3.0.0"
+
+split2@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493"
+  integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==
+  dependencies:
+    through2 "^2.0.2"
+
+split2@^3.0.0:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f"
+  integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==
+  dependencies:
+    readable-stream "^3.0.0"
+
+split@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+  integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+  dependencies:
+    through "2"
+
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+  integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
+
+sshpk@^1.7.0:
+  version "1.17.0"
+  resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
+  integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==
+  dependencies:
+    asn1 "~0.2.3"
+    assert-plus "^1.0.0"
+    bcrypt-pbkdf "^1.0.0"
+    dashdash "^1.12.0"
+    ecc-jsbn "~0.1.1"
+    getpass "^0.1.1"
+    jsbn "~0.1.0"
+    safer-buffer "^2.0.2"
+    tweetnacl "~0.14.0"
+
+ssri@^5.2.4:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06"
+  integrity sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==
+  dependencies:
+    safe-buffer "^5.1.1"
+
+ssri@^6.0.0, ssri@^6.0.1:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
+  integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
+  dependencies:
+    figgy-pudding "^3.5.1"
+
+stack-utils@^1.0.1:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.5.tgz#a19b0b01947e0029c8e451d5d61a498f5bb1471b"
+  integrity sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==
+  dependencies:
+    escape-string-regexp "^2.0.0"
+
+static-extend@^0.1.1:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
+  integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==
+  dependencies:
+    define-property "^0.2.5"
+    object-copy "^0.1.0"
+
+statuses@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+  integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+"statuses@>= 1.4.0 < 2":
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+  integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+
+stealthy-require@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+  integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==
+
+stream-browserify@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
+  integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==
+  dependencies:
+    inherits "~2.0.1"
+    readable-stream "^2.0.2"
+
+stream-each@^1.1.0:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"
+  integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==
+  dependencies:
+    end-of-stream "^1.1.0"
+    stream-shift "^1.0.0"
+
+stream-http@^2.7.2:
+  version "2.8.3"
+  resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc"
+  integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==
+  dependencies:
+    builtin-status-codes "^3.0.0"
+    inherits "^2.0.1"
+    readable-stream "^2.3.6"
+    to-arraybuffer "^1.0.0"
+    xtend "^4.0.0"
+
+stream-shift@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
+  integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
+
+strict-uri-encode@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+  integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
+
+string-length@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
+  integrity sha512-Qka42GGrS8Mm3SZ+7cH8UXiIWI867/b/Z/feQSpQx/rbfB8UGknGEZVaUQMOUVj+soY6NpWAxily63HI1OckVQ==
+  dependencies:
+    astral-regex "^1.0.0"
+    strip-ansi "^4.0.0"
+
+string-width@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    strip-ansi "^3.0.0"
+
+"string-width@^1.0.2 || 2 || 3 || 4":
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
+string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+  integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^4.0.0"
+
+string-width@^3.0.0, string-width@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
+  integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
+  dependencies:
+    emoji-regex "^7.0.1"
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^5.1.0"
+
+string.prototype.matchall@^4.0.7:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3"
+  integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+    get-intrinsic "^1.1.3"
+    has-symbols "^1.0.3"
+    internal-slot "^1.0.3"
+    regexp.prototype.flags "^1.4.3"
+    side-channel "^1.0.4"
+
+string.prototype.trim@^1.2.7:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533"
+  integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+string.prototype.trimend@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533"
+  integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+string.prototype.trimstart@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4"
+  integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.4"
+    es-abstract "^1.20.4"
+
+string_decoder@^1.0.0, string_decoder@^1.1.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+  integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+  dependencies:
+    safe-buffer "~5.2.0"
+
+string_decoder@~1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+  integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+  dependencies:
+    safe-buffer "~5.1.0"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+  integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==
+  dependencies:
+    ansi-regex "^3.0.0"
+
+strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+  integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+  dependencies:
+    ansi-regex "^4.1.0"
+
+strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
+strip-bom@3.0.0, strip-bom@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+  integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==
+  dependencies:
+    is-utf8 "^0.2.0"
+
+strip-eof@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+  integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
+
+strip-indent@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+  integrity sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==
+  dependencies:
+    get-stdin "^4.0.1"
+
+strip-indent@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
+  integrity sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==
+
+strip-indent@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+  integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+  dependencies:
+    min-indent "^1.0.0"
+
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+  integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+strong-log-transformer@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10"
+  integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==
+  dependencies:
+    duplexer "^0.1.1"
+    minimist "^1.2.0"
+    through "^2.3.4"
+
+style-loader@0.23.0:
+  version "0.23.0"
+  resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.0.tgz#8377fefab68416a2e05f1cabd8c3a3acfcce74f1"
+  integrity sha512-uCcN7XWHkqwGVt7skpInW6IGO1tG6ReyFQ1Cseh0VcN6VdcFQi62aG/2F3Y9ueA8x4IVlfaSUxpmQXQD9QrEuQ==
+  dependencies:
+    loader-utils "^1.1.0"
+    schema-utils "^0.4.5"
+
+stylis@4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
+  integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
+
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+  integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
+
+supports-color@^3.1.2:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+  integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==
+  dependencies:
+    has-flag "^1.0.0"
+
+supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^7.1.0:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+  integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+  dependencies:
+    has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+  integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+symbol-tree@^3.2.2:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+  integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
+tapable@^1.0.0, tapable@^1.1.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
+  integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+
+tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
+  version "4.4.19"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
+  integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==
+  dependencies:
+    chownr "^1.1.4"
+    fs-minipass "^1.2.7"
+    minipass "^2.9.0"
+    minizlib "^1.3.3"
+    mkdirp "^0.5.5"
+    safe-buffer "^5.2.1"
+    yallist "^3.1.1"
+
+temp-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
+  integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==
+
+temp-write@^3.4.0:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492"
+  integrity sha512-P8NK5aNqcGQBC37i/8pL/K9tFgx14CF2vdwluD/BA/dGWGD4T4E59TE7dAxPyb2wusts2FhMp36EiopBBsGJ2Q==
+  dependencies:
+    graceful-fs "^4.1.2"
+    is-stream "^1.1.0"
+    make-dir "^1.0.0"
+    pify "^3.0.0"
+    temp-dir "^1.0.0"
+    uuid "^3.0.1"
+
+terser-webpack-plugin@1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz#7545da9ae5f4f9ae6a0ac961eb46f5e7c845cc26"
+  integrity sha512-GGSt+gbT0oKcMDmPx4SRSfJPE1XaN3kQRWG4ghxKQw9cn5G9x6aCKSsgYdvyM0na9NJ4Drv0RG6jbBByZ5CMjw==
+  dependencies:
+    cacache "^11.0.2"
+    find-cache-dir "^2.0.0"
+    schema-utils "^1.0.0"
+    serialize-javascript "^1.4.0"
+    source-map "^0.6.1"
+    terser "^3.8.1"
+    webpack-sources "^1.1.0"
+    worker-farm "^1.5.2"
+
+terser-webpack-plugin@^1.1.0:
+  version "1.4.5"
+  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b"
+  integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==
+  dependencies:
+    cacache "^12.0.2"
+    find-cache-dir "^2.1.0"
+    is-wsl "^1.1.0"
+    schema-utils "^1.0.0"
+    serialize-javascript "^4.0.0"
+    source-map "^0.6.1"
+    terser "^4.1.2"
+    webpack-sources "^1.4.0"
+    worker-farm "^1.7.0"
+
+terser@^3.8.1:
+  version "3.17.0"
+  resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2"
+  integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==
+  dependencies:
+    commander "^2.19.0"
+    source-map "~0.6.1"
+    source-map-support "~0.5.10"
+
+terser@^4.1.2:
+  version "4.8.1"
+  resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f"
+  integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==
+  dependencies:
+    commander "^2.20.0"
+    source-map "~0.6.1"
+    source-map-support "~0.5.12"
+
+test-exclude@^4.2.1:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
+  integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
+  dependencies:
+    arrify "^1.0.1"
+    micromatch "^2.3.11"
+    object-assign "^4.1.0"
+    read-pkg-up "^1.0.1"
+    require-main-filename "^1.0.1"
+
+text-extensions@^1.0.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
+  integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
+
+text-table@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+  integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
+thenify-all@^1.0.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
+  integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
+  dependencies:
+    thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
+  integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
+  dependencies:
+    any-promise "^1.0.0"
+
+throat@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
+  integrity sha512-wCVxLDcFxw7ujDxaeJC6nfl2XfHJNYs8yUYJnvMgtPEFlttP9tHSfRUv2vBe6C4hkVFPWoP1P6ZccbYjmSEkKA==
+
+through2@^2.0.0, through2@^2.0.2:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+  integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+  dependencies:
+    readable-stream "~2.3.6"
+    xtend "~4.0.1"
+
+through2@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4"
+  integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==
+  dependencies:
+    inherits "^2.0.4"
+    readable-stream "2 || 3"
+
+through2@^4.0.0:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"
+  integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==
+  dependencies:
+    readable-stream "3"
+
+through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+  integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
+
+thunky@^1.0.2:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
+  integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
+
+timers-browserify@^2.0.4:
+  version "2.0.12"
+  resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee"
+  integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==
+  dependencies:
+    setimmediate "^1.0.4"
+
+tiny-invariant@^1.0.2:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
+  integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
+
+tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
+  integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
+tmp@^0.0.33:
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+  integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+  dependencies:
+    os-tmpdir "~1.0.2"
+
+tmpl@1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+  integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
+
+to-arraybuffer@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
+  integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==
+
+to-fast-properties@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+  integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==
+
+to-fast-properties@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+  integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
+
+to-object-path@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
+  integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==
+  dependencies:
+    kind-of "^3.0.2"
+
+to-regex-range@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
+  integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==
+  dependencies:
+    is-number "^3.0.0"
+    repeat-string "^1.6.1"
+
+to-regex-range@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+  integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+  dependencies:
+    is-number "^7.0.0"
+
+to-regex@^3.0.1, to-regex@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
+  integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
+  dependencies:
+    define-property "^2.0.2"
+    extend-shallow "^3.0.2"
+    regex-not "^1.0.2"
+    safe-regex "^1.1.0"
+
+toidentifier@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+  integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+toposort@^1.0.0:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
+  integrity sha512-FclLrw8b9bMWf4QlCJuHBEVhSRsqDj6u3nIjAzPeJvgl//1hBlffdlk0MALceL14+koWEdU4ofRAXofbODxQzg==
+
+tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.5.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+  integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+  dependencies:
+    psl "^1.1.28"
+    punycode "^2.1.1"
+
+tr46@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+  integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==
+  dependencies:
+    punycode "^2.1.0"
+
+tr46@~0.0.3:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+  integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
+
+trim-newlines@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+  integrity sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==
+
+trim-newlines@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
+  integrity sha512-MTBWv3jhVjTU7XR3IQHllbiJs8sc75a80OEhB6or/q7pLTWgQ0bMGQXXYQSrSuXe6WiKWDZ5txXY5P59a/coVA==
+
+trim-newlines@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
+  integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
+
+trim-right@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+  integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==
+
+ts-jest@23.10.5:
+  version "23.10.5"
+  resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-23.10.5.tgz#cdb550df4466a30489bf70ba867615799f388dd5"
+  integrity sha512-MRCs9qnGoyKgFc8adDEntAOP64fWK1vZKnOYU1o2HxaqjdJvGqmkLCPCnVq1/If4zkUmEjKPnCiUisTrlX2p2A==
+  dependencies:
+    bs-logger "0.x"
+    buffer-from "1.x"
+    fast-json-stable-stringify "2.x"
+    json5 "2.x"
+    make-error "1.x"
+    mkdirp "0.x"
+    resolve "1.x"
+    semver "^5.5"
+    yargs-parser "10.x"
+
+ts-loader@5.2.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.2.1.tgz#e6815c631dcafc24319ce8be6f8af94908749cf3"
+  integrity sha512-KC0cOvsFVyxBlg5h9jvaMlIL2tNsyQLvT2/OvIlO0AMUBJ4iXTtOfaDEqvmqv2lM/icekQfDsP2PsYBCDHpuOQ==
+  dependencies:
+    chalk "^2.3.0"
+    enhanced-resolve "^4.0.0"
+    loader-utils "^1.0.2"
+    micromatch "^3.1.4"
+    semver "^5.0.1"
+
+tsconfig-paths@^3.14.1:
+  version "3.14.2"
+  resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
+  integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
+  dependencies:
+    "@types/json5" "^0.0.29"
+    json5 "^1.0.2"
+    minimist "^1.2.6"
+    strip-bom "^3.0.0"
+
+tslib@1.9.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
+  integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==
+
+tslib@^1.0.0, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslint-config-airbnb-base@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/tslint-config-airbnb-base/-/tslint-config-airbnb-base-0.2.0.tgz#d3398daa62df820734f56dee801b79b69def4765"
+  integrity sha512-aYkkvnnaAioFEME6FaMSsKgZvU3hsTbnTuVa3I5y4/SK2CpPOIh1xo9daTBgxhvmpXuFApI1g4zgdUQwf0vyzQ==
+  dependencies:
+    tslint-consistent-codestyle "^1.13.2"
+    tslint-eslint-rules "^5.3.1"
+
+tslint-config-airbnb@5.11.1:
+  version "5.11.1"
+  resolved "https://registry.yarnpkg.com/tslint-config-airbnb/-/tslint-config-airbnb-5.11.1.tgz#51a27fbb8bf24c144d064a274a71da47e7ece617"
+  integrity sha512-hkaittm2607vVMe8eotANGN1CimD5tor7uoY3ypg2VTtEcDB/KGWYbJOz58t8LI4cWSyWtgqYQ5F0HwKxxhlkQ==
+  dependencies:
+    tslint-consistent-codestyle "^1.14.1"
+    tslint-eslint-rules "^5.4.0"
+    tslint-microsoft-contrib "~5.2.1"
+
+tslint-config-prettier@1.17.0:
+  version "1.17.0"
+  resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.17.0.tgz#946ed6117f98f3659a65848279156d87628c33dc"
+  integrity sha512-NKWNkThwqE4Snn4Cm6SZB7lV5RMDDFsBwz6fWUkTxOKGjMx8ycOHnjIbhn7dZd5XmssW3CwqUjlANR6EhP9YQw==
+
+tslint-consistent-codestyle@^1.13.2, tslint-consistent-codestyle@^1.14.1:
+  version "1.16.0"
+  resolved "https://registry.yarnpkg.com/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.16.0.tgz#52348ea899a7e025b37cc6545751c6a566a19077"
+  integrity sha512-ebR/xHyMEuU36hGNOgCfjGBNYxBPixf0yU1Yoo6s3BrpBRFccjPOmIVaVvQsWAUAMdmfzHOCihVkcaMfimqvHw==
+  dependencies:
+    "@fimbul/bifrost" "^0.21.0"
+    tslib "^1.7.1"
+    tsutils "^2.29.0"
+
+tslint-eslint-rules@4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.1.1.tgz#7c30e7882f26bc276bff91d2384975c69daf88ba"
+  integrity sha512-QS9o6vNZ2XwWxW+DE5uXde1dhQ2ebNuvebjfF/P4b9uACPdzxQCkaHjNU5GO+0UqPuOmZNR7mwsBaSlWQfCgVg==
+  dependencies:
+    doctrine "^0.7.2"
+    tslib "^1.0.0"
+    tsutils "^1.4.0"
+
+tslint-eslint-rules@^5.3.1, tslint-eslint-rules@^5.4.0:
+  version "5.4.0"
+  resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz#e488cc9181bf193fe5cd7bfca213a7695f1737b5"
+  integrity sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==
+  dependencies:
+    doctrine "0.7.2"
+    tslib "1.9.0"
+    tsutils "^3.0.0"
+
+tslint-microsoft-contrib@~5.2.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz#a6286839f800e2591d041ea2800c77487844ad81"
+  integrity sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==
+  dependencies:
+    tsutils "^2.27.2 <2.29.0"
+
+tslint-react-recommended@1.0.15:
+  version "1.0.15"
+  resolved "https://registry.yarnpkg.com/tslint-react-recommended/-/tslint-react-recommended-1.0.15.tgz#4166dc7d87b57280110673c99315a35ac5a76a7e"
+  integrity sha512-kEPJ+8D4Di30vqcU9ogFHXubyFvphM41EDb7ISnVuIhS0Zes8CntcgG9d9WDZvhPIjyd9pXvLOqc61RA450cpw==
+
+tslint-react@3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.6.0.tgz#7f462c95c4a0afaae82507f06517ff02942196a1"
+  integrity sha512-AIv1QcsSnj7e9pFir6cJ6vIncTqxfqeFF3Lzh8SuuBljueYzEAtByuB6zMaD27BL0xhMEqsZ9s5eHuCONydjBw==
+  dependencies:
+    tsutils "^2.13.1"
+
+tslint@5.12.1:
+  version "5.12.1"
+  resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.12.1.tgz#8cec9d454cf8a1de9b0a26d7bdbad6de362e52c1"
+  integrity sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==
+  dependencies:
+    babel-code-frame "^6.22.0"
+    builtin-modules "^1.1.1"
+    chalk "^2.3.0"
+    commander "^2.12.1"
+    diff "^3.2.0"
+    glob "^7.1.1"
+    js-yaml "^3.7.0"
+    minimatch "^3.0.4"
+    resolve "^1.3.2"
+    semver "^5.3.0"
+    tslib "^1.8.0"
+    tsutils "^2.27.2"
+
+tsutils@^1.4.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0"
+  integrity sha512-Z4MMpdLvxER0Wz+l9TM71URBKGoHKBzArEraOFmTp44jxzdqiG8oTCtpjiZ9YtFXNwWQfMv+g8VAxTlBEVS6yw==
+
+tsutils@^2.13.1, tsutils@^2.27.2, tsutils@^2.29.0:
+  version "2.29.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
+  integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
+  dependencies:
+    tslib "^1.8.1"
+
+"tsutils@^2.27.2 <2.29.0":
+  version "2.28.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.28.0.tgz#6bd71e160828f9d019b6f4e844742228f85169a1"
+  integrity sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==
+  dependencies:
+    tslib "^1.8.1"
+
+tsutils@^3.0.0, tsutils@^3.21.0, tsutils@^3.5.0:
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+  integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+  dependencies:
+    tslib "^1.8.1"
+
+tty-browserify@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+  integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==
+
+tunnel-agent@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+  integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
+  dependencies:
+    safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+  version "0.14.5"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+  integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
+
+type-check@^0.4.0, type-check@~0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+  integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+  dependencies:
+    prelude-ls "^1.2.1"
+
+type-check@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==
+  dependencies:
+    prelude-ls "~1.1.2"
+
+type-fest@^0.18.0:
+  version "0.18.1"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
+  integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
+
+type-fest@^0.20.2:
+  version "0.20.2"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+  integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+type-fest@^0.3.0:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"
+  integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==
+
+type-fest@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
+  integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
+
+type-fest@^0.8.1:
+  version "0.8.1"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+  integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+
+type-is@~1.6.18:
+  version "1.6.18"
+  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+  dependencies:
+    media-typer "0.3.0"
+    mime-types "~2.1.24"
+
+typed-array-length@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb"
+  integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
+  dependencies:
+    call-bind "^1.0.2"
+    for-each "^0.3.3"
+    is-typed-array "^1.1.9"
+
+typedarray@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+  integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
+
+typescript@4.1.4:
+  version "4.1.4"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.4.tgz#f058636e2f4f83f94ddaae07b20fd5e14598432f"
+  integrity sha512-+Uru0t8qIRgjuCpiSPpfGuhHecMllk5Zsazj5LZvVsEStEjmIRRBZe+jHjGQvsgS7M1wONy2PQXd67EMyV6acg==
+
+typings-for-css-modules-loader@1.7.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/typings-for-css-modules-loader/-/typings-for-css-modules-loader-1.7.0.tgz#a9b5c5a0e19b719d616edfc72855ab47dedd00ae"
+  integrity sha512-Mp7zDrcUmbUKl3JTLamTsMX+lntMotEm5I05j2RHB5EHb0WL1dAXlynpdlGR5Ye/QTvtL5w+RGB2jP32YoUpZw==
+  dependencies:
+    colour "0.7.1"
+    graceful-fs "4.1.4"
+    loader-utils "0.2.16"
+
+uglify-js@3.4.x:
+  version "3.4.10"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
+  integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==
+  dependencies:
+    commander "~2.19.0"
+    source-map "~0.6.1"
+
+uglify-js@^3.1.4:
+  version "3.17.4"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c"
+  integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==
+
+uid-number@0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+  integrity sha512-c461FXIljswCuscZn67xq9PpszkPT6RjheWFQTgCyabJrTUozElanb0YEqv2UGgk247YpcJkFBuSGNvBlpXM9w==
+
+umask@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
+  integrity sha512-lE/rxOhmiScJu9L6RTNVgB/zZbF+vGC0/p6D3xnkAePI2o0sMyFG966iR5Ki50OI/0mNi2yaRnxfLsPmEZF/JA==
+
+unbox-primitive@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+  integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+  dependencies:
+    call-bind "^1.0.2"
+    has-bigints "^1.0.2"
+    has-symbols "^1.0.3"
+    which-boxed-primitive "^1.0.2"
+
+unicode-canonical-property-names-ecmascript@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
+  integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==
+
+unicode-match-property-ecmascript@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
+  integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==
+  dependencies:
+    unicode-canonical-property-names-ecmascript "^2.0.0"
+    unicode-property-aliases-ecmascript "^2.0.0"
+
+unicode-match-property-value-ecmascript@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0"
+  integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==
+
+unicode-property-aliases-ecmascript@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
+  integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
+
+union-value@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
+  integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
+  dependencies:
+    arr-union "^3.1.0"
+    get-value "^2.0.6"
+    is-extendable "^0.1.1"
+    set-value "^2.0.1"
+
+union@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/union/-/union-0.5.0.tgz#b2c11be84f60538537b846edb9ba266ba0090075"
+  integrity sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==
+  dependencies:
+    qs "^6.4.0"
+
+unique-filename@^1.1.0, unique-filename@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
+  integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
+  dependencies:
+    unique-slug "^2.0.0"
+
+unique-slug@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
+  integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
+  dependencies:
+    imurmurhash "^0.1.4"
+
+universal-user-agent@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"
+  integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==
+  dependencies:
+    os-name "^3.1.0"
+
+universal-user-agent@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9"
+  integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==
+  dependencies:
+    os-name "^3.1.0"
+
+universal-user-agent@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
+  integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
+
+universalify@^0.1.0:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+  integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+unpipe@1.0.0, unpipe@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+  integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
+
+unset-value@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
+  integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==
+  dependencies:
+    has-value "^0.3.1"
+    isobject "^3.0.0"
+
+upath@^1.1.1, upath@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
+  integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
+
+update-browserslist-db@^1.0.10:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
+  integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
+  dependencies:
+    escalade "^3.1.1"
+    picocolors "^1.0.0"
+
+upper-case@^1.1.1:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
+  integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==
+
+uri-js@^4.2.2:
+  version "4.4.1"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+  integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+  dependencies:
+    punycode "^2.1.0"
+
+urix@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+  integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==
+
+url-join@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728"
+  integrity sha512-c2H1fIgpUdwFRIru9HFno5DT73Ok8hg5oOb5AT3ayIgvCRfxgs2jyt5Slw8kEB7j3QUr6yJmMPDT/odjk7jXow==
+
+url-loader@1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8"
+  integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==
+  dependencies:
+    loader-utils "^1.1.0"
+    mime "^2.0.3"
+    schema-utils "^1.0.0"
+
+url-parse@^1.4.3:
+  version "1.5.10"
+  resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
+  integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
+  dependencies:
+    querystringify "^2.1.1"
+    requires-port "^1.0.0"
+
+url@^0.11.0:
+  version "0.11.0"
+  resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+  integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==
+  dependencies:
+    punycode "1.3.2"
+    querystring "0.2.0"
+
+use@^3.1.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
+  integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
+
+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+  integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+util-promisify@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53"
+  integrity sha512-K+5eQPYs14b3+E+hmE2J6gCZ4JmMl9DbYS6BeP2CHq6WMuNxErxf5B/n0fz85L8zUuoO6rIzNNmIQDu/j+1OcA==
+  dependencies:
+    object.getownpropertydescriptors "^2.0.3"
+
+util.promisify@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+  integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
+  dependencies:
+    define-properties "^1.1.2"
+    object.getownpropertydescriptors "^2.0.3"
+
+util.promisify@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db"
+  integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.2.0"
+    for-each "^0.3.3"
+    has-proto "^1.0.1"
+    has-symbols "^1.0.3"
+    object.getownpropertydescriptors "^2.1.6"
+    safe-array-concat "^1.0.0"
+
+util@0.10.3:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+  integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==
+  dependencies:
+    inherits "2.0.1"
+
+util@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61"
+  integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==
+  dependencies:
+    inherits "2.0.3"
+
+utila@~0.4:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
+  integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==
+
+utils-merge@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+  integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
+
+uuid@^3.0.1, uuid@^3.3.2:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+  integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+
+v8-compile-cache@^2.0.2:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
+  integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+
+validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+  integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+  dependencies:
+    spdx-correct "^3.0.0"
+    spdx-expression-parse "^3.0.0"
+
+validate-npm-package-name@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
+  integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==
+  dependencies:
+    builtins "^1.0.3"
+
+value-equal@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
+  integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
+
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+  integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
+
+verror@1.10.0:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+  integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==
+  dependencies:
+    assert-plus "^1.0.0"
+    core-util-is "1.0.2"
+    extsprintf "^1.2.0"
+
+vm-browserify@^1.0.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
+  integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
+
+w3c-hr-time@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
+  integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
+  dependencies:
+    browser-process-hrtime "^1.0.0"
+
+walker@~1.0.5:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
+  integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
+  dependencies:
+    makeerror "1.0.12"
+
+watch@~0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
+  integrity sha512-oUcoHFG3UF2pBlHcMORAojsN09BfqSfWYWlR3eSSjUFR7eBEx53WT2HX/vZeVTTIVCGShcazb+t6IcBRCNXqvA==
+  dependencies:
+    exec-sh "^0.2.0"
+    minimist "^1.2.0"
+
+watchpack-chokidar2@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957"
+  integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==
+  dependencies:
+    chokidar "^2.1.8"
+
+watchpack@^1.5.0:
+  version "1.7.5"
+  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453"
+  integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==
+  dependencies:
+    graceful-fs "^4.1.2"
+    neo-async "^2.5.0"
+  optionalDependencies:
+    chokidar "^3.4.1"
+    watchpack-chokidar2 "^2.0.1"
+
+wbuf@^1.1.0, wbuf@^1.7.3:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
+  integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
+  dependencies:
+    minimalistic-assert "^1.0.0"
+
+wcwidth@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+  integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
+  dependencies:
+    defaults "^1.0.3"
+
+webidl-conversions@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+  integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+
+webidl-conversions@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+  integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+
+webpack-cli@3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.1.tgz#779c696c82482491f0803907508db2e276ed3b61"
+  integrity sha512-jeJveHwz/vwpJ3B8bxEL5a/rVKIpRNJDsKggfKnxuYeohNDW4Y/wB9N/XHJA093qZyS0r6mYL+/crLsIol4WKA==
+  dependencies:
+    chalk "^2.4.1"
+    cross-spawn "^6.0.5"
+    enhanced-resolve "^4.1.0"
+    findup-sync "^2.0.0"
+    global-modules "^1.0.0"
+    global-modules-path "^2.3.0"
+    import-local "^2.0.0"
+    interpret "^1.1.0"
+    lightercollective "^0.1.0"
+    loader-utils "^1.1.0"
+    supports-color "^5.5.0"
+    v8-compile-cache "^2.0.2"
+    yargs "^12.0.4"
+
+webpack-dev-middleware@3.4.0:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
+  integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==
+  dependencies:
+    memory-fs "~0.4.1"
+    mime "^2.3.1"
+    range-parser "^1.0.3"
+    webpack-log "^2.0.0"
+
+webpack-dev-server@3.1.14:
+  version "3.1.14"
+  resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz#60fb229b997fc5a0a1fc6237421030180959d469"
+  integrity sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==
+  dependencies:
+    ansi-html "0.0.7"
+    bonjour "^3.5.0"
+    chokidar "^2.0.0"
+    compression "^1.5.2"
+    connect-history-api-fallback "^1.3.0"
+    debug "^3.1.0"
+    del "^3.0.0"
+    express "^4.16.2"
+    html-entities "^1.2.0"
+    http-proxy-middleware "~0.18.0"
+    import-local "^2.0.0"
+    internal-ip "^3.0.1"
+    ip "^1.1.5"
+    killable "^1.0.0"
+    loglevel "^1.4.1"
+    opn "^5.1.0"
+    portfinder "^1.0.9"
+    schema-utils "^1.0.0"
+    selfsigned "^1.9.1"
+    semver "^5.6.0"
+    serve-index "^1.7.2"
+    sockjs "0.3.19"
+    sockjs-client "1.3.0"
+    spdy "^4.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^5.1.0"
+    url "^0.11.0"
+    webpack-dev-middleware "3.4.0"
+    webpack-log "^2.0.0"
+    yargs "12.0.2"
+
+webpack-log@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
+  integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
+  dependencies:
+    ansi-colors "^3.0.0"
+    uuid "^3.3.2"
+
+webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
+  integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
+  dependencies:
+    source-list-map "^2.0.0"
+    source-map "~0.6.1"
+
+webpack@4.28.4:
+  version "4.28.4"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.28.4.tgz#1ddae6c89887d7efb752adf0c3cd32b9b07eacd0"
+  integrity sha512-NxjD61WsK/a3JIdwWjtIpimmvE6UrRi3yG54/74Hk9rwNj5FPkA4DJCf1z4ByDWLkvZhTZE+P3C/eh6UD5lDcw==
+  dependencies:
+    "@webassemblyjs/ast" "1.7.11"
+    "@webassemblyjs/helper-module-context" "1.7.11"
+    "@webassemblyjs/wasm-edit" "1.7.11"
+    "@webassemblyjs/wasm-parser" "1.7.11"
+    acorn "^5.6.2"
+    acorn-dynamic-import "^3.0.0"
+    ajv "^6.1.0"
+    ajv-keywords "^3.1.0"
+    chrome-trace-event "^1.0.0"
+    enhanced-resolve "^4.1.0"
+    eslint-scope "^4.0.0"
+    json-parse-better-errors "^1.0.2"
+    loader-runner "^2.3.0"
+    loader-utils "^1.1.0"
+    memory-fs "~0.4.1"
+    micromatch "^3.1.8"
+    mkdirp "~0.5.0"
+    neo-async "^2.5.0"
+    node-libs-browser "^2.0.0"
+    schema-utils "^0.4.4"
+    tapable "^1.1.0"
+    terser-webpack-plugin "^1.1.0"
+    watchpack "^1.5.0"
+    webpack-sources "^1.3.0"
+
+websocket-driver@>=0.5.1:
+  version "0.7.4"
+  resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
+  integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+  dependencies:
+    http-parser-js ">=0.5.1"
+    safe-buffer ">=5.1.0"
+    websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
+  integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+
+whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+  integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+  dependencies:
+    iconv-lite "0.4.24"
+
+whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+  integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
+whatwg-url@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+  integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+  dependencies:
+    tr46 "~0.0.3"
+    webidl-conversions "^3.0.0"
+
+whatwg-url@^6.4.1:
+  version "6.5.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
+  integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
+  dependencies:
+    lodash.sortby "^4.7.0"
+    tr46 "^1.0.1"
+    webidl-conversions "^4.0.2"
+
+whatwg-url@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
+  integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+  dependencies:
+    lodash.sortby "^4.7.0"
+    tr46 "^1.0.1"
+    webidl-conversions "^4.0.2"
+
+which-boxed-primitive@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+  integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+  dependencies:
+    is-bigint "^1.0.1"
+    is-boolean-object "^1.1.0"
+    is-number-object "^1.0.4"
+    is-string "^1.0.5"
+    is-symbol "^1.0.3"
+
+which-module@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
+  integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
+
+which-typed-array@^1.1.9:
+  version "1.1.9"
+  resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
+  integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
+  dependencies:
+    available-typed-arrays "^1.0.5"
+    call-bind "^1.0.2"
+    for-each "^0.3.3"
+    gopd "^1.0.1"
+    has-tostringtag "^1.0.0"
+    is-typed-array "^1.1.10"
+
+which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+  integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+  dependencies:
+    isexe "^2.0.0"
+
+which@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+  integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+  dependencies:
+    isexe "^2.0.0"
+
+wide-align@^1.1.0:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
+  integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
+  dependencies:
+    string-width "^1.0.2 || 2 || 3 || 4"
+
+windows-release@^3.1.0:
+  version "3.3.3"
+  resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999"
+  integrity sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==
+  dependencies:
+    execa "^1.0.0"
+
+word-wrap@^1.2.3, word-wrap@~1.2.3:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+  integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+wordwrap@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+  integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
+
+wordwrap@~0.0.2:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+  integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==
+
+worker-farm@^1.5.2, worker-farm@^1.7.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
+  integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==
+  dependencies:
+    errno "~0.1.7"
+
+wrap-ansi@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+  integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+
+wrap-ansi@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
+  integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
+  dependencies:
+    ansi-styles "^3.2.0"
+    string-width "^3.0.0"
+    strip-ansi "^5.0.0"
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+  integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+write-file-atomic@^2.0.0, write-file-atomic@^2.1.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.2:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+  integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+  dependencies:
+    graceful-fs "^4.1.11"
+    imurmurhash "^0.1.4"
+    signal-exit "^3.0.2"
+
+write-json-file@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f"
+  integrity sha512-84+F0igFp2dPD6UpAQjOUX3CdKUOqUzn6oE9sDBNzUXINR5VceJ1rauZltqQB/bcYsx3EpKys4C7/PivKUAiWQ==
+  dependencies:
+    detect-indent "^5.0.0"
+    graceful-fs "^4.1.2"
+    make-dir "^1.0.0"
+    pify "^3.0.0"
+    sort-keys "^2.0.0"
+    write-file-atomic "^2.0.0"
+
+write-json-file@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a"
+  integrity sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==
+  dependencies:
+    detect-indent "^5.0.0"
+    graceful-fs "^4.1.15"
+    make-dir "^2.1.0"
+    pify "^4.0.1"
+    sort-keys "^2.0.0"
+    write-file-atomic "^2.4.2"
+
+write-pkg@^3.1.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.2.0.tgz#0e178fe97820d389a8928bc79535dbe68c2cff21"
+  integrity sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==
+  dependencies:
+    sort-keys "^2.0.0"
+    write-json-file "^2.2.0"
+
+ws@^5.2.0:
+  version "5.2.3"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d"
+  integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==
+  dependencies:
+    async-limiter "~1.0.0"
+
+x2js@*:
+  version "3.4.4"
+  resolved "https://registry.yarnpkg.com/x2js/-/x2js-3.4.4.tgz#42f8b82667dbfdf7c5375ca06d2a81c0ea8e4c00"
+  integrity sha512-yG/ThaBCgnsa3aoMPAe7QwDpcyU4D70hjXC4Y1lZSfD/Tgd0MpE19FnZZRAjekryw0c8cffpOt9zsPEiqktO6Q==
+  dependencies:
+    "@xmldom/xmldom" "^0.8.3"
+
+xml-name-validator@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+  integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
+
+xregexp@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
+  integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==
+
+xtend@^4.0.0, xtend@~4.0.1:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+  integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+y18n@^3.2.1:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
+  integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
+
+"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+  integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
+yallist@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+  integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==
+
+yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+  integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yallist@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+  integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yaml@^1.10.0:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
+  integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
+yargs-parser@10.x, yargs-parser@^10.1.0:
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
+  integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
+  dependencies:
+    camelcase "^4.1.0"
+
+yargs-parser@^11.1.1:
+  version "11.1.1"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
+  integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
+yargs-parser@^15.0.1:
+  version "15.0.3"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.3.tgz#316e263d5febe8b38eef61ac092b33dfcc9b1115"
+  integrity sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
+yargs-parser@^20.2.3:
+  version "20.2.9"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
+  integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
+
+yargs-parser@^9.0.2:
+  version "9.0.2"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
+  integrity sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==
+  dependencies:
+    camelcase "^4.1.0"
+
+yargs@12.0.2:
+  version "12.0.2"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
+  integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==
+  dependencies:
+    cliui "^4.0.0"
+    decamelize "^2.0.0"
+    find-up "^3.0.0"
+    get-caller-file "^1.0.1"
+    os-locale "^3.0.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1 || ^4.0.0"
+    yargs-parser "^10.1.0"
+
+yargs@^11.0.0:
+  version "11.1.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766"
+  integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==
+  dependencies:
+    cliui "^4.0.0"
+    decamelize "^1.1.1"
+    find-up "^2.1.0"
+    get-caller-file "^1.0.1"
+    os-locale "^3.1.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^9.0.2"
+
+yargs@^12.0.4:
+  version "12.0.5"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
+  integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
+  dependencies:
+    cliui "^4.0.0"
+    decamelize "^1.2.0"
+    find-up "^3.0.0"
+    get-caller-file "^1.0.1"
+    os-locale "^3.0.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1 || ^4.0.0"
+    yargs-parser "^11.1.1"
+
+yargs@^14.2.2:
+  version "14.2.3"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414"
+  integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==
+  dependencies:
+    cliui "^5.0.0"
+    decamelize "^1.2.0"
+    find-up "^3.0.0"
+    get-caller-file "^2.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^3.0.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^15.0.1"
+
+yocto-queue@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+  integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
diff --git a/sdnr/wt-odlux/pom.xml b/sdnr/wt-odlux/pom.xml
new file mode 100644
index 0000000..f418b1d
--- /dev/null
+++ b/sdnr/wt-odlux/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps.sdnr
+ * ================================================================================
+ * Copyright (C) 2018 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ -->
+<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>org.onap.ccsdk.features.sdnr.odlux</groupId>
+    <artifactId>sdnr-odlux</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>ccsdk-sdnr :: micro-services odlux only</name>
+    <description>SDN-R micro-services odlux only</description>
+
+    <modules>
+        <module>helpserver</module>
+        <module>odlux</module>
+    </modules>
+</project>
diff --git a/sdnr/wt-odlux/readthedocs/README.md b/sdnr/wt-odlux/readthedocs/README.md
new file mode 100644
index 0000000..14e79fd
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/README.md
@@ -0,0 +1,42 @@
+# SDNR/WT specific scripts to generate ReadTheDocs content
+
+This repository is creating a maven artifact with SDNR readthedocs documents.
+
+The repository is using the md and png files from "help app" input to create readthedocs structure with rst files. 
+Further files are added from src directory of this maven project.
+
+Script "convert.sh" is merging all information to "target/docs". 
+
+Build command: "mvn clean install"
+
+Result for test purpose is bundled in a zip artifact (version may vary):
+```
+    <groupId>org.onap.ccsdk.features.sdnr.wt.sulfur.sr1</groupId>
+    <artifactId>sdnr-wt-readthedocs-installer</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+```
+
+## 5GBerlin Test
+
+The artifact is only used for doing a local test of the readme system.
+
+## ONAP gerrit
+
+For synchronization with gerrit the output in target can be used: "target/docs".<br>
+The docs content has to be placed in ONAP/cssdk/features repository in docs content. 
+
+It is not a direct copy .. so only "target/docs" parts have to be copied over to "ONAP gerrit:cssdk/features/docs"
+
+ONAP/gerrit has its own propess of creating the ONAP Readthedocs.
+
+## Places
+
+
+### sdnr/wt/readthedocs
+ Scripts and source data for creation of documentation. 
+ 
+ Other sources are located in related implementation directory
+ 
+### docs 
+ destination of documentation files to be placed in a SDNC repository. 
+ Fully created by script. <- Stimmt nicht
diff --git a/sdnr/wt-odlux/readthedocs/convert.sh b/sdnr/wt-odlux/readthedocs/convert.sh
new file mode 100755
index 0000000..261c7ec
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/convert.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+# Source definition
+PATH_SOURCE_HELPSERVER="../helpserver/provider/src/main/resources/help"
+
+# Destination
+PATH_TARGET="./target"
+PATH_DOC_USERDOC_DST="$PATH_TARGET/docs/guides/onap-user"
+
+echo_sep() {
+  echo "== $1 ====================================="
+}
+
+# Main
+
+# Create PATH in dst
+echo_sep "create target"
+mkdir -p "$PATH_DOC_USERDOC_DST"
+
+# Convert src MD -> dst RST
+echo_sep "Converting md to rst files"
+markdown_files=$(find "$PATH_SOURCE_HELPSERVER/sdnr" -type f -iname "*.md")
+
+for file in ${markdown_files[@]}; do
+  append_name=`echo "$file" | awk -F"/" '{print $(NF-1)}'`
+  f="$(basename -- $file)"
+  if [ "${f,,}" = "readme.md" ]; then
+    rstfile="$append_name.rst"
+  else
+    rstfile="${f%.md}.rst"
+  fi
+
+  echo "$file to $PATH_DOC_USERDOC_DST/$rstfile"
+  pandoc -s --toc -f markdown -t rst $file > "$PATH_DOC_USERDOC_DST/$rstfile"
+done
+
+# Copy PNG to dst
+echo_sep "Copy PNG files from helpserver"
+png_files=$(find "$PATH_SOURCE_HELPSERVER/sdnr" -type f -iname "*.png")
+for file in ${png_files[@]}; do
+  f="$(basename -- $file)"
+  echo "$file to $f"
+  cp $file "$PATH_DOC_USERDOC_DST/$f"
+done
+
+# Copy src to dst
+echo_sep "Copy additional src files"
+cp -r ./src/docs "$PATH_TARGET"
+
+# Fix
+echo_sep "Fix src"
+# Fix abbreviations.rst
+FN1="$PATH_DOC_USERDOC_DST/abbreviations.rst"
+echo "Fix broken links: $FN1"
+sed -i 's/ < / <h/' $FN1 
+sed -i -E 's/\| http(.*) \|/\| ttp\1  \|/' $FN1
+sed -i -E 's/\|  <http(.*) \|/\| <http\1  \|/' $FN1
+# Fix end  
+
+echo_sep "================Done=========================================="
diff --git a/sdnr/wt-odlux/readthedocs/pom.xml b/sdnr/wt-odlux/readthedocs/pom.xml
new file mode 100644
index 0000000..22061df
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : ccsdk features
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" 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.ccsdk.parent</groupId>
+        <artifactId>odlparent-lite</artifactId>
+        <version>2.6.1</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+    <artifactId>sdnr-wt-readthedocs-installer</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>ccsdk-features :: ${project.artifactId}</name>
+
+    <properties>
+        <application.name>sdnr-wt-readthedocs-installer</application.name>
+        <include.transitive.dependencies>false</include.transitive.dependencies>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>exec-maven-plugin</artifactId>
+                <groupId>org.codehaus.mojo</groupId>
+                <executions>
+                    <execution><!-- Run our version calculation script -->
+                        <id>generate readthedocs files from helpserver markdowns</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <executable>convert.sh</executable>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>maven-repo-zip</id>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                            <attach>true</attach>
+                            <finalName>stage/${application.name}-${project.version}</finalName>
+                            <descriptors>
+                                <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+                            </descriptors>
+                            <appendAssemblyId>true</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>3.1.0</version>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <!-- here the phase you need -->
+                        <!-- <phase>validate</phase> -->
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}/assembly/docs/</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>target/docs/</directory>
+                                    <filtering>true</filtering>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt-odlux/readthedocs/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt-odlux/readthedocs/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 0000000..dfe5060
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,47 @@
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : ccsdk features
+  ~ ================================================================================
+  ~ Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ 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.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+    <id>repo</id>
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <!--  we want "system" and related files right at the root level
+          as this file is suppose to be unzip on top of a karaf
+          distro. -->
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>target/assembly/</directory>
+            <outputDirectory>.</outputDirectory>
+            <excludes>
+            </excludes>
+        </fileSet>
+    </fileSets>
+
+</assembly>
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/conf.py b/sdnr/wt-odlux/readthedocs/src/docs/conf.py
new file mode 100755
index 0000000..01f49c1
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/conf.py
@@ -0,0 +1,496 @@
+# -*- coding: utf-8 -*-
+#
+# ONAP documentation build configuration file, created by
+# sphinx-quickstart on Wed Jul 19 16:25:31 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+import shlex
+#import sphinx_bootstrap_theme
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.5.3'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.doctest',
+    'sphinx.ext.graphviz',
+    'sphinx.ext.todo',
+    'sphinx.ext.imgmath',
+    'sphinx.ext.viewcode',
+    'sphinxcontrib.blockdiag',
+    'sphinxcontrib.needs',
+    'sphinxcontrib.nwdiag',
+    'sphinxcontrib.seqdiag',
+    'sphinx.ext.ifconfig',
+    'sphinx.ext.todo',
+    'sphinxcontrib.plantuml',
+    'sphinxcontrib.swaggerdoc'
+]
+
+# Font path for seqdiag
+seqdiag_fontpath = '/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf'
+nwdiag_fontpath =  '/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u''
+copyright = u'2019 ONAP. Licensed under Creative Commons Attribution 4.0 International License'
+
+
+author = u'Open Network Automation Platform'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+# The short X.Y version.
+version = 'master branch'
+# The full version, including alpha/beta/rc tags.
+release = 'master branch'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = [
+	'_build'
+	]
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#html_theme = 'classic'
+html_theme = 'sphinx_rtd_theme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+html_theme_options = {
+	'style_nav_header_background': 'white',
+	'sticky_navigation': False
+	}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = '_static/logo_onap_2017.png'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+html_favicon = '_static/favicon.ico'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%d-%b-%y %H:%M'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+html_show_sphinx = False
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'ONAPdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+  (master_doc, 'ONAP.tex', u'ONAP Documentation',
+   u'ONAP Contributors', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'onap', u'ONAP Documentation',
+     [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  (master_doc, 'ONAP', u'ONAP Documentation',
+   author, 'ONAP', 'Open Network Automation Platform',
+   'Platform'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The basename for the epub file. It defaults to the project name.
+#epub_basename = project
+
+# The HTML theme for the epub output. Since the default themes are not optimized
+# for small screen space, using the same theme for HTML and epub output is
+# usually not wise. This defaults to 'epub', a theme designed to save visual
+# space.
+#epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or 'en' if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#epub_tocscope = 'default'
+
+# Fix unsupported image types using the Pillow.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#epub_use_index = True
+
+# Patterns to ignore in linkcheck builder
+linkcheck_ignore = [
+	r'http://$',
+	r'http:/$',
+	r'http://10\.',
+	r'http://127\.',
+	r'http://172\.[123]',
+	r'http://app_host:port/',
+	r'http://app-host:port/',
+	r'http://ESR_SERVICE_IP',
+	r'http://ESR_SERVER_IP',
+	r'http://hostIP:\d+/',
+	r'http://load-balanced-address:\d+/',
+	r'http://localhost',
+	r'http://\$msb_address/',
+	r'http://\$MSB_SERVER_IP:\d+/',
+	r'http://msb_docker_host_ip:\d+/',
+	r'http://MSB_IP:MSB_PORT/',
+	r'http://msb.onap.org',
+	r'http://MSB_SERVER_IP:\d+/',
+	r'http://org.openecomp.',
+	r'http://{PDP_URL}:\d+/',
+	r'http://servername.domain.com',
+	r'http://.*simpledemo.openecomp.org',
+	r'http://.*simpledemo.onap.org',
+	r'http://.*test.att.com:\d+/',
+	r'http://we-are-data-router.us',
+	r'http://we-are-message-router.us:\d+/'
+	r'http://www.\[host\]:\[port\]/',
+	r'http://yourhostname',
+	r'https://$',
+	r'https:/$',
+	r'https://10\.',
+	r'https://127\.',
+	r'https://172\.[123]',
+	r'https://aaf.onap.org',
+	r'https://\$CBAM_IP',
+	r'https://ESR_SERVICE_IP',
+	r'https://ESR_SERVER_IP',
+	r'https://msb.onap.org',
+	r'https://my-subscriber-app.dcae',
+	r'https://\$CBAM_IP:\d+/',
+	r'https://load-balanced-address:\d+/',
+	r'https://prov.datarouternew.com:8443',
+	r'https://.*simpledemo.openecomp.org',
+	r'https://.*simpledemo.onap.org',
+	r'https://.*test.att.com:\d+/',
+	r'https://we-are-data-router.us',
+	r'https://we-are-message-router.us:\d+/'
+	]
+
+from docutils.parsers.rst import directives
+
+needs_extra_options = {
+    "target": directives.unchanged,
+    "keyword": directives.unchanged,
+    "introduced": directives.unchanged,
+    "updated": directives.unchanged,
+    "impacts": directives.unchanged,
+    "validation_mode": directives.unchanged,
+    "validated_by": directives.unchanged,
+    "test": directives.unchanged,
+    "test_case": directives.unchanged,
+    "test_file": directives.unchanged,
+    "notes": directives.unchanged,
+}
+
+needs_id_regex = "^[A-Z0-9]+-[A-Z0-9]+"
+needs_id_required = True
+needs_title_optional = True
+
+needs_template_collapse = """
+.. _{{id}}:
+
+{% if hide == false -%}
+.. role:: needs_tag
+.. role:: needs_status
+.. role:: needs_type
+.. role:: needs_id
+.. role:: needs_title
+
+.. rst-class:: need
+.. rst-class:: need_{{type_name}}
+
+.. container:: need
+
+    `{{id}}` - {{content|indent(4)}}
+
+    .. container:: toggle
+
+        .. container:: header
+
+            Details
+
+{% if status and  status|upper != "NONE" and not hide_status %}        | status: :needs_status:`{{status}}`{% endif %}
+{% if tags and not hide_tags %}        | tags: :needs_tag:`{{tags|join("` :needs_tag:`")}}`{% endif %}
+{% if keyword %}        | keyword: `{{keyword}}` {% endif %}
+{% if target %}        | target: `{{target}}` {% endif %}
+{% if introduced %}        | introduced: `{{introduced}}` {% endif %}
+{% if updated %}        | updated: `{{updated}}` {% endif %}
+{% if impacts %}        | impacts: `{{impacts}}` {% endif %}
+{% if validation_mode %}        | validation mode: `{{validation_mode}}` {% endif %}
+{% if validated_by %}        | validated by: `{{validated_by}}` {% endif %}
+{% if test %}        | test: `{{test}}` {% endif %}
+{% if test_case %}        | test case: {{test_case}} {% endif %}
+{% if test_file %}        | test file: `{{test_file}}` {% endif %}
+{% if notes %}        | notes: `{{notes}}` {% endif %}
+        | children: :need_incoming:`{{id}}`
+        | parents: :need_outgoing:`{{id}}`
+{% endif -%}
+"""
+
+def setup(app):
+    app.add_css_file("css/ribbon.css")
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/conf.pyc b/sdnr/wt-odlux/readthedocs/src/docs/conf.pyc
new file mode 100644
index 0000000..5fbd07b
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/conf.pyc
Binary files differ
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/applications.rst b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/applications.rst
new file mode 100644
index 0000000..2c0c9c6
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/applications.rst
@@ -0,0 +1,18 @@
+Applications
+============
+Below are the UX Applications.
+
+
+.. toctree::
+   :maxdepth: 1
+
+   connect
+   pnfFault
+   pnfMaintenance
+   pnfConfig
+   pnfPerformance
+   pnfInventory
+   pnfEventLog
+   pnfMediator
+   networkMap
+   linkCalculator
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/home.rst b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/home.rst
new file mode 100644
index 0000000..217e565
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/home.rst
@@ -0,0 +1,32 @@
+
+.. contents::
+   :depth: 3
+..
+
+SDN controller for 'Radio' (SDN-R)
+==================================
+
+SDN-R adds features and functionality to the OpenDaylight-based ONAP
+controller 'SDN-C'. It is built on the Common Controller Framework to
+control and manage wireless resources. Wireless resources are virtual
+network functions (e.g. vBBU, vEPC) or physical network functions (e.g.
+microwave and millimeter wave radios, eNodeB, RRH, DAS equipment).
+
+| SDN-R is integrated into ONAP. Therefore it is interfacing with PNFs
+  and VNFs and with other ONAP components, such as A&AI, DCAE and SO.
+| `See abbreviations <abbreviations.html>`__
+
+.. figure:: ./ONAP-SDN-R.png
+   :alt: SDN-R in ONAP
+
+   SDN-R in ONAP
+
+
+.. toctree::
+   :maxdepth: 1
+
+   general
+   applications
+   installation
+   faq
+   abbreviations
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/installation.rst b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/installation.rst
new file mode 100644
index 0000000..7fe4daf
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/installation.rst
@@ -0,0 +1,14 @@
+Installation
+============
+
+Below is the installation procedure for SDN-R Images and Configuration parameters
+
+
+.. toctree::
+   :maxdepth: 1
+
+   sdnr_WT_Service_Configuration_parameters
+   sdnr_Docker_Image_configuration
+
+
+
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/sdnr_Docker_Image_configuration.rst b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/sdnr_Docker_Image_configuration.rst
new file mode 100644
index 0000000..5297a09
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/sdnr_Docker_Image_configuration.rst
@@ -0,0 +1,52 @@
+.. contents::
+   :depth: 3
+..
+
+SDN-R Docker Image configuration
+================================
+
+Introduction
+~~~~~~~~~~~~
+
+ONAP SDN-R is running in a docker container using ONAP/SDN-C image
+"onap/sdnc".
+
+The container is available as Alpine and Ubuntu version. The description
+uses examples for the Alpine version.
+
+The alpine based sdnc docker imanges are stored in \ `ONAP Nexus sdnc
+image <https://nexus3.onap.org:10001/v2/onap/sdnc-image/tags/list>`__.
+
+The docker image contains a Opendaylight distribution in a standard
+configuration and ONAP/SDN-R specific microservices.
+
+The Root location of ODL Karaf directory structure
+is \ *ODL\_HOME=/opt/opendaylight.*
+
+During container provisioning the installation of the feature is done,
+according to the provided configuration setting.
+
+The docker image configuration is done by
+
+-  Specific Environment variables settings
+
+-  Files that are provided
+
+Container startup parameters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The SDN-R specific configurations are provided during container start. 
+
+Different SDN-R services are using different parameter to be installed.
+
++------------------+---------------------+-------------------------------------------------------------------------------------------------------------------------+
+| **Parameter**    | **Content**         | **Description**                                                                                                         |
++==================+=====================+=========================================================================================================================+
+| SDNRWT           | true\|\ **false**   | Set true to activate sdnr wt featureset. Set this during container start.                                               |
+|                  |                     |                                                                                                                         |
+|                  |                     | Devicemanager configuration is provided via *$ODL\_HOME/etc/devicemanager.properties*                                   |
+|                  |                     |                                                                                                                         |
+|                  |                     | See  `SDN-R WT Service Configuration parameters <sdnr_WT_Service_Configuration_parameters.html>`__			   |
++------------------+---------------------+-------------------------------------------------------------------------------------------------------------------------+
+| SDNRNORTHBOUND   | true\|\ **false**   | Set true to activate sdnr oofpci service.                                                                               |
++------------------+---------------------+-------------------------------------------------------------------------------------------------------------------------+
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/sdnr_WT_Service_Configuration_parameters.rst b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/sdnr_WT_Service_Configuration_parameters.rst
new file mode 100644
index 0000000..a27e511
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/guides/onap-user/sdnr_WT_Service_Configuration_parameters.rst
@@ -0,0 +1,118 @@
+.. contents::
+   :depth: 3
+..
+
+SDN-R WT Service Configuration parameters
+=========================================
+
+ODL is operated as a cluster. The configuration settings must be the
+same for each cluster node.
+
+-  `Sections <#SDN-RWTServiceConfigurationparameters-S>`__
+
+   -  `toggleAlarmFilter <#SDN-RWTServiceConfigurationparameters-t>`__
+   -  `devicemonitor <#SDN-RWTServiceConfigurationparameters-d>`__
+
+Backgrounds regarding the container inter structure is described
+in \ `SDN-R Docker Image configuration <sdnr_Docker_Image_configuration.html>`__.
+
+The configuration information of sdnr wireless transport parameters are
+in a single file.
+
+For different devicemanager services, like DeviceMonitor there  are
+individual sections in the configuration file available.
+
+Configuration file location: 
+***$ODL\_HOME/etc/devicemanager.properties***
+
+If SDN-R WT is starting
+
+-  and the file exists, the configuration is used. 
+-  if it does not exist it will be created with the default parameters.
+
+Below an example of the content.
+
+- Example 
+  ::
+
+    [toggleAlarmFilter]
+    taEnabled=true
+    taDelay=3000
+ 
+    [es]
+    esCluster=sdnr
+    esArchiveCheckIntervalSeconds=0
+    esArchiveLifetimeSeconds=2592000
+
+    [dcae]
+    dcaeUrl=off
+    dcaeUserCredentials=admin:admin
+    dcaeHeartbeatPeriodSeconds=120
+
+    [aai]
+    aaiUrl=off
+    aaiUserCredentials=
+    aaiHeaders=["X-TransactionId: 9999"]
+    aaiDeleteOnMountpointRemove=false
+    aaiTrustAllCerts=false
+    aaiPropertiesFile=
+    aaiApiVersion=aai/v13
+    aaiApplicationId=SDNR
+    aaiClientConnectionTimeout=30000
+    aaiPcks12ClientCertFile=
+    aaiPcks12ClientCertPassphrase=
+
+    [pm]
+    pmEnabled=true
+    pmCluster=sdnr
+
+    [devicemonitor]
+    SeverityconnectionLossOAM=Major
+    SeverityconnectionLossMediator=Major
+    SeverityconnectionLossNeOAM=Major
+
+Sections
+--------
+
+toggleAlarmFilter
+~~~~~~~~~~~~~~~~~
+
+Configure toggle alarm filter.
+
+taEnabled=true taDelay=3000
+
++-----------------+---------------+---------------+----------------+------------------------------------------------------+
+| **Parameter**   | **Values**    | **Default**   | **Unit**       | **Description**                                      |
++=================+===============+===============+================+======================================================+
+| taEnabled       | true, false   | false         |                | Enable or disable this service                       |
++-----------------+---------------+---------------+----------------+------------------------------------------------------+
+| taDelay         | number        |               | milliseconds   | Integration time to take over the new alarm status   |
++-----------------+---------------+---------------+----------------+------------------------------------------------------+
+
+devicemonitor
+~~~~~~~~~~~~~
+
+Configure alarm severity of related alarms, generated by Device Monitor.
+
+`SDNC-616 <https://jira.onap.org/browse/SDNC-616>`__ - SDN-R WT app need to change alarm severity "Configurable" for ConnectionLossxxx alarm family (received from Mediator) , when it passed to DCAE VES collector.
+
+
+Syntax: Parameter=Value
+
+Example: SeverityconnectionLossOAM=Major
+
++----------------------------------+-----------------------------------------------+---------------+------------+--------------------------------------------------------------+
+|                                  | **Values**                                    | **Default**   | **Unit**   | **Description**                                              |
++==================================+===============================================+===============+============+==============================================================+
+| SeverityconnectionLossOAM        | NonAlarmed, Warning, Minor, Major, Critical   | Major         |            | SDN-Controller <> Mediator                                   |
+|                                  |                                               |               |            |                                                              |
+|                                  |                                               |               |            | Mountpoint monitoring. Indicates a not connected mounpoint   |
++----------------------------------+-----------------------------------------------+---------------+------------+--------------------------------------------------------------+
+| SeverityconnectionLossMediator   | NonAlarmed, Warning, Minor, Major, Critical   | Major         |            | SDN-Controller <> NetworkElement                             |
+|                                  |                                               |               |            |                                                              |
+|                                  |                                               |               |            | Device monitoring. No LTPs provided                          |
++----------------------------------+-----------------------------------------------+---------------+------------+--------------------------------------------------------------+
+| SeverityconnectionLossNeOAM      | NonAlarmed, Warning, Minor, Major, Critical   | Major         |            | SDN-Controller <> NetworkElement                             |
+|                                  |                                               |               |            |                                                              |
+|                                  |                                               |               |            | Device monitoring. SSH Connetion, Core model not answering   |
++----------------------------------+-----------------------------------------------+---------------+------------+--------------------------------------------------------------+
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/index.rst b/sdnr/wt-odlux/readthedocs/src/docs/index.rst
new file mode 100644
index 0000000..1da5c6c
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/index.rst
@@ -0,0 +1,12 @@
+=================
+SDN-R Online help
+=================
+
+Below are the references for SDN-R User Documentation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+.. toctree::
+   :maxdepth: 1
+
+   guides/onap-user/home
diff --git a/sdnr/wt-odlux/readthedocs/src/docs/requirements.txt b/sdnr/wt-odlux/readthedocs/src/docs/requirements.txt
new file mode 100644
index 0000000..203f061
--- /dev/null
+++ b/sdnr/wt-odlux/readthedocs/src/docs/requirements.txt
@@ -0,0 +1,6 @@
+lfdocs-conf
+sphinx>=4.2.0  # BSD
+sphinx-rtd-theme>=1.0.0  # MIT
+autopep8
+sphinxcontrib-spelling
+pylint
\ No newline at end of file