Add sdnr wt odlux

Add complete sdnr wireless transport app odlux core and apps

Change-Id: I5dcbfb8f3b790e3bda7c8df67bd69d81958f65e5
Issue-ID: SDNC-576
Signed-off-by: Herbert Eiselt <herbert.eiselt@highstreet-technologies.com>
diff --git a/sdnr/wt/odlux/apps/apiDemo/.babelrc b/sdnr/wt/odlux/apps/apiDemo/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/apiDemo/package.json b/sdnr/wt/odlux/apps/apiDemo/package.json
new file mode 100644
index 0000000..8d88a60
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/package.json
@@ -0,0 +1,40 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*"
+   },
+  "peerDependencies": {
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/pom.xml b/sdnr/wt/odlux/apps/apiDemo/pom.xml
new file mode 100644
index 0000000..ffa83b7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-apiDemo</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-apiDemo</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts b/sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts
new file mode 100644
index 0000000..206ce8a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts
@@ -0,0 +1,8 @@
+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/apps/apiDemo/src/handlers/apiDemoRootHandler.ts b/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
new file mode 100644
index 0000000..ec41876
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
@@ -0,0 +1,23 @@
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+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/apps/apiDemo/src/handlers/modulesHandler.ts b/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
new file mode 100644
index 0000000..2b6c019
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
@@ -0,0 +1,16 @@
+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/apps/apiDemo/src/index.html b/sdnr/wt/odlux/apps/apiDemo/src/index.html
new file mode 100644
index 0000000..c01df6b
--- /dev/null
+++ b/sdnr/wt/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/apps/apiDemo/src/models/module.ts b/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
new file mode 100644
index 0000000..aab8db3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
@@ -0,0 +1,11 @@
+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/apps/apiDemo/src/plugin.tsx b/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
new file mode 100644
index 0000000..8491760
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
@@ -0,0 +1,36 @@
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faNewspaper } from '@fortawesome/free-solid-svg-icons';
+
+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 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/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..0877578
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="apiDemo"/>
+        <property name="index" value="999"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/tsconfig.json b/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/apiDemo/webpack.config.js b/sdnr/wt/odlux/apps/apiDemo/webpack.config.js
new file mode 100644
index 0000000..1c699e1
--- /dev/null
+++ b/sdnr/wt/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/apps/app-feature/pom.xml b/sdnr/wt/odlux/apps/app-feature/pom.xml
new file mode 100644
index 0000000..aadee55
--- /dev/null
+++ b/sdnr/wt/odlux/apps/app-feature/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- * ============LICENSE_START======================================================= 
+	* ONAP : CCSDK.feature.sdnr.wt * ================================================================================ 
+	* 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.wt</groupId>
+	<artifactId>sdnr-wt-odlux-apps-feature</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>feature</packaging>
+	<name>ccsdk-features-sdnr-wt :: ${project.artifactId} :: feature</name>
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>single-feature-parent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-connectApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-faultApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-helpApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-inventoryApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/sdnr/wt/odlux/apps/app-installer/pom.xml b/sdnr/wt/odlux/apps/app-installer/pom.xml
new file mode 100755
index 0000000..999082f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/app-installer/pom.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-apps-installer</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>pom</packaging>
+	<name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name>
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent-lite</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+
+	<properties>
+		<application.name>sdnr-wt-odlux-apps</application.name>
+		<include.transitive.dependencies>false</include.transitive.dependencies>
+	</properties>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+			<artifactId>${application.name}-feature</artifactId>
+			<version>${project.version}</version>
+			<type>xml</type>
+			<classifier>features</classifier>
+			<exclusions>
+				<exclusion>
+					<groupId>*</groupId>
+					<artifactId>*</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-apiDemo</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-connectApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-demoApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-faultApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-helpApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-inventoryApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-minimumApp</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-app-mediatorApp</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/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 0000000..c4eb9aa
--- /dev/null
+++ b/sdnr/wt/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP : CCSDK
+  ================================================================================
+  Copyright (C) 2017 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="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	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/apps/connectApp/.babelrc b/sdnr/wt/odlux/apps/connectApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json
new file mode 100644
index 0000000..29e1cb9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/package.json
@@ -0,0 +1,40 @@
+{
+  "name": "@odlux/connect-app",
+  "version": "0.1.1",
+  "description": "A react based modular UI to display network 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": "MIT",
+  "dependencies": {
+    "@odlux/framework" : "*"
+  },
+  "peerDependencies": {
+     "@types/react": "16.4.14",
+     "@types/react-dom": "16.0.8",
+     "@types/react-router-dom": "4.3.1",
+     "@material-ui/core": "3.8.3",
+     "@material-ui/icons": "3.0.2",
+     "@types/classnames": "2.2.6",
+     "@types/flux": "3.1.8",
+     "@types/jquery": "3.3.10",
+     "jquery": "3.3.1",
+     "react": "16.5.2",
+     "react-dom": "16.5.2",
+     "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml
new file mode 100644
index 0000000..b1cabdb
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-connectApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-connectApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
new file mode 100644
index 0000000..e342f63
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
@@ -0,0 +1,90 @@
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { MountedNetworkElementType } from '../models/mountedNetworkElements';
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+
+import { connectService } from '../services/connectService';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an action causing the store to load all mounted network elements. */
+export class LoadAllMountedNetworkElementsAction extends BaseAction { }
+
+/** Represents an action causing the store to update all mounted network elements. */
+export class AllMountedNetworkElementsLoadedAction extends BaseAction {
+  constructor(public mountedNetworkElements: MountedNetworkElementType[] | null, public error?: string) {
+    super();
+  }
+}
+
+/** Represents an action causing the store to update all mounted network elements. */
+export class AddMountedNetworkElement extends BaseAction {
+  constructor(public mountedNetworkElement: MountedNetworkElementType | null, public error?: string) {
+    super();
+  }
+}
+
+export class RemoveMountedNetworkElement extends BaseAction {
+  constructor(public mountId: string) {
+    super();
+  }
+}
+
+export class UpdateConnectionStateMountedNetworkElement extends BaseAction {
+  constructor(public mountId: string, connectionState: string) {
+    super();
+  }
+}
+
+
+export class UpdateRequiredMountedNetworkElement extends BaseAction {
+  constructor(public mountId: string, public required: boolean) {
+    super();
+  }
+}
+
+/**
+ *  An actioncrator for a async thunk action to add an allready mounted element to the state of this app. 
+ *  Note: Use this action to add created object notified by the websocket. 
+*/
+export const addMountedNetworkElementAsyncActionCreator = (mountId: string) => async (dispatch: Dispatch) => {
+  connectService.getMountedNetworkElementByMountId(mountId).then(mountedNetworkElement => {
+    mountedNetworkElement && dispatch(new AddMountedNetworkElement(mountedNetworkElement));
+  }).catch(error => {
+    dispatch(new AddMountedNetworkElement(null, error));
+  });
+};
+
+/** Represents an async thunk action to load all mounted network elements. */
+export const loadAllMountedNetworkElementsAsync = (dispatch: Dispatch) => {
+  dispatch(new LoadAllMountedNetworkElementsAction());
+    connectService.getMountedNetworkElementsList().then(mountedNetworkElements => { 
+      mountedNetworkElements && dispatch(new AllMountedNetworkElementsLoadedAction(mountedNetworkElements));
+  }).catch(error => {
+    dispatch(new AllMountedNetworkElementsLoadedAction(null, error));
+  });
+};
+
+/** Represents an async thunk action to load all mounted network elements. */
+export const mountNetworkElementActionCreatorAsync = (networkElement: RequiredNetworkElementType) => (dispatch: Dispatch) => {
+  connectService.mountNetworkElement(networkElement).then((success) => {
+    success && dispatch(new AddSnackbarNotification({ message: `Requesting mount [${ networkElement.mountId }]`, options: { variant: 'info' } }))
+      || dispatch(new AddSnackbarNotification({ message: `Failed to mount [${ networkElement.mountId }]`, options: { variant: 'warning' } }));
+  }).catch(error => {
+    dispatch(new AddMountedNetworkElement(null, error));
+  });
+};
+
+export const unmountNetworkElementActionCreatorAsync = (mountId: string) => (dispatch: Dispatch) => {
+  connectService.unmountNetworkElement(mountId).then((success) => {
+    success && dispatch(new AddSnackbarNotification({ message: `Requesting unmount [${ mountId }]`, options: { variant: 'info' } }))
+      || dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${ mountId }]`, options: { variant: 'warning' } }));
+  }).catch(error => {
+    dispatch(new AddMountedNetworkElement(null, error));
+  });
+};
+
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/requiredNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/requiredNetworkElementsActions.ts
new file mode 100644
index 0000000..9793219
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/requiredNetworkElementsActions.ts
@@ -0,0 +1,38 @@
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+import { requiredNetworkElementsReloadAction } from '../handlers/requiredNetworkElementsHandler';
+import { UpdateRequiredMountedNetworkElement } from '../actions/mountedNetworkElementsActions';
+
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+
+import { connectService } from '../services/connectService';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+
+/** Represents an async thunk action that will add an element to the required network elements. */
+export const addToRequiredNetworkElementsAsyncActionCreator = (element: RequiredNetworkElementType) => (dispatch: Dispatch) => {
+  connectService.insertRequiredNetworkElement(element).then(_ => {
+    window.setTimeout(() => {
+      dispatch(requiredNetworkElementsReloadAction);
+      dispatch(new UpdateRequiredMountedNetworkElement(element.mountId, true));
+      dispatch(new AddSnackbarNotification({ message: `Successfully added [${ element.mountId }]`, options: { variant: 'success' } }));
+    }, 900);
+  });
+};
+
+/** Represents an async thunk action that will delete an element from the required network elements. */
+export const removeFromRequiredNetworkElementsAsyncActionCreator = (element: RequiredNetworkElementType) => (dispatch: Dispatch) => {
+  connectService.deleteRequiredNetworkElement(element).then(_ => {
+    window.setTimeout(() => {
+      dispatch(requiredNetworkElementsReloadAction);
+      dispatch(new UpdateRequiredMountedNetworkElement(element.mountId, false));
+      dispatch(new AddSnackbarNotification({ message: `Successfully removed [${ element.mountId }]`, options: { variant: 'success' } }));
+    }, 900);
+  });
+};
+
+
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
new file mode 100644
index 0000000..b4b08fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
@@ -0,0 +1,36 @@
+import * as React from 'react';
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+
+import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler';
+import { ConnectionStatusLogType } from '../models/connectionStatusLog';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  connectionStatusLogProperties: createConnectionStatusLogProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+    connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch),
+});
+  
+const ConnectionStatusTable = MaterialTable as MaterialTableCtorType<ConnectionStatusLogType>;
+
+type ConnectionStatusLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>;
+
+class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps> {
+  render(): JSX.Element {
+    return (
+      <ConnectionStatusTable columns={ [
+        { property: "timeStamp", title: "Time", type: ColumnType.text },
+        { property: "objectId", title: "Name", type: ColumnType.text },
+        { property: "elementStatus", title: "Connection status", type: ColumnType.text, disableFilter: true, disableSorting: true },
+      ] } idProperty="_id" { ...this.props.connectionStatusLogActions } {...this.props.connectionStatusLogProperties } >
+      </ConnectionStatusTable>
+    );
+  };
+
+}
+
+export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent);
+export default ConnectionStatusLog;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
new file mode 100644
index 0000000..ee876e8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -0,0 +1,228 @@
+import * as React from 'react';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import {
+  addToRequiredNetworkElementsAsyncActionCreator,
+  removeFromRequiredNetworkElementsAsyncActionCreator
+} from '../actions/requiredNetworkElementsActions';
+
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+import { unmountNetworkElementActionCreatorAsync, mountNetworkElementActionCreatorAsync } from '../actions/mountedNetworkElementsActions';
+export enum EditNetworkElementDialogMode {
+  None = "none",
+  UnknownNetworkElementToRequiredNetworkElements = "unknownNetworkElementToRequiredNetworkElements",
+  RequiredNetworkElementToUnknownNetworkElements = "requiredNetworkElementToUnknownNetworkElements",
+  MountNetworkElementToRequiredNetworkElements = "mountNetworkElementToRequiredNetworkElements",
+  MountNetworkElementToUnknonwNetworkElements = "mountNetworkElementToRequiredUnknownElements",
+  MountNetworkElement = "mountNetworkElement",
+  UnmountNetworkElement = "unmountNetworkElement",
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  addToRequiredNetworkElements: (element: RequiredNetworkElementType) => {
+    dispatcher.dispatch(addToRequiredNetworkElementsAsyncActionCreator(element));
+  },
+  removeFromRequiredNetworkElements: (element: RequiredNetworkElementType) => {
+    dispatcher.dispatch(removeFromRequiredNetworkElementsAsyncActionCreator(element));
+  },
+  mountNetworkElement: (element: RequiredNetworkElementType) => {
+    dispatcher.dispatch(mountNetworkElementActionCreatorAsync(element));
+  },
+  mountAndRquireNetworkElement: (element: RequiredNetworkElementType) => {
+    dispatcher.dispatch(addToRequiredNetworkElementsAsyncActionCreator(element));
+    dispatcher.dispatch(mountNetworkElementActionCreatorAsync(element));
+  },
+  unmountNetworkElement: (element: RequiredNetworkElementType) => {
+    dispatcher.dispatch(unmountNetworkElementActionCreatorAsync(element && element.mountId));
+  }
+}
+);
+
+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.UnknownNetworkElementToRequiredNetworkElements] : {
+    dialogTitle: "Add to required network elements" ,
+    dialogDescription: "Create a new NetworkElement in planning database as clone of existing real NetworkElement." ,
+    applyButtonText: "Add to required network elements" , 
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: false,
+    enableUsernameEditor: true,
+    enableExtendedEditor: false,
+  },
+  [EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements]: {
+    dialogTitle: "Remove from required network elements",
+    dialogDescription: "Do you really want to remove the required element:",
+    applyButtonText: "Remove network element",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [EditNetworkElementDialogMode.MountNetworkElementToUnknonwNetworkElements]: {
+    dialogTitle: "Mount to unknown network elements",
+    dialogDescription: "Mount this network element:",
+    applyButtonText: "Mount network element",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+  [EditNetworkElementDialogMode.MountNetworkElementToRequiredNetworkElements]: {
+    dialogTitle: "Mount to required network elements",
+    dialogDescription: "Mount this network element:",
+    applyButtonText: "Mount network element",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: true,
+    enableUsernameEditor: true,
+    enableExtendedEditor: true,
+  },
+  [EditNetworkElementDialogMode.MountNetworkElement]: {
+    dialogTitle: "Mount network element",
+    dialogDescription: "mount this network element:",
+    applyButtonText: "mount network element",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+  [EditNetworkElementDialogMode.UnmountNetworkElement]: {
+    dialogTitle: "Unmount network element",
+    dialogDescription: "unmount this network element:",
+    applyButtonText: "Unmount network element",
+    cancelButtonText: "Cancel",
+    enableMountIdEditor: false,
+    enableUsernameEditor: false,
+    enableExtendedEditor: false,
+  },
+}
+
+type EditNetworkElementDialogComponentProps = Connect<undefined,typeof mapDispatch> & {
+  mode: EditNetworkElementDialogMode;
+  initialNetworkElement: RequiredNetworkElementType;
+  onClose: () => void;
+};
+
+type EditNetworkElementDialogComponentState = RequiredNetworkElementType & {
+  required: boolean;
+};
+
+class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
+  constructor(props: EditNetworkElementDialogComponentProps) {
+    super(props);
+    
+    this.state = {
+      mountId: this.props.initialNetworkElement.mountId,
+      host: this.props.initialNetworkElement.host,
+      port: this.props.initialNetworkElement.port,
+      password: this.props.initialNetworkElement.password,
+      username: this.props.initialNetworkElement.username,
+      required: false
+    };
+  }
+
+  render(): JSX.Element {
+    const setting = settings[this.props.mode];
+    return (
+      <Dialog open={ this.props.mode !== EditNetworkElementDialogMode.None }>
+        <DialogTitle id="form-dialog-title">{ setting.dialogTitle }</DialogTitle>
+        <DialogContent>
+          <DialogContentText>
+            { setting.dialogDescription }
+          </DialogContentText>
+          <TextField disabled={ !setting.enableMountIdEditor } spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={ this.state.mountId } onChange={(event)=>{ this.setState({mountId: event.target.value}); } } />
+          <TextField disabled={ !setting.enableMountIdEditor } spellCheck={false} margin="dense" id="ipaddress" label="IP address" type="text" fullWidth value={ this.state.host } onChange={(event)=>{ this.setState({host: event.target.value}); } }/>
+          <TextField disabled={ !setting.enableMountIdEditor } spellCheck={false} margin="dense" id="netconfport" label="NetConf port" type="number" fullWidth value={ this.state.port.toString() } onChange={(event)=>{ this.setState({port: +event.target.value}); } }/>
+          { setting.enableUsernameEditor && <TextField disabled={ !setting.enableUsernameEditor } spellCheck={ false } margin="dense" id="username" label="Username" type="text" fullWidth value={ this.state.username } onChange={ (event) => { this.setState({ username: event.target.value }); } } /> || null }
+          { setting.enableUsernameEditor && <TextField disabled={ !setting.enableUsernameEditor } spellCheck={ false } margin="dense" id="password" label="Password" type="password" fullWidth value={ this.state.password } onChange={ (event) => { this.setState({ password: event.target.value }); } } /> || null }
+        </DialogContent>
+        <DialogActions>
+          <Button onClick={ (event) => {
+            this.onApply({
+              mountId: this.state.mountId,
+              host: this.state.host,
+              port: this.state.port,
+              username: this.state.username,
+              password: this.state.password
+            });
+            event.preventDefault();
+            event.stopPropagation();
+          } } > { setting.applyButtonText } </Button>
+          <Button onClick={ (event) => {
+            this.onCancel();
+            event.preventDefault();
+            event.stopPropagation();
+          } } color="secondary"> { setting.cancelButtonText } </Button>
+        </DialogActions>
+      </Dialog>
+    )
+  }
+
+  private onApply = (element: RequiredNetworkElementType) => {
+    this.props.onClose && this.props.onClose();
+    switch (this.props.mode) {
+      case EditNetworkElementDialogMode.UnknownNetworkElementToRequiredNetworkElements:
+        element && this.props.addToRequiredNetworkElements(element);
+        break;
+      case EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements:
+        element && this.props.removeFromRequiredNetworkElements(element);
+        break;
+      case EditNetworkElementDialogMode.MountNetworkElementToUnknonwNetworkElements:
+        element && this.props.mountNetworkElement(element);
+        break;
+      case EditNetworkElementDialogMode.MountNetworkElementToRequiredNetworkElements:
+        element && this.props.mountAndRquireNetworkElement(element);
+        break;
+      case EditNetworkElementDialogMode.MountNetworkElement:
+        element && this.props.mountNetworkElement(element);
+        break;
+      case EditNetworkElementDialogMode.UnmountNetworkElement:
+        element && this.props.unmountNetworkElement(element);
+        break;
+    }
+  };
+
+  private onCancel = () => {
+    this.props.onClose && this.props.onClose();
+  }
+
+  static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: RequiredNetworkElementType }): EditNetworkElementDialogComponentState & { _initialNetworkElement: RequiredNetworkElementType } {
+    if (props.initialNetworkElement !== state._initialNetworkElement) {
+      state = {
+        ...state,
+        ...props.initialNetworkElement,
+        _initialNetworkElement: props.initialNetworkElement,
+      };
+    }
+    return state;
+  }
+}
+
+export const EditNetworkElementDialog = connect(undefined, mapDispatch)(EditNetworkElementDialogComponent);
+export default EditNetworkElementDialog;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx
new file mode 100644
index 0000000..13f5fec
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx
@@ -0,0 +1,194 @@
+import * as React from 'react';
+import { Theme, createStyles, withStyles, WithStyles } from '@material-ui/core/styles';
+
+import AddIcon from '@material-ui/icons/Add';
+import LinkIcon from '@material-ui/icons/Link';
+import LinkOffIcon from '@material-ui/icons/LinkOff';
+import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
+
+import Button from '@material-ui/core/Button';
+import IconButton from '@material-ui/core/IconButton';
+
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+import { createRequiredNetworkElementsActions, createRequiredNetworkElementsProperties } from '../handlers/requiredNetworkElementsHandler';
+
+import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
+import { Tooltip } from '@material-ui/core';
+import { NetworkElementBaseType } from 'models/networkElementBase';
+
+const styles = (theme: Theme) => createStyles({
+  connectionStatusConnected: {
+    color: 'darkgreen',
+  },
+  connectionStatusConnecting: {
+    color: theme.palette.primary.main,
+  },
+  connectionStatusDisconnected: {
+    color: 'red',
+  },
+  button: {
+    margin: 0,
+    padding: "6px 6px",
+    minWidth: 'unset'
+  },
+  spacer: {
+    marginLeft: theme.spacing.unit,
+    marginRight: theme.spacing.unit,
+    display: "inline"
+  }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  requiredNetworkElementsProperties: createRequiredNetworkElementsProperties(state),
+  mountedNetworkElements: state.connectApp.mountedNetworkElements
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  requiredNetworkElementsActions: createRequiredNetworkElementsActions(dispatcher.dispatch),
+  navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+});
+
+type RequiredNetworkElementsListComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
+type RequiredNetworkElementsListComponentState = {
+  networkElementToEdit: RequiredNetworkElementType,
+  networkElementEditorMode: EditNetworkElementDialogMode
+}
+
+const emptyRequireNetworkElement = { mountId: '', host: '', port: 0 };
+
+const RequiredNetworkElementTable = MaterialTable as MaterialTableCtorType<RequiredNetworkElementType>;
+
+export class RequiredNetworkElementsListComponent extends React.Component<RequiredNetworkElementsListComponentProps, RequiredNetworkElementsListComponentState> {
+
+  constructor(props: RequiredNetworkElementsListComponentProps) {
+    super(props);
+
+    this.state = {
+      networkElementToEdit: emptyRequireNetworkElement,
+      networkElementEditorMode: EditNetworkElementDialogMode.None
+    };
+  }
+
+  //  private navigationCreator 
+
+  render(): JSX.Element {
+    const { classes } = this.props;
+    const { networkElementToEdit } = this.state;
+    const addRequireNetworkElementAction = {
+      icon: AddIcon, tooltip: 'Add', onClick: () => {
+        this.setState({
+          networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElementToRequiredNetworkElements,
+          networkElementToEdit: emptyRequireNetworkElement,
+        });
+      }
+    };
+    return (
+      <>
+        <RequiredNetworkElementTable customActionButtons={ [addRequireNetworkElementAction] } columns={ [
+          { property: "mountId", title: "Name", type: ColumnType.text },
+          {
+            property: "connectionStatus", title: "Connection Status", type: ColumnType.custom, disableFilter: true, disableSorting: true, customControl: ({ rowData }) => {
+              const unknownNetworkElement = this.props.mountedNetworkElements.elements.find(el => el.mountId === rowData.mountId);
+              const connectionStatus = unknownNetworkElement && unknownNetworkElement.connectionStatus || 'disconnected';
+              const cssClasses = connectionStatus === "connected"
+                ? classes.connectionStatusConnected
+                : connectionStatus === "disconnected"
+                  ? classes.connectionStatusDisconnected
+                  : classes.connectionStatusConnecting
+              return <div className={ cssClasses } >{ connectionStatus } </div>
+
+            }
+          },
+          { property: "host", title: "Host", type: ColumnType.text },
+          { property: "port", title: "Port", type: ColumnType.text },
+          // { property: "username", title: "Username", type: ColumnType.text },
+          // { property: "password", title: "Password", type: ColumnType.text },
+          {
+            property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => {
+              const unknownNetworkElement = this.props.mountedNetworkElements.elements.find(el => el.mountId === rowData.mountId);
+              const connectionStatus = unknownNetworkElement && unknownNetworkElement.connectionStatus || 'disconnected';
+              return (
+                <>
+                  <div className={ classes.spacer }>
+                    <Tooltip title={ "Mount" } ><IconButton className={ classes.button } onClick={ event => this.onOpenMountdNetworkElementsDialog(event, rowData) }><LinkIcon /></IconButton></Tooltip>
+                    <Tooltip title={ "Unmount" } ><IconButton className={ classes.button } onClick={ event => this.onOpenUnmountdNetworkElementsDialog(event, rowData) }><LinkOffIcon /></IconButton></Tooltip>
+                    <Tooltip title={ "Remove" } ><IconButton className={ classes.button } onClick={ event => this.onOpenRemoveRequiredNetworkElementDialog(event, rowData) } ><RemoveIcon /></IconButton></Tooltip>
+                  </div>
+                  <div className={ classes.spacer }>
+                    <Tooltip title={ "Info" } ><Button className={ classes.button } >I</Button></Tooltip>
+                  </div>
+                  <div className={ classes.spacer }>
+                    <Tooltip title={ "Fault" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("faultApp", rowData) } >F</Button></Tooltip>
+                    <Tooltip title={ "Configure" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("configureApp", rowData)} >C</Button></Tooltip>
+                    <Tooltip title={ "Accounting " } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("accountingApp", rowData) }>A</Button></Tooltip>
+                    <Tooltip title={ "Performance" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("performanceApp", rowData) }>P</Button></Tooltip>
+                    <Tooltip title={ "Security" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("securityApp", rowData) }>S</Button></Tooltip>
+                  </div>
+                </>
+              )
+            }
+          },
+        ] } idProperty="mountId" { ...this.props.requiredNetworkElementsActions } { ...this.props.requiredNetworkElementsProperties } asynchronus >
+        </RequiredNetworkElementTable>
+        <EditNetworkElementDialog
+          initialNetworkElement={ networkElementToEdit }
+          mode={ this.state.networkElementEditorMode }
+          onClose={ this.onCloseEditNetworkElementDialog }
+        />
+      </>
+    );
+  };
+
+  public componentDidMount() {
+    this.props.requiredNetworkElementsActions.onRefresh();
+  }
+
+  private onOpenRemoveRequiredNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: RequiredNetworkElementType) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements
+    });
+    event.preventDefault();
+    event.stopPropagation();
+  }
+
+  private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: RequiredNetworkElementType) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement
+    });
+    event.preventDefault();
+    event.stopPropagation();
+  }
+
+  private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: RequiredNetworkElementType) => {
+    this.setState({
+      networkElementToEdit: element,
+      networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement
+    });
+    event.preventDefault();
+    event.stopPropagation();
+  }
+
+  private onCloseEditNetworkElementDialog = () => {
+    this.setState({
+      networkElementEditorMode: EditNetworkElementDialogMode.None,
+      networkElementToEdit: emptyRequireNetworkElement,
+    });
+  }
+
+  private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementBaseType) => (event: React.MouseEvent<HTMLElement>) => {
+    this.props.navigateToApplication(applicationName, element.mountId);
+    event.preventDefault();
+    event.stopPropagation();
+  }
+}
+
+export const RequiredNetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(RequiredNetworkElementsListComponent));
+export default RequiredNetworkElementsList;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx
new file mode 100644
index 0000000..4321031
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx
@@ -0,0 +1,196 @@
+import * as React from 'react';
+import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
+
+import AddIcon from '@material-ui/icons/Add';
+import LinkOffIcon from '@material-ui/icons/LinkOff';
+import AddCircleIcon from '@material-ui/icons/AddCircleOutline';
+
+import Button from '@material-ui/core/Button';
+import IconButton from '@material-ui/core/IconButton';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+import { IMountedNetworkElementsState } from '../handlers/mountedNetworkElementsHandler';
+import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
+import { NetworkElementBaseType } from 'models/networkElementBase';
+
+
+const styles = (theme: Theme) => createStyles({
+  button: {
+    margin: 0,
+    padding: "6px 6px",
+    minWidth: 'unset'
+  },
+  spacer: {
+    marginLeft: theme.spacing.unit,
+    marginRight: theme.spacing.unit,
+    display: "inline"
+  }
+});
+
+const mapProps = ({ connectApp: state }: IApplicationStoreState) => ({
+  mountedNetworkElements: state.mountedNetworkElements
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+  navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+});
+type UnknownNetworkElementDisplayType = NetworkElementBaseType & {
+  connectionStatus: string,
+  coreModelRev: string,
+  airInterfaceRev: string
+}
+
+type UnknownNetworkElementsListProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch> & {}
+
+type UnknownNetworkElementsListState = {
+  
+  unknownNetworkElements: UnknownNetworkElementDisplayType[];
+
+  networkElementToEdit: RequiredNetworkElementType;
+  networkElementEditorMode: EditNetworkElementDialogMode;
+}
+
+
+const emptyRequireNetworkElement = { mountId: '', host: '', port: 0 };
+const UnknownNetworkElementTable = MaterialTable as MaterialTableCtorType<UnknownNetworkElementDisplayType>;
+export class UnknownNetworkElementsListComponent extends React.Component<UnknownNetworkElementsListProps, UnknownNetworkElementsListState> {
+
+  constructor(props: UnknownNetworkElementsListProps) {
+    super(props);
+
+    this.state = {
+      unknownNetworkElements: [],
+      networkElementToEdit: emptyRequireNetworkElement,
+      networkElementEditorMode: EditNetworkElementDialogMode.None,
+    };
+  }
+
+  static getDerivedStateFromProps(props: UnknownNetworkElementsListProps, state: UnknownNetworkElementsListState & { _mountedNetworkElements: IMountedNetworkElementsState }) {
+    if (props.mountedNetworkElements != state._mountedNetworkElements) {
+      state.unknownNetworkElements = props.mountedNetworkElements.elements.filter(element => !element.required).map(element => {
+        
+        // handle onfCoreModelRevision
+        const onfCoreModelRevision = element.capabilities.find((cap) => {
+          return cap.module === 'core-model' || cap.module === 'CoreModel-CoreNetworkModule-ObjectClasses' ;
+        });
+        const onfAirInterfaceRevision = element.capabilities.find((cap) => {
+          return cap.module === 'microwave-model' || cap.module === 'MicrowaveModel-ObjectClasses-AirInterface' ;
+        });
+        return {
+          mountId: element.mountId,
+          host: element.host,
+          port: element.port,
+          connectionStatus: element.connectionStatus,
+          coreModelRev: onfCoreModelRevision && onfCoreModelRevision.revision || 'unknown',
+          airInterfaceRev: onfAirInterfaceRevision && onfAirInterfaceRevision.revision || 'unknown'
+        }
+      }
+      );
+    }
+    return state;
+  }
+  
+  render(): JSX.Element {
+    const { classes } = this.props;
+    const { networkElementToEdit, networkElementEditorMode, unknownNetworkElements } = this.state;
+    const addRequireNetworkElementAction = {
+      icon: AddIcon, tooltip: 'Add', onClick: () => {
+        this.setState({
+          networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElementToUnknonwNetworkElements,
+          networkElementToEdit: emptyRequireNetworkElement,
+        });
+      }
+    };
+    return (
+      <>
+        <UnknownNetworkElementTable customActionButtons={ [addRequireNetworkElementAction] } asynchronus rows={ unknownNetworkElements } columns={ [
+          { property: "mountId", title: "Name", type: ColumnType.text },
+          { property: "connectionStatus", title: "Connection Status", type: ColumnType.text },
+          { property: "host", title: "Host", type: ColumnType.text },
+          { property: "port", title: "Port", type: ColumnType.text },
+          { property: "coreModelRev", title: "Core Model", type: ColumnType.text },
+          { property: "airInterfaceRev", title: "Air interface", type: ColumnType.text },
+          {
+            property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => (
+              <>
+                <div className={ classes.spacer }>
+                  <Tooltip title={ "Unmount" } ><IconButton className={ classes.button } onClick={ event => this.onOpenUnmountdNetworkElementsDialog(event, rowData) } ><LinkOffIcon /></IconButton></Tooltip>
+                  <Tooltip title={ "Add to required" } ><IconButton className={ classes.button } onClick={ event => this.onOpenAddToRequiredNetworkElementsDialog(event, rowData) } ><AddCircleIcon /></IconButton></Tooltip>
+                </div>
+                <div className={ classes.spacer }>
+                  <Tooltip title={ "Info" } ><Button className={ classes.button } >I</Button></Tooltip>
+                </div>
+                <div className={ classes.spacer }>
+                  <div className={ classes.spacer }>
+                    <Tooltip title={ "Fault" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("faultApp", rowData) } >F</Button></Tooltip>
+                    <Tooltip title={ "Configure" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("configureApp", rowData) } >C</Button></Tooltip>
+                    <Tooltip title={ "Accounting " } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("accountingApp", rowData) }>A</Button></Tooltip>
+                    <Tooltip title={ "Performance" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("performanceApp", rowData) }>P</Button></Tooltip>
+                    <Tooltip title={ "Security" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("securityApp", rowData) }>S</Button></Tooltip>
+                  </div>
+                </div>                
+              </>
+            )
+          },
+        ] } idProperty="mountId" >
+        </UnknownNetworkElementTable>
+        
+        <EditNetworkElementDialog 
+          mode={ networkElementEditorMode }
+          initialNetworkElement={ networkElementToEdit }
+          onClose={ this.onCloseEditNetworkElementDialog }
+        />
+      </>
+    );
+  };
+
+  private onOpenAddToRequiredNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: UnknownNetworkElementDisplayType) => {
+    this.setState({
+      networkElementToEdit: {
+        mountId: element.mountId,
+        host: element.host,
+        port: element.port,
+        username: 'admin',
+        password: 'admin',
+      },
+      networkElementEditorMode: EditNetworkElementDialogMode.UnknownNetworkElementToRequiredNetworkElements
+    });
+    event.preventDefault();
+    event.stopPropagation();
+  }
+
+  private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: UnknownNetworkElementDisplayType) => {
+    this.setState({
+      networkElementToEdit: {
+        mountId: element.mountId,
+        host: element.host,
+        port: element.port
+      },
+      networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement
+    });
+    event.preventDefault();
+    event.stopPropagation();
+  }
+
+  private onCloseEditNetworkElementDialog = () => {
+    this.setState({
+      networkElementEditorMode: EditNetworkElementDialogMode.None,
+      networkElementToEdit: emptyRequireNetworkElement,
+    });
+  }
+
+  private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementBaseType) => (event: React.MouseEvent<HTMLElement>) => {
+    this.props.navigateToApplication(applicationName, element.mountId);
+    event.preventDefault();
+    event.stopPropagation();
+  }
+
+}
+
+export const UnknownNetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(UnknownNetworkElementsListComponent));
+export default UnknownNetworkElementsList;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.tsx
new file mode 100644
index 0000000..26d02c4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.tsx
@@ -0,0 +1,26 @@
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+import { IRequiredNetworkElementsState, requiredNetworkElementsActionHandler  } from './requiredNetworkElementsHandler';
+import { IMountedNetworkElementsState, mountedNetworkElementsActionHandler } from './mountedNetworkElementsHandler';
+import { IConnectionStatusLogState, connectionStatusLogActionHandler } from './connectionStatusLogHandler';
+
+export interface IConnectAppStoreState {
+
+  requiredNetworkElements: IRequiredNetworkElementsState;
+  mountedNetworkElements: IMountedNetworkElementsState;
+  connectionStatusLog: IConnectionStatusLogState;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    connectApp: IConnectAppStoreState
+  }
+}
+
+const actionHandlers = {
+  requiredNetworkElements: requiredNetworkElementsActionHandler,
+  mountedNetworkElements: mountedNetworkElementsActionHandler,
+  connectionStatusLog: connectionStatusLogActionHandler
+};
+
+export const connectAppRootHandler = combineActionHandler <IConnectAppStoreState>(actionHandlers);
+export default connectAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.tsx
new file mode 100644
index 0000000..140020e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.tsx
@@ -0,0 +1,30 @@
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { ConnectionStatusLogType } from '../models/connectionStatusLog';
+export interface IConnectionStatusLogState extends IExternalTableState<ConnectionStatusLogType> { }
+
+// create eleactic search material data fetch handler
+const connectionStatusLogSearchHandler = createSearchDataHandler<{ event: ConnectionStatusLogType }, ConnectionStatusLogType>('sdnevents_v1/eventlog', null,
+  (event) => ({
+    _id: event._id,
+    timeStamp: event._source.event.timeStamp,
+    objectId: event._source.event.objectId,
+    type: event._source.event.type,
+    elementStatus: event._source.event.type === 'ObjectCreationNotificationXml'
+      ? 'connected'
+      : event._source.event.type === 'ObjectDeletionNotificationXml'
+        ? 'disconnected'
+        : 'unknown'
+  }),
+  (name) => `event.${ name }`);
+
+export const {
+  actionHandler: connectionStatusLogActionHandler,
+  createActions: createConnectionStatusLogActions,
+  createProperties: createConnectionStatusLogProperties,
+  reloadAction: connectionStatusLogReloadAction,
+
+  // set value action, to change a value 
+} = createExternal<ConnectionStatusLogType>(connectionStatusLogSearchHandler, appState => appState.connectApp.connectionStatusLog);
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/mountedNetworkElementsHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/mountedNetworkElementsHandler.tsx
new file mode 100644
index 0000000..70b4d8f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/mountedNetworkElementsHandler.tsx
@@ -0,0 +1,81 @@
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import {
+  AddMountedNetworkElement,
+  AllMountedNetworkElementsLoadedAction,
+  LoadAllMountedNetworkElementsAction,
+  RemoveMountedNetworkElement,
+  UpdateConnectionStateMountedNetworkElement,
+  UpdateRequiredMountedNetworkElement
+} from '../actions/mountedNetworkElementsActions';
+
+import { MountedNetworkElementType } from '../models/mountedNetworkElements';
+
+export interface IMountedNetworkElementsState {
+  elements: MountedNetworkElementType[];
+  busy: boolean;
+}
+
+const mountedNetworkElementsStateInit: IMountedNetworkElementsState = {
+  elements: [],
+  busy: false
+};
+
+export const mountedNetworkElementsActionHandler: IActionHandler<IMountedNetworkElementsState> = (state = mountedNetworkElementsStateInit, action) => {
+  if (action instanceof LoadAllMountedNetworkElementsAction) {
+
+    state = {
+      ...state,
+      busy: true
+    };
+  
+  } else if (action instanceof AllMountedNetworkElementsLoadedAction) {
+    if (!action.error && action.mountedNetworkElements) {
+      state = {
+        ...state,
+        elements: action.mountedNetworkElements,
+        busy: false
+      };
+    } else {
+      state = {
+        ...state,
+        busy: false
+      };
+    }
+  } else if (action instanceof AddMountedNetworkElement) {
+    action.mountedNetworkElement && (state = {
+      ...state,
+      elements: [...state.elements, action.mountedNetworkElement],
+    });
+  } else if (action instanceof RemoveMountedNetworkElement) {
+    state = {
+      ...state,
+      elements: state.elements.filter(e => e.mountId !== action.mountId),
+    };
+  } else if (action instanceof UpdateConnectionStateMountedNetworkElement) {
+    const index = state.elements.findIndex(el => el.mountId === action.mountId);
+    if (index > -1) {
+      state = {
+        ...state,
+        elements: [
+          ...state.elements.slice(0, index),
+          { ...state.elements[index], connectionStatus: action.mountId },
+          ...state.elements.slice(index + 1)
+        ]
+      }
+    }
+  } else if (action instanceof UpdateRequiredMountedNetworkElement) {
+    const index = state.elements.findIndex(el => el.mountId === action.mountId);
+    if (index > -1 && (state.elements[index].required !== action.required)) {
+      state = {
+        ...state,
+        elements: [
+          ...state.elements.slice(0, index),
+          { ...state.elements[index], required: action.required },
+          ...state.elements.slice(index + 1)
+        ]
+      }
+    }
+  };
+  return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/requiredNetworkElementsHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/requiredNetworkElementsHandler.tsx
new file mode 100644
index 0000000..b2d5477
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/requiredNetworkElementsHandler.tsx
@@ -0,0 +1,18 @@
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+export interface IRequiredNetworkElementsState extends IExternalTableState<RequiredNetworkElementType> { }
+
+// create eleactic search material data fetch handler
+const requiredNetworkElementsSearchHandler = createSearchDataHandler<RequiredNetworkElementType>('mwtn/required-networkelement');
+
+export const {
+  actionHandler: requiredNetworkElementsActionHandler,
+  createActions: createRequiredNetworkElementsActions,
+  createProperties: createRequiredNetworkElementsProperties,
+  reloadAction: requiredNetworkElementsReloadAction,
+
+  // set value action, to change a value 
+} = createExternal<RequiredNetworkElementType>(requiredNetworkElementsSearchHandler, appState => appState.connectApp.requiredNetworkElements);
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/index.html b/sdnr/wt/odlux/apps/connectApp/src/index.html
new file mode 100644
index 0000000..c28708a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/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>Document</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"], function (app, connectApp, faultApp) {
+      connectApp.register();
+      faultApp.register();
+      app("./app.tsx")
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
new file mode 100644
index 0000000..d3aa203
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
@@ -0,0 +1,9 @@
+
+export type ConnectionStatusLogType = {
+  _id: string;
+  elementStatus: string;
+  timeStamp: string;
+  objectId: string;
+  type: string;
+}
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/mountedNetworkElements.ts b/sdnr/wt/odlux/apps/connectApp/src/models/mountedNetworkElements.ts
new file mode 100644
index 0000000..4ab7c8e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/mountedNetworkElements.ts
@@ -0,0 +1,11 @@
+import { NetworkElementBaseType } from "./networkElementBase";
+
+/**
+* Represents data of an mounted network elements.
+*/
+export type MountedNetworkElementType = NetworkElementBaseType & {
+  connectionStatus: string;
+  required: boolean;
+  capabilities: { module: string, revision: string }[];
+};
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
new file mode 100644
index 0000000..85390be
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
@@ -0,0 +1,5 @@
+export type NetworkElementBaseType = {
+  mountId: string,
+  host: string,
+  port: number,
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/requiredNetworkElements.ts b/sdnr/wt/odlux/apps/connectApp/src/models/requiredNetworkElements.ts
new file mode 100644
index 0000000..08d1f91
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/requiredNetworkElements.ts
@@ -0,0 +1,10 @@
+import { NetworkElementBaseType } from "./networkElementBase";
+
+/**
+* Represents data of Required Network Elements.
+*/
+export type RequiredNetworkElementType = NetworkElementBaseType & {
+  username?: string;
+  password?: string;
+}
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
new file mode 100644
index 0000000..5cf29c7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
@@ -0,0 +1,36 @@
+export interface UnavailableCapability {
+  capability: string;
+  "failure-reason": string;
+}
+
+export interface NetconfNodeTopologyUnavailableCapabilities {
+  "unavailable-capability": UnavailableCapability[];
+}
+
+export interface AvailableCapability {
+  "capability-origin": string;
+  capability: string;
+}
+
+export interface NetconfNodeTopologyAvailableCapabilities {
+  "available-capability": AvailableCapability[];
+}
+
+export interface NetconfNodeTopologyClusteredConnectionStatus {
+  "netconf-master-node": string
+}
+
+export interface TopologyNode {
+  "node-id": string;
+  "netconf-node-topology:clustered-connection-status": NetconfNodeTopologyClusteredConnectionStatus;
+  "netconf-node-topology:unavailable-capabilities": NetconfNodeTopologyUnavailableCapabilities;
+  "netconf-node-topology:available-capabilities": NetconfNodeTopologyAvailableCapabilities;
+  "netconf-node-topology:host": string;
+  "netconf-node-topology:connection-status": string;
+  "netconf-node-topology:port": number;
+}
+
+export interface Topology {
+  "topology-id": string;
+  node: TopologyNode[];
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/plugin.tsx b/sdnr/wt/odlux/apps/connectApp/src/plugin.tsx
new file mode 100644
index 0000000..4e61c32
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/plugin.tsx
@@ -0,0 +1,39 @@
+
+import { faPlug } from '@fortawesome/free-solid-svg-icons';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService';
+
+import connectAppRootHandler from './handlers/connectAppRootHandler';
+import ConnectApplication  from './views/connectView';
+import { RemoveMountedNetworkElement, addMountedNetworkElementAsyncActionCreator } from './actions/mountedNetworkElementsActions' ;
+import { AddSnackbarNotification } from '../../../framework/src/actions/snackbarActions';
+
+type ObjectNotification = {
+  counter: string;
+  nodeName: string;
+  objectId: string;
+  timeStamp: string;
+}
+
+export function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: "connectApp",
+    icon: faPlug,
+    rootComponent: ConnectApplication,
+    rootActionHandler: connectAppRootHandler,
+    menuEntry: "Connect App"
+  });
+
+  // subscribe to the websocket notifications
+  subscribe<ObjectNotification & IFormatedMessage>(["ObjectCreationNotification", "ObjectDeletionNotification"], (msg => {
+    const store = applicationApi && applicationApi.applicationStore;
+    if (msg && msg.notifType === "ObjectCreationNotification" && store) {
+      store.dispatch(addMountedNetworkElementAsyncActionCreator(msg.objectId));
+      store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${ msg.objectId }]`, options: { variant: 'info' } }));
+    } else if (msg && msg.notifType === "ObjectDeletionNotification" && store) {
+      store.dispatch(new AddSnackbarNotification({ message: `Removing network element [${ msg.objectId }]`, options: { variant: 'info' } }));
+      store.dispatch(new RemoveMountedNetworkElement(msg.objectId));
+    }
+  }));
+}                                     
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
new file mode 100644
index 0000000..0adcd49
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -0,0 +1,204 @@
+import { RequiredNetworkElementType } from '../models/requiredNetworkElements';
+import { MountedNetworkElementType } from 'models/mountedNetworkElements';
+import { Topology, TopologyNode } from 'models/topologyNetconf';
+
+import { requestRest } from '../../../../framework/src/services/restService';
+import { Result, HitEntry } from '../../../../framework/src/models/elasticSearch';
+
+
+/** 
+ * Represents a web api accessor service for all Network Elements actions.
+ */
+class ConnectService {
+  /**
+    * Gets all known required network elements from the backend.
+    */
+  public async getAllRequiredNetworkElements(): Promise<(RequiredNetworkElementType & { _id: string })[] | null> {
+    const path = 'database/mwtn/required-networkelement/_search';
+    const query = { "query": { "match_all": {} } };
+    
+    const result = await requestRest<Result<RequiredNetworkElementType>>(path, { method: "POST", body: JSON.stringify(query) });
+    return result && result.hits && result.hits.hits && result.hits.hits.map(ne => ({
+      _id: ne._id,
+      mountId: ne._source && ne._source.mountId,
+      host: ne._source && ne._source.host,
+      port: ne._source && ne._source.port,
+      username: ne._source && ne._source.username,
+      password: ne._source && ne._source.password,
+    })) || null;
+  }
+
+  public async getRequiredNetworkElementByMountId(mountId:string): Promise<(RequiredNetworkElementType & { _id: string }) | null> {
+    const path = `database/mwtn/required-networkelement/${mountId}`;
+    
+    const result = await requestRest<HitEntry<RequiredNetworkElementType> & { found: boolean }>(path, { method: "GET" });
+    return result && result.found && result._source  && {
+      _id: result._id,
+      mountId:  result._source.mountId,
+      host: result._source.host,
+      port: result._source.port,
+      username: result._source.username,
+      password: result._source.password,
+    } || null;
+
+  }
+
+  /**
+    * Inserts data into the required network elements table.
+    */
+  public async insertRequiredNetworkElement(element: RequiredNetworkElementType): Promise<RequiredNetworkElementType | null> {
+    const path = `database/mwtn/required-networkelement/${ element.mountId }`;
+    const result = await requestRest<RequiredNetworkElementType>(path, { method: "POST", body: JSON.stringify(element) });
+    return result || null;
+  }
+
+  /**
+    * Deletes data from the Required Network Elements backend.
+    */
+  public async deleteRequiredNetworkElement(element: RequiredNetworkElementType): Promise<RequiredNetworkElementType | null> {
+    const path = `database/mwtn/required-networkelement/${ element.mountId }`;
+    const result = await requestRest<RequiredNetworkElementType>(path, { method: "DELETE", body: JSON.stringify(element) });
+    return result || null;
+  }
+
+  
+
+  private static mapTopologyNode = (mountPoint: TopologyNode, required: boolean ) => {
+    // handle onfCapabilities
+    let onfCapabilities: { module: string, revision: string }[] | undefined = undefined;
+    let onfCoreModelRevision: string[] | undefined = undefined;
+    let onfAirInterfaceRevision: string[] | undefined = undefined;
+
+    const capId = 'netconf-node-topology:available-capabilities';
+    if (mountPoint[capId] && mountPoint[capId]['available-capability']) {
+      onfCapabilities = mountPoint[capId]['available-capability'].filter((cap) => {
+        return cap.capability.includes('?revision=');
+      }).map((cap) => {
+        return {
+          module: cap.capability.split(')')[1],
+          revision: cap.capability.split('?revision=')[1].substring(0, 10)
+        };
+      }).sort((a, b) => {
+        if (a.module < b.module) return -1;
+        if (a.module > b.module) return 1;
+        return 0;
+      });
+    }
+
+    // handle clustered-connection-status
+    const statusId = 'netconf-node-topology:clustered-connection-status';
+    let client = 'localhost';
+
+    if (mountPoint[statusId] && mountPoint[statusId]['netconf-master-node']) {
+      let node = mountPoint[statusId]['netconf-master-node'];
+      node = node.substring(node.indexOf('@'));
+      client = node.substring(1, node.indexOf(':'));
+    }
+    const mountId = mountPoint["node-id"];
+    return {
+      mountId: mountId,
+      host: mountPoint["netconf-node-topology:host"],
+      port: mountPoint["netconf-node-topology:port"],
+      connectionStatus: mountPoint['netconf-node-topology:connection-status'],
+      capabilities: onfCapabilities || [],
+      required: required,
+      client
+    }
+  }
+
+  /** Get all mounted network elements and fills the property required according to the database contents. */
+  public async getMountedNetworkElementsList(): Promise<MountedNetworkElementType[] | null> {
+    const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf';
+    
+    const topologyRequestPomise = requestRest<{ topology: Topology[] | null }>(path, { method: "GET" }, true);
+    const requiredNetworkElementsPromise = this.getAllRequiredNetworkElements();
+
+    const [netconfResponse, requiredNetworkElements] = await Promise.all([topologyRequestPomise, requiredNetworkElementsPromise]);
+
+    // process topologyNetconf (get all known network elements)
+    const topologyNetconf = netconfResponse && netconfResponse.topology && netconfResponse.topology.find(topology => topology["topology-id"] === 'topology-netconf');
+    let mountPoints = topologyNetconf && topologyNetconf.node && topologyNetconf.node.filter(
+      mountPoint => mountPoint['node-id'] !== 'controller-config').map(mountedElement => {
+        const required = requiredNetworkElements && requiredNetworkElements.some(
+          requiredElement => requiredElement.mountId === mountedElement["node-id"]);
+        return ConnectService.mapTopologyNode(mountedElement, !!required);
+      });
+
+    return mountPoints || [];
+  }
+
+  /** Get one mounted network element. */ 
+  public async getMountedNetworkElementByMountId(mountId: string): Promise<MountedNetworkElementType | null> {
+    const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + mountId;
+    const getMountedNetworkElementByMountIdPromise = requestRest<{ node: TopologyNode[] | null }>(path, { method: "GET" }, true);
+    const getRequiredNetworkElementByMountIdPromise = this.getRequiredNetworkElementByMountId(mountId);
+
+    const [mountedNetworkElement, requiredNetworkElement] = await Promise.all([getMountedNetworkElementByMountIdPromise, getRequiredNetworkElementByMountIdPromise]);
+    return mountedNetworkElement && mountedNetworkElement.node && ConnectService.mapTopologyNode(mountedNetworkElement.node[0], requiredNetworkElement && requiredNetworkElement.mountId === mountedNetworkElement.node[0]["node-id"] || false) || null;
+  }
+  
+  /** Mounts an required network element. */
+  public async mountNetworkElement(networkElement: RequiredNetworkElementType): Promise<boolean> {
+    const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + networkElement.mountId;
+    const mountXml = [
+      '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+      `<node-id>${ networkElement.mountId }</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('');
+    
+    try {
+      const result = await requestRest<{}>(path, {
+        method: 'PUT',
+        headers: {
+          'Content-Type': 'application/xml',
+          'Accept': 'application/xml',
+          'Authorization': 'Basic YWRtaW46YWRtaW4='
+        },
+        body: mountXml
+      }, true);
+      // expect an empty answer
+      return result === null; 
+    } catch {
+      return false;
+    }
+  };
+
+  /** Unmounts a network element by its id. */
+  public async unmountNetworkElement(mountId: string): Promise<boolean> {
+    const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + mountId;
+  
+    try {
+      const result = await requestRest<{}>(path, {
+        method: 'DELETE',
+        headers: {
+          'Content-Type': 'application/xml',
+          'Accept': 'application/xml',
+          'Authorization': 'Basic YWRtaW46YWRtaW4='
+        },
+      }, true);
+      // expect an empty answer
+      return result === null; 
+      
+    } catch {
+      return false;
+    }
+  };
+
+
+}
+export const connectService = new ConnectService();
+export default connectService;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
new file mode 100644
index 0000000..b73eb39
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
@@ -0,0 +1,93 @@
+import * as React from 'react';
+
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { Panel } from '../../../../framework/src/components/material-ui';
+
+import { requiredNetworkElementsReloadAction } from '../handlers/requiredNetworkElementsHandler';
+import { loadAllMountedNetworkElementsAsync } from '../actions/mountedNetworkElementsActions';
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
+
+import { RequiredNetworkElementsList } from '../components/requiredNetworkElements';
+import { ConnectionStatusLog } from '../components/connectionStatusLog';
+import { UnknownNetworkElementsList } from '../components/unknownNetworkElements';
+
+const mapDispatcher = (dispatcher: IDispatcher) => ({
+  onLoadUnknownNetworkElements: () => {
+    dispatcher.dispatch(loadAllMountedNetworkElementsAsync);
+  },
+  onLoadRequiredNetworkElements: () => {
+    dispatcher.dispatch(requiredNetworkElementsReloadAction);
+  },
+  onLoadConnectionStatusLog: () => {
+    dispatcher.dispatch(connectionStatusLogReloadAction);
+  }
+});
+
+type PanelId = null | "RequiredNetworkElements" | "UnknownNetworkElements" | "ConnectionStatusLog";
+
+type ConnectApplicationComponentProps = Connect<undefined, typeof mapDispatcher> ;
+
+type ConnectApplicationComponentState = {
+  activePanel: PanelId;
+};
+
+class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps, ConnectApplicationComponentState>{
+  /**
+   * Initialises this instance
+   */
+  constructor(props: ConnectApplicationComponentProps) {
+    super(props);
+    
+    this.state = {
+      activePanel: null
+    };
+  }
+  private onTogglePanel = (panelId: PanelId) => {
+    const nextActivePanel = panelId === this.state.activePanel ? null : panelId;
+    this.setState({
+      activePanel: nextActivePanel
+    }, () => {
+      switch (nextActivePanel) {
+        case 'RequiredNetworkElements':
+          this.props.onLoadRequiredNetworkElements();
+          break;
+        case 'UnknownNetworkElements':
+          // todo: should we update the application state ?
+          break;
+        case 'ConnectionStatusLog':
+          this.props.onLoadConnectionStatusLog();
+          break;
+        case null:
+          // do nothing if all panels are closed
+          break;
+        default:
+          console.warn("Unknown nextActivePanel [" + nextActivePanel + "] in connectView");
+          break;
+      }
+    });
+  };
+
+  render(): JSX.Element {
+    const { activePanel } = this.state;
+    
+    return (
+      <>
+        <Panel activePanel={ activePanel } panelId={ 'RequiredNetworkElements' } onToggle={ this.onTogglePanel } title={ "Required Network Elements" }>
+          <RequiredNetworkElementsList />
+        </Panel>
+        <Panel activePanel={ activePanel } panelId={ 'UnknownNetworkElements' } onToggle={ this.onTogglePanel } title={ "Unknown Network Elements" }>
+          <UnknownNetworkElementsList />
+        </Panel>
+        <Panel activePanel={ activePanel } panelId={ 'ConnectionStatusLog' } onToggle={ this.onTogglePanel } title={ "Connection Status Log" }>
+          <ConnectionStatusLog />
+        </Panel>
+      </>
+    );
+  };
+  public componentDidMount() {
+    this.props.onLoadUnknownNetworkElements();
+  }
+}
+
+export const ConnectApplication = (connect(undefined, mapDispatcher)(ConnectApplicationComponent));
+export default ConnectApplication;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..adc9b77
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="connectApp"/>
+        <property name="index" value="0"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/tsconfig.json b/sdnr/wt/odlux/apps/connectApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/connectApp/webpack.config.js b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
new file mode 100644
index 0000000..a70e629
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/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: {
+      connectApp: ["./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: {
+        "/restconf": {
+          target: "http://localhost:8181",
+          secure: false
+        },
+        "/database": {
+          target: "http://localhost:8181",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/.babelrc b/sdnr/wt/odlux/apps/demoApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/demoApp/package.json b/sdnr/wt/odlux/apps/demoApp/package.json
new file mode 100644
index 0000000..c407149
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/package.json
@@ -0,0 +1,40 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*"
+   },
+  "peerDependencies": {
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/pom.xml b/sdnr/wt/odlux/apps/demoApp/pom.xml
new file mode 100644
index 0000000..eed078d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-demoApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-demoApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts b/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
new file mode 100644
index 0000000..9ce1d59
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
@@ -0,0 +1,34 @@
+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 {
+  constructor() {
+    super();
+  }
+}
+
+// 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/apps/demoApp/src/components/counter.tsx b/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
new file mode 100644
index 0000000..30f7281
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
@@ -0,0 +1,17 @@
+import * as React from 'react';
+
+export class Counter extends React.Component<{}, { counter: number }> {
+  constructor(props: {}) {
+    super(props);
+
+    this.state = {
+      counter: 0
+    };
+  }
+  
+  render() {
+    return (
+      <button onClick={ () => this.setState({ counter: this.state.counter + 1 }) }>{ this.state.counter }</button>
+    )
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
new file mode 100644
index 0000000..ee21a9c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
@@ -0,0 +1,26 @@
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+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 {
+    demoApp: IDemoAppStoreState
+  }
+}
+
+const actionHandlers = {
+  listAuthors: listAuthorsHandler,
+  editAuthor: editAuthorHandler,
+};
+
+export const demoAppRootHandler = combineActionHandler <IDemoAppStoreState>(actionHandlers);
+export default demoAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
new file mode 100644
index 0000000..2f00b0d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
@@ -0,0 +1,16 @@
+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/apps/demoApp/src/handlers/listAuthorsHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
new file mode 100644
index 0000000..74228dd
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
@@ -0,0 +1,40 @@
+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/apps/demoApp/src/index.html b/sdnr/wt/odlux/apps/demoApp/src/index.html
new file mode 100644
index 0000000..e85bcbb
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/index.html
@@ -0,0 +1,25 @@
+<!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");
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/models/author.ts b/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
new file mode 100644
index 0000000..7e28ae8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
@@ -0,0 +1,19 @@
+/**
+ * Represents an author.
+ */
+export interface IAuthor {
+  /**
+   * Defines the unique id of the autor. 
+   */
+  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/apps/demoApp/src/plugin.tsx b/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
new file mode 100644
index 0000000..f450275
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
@@ -0,0 +1,37 @@
+import * as React from "react"; 
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faAddressBook, faRegistered } from '@fortawesome/free-solid-svg-icons';
+
+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() {
+  const applicationApi = applicationManager.registerApplication({
+    name: "demoApp",
+    icon: faAddressBook,
+    rootComponent: FinalApp,
+    rootActionHandler: demoAppRootHandler,
+    exportedComponents: { counter: Counter },
+    menuEntry: "Demo App"
+  });
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts b/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
new file mode 100644
index 0000000..d266f6b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
@@ -0,0 +1,55 @@
+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/apps/demoApp/src/views/authorsList.tsx b/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
new file mode 100644
index 0000000..b192fcc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
@@ -0,0 +1,70 @@
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import Table from '@material-ui/core/Table';
+import TableBody from '@material-ui/core/TableBody';
+import TableCell from '@material-ui/core/TableCell';
+import TableHead from '@material-ui/core/TableHead';
+import TableRow from '@material-ui/core/TableRow';
+import Paper from '@material-ui/core/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 (
+      <Paper>
+        <Table >
+          <TableHead>
+            <TableRow>
+              <TableCell numeric>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) => {
+    author && this.props.history.push(this.props.match.path + '/' + author.id);
+  };
+}
+
+export const AuthorsList = withRouter(
+  connect(
+    ({ demoApp: state }) => ({
+      authors: state.listAuthors.authors,
+      busy: state.listAuthors.busy
+    }),
+    (dispatcher) => ({
+      onLoadAllAuthors: () => {
+        dispatcher.dispatch(loadAllAuthorsAsync)
+      }
+    }))(AuthorsListComponent));
+export default AuthorsList;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx b/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
new file mode 100644
index 0000000..31bfafc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
@@ -0,0 +1,17 @@
+import * as 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/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..91f6002
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/tsconfig.json b/sdnr/wt/odlux/apps/demoApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/demoApp/webpack.config.js b/sdnr/wt/odlux/apps/demoApp/webpack.config.js
new file mode 100644
index 0000000..61dd8f6
--- /dev/null
+++ b/sdnr/wt/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/apps/faultApp/.babelrc b/sdnr/wt/odlux/apps/faultApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json
new file mode 100644
index 0000000..80d7f7f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/package.json
@@ -0,0 +1,40 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*"
+   },
+  "peerDependencies": {
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml
new file mode 100644
index 0000000..bdb98a6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-faultApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-faultApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts
new file mode 100644
index 0000000..be49085
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts
@@ -0,0 +1,16 @@
+import { Action } from '../../../../framework/src/flux/action';
+
+import { Fault } from '../models/fault';
+
+export class FaultApplicationBaseAction extends Action { }
+
+
+export class AddFaultNotificationAction extends FaultApplicationBaseAction {
+  constructor(public fault:Fault) {
+    super();
+  }
+}
+
+export class ResetFaultNotificationsAction extends FaultApplicationBaseAction {
+ 
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
new file mode 100644
index 0000000..dea07a0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
@@ -0,0 +1,9 @@
+import { Action } from '../../../../framework/src/flux/action';
+import { PanelId } from '../models/panelId';
+
+export class SetPanelAction extends Action {
+  constructor(public panelId: PanelId) {
+    super();
+  }
+}
+
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
new file mode 100644
index 0000000..0b97420
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
@@ -0,0 +1,24 @@
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault, FaultLog } from '../models/fault';
+
+export interface IAlarmLogEntriesState extends IExternalTableState<Fault> { }
+
+// create eleactic search material data fetch handler
+const alarmLogEntriesSearchHandler = createSearchDataHandler<FaultLog, Fault>(
+  'sdnevents/faultlog',
+  null,
+  (hit) => ({ _id: hit._id, ...hit._source.fault }),
+  (name) => `fault.${ name }`
+);
+
+export const {
+  actionHandler: alarmLogEntriesActionHandler,
+  createActions: createAlarmLogEntriesActions,
+  createProperties: createAlarmLogEntriesProperties,
+  reloadAction: alarmLogEntriesReloadAction,
+
+  // set value action, to change a value 
+} = createExternal<Fault>(alarmLogEntriesSearchHandler, appState => appState.faultApp.alarmLogEntries);
+
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts
new file mode 100644
index 0000000..6bbe297
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts
@@ -0,0 +1,24 @@
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { FaultResult, Fault } from '../models/fault';
+
+export interface ICurrentProblemsState extends IExternalTableState<Fault> { }
+
+// create eleactic search material data fetch handler
+const currentProblemsSearchHandler = createSearchDataHandler<FaultResult, Fault>(
+    'sdnevents/faultcurrent',
+    null,
+    (hit) => ({ _id: hit._id, ...hit._source.faultCurrent }),
+    (name) => `faultCurrent.${name}`
+  );
+
+export const {
+  actionHandler: currentProblemsActionHandler,
+  createActions: createCurrentProblemsActions,
+  createProperties: createCurrentProblemsProperties,
+  reloadAction: currentProblemsReloadAction,
+
+  // set value action, to change a value 
+} = createExternal<Fault>(currentProblemsSearchHandler, appState => appState.faultApp.currentProblems);
+
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
new file mode 100644
index 0000000..005e3e5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -0,0 +1,42 @@
+// 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 { IFaultNotifications, faultNotificationsHandler } from './notificationsHandler';
+import { ICurrentProblemsState, currentProblemsActionHandler } from './currentProblemsHandler';
+import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler';
+import { SetPanelAction } from '../actions/panelChangeActions';
+
+export interface IFaultAppStoreState {
+  currentProblems: ICurrentProblemsState;
+  faultNotifications: IFaultNotifications;
+  alarmLogEntries: IAlarmLogEntriesState;
+  currentOpenPanel: string|null;
+}
+
+const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
+  if (action instanceof SetPanelAction) {
+    state = action.panelId;
+  }
+  return state;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    faultApp: IFaultAppStoreState;
+  }
+}
+
+const actionHandlers = {
+  currentProblems: currentProblemsActionHandler,
+  faultNotifications: faultNotificationsHandler,
+  alarmLogEntries: alarmLogEntriesActionHandler,
+  currentOpenPanel: currentOpenPanelHandler
+};
+
+export const faultAppRootHandler = combineActionHandler<IFaultAppStoreState>(actionHandlers);
+export default faultAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
new file mode 100644
index 0000000..b73ed14
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
@@ -0,0 +1,30 @@
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions';
+import { Fault } from '../models/fault';
+
+export interface IFaultNotifications {
+  faults: Fault[];
+  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/apps/faultApp/src/index.html b/sdnr/wt/odlux/apps/faultApp/src/index.html
new file mode 100644
index 0000000..5f6794f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/index.html
@@ -0,0 +1,25 @@
+<!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"], function (app, faultApp) {
+      faultApp.register();
+      app("./app.tsx");
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
new file mode 100644
index 0000000..ecd0c99
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
@@ -0,0 +1,14 @@
+export type FaultType = {
+  nodeName: string;
+  counter: string;
+  timeStamp: string;
+  objectId: string;
+  problem: string;
+  severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical' ;
+  type: string;
+}
+export type FaultResult = { faultCurrent: FaultType };
+
+export type FaultLog = { fault: FaultType };
+
+export type Fault = FaultType & { _id: string };
diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
new file mode 100644
index 0000000..56f117a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
@@ -0,0 +1 @@
+export type PanelId = null | "CurrentProblem" | "AlarmNotifications" | "AlarmLog";
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/plugin.tsx b/sdnr/wt/odlux/apps/faultApp/src/plugin.tsx
new file mode 100644
index 0000000..6f83e74
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/plugin.tsx
@@ -0,0 +1,78 @@
+// app configuration and main entry point for the app
+
+
+import * as React from "react"; 
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { faBell } from '@fortawesome/free-solid-svg-icons';  // select app icon
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+
+import { faultAppRootHandler } from './handlers/faultAppRootHandler';
+import { FaultApplication } from "./views/faultApplication";
+
+import { Fault } from "./models/fault";
+import { PanelId } from "./models/panelId";
+
+import { SetPanelAction } from "./actions/panelChangeActions";
+import { AddFaultNotificationAction } from "./actions/notificationActions";
+
+import { createCurrentProblemsProperties, createCurrentProblemsActions } from "./handlers/currentProblemsHandler";
+
+let currentMountId: string | undefined = undefined; 
+
+const mapProps = (state: IApplicationStoreState) => ({
+  currentProblemsProperties: createCurrentProblemsProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch, true),
+  setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId))
+});
+
+const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+  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("CurrentProblem");
+        props.currentProblemsActions.onFilterChanged("objectId", currentMountId);
+        props.currentProblemsProperties.showFilter || (props.currentProblemsActions.onToggleFilter());
+        props.currentProblemsActions.onRefresh();
+      }
+    });
+  }
+  return (
+    <FaultApplication />
+  )
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+  <Switch>
+    <Route path={ `${ props.match.path }/:mountId?` } component={ FaultApplicationRouteAdapter } /> 
+    <Redirect to={ `${ props.match.path }` } />
+   </Switch>
+)); 
+ 
+export function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: "faultApp",
+    icon: faBell,
+    rootComponent: App,
+    rootActionHandler: faultAppRootHandler,
+    menuEntry: "Fault"
+  });
+
+  // subscribe to the websocket notifications
+  subscribe<Fault & IFormatedMessage>("ProblemNotification", (fault => {
+    const store = applicationApi && applicationApi.applicationStore;
+    if (fault && store) {
+      store.dispatch(new AddFaultNotificationAction(fault));
+    }
+  }));
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
new file mode 100644
index 0000000..9eb3a00
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -0,0 +1,114 @@
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';  
+
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { Panel } from '../../../../framework/src/components/material-ui';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { Fault } from '../models/fault';
+import { PanelId } from '../models/panelId';
+
+import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
+import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
+import { SetPanelAction } from '../actions/panelChangeActions';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  activePanel: state.faultApp.currentOpenPanel,
+  currentProblemsProperties: createCurrentProblemsProperties(state),
+  faultNotifications: state.faultApp.faultNotifications,
+  alarmLogEntriesProperties: createAlarmLogEntriesProperties(state)
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch),
+  alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch),
+  reloadCurrentProblems: () => dispatcher.dispatch(currentProblemsReloadAction),
+  reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
+  setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId))
+});
+
+type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
+
+
+const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
+
+class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps>{
+   
+  render(): JSX.Element {
+    
+    const { activePanel } = this.props;
+    
+    const onTogglePanel = (panelId: PanelId) => {
+      const nextActivePanel = panelId === this.props.activePanel ? null : panelId;
+      this.props.setCurrentPanel(nextActivePanel);
+      
+      switch (nextActivePanel) {
+        case 'CurrentProblem':
+          this.props.reloadCurrentProblems();
+          break;
+        case 'AlarmLog':
+          this.props.reloadAlarmLogEntries();
+          break;
+        case 'AlarmNotifications':
+        case null:
+        default:
+          // nothing to do
+          break;
+      }
+    };
+
+    return (
+      <>
+        <Panel activePanel={ activePanel } panelId={ 'CurrentProblem' } onToggle={ onTogglePanel } title={ 'Current Problem List' }>
+          <FaultTable idProperty={ '_id' }  columns={ [ 
+              { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+              { property: "timeStamp", type: ColumnType.text, title: "Time Stamp" },
+              { property: "nodeName", 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 },
+              { property: "severity", title: "Severity", type: ColumnType.text, width: "140px" },
+              ] } { ...this.props.currentProblemsProperties } { ...this.props.currentProblemsActions }  />
+        </Panel>
+        <Panel activePanel={ activePanel } panelId={ 'AlarmNotifications' } onToggle={ onTogglePanel } title={ `Alarm Notifications ${this.props.faultNotifications.faults.length} ${this.props.faultNotifications.since}` }>
+          <FaultTable rows={ this.props.faultNotifications.faults } asynchronus columns={ [
+            { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+            { property: "timeStamp", title: "Time Stamp" },
+            { property: "nodeName", title: "Node Name" },
+            { property: "counter", title: "Count", width: "100px" },
+            { property: "objectId", title: "Object Id" },
+            { property: "problem", title: "Alarm Type" },
+            { property: "severity", title: "Severity", width: "140px" },
+            ] } idProperty={ '_id' } />
+        </Panel>
+        <Panel activePanel={ activePanel } panelId={ 'AlarmLog' } onToggle={ onTogglePanel } title={ 'Alarm Log' }>
+          <FaultTable idProperty={ '_id' } columns={ [
+            { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+            { property: "timeStamp", title: "Time Stamp" },
+            { property: "nodeName", title: "Node Name" },
+            { property: "counter", title: "Count", type: ColumnType.numeric, width: "100px" },
+            { property: "objectId", title: "Object Id" },
+            { property: "problem", title: "Alarm Type" },
+            { property: "severity", title: "Severity", width: "140px" },
+          ] } { ...this.props.alarmLogEntriesProperties } { ...this.props.alarmLogEntriesActions }/>
+         </Panel>
+      </>
+    );
+  };
+
+  private renderIcon = (props: { rowData: Fault }) => {
+    return (
+      <FontAwesomeIcon icon={ faExclamationTriangle } /> 
+    );
+  }; 
+
+}
+
+export const FaultApplication = withRouter(connect(mapProps, mapDisp)(FaultApplicationComponent));
+export default FaultApplication;
diff --git a/sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..e7c262b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="faultApp"/>
+         <property name="index" value="10"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/tsconfig.json b/sdnr/wt/odlux/apps/faultApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/faultApp/webpack.config.js b/sdnr/wt/odlux/apps/faultApp/webpack.config.js
new file mode 100644
index 0000000..a0284c5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/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: {
+      faultApp: ["./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: {
+        "/database": {
+          target: "http://localhost:8181",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/.babelrc b/sdnr/wt/odlux/apps/helpApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/helpApp/package.json b/sdnr/wt/odlux/apps/helpApp/package.json
new file mode 100644
index 0000000..a1bcc39
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/package.json
@@ -0,0 +1,45 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*",
+     "marked" : "0.6.0",
+     "@types/marked": "0.6.0",
+     "highlight.js" : "9.13.1",
+     "@types/highlight.js": "9.12.3",
+     "github-markdown-css": "2.10.0"
+   },
+  "peerDependencies": {
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/pom.xml b/sdnr/wt/odlux/apps/helpApp/pom.xml
new file mode 100644
index 0000000..439e05a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-helpApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-helpApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts b/sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts
new file mode 100644
index 0000000..ba8969a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts
@@ -0,0 +1,61 @@
+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/apps/helpApp/src/components/markdown.tsx b/sdnr/wt/odlux/apps/helpApp/src/components/markdown.tsx
new file mode 100644
index 0000000..ea272bc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/components/markdown.tsx
@@ -0,0 +1,60 @@
+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/apps/helpApp/src/components/subMenuEntry.tsx b/sdnr/wt/odlux/apps/helpApp/src/components/subMenuEntry.tsx
new file mode 100644
index 0000000..72bb39e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/components/subMenuEntry.tsx
@@ -0,0 +1,37 @@
+import * as React from 'react';
+
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { TreeView, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView';
+
+import { ListItemText } from '@material-ui/core';
+
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+import { TocTreeNode } from '../models/tocNode';
+
+const TocTree = TreeView as any as TreeViewCtorType<TocTreeNode>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+  helpToc: state.helpApp.toc,
+  helpBusy: state.helpApp.busy
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  requestDocument: (node: TocTreeNode) => dispatcher.dispatch(new NavigateToApplication("helpApp", node.uri))
+});
+
+const SubMenuEntryComponent: React.SFC<Connect<typeof mapProps, typeof mapDisp>> = (props) => {
+  return props.helpToc
+  ? (
+    <TocTree items={ props.helpToc } contentProperty={ "label" } childrenProperty={ "nodes" } depthOffset={ 1 } 
+        useFolderIcons={ false } enableSearchBar={ false } onItemClick={ props.requestDocument } />
+    )
+  : ( 
+    <ListItemText >Loading ...</ListItemText>   
+  )  
+};
+
+export const SubMenuEntry = connect(mapProps, mapDisp)(SubMenuEntryComponent);
+export default SubMenuEntry;
+
diff --git a/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts b/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
new file mode 100644
index 0000000..efdc6e8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
@@ -0,0 +1,58 @@
+// main state handler
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { TocTreeNode } from 'models/tocNode';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { LoadTocAction, TocLoadedAction, LoadDocumentAction, DocumentLoadedAction } from '../actions/helpActions';
+
+export interface IHelpAppStoreState {
+  busy: boolean;
+  toc: TocTreeNode[] | undefined;
+  content: string | undefined;
+  currentPath: string | undefined;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    helpApp: IHelpAppStoreState
+  }
+}
+
+const helpAppStoreStateInit: IHelpAppStoreState = {
+  busy: false,
+  toc: undefined,
+  content: undefined, 
+  currentPath: undefined
+};
+
+export const helpAppRootHandler: IActionHandler<IHelpAppStoreState> = (state = helpAppStoreStateInit, 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/apps/helpApp/src/index.html b/sdnr/wt/odlux/apps/helpApp/src/index.html
new file mode 100644
index 0000000..2d20410
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/index.html
@@ -0,0 +1,25 @@
+<!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) {
+      helpApp.register();
+      app("./app.tsx")
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts b/sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts
new file mode 100644
index 0000000..ae73ec4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts
@@ -0,0 +1,24 @@
+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 = {
+  label: string;
+  uri: string;
+  nodes?: TocTreeNode[];
+  disabled?: boolean;
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx b/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
new file mode 100644
index 0000000..d1cf808
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
@@ -0,0 +1,69 @@
+// app configuration and main entry point for the app
+
+import * as React from "react"; 
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faFirstAid } from '@fortawesome/free-solid-svg-icons';  // select app icon
+
+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 { SubMenuEntry } from "./components/subMenuEntry";
+
+import '!style-loader!css-loader!highlight.js/styles/default.css';
+
+const mapProps = (state: IApplicationStoreState) => ({
+  
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  requestDocument: (path: string) => {
+    dispatcher.dispatch(requestDocumentAsyncActionCreator(path));
+  }
+});
+
+let currentHelpPath: string | undefined = undefined;
+
+const HelpApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ '0'?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+  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 path={ `${ props.match.path }/*` } component={ HelpApplicationRouteAdapter } />
+    <Redirect to={ `${ props.match.path }` } />
+  </Switch>
+));
+
+export async function register() {
+  const applicationApi = applicationManager.registerApplication({
+    name: "helpApp",
+    icon: faFirstAid,
+    rootComponent: App,
+    rootActionHandler: helpAppRootHandler,
+    menuEntry: "Help",
+    subMenuEntry: SubMenuEntry
+  });
+
+  // start the initial toc request after the application store is initalized
+  const store = await applicationApi.applicationStoreInitialized; 
+  store.dispatch(requestTocAsyncAction);
+
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts b/sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts
new file mode 100644
index 0000000..480cdd0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts
@@ -0,0 +1,47 @@
+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');
+    if (result !== false) {
+      const mapNodesCollection = (col: TocNodeCollection): TocTreeNode[] => {
+        return Object.keys(col).reduce <TocTreeNode[]>((acc, key) => {
+          const current = col[key];
+          acc.push({
+            label: current.label,
+            uri: current.versions.current.path,
+            nodes: current.nodes && mapNodesCollection(current.nodes) || undefined
+          });
+          return acc;
+        }, []);
+      }
+
+      this.tocNodeCollection = result && mapNodesCollection(result);
+    }
+    return this.tocNodeCollection  || null;
+  }
+}
+
+export const helpService = new HelpService();
+export default helpService;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts b/sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts
new file mode 100644
index 0000000..3cc58a2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts
@@ -0,0 +1,62 @@
+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/apps/helpApp/src/views/helpApplication.tsx b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
new file mode 100644
index 0000000..dedb936
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
@@ -0,0 +1,53 @@
+import * as 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.helpApp.content,
+  currentPath: state.helpApp.currentPath
+});
+
+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('#/helpApp/', 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 ? (
+      <Markdown text={ this.props.content } markedOptions={ { renderer: this.renderer } } className="markdown-body" 
+         style={{ maxWidth: "960px", margin: "1.5em auto" }} />
+    ) : (<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/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..a0e3dac
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="helpApp"/>
+        <property name="index" value="100"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/tsconfig.json b/sdnr/wt/odlux/apps/helpApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/helpApp/webpack.config.js b/sdnr/wt/odlux/apps/helpApp/webpack.config.js
new file mode 100644
index 0000000..fdae7d9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/webpack.config.js
@@ -0,0 +1,153 @@
+/**
+ * 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]
+          }
+        }]
+      }]
+    },
+
+    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: {
+        "/help": {
+          target: "http://localhost:8181",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/.babelrc b/sdnr/wt/odlux/apps/inventoryApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/inventoryApp/package.json b/sdnr/wt/odlux/apps/inventoryApp/package.json
new file mode 100644
index 0000000..8f77c4b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/package.json
@@ -0,0 +1,40 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*"
+   },
+  "peerDependencies": {
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/pom.xml b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
new file mode 100644
index 0000000..8a3b35d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-inventoryApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-inventoryApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/index.html b/sdnr/wt/odlux/apps/inventoryApp/src/index.html
new file mode 100644
index 0000000..d24358e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/index.html
@@ -0,0 +1,25 @@
+<!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"], function (app, inventoryApp) {
+      inventoryApp.register();
+      app("./app.tsx");
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
new file mode 100644
index 0000000..c8c9c57
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
@@ -0,0 +1,17 @@
+export { HitEntry, Result } from '../../../../framework/src/models';
+export type InventoryType = {
+  treeLevel: number;
+  parentUuid: string;
+  mountpoint: string;
+  uuid: string;
+  containedHolder?: (string)[] | null;
+  manufacturerName?: string ;
+  manufacturerIdentifier: string;
+  serial: string;
+  date: string;
+  version: string;
+  description: string;
+  partTypeId: string;
+  modelIdentifier: string;
+  typeName: string;
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/plugin.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/plugin.tsx
new file mode 100644
index 0000000..52e1d48
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/plugin.tsx
@@ -0,0 +1,17 @@
+// app configuration and main entry point for the app
+
+
+import { faShoppingBag } from '@fortawesome/free-solid-svg-icons';  // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { Dashboard } from  './views/dashboard';
+
+export function register() {
+  applicationManager.registerApplication({
+    name: "inventoryApp",
+    icon: faShoppingBag,
+    rootComponent: Dashboard,
+    menuEntry: "Inventory App"
+  });
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
new file mode 100644
index 0000000..8d07fa8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
@@ -0,0 +1,73 @@
+import * as React from "react";
+import { MaterialTable, DataCallback, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+
+import { Result, InventoryType } from '../models/inventory';
+
+
+const url = `${ window.location.origin}/database/sdnevents/inventoryequipment/_search`;
+
+const fetchData: DataCallback = async (page, rowsPerPage, orderBy, order, filter) => { 
+  const from = rowsPerPage && page != null && !isNaN(+page)
+    ? (+page) * rowsPerPage
+    : null;
+
+  const filterKeys = filter && Object.keys(filter) || [];
+  
+  const query = {
+    ...filterKeys.length > 0 ? {
+      query: {
+        bool: {
+          must: filterKeys.reduce((acc, cur) => {
+            if (acc && filter && filter[cur]) {
+              acc.push({ [filter[cur].indexOf("*") > -1 || filter[cur].indexOf("?") > -1 ? "wildcard" : "prefix"]: { [cur]: filter[cur] } });
+            }
+            return acc;
+          }, [] as any[])
+        }
+      }
+    }: { "query": { "match_all": {} } },
+    ...rowsPerPage ? { "size": rowsPerPage } : {} ,
+    ...from ? { "from": from } : {},
+    ...orderBy && order ? { "sort": [{ [orderBy]: order }] } : {},
+  };
+  
+  const result = await fetch(url, {
+    method: "POST",       // *GET, POST, PUT, DELETE, etc.
+    mode: "no-cors",      // no-cors, cors, *same-origin
+    cache: "no-cache",    // *default, no-cache, reload, force-cache, only-if-cached
+    headers: {
+      "Content-Type": "application/json; charset=utf-8",
+      // "Content-Type": "application/x-www-form-urlencoded",
+    },
+    body: JSON.stringify(query), // body data type must match "Content-Type" header
+  });
+
+  if (result.ok) {
+    const queryResult: Result<InventoryType> = await result.json();
+    const data = {
+      page: Math.min(page || 0, queryResult.hits.total || 0 / (rowsPerPage || 1)), rowCount: queryResult.hits.total, rows: queryResult && queryResult.hits && queryResult.hits.hits && queryResult.hits.hits.map(h => (
+      { ...h._source, _id: h._id }
+      )) || []
+    };
+    return data;
+  }
+
+  return { page: 0, rowCount: 0, rows: [] };
+};
+
+const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & {_id: string}>;
+
+export const Dashboard : React.SFC = (props) => (
+  <InventoryTable onRequestData={ fetchData } columns={ [
+    { property: "uuid", title: "Name" },
+    { property: "parentUuid", title: "Parent" },
+    { property: "mountpoint", title: "Mountpoint" },
+    { property: "manufacturerIdentifier", title: "Manufacturer" },
+    { property: "serial", title: "Serial" },
+    { property: "typeName", title: "Type" },
+  ] } title="Inventory" idProperty="_id" >
+
+  </InventoryTable>
+);
+
+export default Dashboard;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
new file mode 100644
index 0000000..3f0ffcc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
@@ -0,0 +1,24 @@
+import * as React from "react";
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import Button from '@material-ui/core/Button';
+import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles'; // infra for styling
+
+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 className={ props.classes.warnButton } variant={"contained"}>Stop</Button>
+  </div>
+)));
+
+export default Detail;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..f0bf054
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="inventoryApp"/>
+         <property name="index" value="70"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json b/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/inventoryApp/webpack.config.js b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
new file mode 100644
index 0000000..e992a10
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/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: {
+      inventoryApp: ["./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: {
+        "/database": {
+          target: "http://localhost:8181",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/.babelrc b/sdnr/wt/odlux/apps/mediatorApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/mediatorApp/package.json b/sdnr/wt/odlux/apps/mediatorApp/package.json
new file mode 100644
index 0000000..a67c08a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/package.json
@@ -0,0 +1,41 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*"
+   },
+  "peerDependencies": {
+    "@fortawesome/free-solid-svg-icons": "5.6.3",
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
new file mode 100644
index 0000000..14bd084
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.1.2</version>
+		<relativePath />
+	</parent>
+
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-mediatorApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts
new file mode 100644
index 0000000..4cbad42
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts
@@ -0,0 +1,41 @@
+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/apps/mediatorApp/src/actions/mediatorConfigActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts
new file mode 100644
index 0000000..fcfc63e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts
@@ -0,0 +1,137 @@
+
+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 { mediatorApp: { mediatorServerState: { url } } } = getState();
+  if (url) {
+    mediatorService.startMediatorByName(url, 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(url, 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 { mediatorApp: { mediatorServerState: { url } } } = getState();
+  if (url) {
+    mediatorService.stopMediatorByName(url, 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(url, 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 { mediatorApp: { mediatorServerState: { url } } } = getState();
+  if (url) {
+    mediatorService.createMediatorConfig(url, 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(url, 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 { mediatorApp: { mediatorServerState: { url } } } = getState();
+  if (url) {
+    mediatorService.deleteMediatorConfigByName(url, 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(url, 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/apps/mediatorApp/src/actions/mediatorServerActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts
new file mode 100644
index 0000000..b8e8c7e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts
@@ -0,0 +1,84 @@
+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 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 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("mediatorApp"));
+      return; 
+    }
+    dispatch(new SetMediatorServerInfo(mediatorServer.name, mediatorServer.url));
+  
+    mediatorService.getMediatorServerVersion(mediatorServer.url).then(versionInfo => {
+      dispatch(new SetMediatorServerVersion(versionInfo));
+    });
+
+    Promise.all([
+      mediatorService.getMediatorServerAllConfigs(mediatorServer.url),
+      mediatorService.getMediatorServerSupportedDevices(mediatorServer.url)
+    ]).then(([configurations,supportedDevices]) => {
+      dispatch(new SetAllMediatorServerConfigurations(configurations));
+      dispatch(new SetMediatorServerSupportedDevices(supportedDevices));
+      dispatch(new SetMediatorServerBusy(false));
+    });
+  });
+};
+
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx
new file mode 100644
index 0000000..889b05e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx
@@ -0,0 +1,315 @@
+import * as React from 'react';
+import { Theme, createStyles, WithStyles, withStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Select from '@material-ui/core/Select';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import Tabs from '@material-ui/core/Tabs';
+import Tab from '@material-ui/core/Tab';
+
+import Fab from '@material-ui/core/Fab';
+import AddIcon from '@material-ui/icons/Add';
+import DeleteIcon from '@material-ui/icons/Delete';
+import IconButton from '@material-ui/core/IconButton';
+
+import { addMediatorConfigAsyncActionCreator, updateMediatorConfigAsyncActionCreator, removeMediatorConfigAsyncActionCreator } from '../actions/mediatorConfigActions';
+import { MediatorConfig, ODLConfig } from '../models/mediatorServer';
+import FormControl from '@material-ui/core/FormControl';
+import InputLabel from '@material-ui/core/InputLabel';
+import MenuItem from '@material-ui/core/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.unit,
+    right: theme.spacing.unit,
+  },
+  title: {
+    fontSize: 14,
+  },
+  center: {
+    flex: "1",
+    display: "flex",
+    alignItems: "center",
+    justifyContent: "center",
+  },
+  alignInOneLine: {
+    display: 'flex',
+    flexDirection: 'row'
+  },
+  left: {
+    marginRight: theme.spacing.unit,
+  },
+  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.mediatorApp.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 Medator Configuration",
+    dialogDescription: "",
+    applyButtonText: "Add",
+    cancelButtonText: "Cancel",
+    readonly: false,
+    readonlyName: false,
+  },
+  [EditMediatorConfigDialogMode.EditMediatorConfig]: {
+    dialogTitle: "Edit Medator 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 };
+
+class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConfigDialogComponentProps, EditMediatorConfigDialogComponentState> {
+  constructor (props: EditMediatorConfigDialogComponentProps) {
+    super(props);
+
+    this.state = {
+      ...this.props.mediatorConfig,
+      activeTab: 0,
+      activeOdlConfig: ""
+    };
+  }
+
+  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="primary" textColor="primary" onChange={(event, value) => this.setState({ activeTab: value })} >
+            <Tab label="Config" />
+            <Tab label="ODL AutoConnect" />
+          </Tabs>
+          { this.state.activeTab === 0 ? <TabContainer >
+            <TextField 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 fullWidth disabled={setting.readonly}>
+              <InputLabel htmlFor="deviceType">Device</InputLabel>
+              <Select value={this.state.DeviceType} onChange={(event) => {
+                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 disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ipAddress" label="IP Address" type="text" fullWidth value={this.state.DeviceIp} onChange={(event) => { this.setState({ DeviceIp: event.target.value }); }} />
+            <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="devicePort" label="Port" type="number" fullWidth value={this.state.DevicePort || ""} onChange={(event) => { this.setState({ DevicePort: +event.target.value }); }} />
+            <TextField 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 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 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 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)
+                    ]
+                  });
+                }} ><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 || "") })} >
+                    <div className={classes.alignInOneLine}>
+                    <FormControl className={classes.left} margin={"dense"} >
+                        <InputLabel htmlFor={`protocol-${ind}`}>Protocoll</InputLabel>
+                        <Select value={cfg.Protocol} onChange={ this.odlConfigValueChangeHandlerCreator(ind, "Protocol", e => (e.target.value)) } inputProps={{ name: `protocol-${ind}`, id: `protocol-${ind}` }} fullWidth >
+                          <MenuItem value={"http"}>http</MenuItem>
+                          <MenuItem value={"https"}>https</MenuItem>
+                        </Select>
+                      </FormControl>
+                      <TextField 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 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>
+                    <div className={classes.alignInOneLine}>
+                      <TextField 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 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>
+                );
+              })
+              : <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 onClick={(event) => {
+            this.onApply(Object.keys(this.state).reduce<MediatorConfig & { [kex: string]: any }>((acc, key) => {
+              // do not copy activeTab and activeOdlConfig
+              if (key !== "activeTab" && key !== "activeOdlConfig" && key !== "_initialMediatorConfig") acc[key] = (this.state as any)[key];
+              return acc;
+            }, {} as MediatorConfig));
+            event.preventDefault();
+            event.stopPropagation();
+          }} > {setting.applyButtonText} </Button>
+          <Button onClick={(event) => {
+            this.onCancel();
+            event.preventDefault();
+            event.stopPropagation();
+          }} color="secondary"> {setting.cancelButtonText} </Button>
+        </DialogActions>
+      </Dialog>
+    )
+  }
+
+  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;
+
+
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
new file mode 100644
index 0000000..3937e97
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
@@ -0,0 +1,156 @@
+import * as React from 'react';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { addAvaliableMediatorServerAsyncActionCreator, removeAvaliableMediatorServerAsyncActionCreator, updateAvaliableMediatorServerAsyncActionCreator } from '../actions/avaliableMediatorServersActions';
+import { MediatorServer } from '../models/mediatorServer';
+
+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 Medator Server",
+    dialogDescription: "",
+    applyButtonText: "Add",
+    cancelButtonText: "Cancel",
+    readonly: false,
+  },
+  [EditMediatorServerDialogMode.EditMediatorServer]: {
+    dialogTitle: "Edit Medator 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;
+};
+
+type EditMediatorServerDialogComponentState = MediatorServer ;
+
+class EditMediatorServerDialogComponent extends React.Component<EditMediatorServerDialogComponentProps, EditMediatorServerDialogComponentState> {
+  constructor(props: EditMediatorServerDialogComponentProps) {
+    super(props);
+    
+    this.state = {
+      ...this.props.mediatorServer
+    };
+  }
+
+  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 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 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}); } }/>
+         </DialogContent>
+        <DialogActions>
+          <Button onClick={ (event) => {
+            this.onApply({
+              _id: this.state._id,
+              name: this.state.name,
+              url: this.state.url,
+            });
+            event.preventDefault();
+            event.stopPropagation();
+          } } > { setting.applyButtonText } </Button>
+          <Button onClick={ (event) => {
+            this.onCancel();
+            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/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts
new file mode 100644
index 0000000..447e5e5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts
@@ -0,0 +1,19 @@
+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.mediatorApp.avaliableMediatorServers);
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts
new file mode 100644
index 0000000..bfebbdf
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts
@@ -0,0 +1,26 @@
+// 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 {
+    mediatorApp: IMediatorAppStoreState
+  }
+}
+
+const actionHandlers = {
+  avaliableMediatorServers: avaliableMediatorServersActionHandler,
+  mediatorServerState: mediatorServerHandler,
+};
+
+export const mediatorAppRootHandler = combineActionHandler<IMediatorAppStoreState>(actionHandlers);
+export default mediatorAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts
new file mode 100644
index 0000000..2d3f71c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts
@@ -0,0 +1,96 @@
+import { XmlFileInfo, MediatorConfig, BusySymbol, MediatorConfigResponse, MediatorServerDevice } from "../models/mediatorServer";
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { SetMediatorServerVersion, SetMediatorServerInfo, SetAllMediatorServerConfigurations, SetMediatorServerBusy, SetMediatorServerSupportedDevices } from "../actions/mediatorServerActions";
+import { SetMediatorBusyByName, UpdateMediatorConfig, AddMediatorConfig, RemoveMediatorConfig } from "../actions/mediatorConfigActions";
+
+export type MediatorServerState = {
+  busy: boolean;
+  name: string| null ;
+  url: string | null;
+  serverVersion: string| null;
+  mediatorVersion: string| null;
+  nexmls: XmlFileInfo[]; 
+  configurations: MediatorConfigResponse[]; 
+  supportedDevices: MediatorServerDevice[];
+}
+
+const mediatorServerInit: MediatorServerState = {
+  busy: false,
+  name: null,
+  url: null,
+  serverVersion : null,
+  mediatorVersion: null,
+  nexmls: [],
+  configurations: [], 
+  supportedDevices: []
+}
+
+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,
+    };
+  } 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)
+      ] 
+    };
+  }
+  return state;
+} 
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/index.html b/sdnr/wt/odlux/apps/mediatorApp/src/index.html
new file mode 100644
index 0000000..95bf9ec
--- /dev/null
+++ b/sdnr/wt/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/apps/mediatorApp/src/models/mediatorServer.ts b/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts
new file mode 100644
index 0000000..ff084b0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts
@@ -0,0 +1,60 @@
+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/apps/mediatorApp/src/plugin.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
new file mode 100644
index 0000000..0878fee
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
@@ -0,0 +1,66 @@
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faGlobe } from '@fortawesome/free-solid-svg-icons';  // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+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";
+
+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: "mediatorApp",
+    icon: faGlobe,
+    rootComponent: FinalApp,
+    rootActionHandler: mediatorAppRootHandler,
+    menuEntry: "Mediator App"
+  });
+
+  // prefetch all avaliable mediator servers
+  applicationApi.applicationStoreInitialized.then(applicationStore => {
+    applicationStore.dispatch(avaliableMediatorServersReloadAction)
+  });
+};
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts b/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts
new file mode 100644
index 0000000..50fd869
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts
@@ -0,0 +1,149 @@
+import * as $ from 'jquery';
+
+import { requestRest } from '../../../../framework/src/services/restService';
+import { MediatorServer, MediatorServerVersionInfo, MediatorConfig, MediatorServerDevice, MediatorConfigResponse } from '../models/mediatorServer';
+import { HitEntry } from '../../../../framework/src/models';
+
+export const mediatorServerResourcePath = "mwtn/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<MediatorServer | null> {
+    const path = `database/${mediatorServerResourcePath}`;
+    const data = Object.keys(server).reduce((acc, cur) => {
+      if (cur !== "_id") acc[cur] = server[cur];
+      return acc;
+    }, {} as IndexableMediatorServer);
+    const result = await requestRest<MediatorServer>(path, { method: "POST", body: JSON.stringify(data) });
+    return result || null;
+  }
+
+  /**
+    * Updates data into the mediator servers table.
+    */
+  public async updateMediatorServer(server: IndexableMediatorServer): Promise<MediatorServer | null> {
+    const path = `database/${mediatorServerResourcePath}/${server._id}`;
+    const data = Object.keys(server).reduce((acc, cur) => {
+      if (cur !== "_id") { acc[cur] = server[cur] } else { acc["id"] = 0 };
+      return acc;
+    }, {} as IndexableMediatorServer);
+    const result = await requestRest<MediatorServer>(path, { method: "PUT", body: JSON.stringify(data) });
+    return result || null;
+  }
+
+  /**
+    * Deletes data from the mediator servers table.
+    */
+  public async deleteMediatorServer(server: MediatorServer): Promise<MediatorServer | null> {
+    const path = `database/${mediatorServerResourcePath}/${server._id}`;
+    const result = await requestRest<MediatorServer>(path, { method: "DELETE" });
+    return result || null;
+  }
+
+  public async getMediatorServerById(serverId: string): Promise<MediatorServer | null> {
+    const path = `database/${mediatorServerResourcePath}/${serverId}`;
+    const result = await requestRest<HitEntry<MediatorServer> & { found: boolean }>(path, { method: "GET" });
+    return result && result.found && result._source && {
+      _id: result._id,
+      name: result._source.name,
+      url: result._source.url,
+    } || null;
+  }
+
+  // https://cloud-highstreet-technologies.com/wiki/doku.php?id=att:ms:api
+
+  private accassMediatorServer<TData ={}>(mediatorServerUrl: string, task: string, data?: {}): Promise<MediatorServerResponse<TData> | null> {
+    const url = `${mediatorServerUrl}/api/?task=${task}`;
+    // return (await requestRest<{ code: number, data: TData}>(path, { method: "POST" })) || null ;
+    return new Promise<{ code: number, data: TData }>((resolve, reject) => {
+      $.post({
+        url,
+        data: data,
+        //contentType: 'application/json'
+      }).then((result: any) => {
+        if (typeof result === "string") {
+          resolve(JSON.parse(result));
+        } else {
+          resolve(result);
+        };
+      });
+    });
+  }
+
+  public async getMediatorServerVersion(mediatorServerUrl: string): Promise<MediatorServerVersionInfo | null> {
+    const result = await this.accassMediatorServer<MediatorServerVersionInfo>(mediatorServerUrl, 'version');
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerAllConfigs(mediatorServerUrl: string): Promise<MediatorConfigResponse[] | null> {
+    const result = await this.accassMediatorServer<MediatorConfigResponse[]>(mediatorServerUrl, 'getconfig');
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerConfigByName(mediatorServerUrl: string, name: string): Promise<MediatorConfigResponse | null> {
+    const result = await this.accassMediatorServer<MediatorConfigResponse[]>(mediatorServerUrl, 'getconfig', { name } );
+    if (result && result.code === 1 && result.data && result.data.length === 1) return result.data[0];
+    return null;
+  }
+
+  public async getMediatorServerSupportedDevices(mediatorServerUrl: string): Promise<MediatorServerDevice[] | null> {
+    const result = await this.accassMediatorServer<MediatorServerDevice[]>(mediatorServerUrl, 'getdevices' );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async startMediatorByName(mediatorServerUrl: string, name: string): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerUrl, 'start', { name } );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async stopMediatorByName(mediatorServerUrl: string, name: string): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerUrl, 'stop', { name } );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async createMediatorConfig(mediatorServerUrl: string, config: MediatorConfig): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerUrl, 'create', { config: JSON.stringify(config) }  );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async updateMediatorConfigByName(mediatorServerUrl: string, config: MediatorConfig): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerUrl, 'update', { config: JSON.stringify(config) } );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async deleteMediatorConfigByName(mediatorServerUrl: string, name: string): Promise<string | null> {
+    const result = await this.accassMediatorServer<string>(mediatorServerUrl, 'delete', { name } );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+
+  public async getMediatorServerFreeNcPorts(mediatorServerUrl: string, limit?: number): Promise<number[] | null> {
+    const result = await this.accassMediatorServer<number[]>(mediatorServerUrl, 'getncports', { limit } );
+    if (result && result.code === 1) return result.data;
+    return null;
+  }
+  
+  public async getMediatorServerFreeSnmpPorts(mediatorServerUrl: string, limit?: number): Promise<number[] | null> {
+    const result = await this.accassMediatorServer<number[]>(mediatorServerUrl, '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/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
new file mode 100644
index 0000000..11feb46
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
@@ -0,0 +1,220 @@
+import * as React from 'react';
+import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
+
+import AddIcon from '@material-ui/icons/Add';
+import IconButton from '@material-ui/core/IconButton';
+import EditIcon from '@material-ui/icons/Edit';
+import DeleteIcon from '@material-ui/icons/Delete';
+import InfoIcon from '@material-ui/icons/Info';
+import StartIcon from '@material-ui/icons/PlayArrow';
+import StopIcon from '@material-ui/icons/Stop';
+
+import CircularProgress from '@material-ui/core/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';
+
+const styles = (theme: Theme) => createStyles({
+  root: {
+    display: 'flex',
+    flexDirection: 'column',
+    flex: '1',
+  },
+  formControl: {
+    margin: theme.spacing.unit,
+    minWidth: 300,
+  },
+  button: {
+    margin: 0,
+    padding: "6px 6px",
+    minWidth: 'unset'
+  },
+  spacer: {
+    marginLeft: theme.spacing.unit,
+    marginRight: theme.spacing.unit,
+    display: "inline"
+  },
+  progress: {
+    flex: '1 1 100%',
+    display: 'flex',
+    alignItems: 'center',
+    justifyContent: 'center',
+    pointerEvents: 'none'
+  }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+  serverName: state.mediatorApp.mediatorServerState.name,
+  serverUrl: state.mediatorApp.mediatorServerState.url,
+  serverVersion: state.mediatorApp.mediatorServerState.serverVersion,
+  mediatorVersion: state.mediatorApp.mediatorServerState.mediatorVersion,
+  configurations: state.mediatorApp.mediatorServerState.configurations,
+  supportedDevices: state.mediatorApp.mediatorServerState.supportedDevices,
+  busy: state.mediatorApp.mediatorServerState.busy,
+});
+
+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>;
+
+type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type MediatorServerSelectionComponentState = {
+  busy: boolean,
+  mediatorConfigToEdit: MediatorConfig,
+  mediatorConfigEditorMode: EditMediatorConfigDialogMode
+}
+
+class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> {
+
+  constructor (props: MediatorApplicationComponentProps) {
+    super(props);
+
+    this.state = {
+      busy: false,
+      mediatorConfigToEdit: emptyMediatorConfig,
+      mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
+    }
+  }
+
+  render() {
+    const { classes } = this.props;
+
+    const renderActions = (rowData: MediatorConfigResponse) => (
+      <>
+        <div className={classes.spacer}>
+          <Tooltip title={"Start"} >
+            <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
+              <StartIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.startMediator(rowData.Name); }} />
+            </IconButton>
+          </Tooltip>
+          <Tooltip title={"Stop"} >
+            <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
+              <StopIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.stopMediator(rowData.Name); }} />
+            </IconButton>
+          </Tooltip>
+        </div>
+        <div className={classes.spacer}>
+          <Tooltip title={"Info"} ><IconButton className={classes.button}><InfoIcon /></IconButton></Tooltip>
+        </div>
+        <div className={classes.spacer}>
+          {process.env.NODE_ENV === "development" ? <Tooltip title={"Edit"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenEditConfigurationDialog(event, rowData)}><EditIcon /></IconButton></Tooltip> : null}
+          <Tooltip title={"Remove"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenRemoveConfigutationDialog(event, rowData)}><DeleteIcon /></IconButton></Tooltip>
+        </div>
+      </>
+    );
+
+    const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', onClick: this.onOpenAddConfigurationDialog };
+    return (
+      <div className={classes.root}>
+        {this.props.busy || this.state.busy
+          ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div>
+          : <MediatorServerConfigurationsTable 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) },
+          ]} />
+        }
+
+        <EditMediatorConfigDialog
+          mediatorConfig={this.state.mediatorConfigToEdit}
+          mode={this.state.mediatorConfigEditorMode}
+          onClose={this.onCloseEditMediatorConfigDialog} />
+
+      </div>
+    );
+  }
+
+  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.serverUrl && Promise.all([
+      mediatorService.getMediatorServerFreeNcPorts(this.props.serverUrl, 1),
+      mediatorService.getMediatorServerFreeSnmpPorts(this.props.serverUrl, 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/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
new file mode 100644
index 0000000..38bbdec
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
@@ -0,0 +1,136 @@
+import * as React from 'react';
+import { WithStyles, withStyles, createStyles, Theme, Tooltip } from '@material-ui/core';
+
+import AddIcon from '@material-ui/icons/Add';
+import IconButton from '@material-ui/core/IconButton';
+import EditIcon from '@material-ui/icons/Edit';
+import DeleteIcon from '@material-ui/icons/Delete';
+
+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 { 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.unit,
+    marginRight: theme.spacing.unit,
+    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("mediatorApp", mediatorServerId)),
+});
+
+const emptyMediatorServer: MediatorServer = {
+  _id: "",
+  name: "",
+  url: ""
+};
+
+type MediatorServerSelectionComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type MediatorServerSelectionComponentState = {
+  mediatorServerToEdit: MediatorServer,
+  mediatorServerEditorMode: EditMediatorServerDialogMode
+}
+
+class MediatorServerSelectionComponent extends React.Component<MediatorServerSelectionComponentProps, MediatorServerSelectionComponentState> {
+
+  constructor (props: MediatorServerSelectionComponentProps) {
+    super(props);
+
+    this.state = {
+      mediatorServerEditorMode: EditMediatorServerDialogMode.None,
+      mediatorServerToEdit: emptyMediatorServer,
+    }
+  }
+
+  render() {
+    const { classes } = this.props;
+
+    const addMediatorServerActionButton = {
+      icon: AddIcon, tooltip: 'Add', onClick: () => {
+        this.setState({
+          mediatorServerEditorMode: EditMediatorServerDialogMode.AddMediatorServer,
+          mediatorServerToEdit: emptyMediatorServer,
+        });
+      }
+    };
+    return (
+      <>
+        <MediatorServersTable customActionButtons={[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 title={"Edit"} ><IconButton className={classes.button} onClick={event => { this.onEditMediatorServer(event, rowData); }}><EditIcon /></IconButton></Tooltip>
+                  <Tooltip title={"Remove"} ><IconButton className={classes.button} onClick={event => { this.onRemoveMediatorServer(event, rowData); }}><DeleteIcon /></IconButton></Tooltip>
+                </div>
+              )
+            }
+          ]} onHandleClick={ this.onSelectMediatorServer } />
+        <EditMediatorServerDialog  
+          mediatorServer={ this.state.mediatorServerToEdit }
+          mode={ this.state.mediatorServerEditorMode }
+          onClose={ this.onCloseEditMediatorServerDialog } />
+      </>
+    );
+  }
+
+  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,
+    });
+  }
+}
+
+
+export const MediatorServerSelection = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorServerSelectionComponent));
+export default MediatorServerSelection;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..c11492b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="mediatorApp"/>
+         <property name="index" value="90"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json b/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/mediatorApp/tslint.json b/sdnr/wt/odlux/apps/mediatorApp/tslint.json
new file mode 100644
index 0000000..b5143e9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/tslint.json
@@ -0,0 +1,4 @@
+{
+  "rules":{
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
new file mode 100644
index 0000000..151170b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
@@ -0,0 +1,144 @@
+/**
+ * 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"
+        }]
+      }]
+    },
+
+    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: {
+        "/database/": {
+          target: "http://localhost:8181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://localhost:8181",
+          secure: false
+        },
+        "/help/": {
+          target: "http://localhost:8181",
+          secure: false
+        }
+      }
+    }
+  }];
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/.babelrc b/sdnr/wt/odlux/apps/minimumApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/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/apps/minimumApp/package.json b/sdnr/wt/odlux/apps/minimumApp/package.json
new file mode 100644
index 0000000..0df2cd7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/package.json
@@ -0,0 +1,40 @@
+{
+  "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": "MIT",
+   "dependencies": {
+     "@odlux/framework": "*"
+   },
+  "peerDependencies": {
+    "@types/react": "16.4.14",
+    "@types/react-dom": "16.0.8",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "3.8.3",
+    "@material-ui/icons": "3.0.2",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.5.2",
+    "react-dom": "16.5.2",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/pom.xml b/sdnr/wt/odlux/apps/minimumApp/pom.xml
new file mode 100644
index 0000000..e65d842
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<groupId>org.onap.ccsdk.parent</groupId>
+		<artifactId>odlparent</artifactId>
+		<version>1.2.1-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+	<artifactId>sdnr-wt-odlux-app-minimumApp</artifactId>
+	<version>0.4.1-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>sdnr-wt-odlux-app-minimumApp</name>
+	<licenses>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0</url>
+		</license>
+	</licenses>
+	<dependencies>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>sdnr-wt-odlux-core-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<sourceDirectory>src2/main/java</sourceDirectory>
+		<plugins>
+			<plugin>
+				<artifactId>maven-clean-plugin</artifactId>
+				<version>2.5</version>
+				<configuration>
+					<filesets>
+						<fileset>
+							<directory>dist</directory>
+							<followSymlinks>false</followSymlinks>
+						</fileset>
+					</filesets>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.github.eirslett</groupId>
+				<artifactId>frontend-maven-plugin</artifactId>
+				<version>1.8-SNAPSHOT</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>v8.10.0</nodeVersion>
+							<yarnVersion>v1.12.3</yarnVersion>
+						</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.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+						<Private-Package></Private-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<directory>dist</directory>
+				<targetPath>odlux</targetPath>
+			</resource>
+			<resource>
+				<directory>src2/main/resources</directory>
+			</resource>
+		</resources>
+	</build>
+	<pluginRepositories>
+		<pluginRepository>
+			<id>highstreet repo</id>
+			<url>https://cloud-highstreet-technologies.com/mvn/</url>
+			<snapshots>
+				<enabled>true</enabled>
+				<updatePolicy>always</updatePolicy>
+			</snapshots>
+		</pluginRepository>
+	</pluginRepositories>
+</project>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts b/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
new file mode 100644
index 0000000..d1d0304
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
@@ -0,0 +1,20 @@
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+export interface IMinimumAppStoreState {
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    minimumApp: IMinimumAppStoreState
+  }
+}
+
+const actionHandlers = {
+};
+
+export const minimumAppRootHandler = combineActionHandler<IMinimumAppStoreState>(actionHandlers);
+export default minimumAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/index.html b/sdnr/wt/odlux/apps/minimumApp/src/index.html
new file mode 100644
index 0000000..58865ed
--- /dev/null
+++ b/sdnr/wt/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/apps/minimumApp/src/plugin.tsx b/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
new file mode 100644
index 0000000..dc698e1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
@@ -0,0 +1,31 @@
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faLock } from '@fortawesome/free-solid-svg-icons';  // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import connect, { Connect } from '../../../framework/src/flux/connect';
+
+import { minimumAppRootHandler } from './handlers/minimumAppRootHandler';
+
+type AppProps = RouteComponentProps & Connect;
+
+const App = (props: AppProps) => (
+  <div>Start your app here!!</div>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+  applicationManager.registerApplication({
+    name: "minimumApp",
+    icon: faLock,
+    rootComponent: FinalApp,
+    rootActionHandler: minimumAppRootHandler,
+    menuEntry: "Minimum App"
+  });
+}
+
+
diff --git a/sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..1e882fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============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.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public void clean() {
+        super.clean();
+    }
+
+    @Override
+    public String getResourceFileContent(String filename) {
+        return super.getResourceFileContent(filename);
+    }
+
+    @Override
+    public boolean hasResource(String filename) {
+        return super.hasResource(filename);
+    }
+
+    @Override
+    public void setBundleName(String bundleName) {
+        super.setBundleName(bundleName);
+    }
+
+    @Override
+    public void setLoader(OdluxBundleLoader loader) {
+        super.setLoader(loader);
+    }
+
+    @Override
+    public String getBundleName() {
+        return super.getBundleName();
+    }
+
+    @Override
+    public OdluxBundleLoader getLoader() {
+        return super.getLoader();
+    }
+
+    public MyOdluxBundle() {
+        super();
+    }
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..4c8ed13
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<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="minimumApp"/>
+		<property name="index" value="999" />
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/tsconfig.json b/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./src",
+    "outDir": "./dist",
+    "sourceMap": true,
+    "forceConsistentCasingInFileNames": true,
+    "allowSyntheticDefaultImports": false,
+    "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/apps/minimumApp/webpack.config.js b/sdnr/wt/odlux/apps/minimumApp/webpack.config.js
new file mode 100644
index 0000000..64a5344
--- /dev/null
+++ b/sdnr/wt/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
+        }
+      }
+    }
+  }];
+}