Add link calculation app

Add link calculation app to odlux

Issue-ID: CCSDK-2562
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: Ifc0a5b2a8bb974dfd85d70a9f05990b1f11925a3
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
diff --git a/sdnr/wt/odlux/apps/apiDemo/pom.xml b/sdnr/wt/odlux/apps/apiDemo/pom.xml
index 52ff4bc..1756309 100644
--- a/sdnr/wt/odlux/apps/apiDemo/pom.xml
+++ b/sdnr/wt/odlux/apps/apiDemo/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/app-feature/pom.xml b/sdnr/wt/odlux/apps/app-feature/pom.xml
index bad5196..2aaf573 100644
--- a/sdnr/wt/odlux/apps/app-feature/pom.xml
+++ b/sdnr/wt/odlux/apps/app-feature/pom.xml
@@ -46,6 +46,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
@@ -92,5 +97,10 @@
             <artifactId>sdnr-wt-odlux-app-configurationApp</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-wt-odlux-app-linkCalculationApp</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
index 65ee924..1bf55ed 100755
--- a/sdnr/wt/odlux/apps/app-installer/pom.xml
+++ b/sdnr/wt/odlux/apps/app-installer/pom.xml
@@ -122,6 +122,12 @@
             <artifactId>sdnr-wt-odlux-app-configurationApp</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-wt-odlux-app-linkCalculationApp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/sdnr/wt/odlux/apps/configurationApp/pom.xml b/sdnr/wt/odlux/apps/configurationApp/pom.xml
index f02644a..9f92c99 100644
--- a/sdnr/wt/odlux/apps/configurationApp/pom.xml
+++ b/sdnr/wt/odlux/apps/configurationApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
index ec49191..8f7300c 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
@@ -18,4 +18,4 @@
 
 import { ViewElement } from "../models/uiModels";
 
-export type baseProps = { value: ViewElement, inputValue: string, readOnly: boolean, disabled: boolean, onChange(newValue: string): void };
\ No newline at end of file
+export type BaseProps<TValue = string> = { value: ViewElement, inputValue: TValue, readOnly: boolean, disabled: boolean, onChange(newValue: TValue): void };
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
index 6735888..62ddeb2 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
@@ -24,38 +24,59 @@
 import { InputProps } from "@material-ui/core/Input";
 
 const useStyles = makeStyles((theme: Theme) =>
-    createStyles({
-        iconDark: {
-            color: '#ff8800'
-        },
-        iconLight: {
-            color: 'orange'
-        },
-        padding: {
-            paddingLeft: 10,
-            paddingRight: 10
-        },
-    }),
+  createStyles({
+    iconDark: {
+      color: '#ff8800'
+    },
+    iconLight: {
+      color: 'orange'
+    },
+    padding: {
+      paddingLeft: 10,
+      paddingRight: 10
+    },
+  }),
 );
 
-type ifwhenProps = { element: ViewElementBase, id: any, label: any, style: any, helperText: string, error: boolean, toogleTooltip(value: boolean): void, [x: string]: any };
+type IfwhenProps = InputProps & {
+  label: string;
+  element: ViewElementBase;
+  helperText: string;
+  error: boolean;
+  onChangeTooltipVisuability(value: boolean): void;
+};
 
-export const IfWhenTextInput = (props: ifwhenProps) => {
+export const IfWhenTextInput = (props: IfwhenProps) => {
 
-    const { element, toogleTooltip, id, label, helperText: errorText, error, style, ...otherProps } = props;
-    const classes = useStyles();
+  const { element, onChangeTooltipVisuability: toogleTooltip, id, label, helperText: errorText, error, style, ...otherProps } = props;
+  const classes = useStyles();
 
 
-    const ifFeature = element.ifFeature ? <Tooltip onMouseMove={e => props.toogleTooltip(false)} onMouseOut={e => props.toogleTooltip(true)} title={element.ifFeature}><InputAdornment position="start"><FontAwesomeIcon icon={faAdjust} className={classes.iconDark}></FontAwesomeIcon></InputAdornment></Tooltip> : null;
-    const whenFeature = element.when ? (<Tooltip className={classes.padding} onMouseMove={e => props.toogleTooltip(false)} onMouseOut={e => props.toogleTooltip(true)} title={element.when}>
-        <InputAdornment className={classes.padding} position="end"><FontAwesomeIcon icon={faAdjust} className={classes.iconLight}></FontAwesomeIcon></InputAdornment></Tooltip>) : null;
+  const ifFeature = element.ifFeature
+    ? (
+        <Tooltip onMouseMove={e => props.onChangeTooltipVisuability(false)} onMouseOut={e => props.onChangeTooltipVisuability(true)} title={element.ifFeature}>
+          <InputAdornment position="start">
+            <FontAwesomeIcon icon={faAdjust} className={classes.iconDark} />
+          </InputAdornment>
+        </Tooltip>
+      )
+    : null;
 
-    return (
-        <FormControl error={error} style={style}>
-            <InputLabel htmlFor={id} >{label}</InputLabel>
-            <Input  {...otherProps} id={id} endAdornment={<div>{ifFeature}{whenFeature}</div>} />
-            <FormHelperText>{errorText}</FormHelperText>
-        </FormControl>
+  const whenFeature = element.when
+    ? (
+        <Tooltip className={classes.padding} onMouseMove={() => props.onChangeTooltipVisuability(false)} onMouseOut={() => props.onChangeTooltipVisuability(true)} title={element.when}>
+          <InputAdornment className={classes.padding} position="end">
+            <FontAwesomeIcon icon={faAdjust} className={classes.iconLight}/>
+          </InputAdornment>
+        </Tooltip>
+      ) 
+    : null;
 
-    );
+  return (
+    <FormControl error={error} style={style}>
+      <InputLabel htmlFor={id} >{label}</InputLabel>
+      <Input id={id} endAdornment={<div>{ifFeature}{whenFeature}</div>} {...otherProps}  />
+      <FormHelperText>{errorText}</FormHelperText>
+    </FormControl>
+  );
 }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
index cc141ee..2fbbf95 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
@@ -16,29 +16,28 @@
  * ============LICENSE_END==========================================================================
  */
 
-import { ViewElementBoolean } from "../models/uiModels";
 import * as React from "react"
 import { MenuItem, FormHelperText, Select, FormControl, InputLabel } from "@material-ui/core";
-import { baseProps } from "./baseProps";
 
-type booleanInputProps = baseProps;
+import { ViewElementBoolean } from "../models/uiModels";
+import { BaseProps } from "./baseProps";
 
-export const UiElementBoolean = (props: booleanInputProps) => {
+type BooleanInputProps = BaseProps<boolean>;
+
+export const UiElementBoolean = (props: BooleanInputProps) => {
 
     const element = props.value as ViewElementBoolean;
 
-    let error = "";
     const value = String(props.inputValue).toLowerCase();
-    if (element.mandatory && value !== "true" && value !== "false") {
-        error = "Error";
-    }
+    const mandetoryError = element.mandatory && value !== 'true' && value !== 'false';
+    
     return (!props.readOnly || element.id != null
         ? (<FormControl style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
             <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
             <Select
                 required={!!element.mandatory}
-                error={!!error}
-                onChange={(e) => { props.onChange(e.target.value as any) }}
+                error={mandetoryError}
+                onChange={(e) => { props.onChange(e.target.value === 'true') }}
                 readOnly={props.readOnly}
                 disabled={props.disabled}
                 value={value}
@@ -51,7 +50,7 @@
                 <MenuItem value={'false'}>{element.falseValue || 'False'}</MenuItem>
 
             </Select>
-            <FormHelperText>{error}</FormHelperText>
+            <FormHelperText>{mandetoryError ? "Value is mandetory" : ""}</FormHelperText>
         </FormControl>)
         : null
     );
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
index cf46205..ac4afc1 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
@@ -19,59 +19,52 @@
 import { ViewElementNumber } from "models/uiModels";
 import { Tooltip, InputAdornment } from "@material-ui/core";
 import * as React from 'react';
-import { baseProps } from "./baseProps";
+import { BaseProps } from "./baseProps";
 import { IfWhenTextInput } from "./ifWhenTextInput";
 import { checkRange } from "./verifyer";
 
-type numberInputProps = baseProps;
+type numberInputProps = BaseProps<number>;
 
 export const UiElementNumber = (props: numberInputProps) => {
 
 
-    const [error, setError] = React.useState(false);
-    const [helperText, setHelperText] = React.useState("");
-    const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+  const [error, setError] = React.useState(false);
+  const [helperText, setHelperText] = React.useState("");
+  const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
 
-    const element = props.value as ViewElementNumber;
+  const element = props.value as ViewElementNumber;
 
-    const verifyValue = (data: string) => {
-
-        if (data.trim().length > 0) {
-            const num = Number(data);
-            if (!isNaN(num)) {
-                const result = checkRange(element, num);
-                if (result.length > 0) {
-                    setError(true);
-                    setHelperText(result);
-                } else {
-                    setError(false);
-                    setHelperText("");
-                }
-            } else {
-                setError(true);
-                setHelperText("Input is not a number.");
-            }
-        } else {
-            setError(false);
-            setHelperText("");
-        }
-
-        props.onChange(data);
+  const verifyValue = (data: string) => {
+    const num = Number(data);
+    if (!isNaN(num)) {
+      const result = checkRange(element, num);
+      if (result.length > 0) {
+        setError(true);
+        setHelperText(result);
+      } else {
+        setError(false);
+        setHelperText("");
+      }
+    } else {
+      setError(true);
+      setHelperText("Input is not a number.");
     }
+    props.onChange(num);
+  }
 
-    return (
-        <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
-            <IfWhenTextInput element={element} toogleTooltip={(val: boolean) => setTooltipVisibility(val)}
-                spellCheck={false} autoFocus margin="dense"
-                id={element.id} label={element.label} type="text" value={props.inputValue}
-                style={{ width: 485, marginLeft: 20, marginRight: 20 }}
-                onChange={(e: any) => { verifyValue(e.target.value) }}
-                error={error}
-                readOnly={props.readOnly}
-                disabled={props.disabled}
-                helperText={helperText}
-                startAdornment={element.units != null ? <InputAdornment position="start">{element.units}</InputAdornment> : undefined}
-            />
-        </Tooltip>
-    );
+  return (
+    <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
+      <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
+        spellCheck={false} autoFocus margin="dense"
+        id={element.id} label={element.label} type="text" value={props.inputValue}
+        style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+        onChange={(e) => { verifyValue(e.target.value) }}
+        error={error}
+        readOnly={props.readOnly}
+        disabled={props.disabled}
+        helperText={helperText}
+        startAdornment={element.units != null ? <InputAdornment position="start">{element.units}</InputAdornment> : undefined}
+      />
+    </Tooltip>
+  );
 }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
index 8b0b890..1cec754 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
@@ -17,13 +17,11 @@
  */
 
 import * as React from 'react';
-import { baseProps } from './baseProps';
+import { BaseProps } from './baseProps';
 import { ViewElementSelection } from '../models/uiModels'
 import { FormControl, InputLabel, Select, FormHelperText, MenuItem } from '@material-ui/core';
 
-
-
-type selectionProps = baseProps;
+type selectionProps = BaseProps;
 
 export const UiElementSelection = (props: selectionProps) => {
 
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
index 43c60b5..95841b7 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
@@ -16,14 +16,14 @@
  * ============LICENSE_END==========================================================================
  */
 
+import * as React from "react"
 import { Tooltip, TextField } from "@material-ui/core";
 import { ViewElementString } from "../models/uiModels";
-import * as React from "react"
-import { baseProps } from "./baseProps";
+import { BaseProps } from "./baseProps";
 import { IfWhenTextInput } from "./ifWhenTextInput";
 import { checkRange, checkPattern } from "./verifyer";
 
-type stringEntryProps = baseProps & { isKey: boolean };
+type stringEntryProps = BaseProps & { isKey: boolean };
 
 export const UiElementString = (props: stringEntryProps) => {
 
@@ -40,9 +40,9 @@
             let errorMessage = "";
             const result = checkRange(element, data.length);
 
-            if (result.length > 0)
+            if (result.length > 0) {
                 errorMessage += result;
-
+            }
 
             const patternResult = checkPattern(element.pattern, data)
 
@@ -69,7 +69,7 @@
 
     return (
         <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
-            <IfWhenTextInput element={element} toogleTooltip={(val: boolean) => setTooltipVisibility(val)}
+            <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
                 spellCheck={false} autoFocus margin="dense"
                 id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
                 style={{ width: 485, marginLeft: 20, marginRight: 20 }}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
index 25378d7..669e393 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
@@ -17,77 +17,75 @@
  */
 
 import * as React from 'react'
-import { baseProps } from './baseProps';
+import { BaseProps } from './baseProps';
 import { Tooltip } from '@material-ui/core';
 import { IfWhenTextInput } from './ifWhenTextInput';
 import { ViewElementUnion, isViewElementString, isViewElementNumber, isViewElementObject, ViewElementNumber } from '../models/uiModels';
 import { checkRange, checkPattern } from './verifyer';
 
-type UiElementUnionProps = { isKey: boolean } & baseProps;
+type UiElementUnionProps = { isKey: boolean } & BaseProps;
 
 export const UIElementUnion = (props: UiElementUnionProps) => {
 
-    const [isError, setError] = React.useState(false);
-    const [helperText, setHelperText] = React.useState("");
-    const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+  const [isError, setError] = React.useState(false);
+  const [helperText, setHelperText] = React.useState("");
+  const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
 
-    const element = props.value as ViewElementUnion;
+  const element = props.value as ViewElementUnion;
 
-    const verifyValues = (data: string) => {
+  const verifyValues = (data: string) => {
 
-        let foundObjectElements = 0;
-        let errorMessage = "";
-        let isPatternCorrect = null;
+    let foundObjectElements = 0;
+    let errorMessage = "";
+    let isPatternCorrect = null;
 
-        for (let i = 0; i < element.elements.length; i++) {
-            const unionElement = element.elements[i];
+    for (let i = 0; i < element.elements.length; i++) {
+      const unionElement = element.elements[i];
 
-            if (isViewElementNumber(unionElement)) {
+      if (isViewElementNumber(unionElement)) {
 
-                errorMessage = checkRange(unionElement, Number(data));
+        errorMessage = checkRange(unionElement, Number(data));
 
-            } else if (isViewElementString(unionElement)) {
-                errorMessage += checkRange(unionElement, data.length);
-                isPatternCorrect = checkPattern(unionElement.pattern, data).isValid;
+      } else if (isViewElementString(unionElement)) {
+        errorMessage += checkRange(unionElement, data.length);
+        isPatternCorrect = checkPattern(unionElement.pattern, data).isValid;
 
 
-            } else if (isViewElementObject(unionElement)) {
-                foundObjectElements++;
-            }
+      } else if (isViewElementObject(unionElement)) {
+        foundObjectElements++;
+      }
 
-            if (isPatternCorrect || errorMessage.length === 0) {
-                break;
-            }
-        }
+      if (isPatternCorrect || errorMessage.length === 0) {
+        break;
+      }
+    }
 
-        if (errorMessage.length > 0 || isPatternCorrect !== null && !isPatternCorrect) {
-            setError(true);
-            setHelperText("Input is wrong.");
-        } else {
-            setError(false);
-            setHelperText("");
-        }
+    if (errorMessage.length > 0 || isPatternCorrect !== null && !isPatternCorrect) {
+      setError(true);
+      setHelperText("Input is wrong.");
+    } else {
+      setError(false);
+      setHelperText("");
+    }
 
-        if (foundObjectElements > 0 && foundObjectElements != element.elements.length) {
-            throw new Error(`The union element ${element.id} can't be changed.`);
+    if (foundObjectElements > 0 && foundObjectElements != element.elements.length) {
+      throw new Error(`The union element ${element.id} can't be changed.`);
 
-        } else {
-            props.onChange(data);
-        }
-    };
+    } else {
+      props.onChange(data);
+    }
+  };
 
-
-
-    return <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
-        <IfWhenTextInput element={element} toogleTooltip={(val: boolean) => setTooltipVisibility(val)}
-            spellCheck={false} autoFocus margin="dense"
-            id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
-            onChange={(e: any) => { verifyValues(e.target.value) }}
-            error={isError}
-            style={{ width: 485, marginLeft: 20, marginRight: 20 }}
-            readOnly={props.readOnly}
-            disabled={props.disabled}
-            helperText={helperText}
-        />
-    </Tooltip>;
+  return <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
+    <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
+      spellCheck={false} autoFocus margin="dense"
+      id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+      onChange={(e: any) => { verifyValues(e.target.value) }}
+      error={isError}
+      style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+      readOnly={props.readOnly}
+      disabled={props.disabled}
+      helperText={helperText}
+    />
+  </Tooltip>;
 }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
index 385f3b5..6465feb 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -284,8 +284,12 @@
   private renderUIElement = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
     const isKey = (uiElement.label === keyProperty);
     const canEdit = editMode && (isNew || (uiElement.config && !isKey));
-    if (isViewElementEmpty(uiElement)) {
+    
+    // do not show elements w/o any value from the backend
+    if (viewData[uiElement.id] == null && !editMode) {
       return null;
+    } else  if (isViewElementEmpty(uiElement)) {
+      return null;  
     } else if (isViewElementSelection(uiElement)) {
 
       return <UiElementSelection
@@ -300,7 +304,7 @@
     } else if (isViewElementBoolean(uiElement)) {
       return <UiElementBoolean
         key={uiElement.id}
-        inputValue={viewData[uiElement.id] || ''}
+        inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
         value={uiElement}
         readOnly={!canEdit}
         disabled={editMode && !canEdit}
@@ -309,7 +313,7 @@
     } else if (isViewElementString(uiElement)) {
       return <UiElementString
         key={uiElement.id}
-        inputValue={viewData[uiElement.id] || ''}
+        inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
         value={uiElement}
         isKey={isKey}
         readOnly={!canEdit}
diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml
index 0bbd806..6f984da 100644
--- a/sdnr/wt/odlux/apps/connectApp/pom.xml
+++ b/sdnr/wt/odlux/apps/connectApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
index a7feae9..86861fa 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
@@ -106,8 +106,8 @@
       <>
         <AppBar position="static">
           <Tabs value={activePanelId} onChange={this.onHandleTabChange} aria-label="simple tabs example">
-            <Tab label="Network Elements" value="NetworkElements" />
-            <Tab label="Connection Status Log" value="ConnectionStatusLog" />
+            <Tab aria-lablel="network-elements-list-tab" label="Network Elements" value="NetworkElements" />
+            <Tab aria-lablel="connection-status-log-tab" label="Connection Status Log" value="ConnectionStatusLog" />
           </Tabs>
         </AppBar>
         {activePanelId === 'NetworkElements'
diff --git a/sdnr/wt/odlux/apps/demoApp/pom.xml b/sdnr/wt/odlux/apps/demoApp/pom.xml
index 414c71f..bb0384b 100644
--- a/sdnr/wt/odlux/apps/demoApp/pom.xml
+++ b/sdnr/wt/odlux/apps/demoApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/eventLogApp/pom.xml b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
index 70a25e4..7b762c6 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/pom.xml
+++ b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml
index 00b758e..7818eaa 100644
--- a/sdnr/wt/odlux/apps/faultApp/pom.xml
+++ b/sdnr/wt/odlux/apps/faultApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
index 1ec463f..b711b03 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
@@ -57,12 +57,20 @@
     const { classes, faultStatus } = this.props;
 
     return (
-      <Typography variant="body1" color="inherit" >
+      <>
+      <Typography variant="body1" color="inherit" aria-label="critical-alarms">
         Alarm Status: <FontAwesomeIcon className={`${classes.icon} ${classes.critical}`} icon={faExclamationTriangle} /> { faultStatus.critical  } |
+        </Typography>
+        <Typography variant="body1" color="inherit" aria-label="major-alarms">
         <FontAwesomeIcon className={`${classes.icon} ${classes.major}`} icon={faExclamationTriangle} /> { faultStatus.major } |
+        </Typography>
+        <Typography variant="body1" color="inherit" aria-label="minor-alarms">
         <FontAwesomeIcon className={`${classes.icon} ${classes.minor}`} icon={faExclamationTriangle} /> { faultStatus.minor } |
+        </Typography>
+        <Typography variant="body1" color="inherit" aria-label="warning-alarms">
         <FontAwesomeIcon className={`${classes.icon} ${classes.warning}`} icon={faExclamationTriangle} /> { faultStatus.warning } |
       </Typography>
+      </>
     );
   };
 }
diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
index 1072154..7c29fec 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -138,9 +138,9 @@
       <>
         <AppBar position="static" >
           <Tabs value={activePanelId} onChange={this.onHandleTabChange} aria-label="fault tabs">
-            <Tab label="Current Problem List" value="CurrentProblem" />
-            <Tab label={`Alarm Notifications (${this.props.faultNotifications.faults.length})`} value="AlarmNotifications" />
-            <Tab label="Alarm Log" value="AlarmLog" />
+            <Tab aria-label="current-problem-list-tab" label="Current Problem List" value="CurrentProblem" />
+            <Tab aria-label="alarm-notifications-list-tab" label={`Alarm Notifications (${this.props.faultNotifications.faults.length})`} value="AlarmNotifications" />
+            <Tab aria-label="alarm-log-tab" label="Alarm Log" value="AlarmLog" />
           </Tabs>
         </AppBar>
         {
diff --git a/sdnr/wt/odlux/apps/helpApp/pom.xml b/sdnr/wt/odlux/apps/helpApp/pom.xml
index 3c8410b..6ada280 100644
--- a/sdnr/wt/odlux/apps/helpApp/pom.xml
+++ b/sdnr/wt/odlux/apps/helpApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
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
index 0fe9cd0..aaf395c 100644
--- 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
@@ -25,6 +25,6 @@
     <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"/>
+        <property name="index" value="200"/>
     </bean>
 </blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/pom.xml b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
index fe4ffcd..1184319 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/.babelrc b/sdnr/wt/odlux/apps/linkCalculationApp/.babelrc
new file mode 100644
index 0000000..3d8cd12
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/.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/linkCalculationApp/package.json b/sdnr/wt/odlux/apps/linkCalculationApp/package.json
new file mode 100644
index 0000000..40e1be9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/package.json
@@ -0,0 +1,40 @@
+{
+  "name": "@odlux/linkcalculation-app",
+  "version": "0.1.0",
+  "description": "A react based modular UI to do link analysis.",
+  "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": "Mohammad Boroon",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@odlux/framework": "*"
+  },
+  "peerDependencies": {
+    "@types/react": "16.9.19",
+    "@types/react-dom": "16.9.5",
+    "@types/react-router-dom": "4.3.1",
+    "@material-ui/core": "4.9.0",
+    "@material-ui/icons": "4.5.1",
+    "@types/classnames": "2.2.6",
+    "@types/flux": "3.1.8",
+    "@types/jquery": "3.3.10",
+    "jquery": "3.3.1",
+    "react": "16.12.0",
+    "react-dom": "16.12.0",
+    "react-router-dom": "4.3.1"
+  }
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/pom.xml b/sdnr/wt/odlux/apps/linkCalculationApp/pom.xml
new file mode 100644
index 0000000..8f057bd
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/pom.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============LICENSE_START=======================================================
+  ~ ONAP : ccsdk features
+  ~ ================================================================================
+  ~ Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+  ~ ================================================================================
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~ ============LICENSE_END=======================================================
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onap.ccsdk.parent</groupId>
+        <artifactId>odlparent</artifactId>
+        <version>2.0.1-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+    <artifactId>sdnr-wt-odlux-app-linkCalculationApp</artifactId>
+    <version>1.0.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>ccsdk-features :: ${project.artifactId}</name>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-wt-odlux-core-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <sourceDirectory>src2/main/java</sourceDirectory>
+        <resources>
+            <resource>
+                <directory>dist</directory>
+                <targetPath>odlux</targetPath>
+            </resource>
+            <resource>
+                <directory>src2/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>src2/test/resources</directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <fileset>
+                            <directory>../node_modules</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                        <!-- eclipse bug build bin folder in basedir -->
+                        <fileset>
+                            <directory>bin</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-test-source</id>
+                        <phase>generate-test-sources</phase>
+                        <goals>
+                            <goal>add-test-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src2/test/java</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>de.jacks-it-lab</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.7.2</version>
+                <executions>
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <!-- optional: default phase is "generate-resources" -->
+                        <phase>initialize</phase>
+                        <configuration>
+                            <nodeVersion>v10.16.3</nodeVersion>
+                            <yarnVersion>v1.19.0</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/>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts
new file mode 100644
index 0000000..555954d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts
@@ -0,0 +1,104 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from "../../../../framework/src/flux/action";
+import { Dispatch } from "../../../../framework/src/flux/store";
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+
+
+export class UpdateLinkIdAction extends Action{
+    constructor(public linkId: string){
+        super();
+    }
+}
+
+export class UpdateFrequencyAction extends Action{
+    constructor(public frequency: number){
+        super();
+    }
+}
+export class UpdateSiteAction extends Action{
+    constructor(
+        public siteA?: any,
+        public siteB?: any
+         ){
+        super();
+    }
+}
+export class UpdateRainAttAction extends Action{
+    
+    constructor(public rainAtt: number){
+        super();
+    }
+}
+export class UpdateRainValAction extends Action{
+    constructor(public rainVal: number){
+        super();
+    }
+}
+
+export class updateHideForm extends Action{
+    constructor(public formView: boolean){
+        super();
+    }
+}
+export class UpdateDistanceAction extends Action{
+    constructor(public distance: number){
+        super();
+    }
+}
+
+export class UpdateFslCalculation extends Action{
+    constructor(public fsl: number){
+        super();
+    }
+}
+
+
+export class UpdateLatLonAction extends Action{
+    constructor(
+        public Lat1: number,
+        public Lon1:number,
+        public Lat2: number, 
+        public Lon2: number
+        ){
+        super();
+        
+    }
+}
+export class isCalculationServerReachableAction extends Action{
+    constructor(public reachable: boolean){
+        super();
+    }
+}
+
+// export const checkCalculationsServerConnectivityAction = (callback: Promise<any>) => (dispatcher: Dispatch, getState: () => IApplicationStoreState)=>{
+//     callback
+//     .then(res =>{ 
+//         const {linkCalculation:{calculations: {isCalculationServerAvailable}}} = getState();
+//         if(!isToplogyServerAvailable){
+//             dispatcher(new IsTopologyServerReachableAction(true))
+//         }
+//     })
+//     .catch(error=>{
+//         const {network:{connectivity: {isToplogyServerAvailable}}} = getState();
+//         if(isToplogyServerAvailable){
+//            dispatcher(new IsTopologyServerReachableAction(false))
+//         }
+//     })
+// }
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx
new file mode 100644
index 0000000..c798e48
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react'
+
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
+import { Paper, Typography } from "@material-ui/core";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
+
+
+type props = Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
+
+const ConnectionInfo: React.FunctionComponent<props> = (props) => {
+
+    return (
+        (props.isCalculationServerReachable === false)?  <Paper style={{padding:5, position: 'absolute', top: 160, width: 230, left:"40%"}}>
+        <div style={{display: 'flex', flexDirection: 'column'}}>
+        <div style={{'alignSelf': 'center', marginBottom:5}}> <Typography> <FontAwesomeIcon icon={faExclamationTriangle} /> Connection Error</Typography></div>
+        {props.isCalculationServerReachable === false && <Typography> Calculation data can't be loaded.</Typography>}
+        </div>
+    </Paper> : null
+)}
+
+const mapStateToProps = (state: IApplicationStoreState) => ({
+    isCalculationServerReachable: state.linkCalculation.calculations.reachable
+});
+
+
+
+const mapDispatchToProps = (dispatcher: IDispatcher) => ({
+
+    //zoomToSearchResult: (lat: number, lon: number) => dispatcher.dispatch(new ZoomToSearchResultAction(lat, lon))
+
+});;
+
+
+export default connect(mapStateToProps,mapDispatchToProps)(ConnectionInfo)
+
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/components/denseTable.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/components/denseTable.tsx
new file mode 100644
index 0000000..96d6f4e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/components/denseTable.tsx
@@ -0,0 +1,121 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import Table from '@material-ui/core/Table';
+import TableBody from '@material-ui/core/TableBody';
+import TableCell from '@material-ui/core/TableCell';
+import TableContainer from '@material-ui/core/TableContainer';
+import TableHead from '@material-ui/core/TableHead';
+import TableRow from '@material-ui/core/TableRow';
+import Paper from '@material-ui/core/Paper';
+import { makeStyles, Button, Tooltip } from '@material-ui/core';
+
+type props = { headers: string[], width: number, height:number,  navigate?(applicationName: string, path?: string):void, onLinkClick?(id: string): void, data: any[], hover: boolean, onClick?(id: string): void, actions?:boolean  };
+
+
+const styles = makeStyles({
+    container: {
+        overflow:"auto"
+    },
+    button: {
+        margin: 0,
+        padding: "6px 6px",
+        minWidth: 'unset'
+      }
+    
+  });
+  
+
+const DenseTable: React.FunctionComponent<props> = (props) => {
+
+    const classes = styles();
+
+    const handleClick = (event: any, id: string) =>{
+        event.preventDefault();
+        props.onClick !== undefined && props.onClick(id);
+
+    }
+
+    const handleHover = (event: any, id: string) =>{
+        event.preventDefault();
+
+    }
+
+    return (
+        <Paper style={{borderRadius:"0px", width:props.width, height:props.height}} className={classes.container}>
+       
+            <Table stickyHeader size="small" aria-label="a dense table" >
+                <TableHead>
+                    <TableRow>
+                        {
+                            props.headers.map((data) => {
+                                return <TableCell>{data}</TableCell>
+                            })
+                        }
+                    </TableRow>
+                </TableHead>
+                <TableBody>
+                    {props.data.map((row, index) => {
+
+                        
+                        var filteredRows = Object.keys(row).filter(function(e) { if(e!=="simulatorId") return row });
+                     
+                        //var filteredRows = Object.keys(row).filter(function(e) { if(e!=="simulatorId") return row[e] });
+                        var values = Object.keys(row).map(function(e) {  if(e!=="simulatorId"){ return row[e];} else return undefined });
+                       
+
+                        return (
+                            <TableRow key={index} hover={props.hover} onMouseOver={e => handleHover(e,row.name)} onClick={ e =>  handleClick(e, row.name)}>
+
+                                {
+                                    values.map((data:any) => {
+                                       
+                                        if(data!== undefined)
+                                        return <TableCell >  {data} </TableCell>
+                                        else
+                                        return null;
+                                    })
+                                }
+                                {
+
+                                    props.actions && <TableCell >  
+<div style={{display:"flex"}}>                                           
+    <Tooltip title="Configure">
+    <Button className={classes.button} disabled={row.status!=="connected"} onClick={(e: any) =>{ e.preventDefault(); e.stopPropagation(); props.navigate && props.navigate("configuration", row.simulatorId ? row.simulatorId : row.name)}}>C</Button>
+    </Tooltip>
+    <Tooltip title="Fault">
+    <Button className={classes.button} onClick={(e: any) =>{ e.preventDefault(); e.stopPropagation(); props.navigate && props.navigate("fault", row.simulatorId ? row.simulatorId : row.name)}}>F</Button>
+    </Tooltip>
+    </div> 
+    </TableCell>
+    
+                                }
+                            </TableRow>)
+                    })
+                    }
+
+                </TableBody>
+            </Table>
+       
+        </Paper>
+    );
+
+}
+
+export default DenseTable;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts
new file mode 100644
index 0000000..00dd48d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts
@@ -0,0 +1,115 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+// 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 { UpdateLinkIdAction, UpdateFrequencyAction , UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, updateHideForm, UpdateFslCalculation, UpdateSiteAction, UpdateDistanceAction, isCalculationServerReachableAction} from '../actions/commonLinkCalculationActions';
+
+declare module '../../../../framework/src/store/applicationStore' {
+  interface IApplicationStoreState {
+    linkCalculation: ICalculationsState;
+  }
+}
+
+type ICalculationsState = {
+  calculations:ILinkCalculationAppStateState
+}
+
+export type ILinkCalculationAppStateState= {
+  linkId: string | null,
+  frequency: number,
+  formView:boolean,
+  fsl:number,
+  distance:number,
+  Lat1: number,
+  Lon1: number,
+  Lat2: number, 
+  Lon2: number,
+  rainVal : number,
+  rainAtt : number,
+  siteA: any,
+  siteB: any,
+  reachable: boolean
+}
+
+const initialState: ILinkCalculationAppStateState ={
+  linkId: null,
+  frequency: 0,
+  Lat1: 0,
+  Lon1: 0,
+  Lat2: 0,
+  Lon2: 0,
+  formView : false,
+  fsl:0,
+  distance:0,
+  siteA : '',
+  siteB: '',
+  rainVal : 0,
+  rainAtt: 0,
+  reachable : true
+}
+
+
+
+export const LinkCalculationHandler: IActionHandler<ILinkCalculationAppStateState> = (state=initialState, action) => {
+    
+  if(action instanceof UpdateLinkIdAction){
+      state = Object.assign({}, state, {linkId:action.linkId})
+  } 
+  else if(action instanceof updateHideForm){
+
+    state = Object.assign({}, state, {formView:action.formView})
+  }
+  else if (action instanceof UpdateDistanceAction){
+    state = Object.assign({}, state, {distance:action.distance})
+  }
+  else if (action instanceof UpdateFrequencyAction){
+    state = Object.assign({}, state, {frequency:action.frequency})
+}
+  else if (action instanceof UpdateFslCalculation){
+  state = Object.assign({}, state, {fsl:action.fsl})
+  }
+  else if (action instanceof UpdateLatLonAction){
+    state = Object.assign({}, state, {Lat1:action.Lat1, Lon1:action.Lon1, Lat2:action.Lat2, Lon2:action.Lon2})
+  }
+  else if (action instanceof UpdateRainAttAction){
+    state = Object.assign({}, state, {rainAtt:action.rainAtt})
+  }
+  else if (action instanceof UpdateRainValAction){
+    state = Object.assign({}, state, {rainVal:action.rainVal})
+  }
+  else if (action instanceof UpdateSiteAction){
+    state = Object.assign({}, state, {siteA:action.siteA, siteB:action.siteB})
+  }
+  else if(action instanceof isCalculationServerReachableAction){
+    state = Object.assign({}, state, { reachable: action.reachable });
+}
+  return state
+}
+
+const actionHandlers = {
+  calculations: LinkCalculationHandler
+}
+
+export const LinkCalculationAppRootHandler = combineActionHandler<ICalculationsState>(actionHandlers); 
+export default LinkCalculationAppRootHandler;
+
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html b/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html
new file mode 100644
index 0000000..c1cb3f9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
+  <title>Link Calculation App</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="text/javascript" src="./require.js"></script>
+  <script type="text/javascript" src="./config.js"></script>
+  <script>
+    // run the application
+    require(["app","connectApp", "networkMapApp", "linkCalculationApp"], function (app, connectApp, networkMapApp, linkCalculationApp) {
+      connectApp.register();
+      linkCalculationApp.register();
+      networkMapApp.register();
+      app("./app.tsx").runApplication();
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/pluginLinkCalculation.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/pluginLinkCalculation.tsx
new file mode 100644
index 0000000..fc72f5a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/pluginLinkCalculation.tsx
@@ -0,0 +1,148 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+// 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 { faBookOpen } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import  LinkCalculation  from './views/linkCalculationComponent';
+import LinkCalculationAppRootHandler from './handlers/linkCalculationAppRootHandler';
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import { UpdateLinkIdAction, UpdateLatLonAction, updateHideForm, UpdateSiteAction, UpdateDistanceAction } from "./actions/commonLinkCalculationActions";
+
+
+let currentLinkId: string | null = null;
+let lastUrl: string = "/linkCalculation";
+
+const mapProps = (state: IApplicationStoreState) => ({
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+  updateLinkId: (mountId: string) => dispatcher.dispatch(new UpdateLinkIdAction(mountId)),
+
+  updateSiteName: (siteNameA?:any, siteNameB?:any)=>{
+    dispatcher.dispatch(new UpdateSiteAction(siteNameA, siteNameB))
+  },
+  updateDistance :(distance:number) =>{
+    dispatcher.dispatch(new UpdateDistanceAction(distance))
+  },
+  updateLatLon : (Lat1:number, Lon1:number, Lat2:number, Lon2:number)=> {
+
+    dispatcher.dispatch(new UpdateLatLonAction(Lat1, Lon1, Lat2, Lon2))
+    dispatcher.dispatch(new updateHideForm (true))
+  },
+});
+
+
+const LinkCalculationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+  let linkId: string = "";
+
+  // called when component finshed mounting
+  React.useEffect(() => {
+
+    lastUrl = props.location.pathname;
+    linkId = getLinkId(lastUrl);
+
+    const data= props.location.search
+
+    
+
+    if (data !== undefined && data.length>0){
+
+    
+    
+    const lat1 = data.split('&')[0].split('=')[1]
+    const lon1 = data.split('&')[1].split('=')[1]
+    const lat2 = data.split('&')[2].split('=')[1]
+    const lon2 = data.split('&')[3].split('=')[1]
+
+    const siteNameA = data.split('&')[4].split('=')[1]
+    const siteNameB = data.split('&')[5].split('=')[1]
+
+    const distance = data.split('&')[8].split('=')[1]
+
+
+    props.updateSiteName(String(siteNameA), String(siteNameB))
+    props.updateDistance(Number(distance))
+
+
+    props.updateLatLon(Number(lat1),Number(lon1),Number(lat2),Number(lon2))
+    
+    }
+    
+
+    if (currentLinkId !== linkId) { // new element is loaded
+      currentLinkId = linkId;
+      props.updateLinkId(currentLinkId);
+    } 
+  }, []);
+
+  // called when component gets updated
+  React.useEffect(() => {
+
+    lastUrl = props.location.pathname;
+    linkId = getLinkId(lastUrl);
+
+    if (currentLinkId !== linkId) {
+      currentLinkId = linkId;
+      props.updateLinkId(currentLinkId);
+    }
+  });
+
+  const getLinkId = (lastUrl: string) => {
+    let index = lastUrl.lastIndexOf("linkCalculation/");
+    if (index >= 0) {
+      linkId = lastUrl.substr(index+16);
+    } else {
+      linkId = "";
+    }
+
+    return linkId;
+  }
+
+  
+  return (
+    <LinkCalculation />
+  );
+});
+
+const App = withRouter((props: RouteComponentProps) => {
+  props.history.action = "POP";
+  return (
+    <Switch>
+      <Route path={`${props.match.path}/:linkId`} component={LinkCalculationRouteAdapter} />
+      <Route path={`${props.match.path}`} component={LinkCalculationRouteAdapter} />
+      <Redirect to={`${props.match.path}`} />
+    </Switch>
+  )
+});
+
+export function register() {
+  applicationManager.registerApplication({
+    name: "linkCalculation",
+    icon: faBookOpen,
+    rootActionHandler: LinkCalculationAppRootHandler,
+    rootComponent: App,
+    menuEntry: "Link Calculation"
+  });
+}
+
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx
new file mode 100644
index 0000000..97219b6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx
@@ -0,0 +1,246 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { TextField, Tabs, Tab, Typography, AppBar, Button, Tooltip } from '@material-ui/core';
+import DenseTable from '../components/denseTable'
+
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { UpdateFrequencyAction, UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, UpdateFslCalculation, isCalculationServerReachableAction } from "../actions/commonLinkCalculationActions";
+import { faPlaneArrival } from "@fortawesome/free-solid-svg-icons";
+
+const mapProps = (state: IApplicationStoreState) => ({
+  linkId: state.linkCalculation.calculations.linkId,
+  frequency: state.linkCalculation.calculations.frequency,
+  lat1: state.linkCalculation.calculations.Lat1,
+  lon1: state.linkCalculation.calculations.Lon1,
+  lat2: state.linkCalculation.calculations.Lat2,
+  lon2: state.linkCalculation.calculations.Lon2,
+  rainAtt: state.linkCalculation.calculations.rainAtt,
+  rainVal: state.linkCalculation.calculations.rainVal,
+  formView: state.linkCalculation.calculations.formView,
+  fsl:state.linkCalculation.calculations.fsl,
+  siteA: state.linkCalculation.calculations.siteA,
+  siteB: state.linkCalculation.calculations.siteB,
+  distance: state.linkCalculation.calculations.distance,
+  reachable :state.linkCalculation.calculations.reachable
+});
+
+const BASE_URL="/topology/services"
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+
+  updateFrequency: (frequency: number) => {
+    dispatcher.dispatch(new UpdateFrequencyAction(frequency))
+
+  },
+  updateLatLon: (Lat1: number, Lon1: number, Lat2: number, Lon2: number) => {
+
+    dispatcher.dispatch(new UpdateLatLonAction(Lat1, Lon1, Lat2, Lon2))
+
+  },
+  
+  updateRainValue: (rainVal: number) => {
+    dispatcher.dispatch(new UpdateRainValAction(rainVal))
+  },
+
+  UpdateRainAtt: (rainAtt: number) => {
+    dispatcher.dispatch(new UpdateRainAttAction(rainAtt))
+  },
+
+  specificRain: (rainAtt: number) => {
+    dispatcher.dispatch(new UpdateRainAttAction(rainAtt))
+
+  },
+ 
+  FSL :(free:number)=> {
+    dispatcher.dispatch(new UpdateFslCalculation (free))
+  },
+
+  UpdateConectivity : (reachable:boolean) => {
+    dispatcher.dispatch (new isCalculationServerReachableAction (reachable))
+  }
+});
+
+class LinkCalculation extends React.Component<Connect<typeof mapProps, typeof mapDispatch>, { rainMethodDisplay: boolean }> {
+  constructor(props: any) {
+    super(props)
+    this.state = { rainMethodDisplay: true }
+  }
+
+  handleChange = (e: number) => {
+    this.props.updateFrequency(e)
+  }
+
+  updateLatLon = (e: any) => {
+    
+    if (e.target.id == 'Lat1') this.props.updateLatLon(e.target.value, this.props.lon1, this.props.lat2, this.props.lon2)
+    if (e.target.id == 'Lon1') this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, this.props.lon2)
+    if (e.target.id == 'Lat2') this.props.updateLatLon(this.props.lat1, this.props.lon1, e.target.value, this.props.lon2)
+    if (e.target.id == 'Lon2') this.props.updateLatLon(this.props.lat1, this.props.lon1, this.props.lat2, e.target.value)
+
+  }
+
+  LatLonToDMS = (value: number, isLon: boolean = false) => {
+    const absoluteValue = Math.abs(value);
+    const d = Math.floor(absoluteValue);
+    const m = Math.floor((absoluteValue - d) * 60);
+    const s = (absoluteValue - d - m / 60) * 3600;
+    const dms = `${d}° ${m}' ${s.toFixed(2)}"`
+
+    const sign = Math.sign(value);
+
+    if (isLon) {
+      return (sign === -1 || sign === -0) ? dms + " W" : dms + " E";
+    } else {
+      return (sign === -1 || sign === -0) ? dms + " S" : dms + " N";
+    }
+  }
+
+  calRain = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any) => {
+    fetch(BASE_URL+'/calculations/rain/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + frequency)
+      .then(res => res.json())
+      .then(result => { this.props.UpdateRainAtt(result.RainAtt) })
+  }
+
+
+  updateRainValue = (lat1: any, lon1: any, lat2: any, lon2: any) => {
+    fetch(BASE_URL+'/calculations/rain/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2)
+      .then(res => res.json())
+      .then(result => { this.props.updateRainValue(result.RainAtt) })
+  }
+
+
+  specificRain = (rainfall: number, frequency: number) => {
+    fetch(BASE_URL+'/calculations/rain/' + rainfall + '/' + frequency)
+      .then(res => res.json())
+      .then(result => { this.props.specificRain(result.RainAtt) })
+    }
+
+    FSL = (distance:number, frequency:number) => {
+      fetch(BASE_URL+'/calculations/FSL/' + distance + '/' + frequency)
+      .then(res=>res.json())
+      .then (result => {this.props.FSL(result.free)})
+    }
+
+  buttonHandler =() => {
+      this.FSL(this.props.distance, this.props.frequency)
+
+      if (this.state.rainMethodDisplay === true){
+
+        this.specificRain(this.props.rainVal, this.props.frequency); 
+      }
+      else {
+        this.calRain(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency);
+        this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2)
+      }
+  }
+
+  componentDidMount = () => {
+    fetch (BASE_URL+'/calculations/fsl/0/0')
+    .then(res => {if (res.ok) {this.props.reachable===false && this.props.UpdateConectivity(true)}else {this.props.reachable===true && this.props.UpdateConectivity(false)} })
+    .catch (res => {this.props.reachable===true && this.props.UpdateConectivity(false)} )
+  }
+  
+  render() {
+    console.log(this.props);
+    const data = [
+
+      { name: "Site Name", val1: this.props.siteA, val2: '', val3:  this.props.siteB},
+      { name: "Latitude", val1: this.props.lat1 && this.LatLonToDMS(this.props.lat1), val2:'', val3: this.props.lat2 && this.LatLonToDMS(this.props.lat2) },
+      { name: "Longitude", val1: this.props.lon1 && this.LatLonToDMS(this.props.lon1, true), val2:'', val3: this.props.lon2 && this.LatLonToDMS(this.props.lon2, true) },
+      { name: "Azimuth in °", val1: '', val2: '' , val3:''},
+      { name: "", val1: '', val2: '' , val3:''},
+      { name: "Distance (km)", val1: '', val2: (this.props.distance).toFixed(3) ,val3:'' },
+      {name: 'Polarization', val1:'', val2: <div><input type='checkbox' id='Horizontal' value ="Horizontal"></input>Horizontal<br />
+      <input type='checkbox' id='Vertical' value ="Vertical"></input>Vertical
+      </div>, val3:''},
+      {name : 'Frequency (GHz)', val1: '', val2:  <div> 
+      <select onChange={(e) => this.handleChange(Number(e.target.value))}>
+      <option value='' >Select Freq</option>
+      <option value='7' >7 GHz</option>
+      <option value='11' >11 GHz</option>
+      <option value='15' >15 GHz</option>
+      <option value='23' >23 GHz</option>
+      <option value='26' >26 GHz</option>
+      <option value='28' >28 GHz</option>
+      <option value='38' >38 GHz</option>
+      <option value='42' >42 GHz</option>
+      <option value='80' >80 GHz</option>
+        </select></div>,val3: ''},
+      {name: 'Free Space Loss (dB)' ,val1: '', val2: this.props.fsl,val3: ''},
+      {name:'Rain Model', val1:'', val2: <div>
+      <select onChange={e => { this.setState({ rainMethodDisplay: !this.state.rainMethodDisplay }) }} >
+        <option value='' >Select Rain Method</option>
+        <option value='itu' onSelect={e => { this.setState({ rainMethodDisplay: false }) }}>ITU-R P.837-7</option>
+        <option value='manual' onSelect={(e) => { this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2) }}  >Specific Rain</option>
+      </select> </div>, val3:''},
+      {name: 'Rainfall Rate (mm/h)', val1: '', val2:<label>
+       <input type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => { this.props.updateRainValue(Number(e.target.value)) }}
+        value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}>
+      </input></label>, val3:''},
+      {name: 'Rain Loss (dB/km)', val1: '', val2: this.props.rainAtt, val3: ''},
+      {name: '', val1:'', val2:<button style={{color: '#222', fontFamily:'Arial', boxAlign: 'center', display:'inline-block', insetInlineStart: '20' }}
+      onClick = {(e) => this.buttonHandler()} >Calculate</button>, val3:'' }
+     
+    ];
+
+
+    return <div>
+      Link Calculation app. LinkId: {this.props.linkId} <br />
+
+      {!this.props.formView && <form>
+          <div>
+          
+            <br />Site A 
+            <br /> Site Id:
+                <label style={{ marginInlineStart: 20 }}> latitude
+                <input id='Lat1' type='number' onChange={(e: any) => this.updateLatLon(e)} />
+            </label>
+            <label style={{ marginInlineStart: 20 }}>longitude
+                <input id='Lon1' type='number' onChange={(e: any) => this.updateLatLon(e)} />
+            </label><br /><br />
+
+          </div>
+          <div> <br />Site B<br /> Site Id:
+                <label style={{ marginInlineStart: 20 }}> latitude
+                <input id='Lat2' type='number' onChange={(e: any) => this.updateLatLon(e)} />
+            </label>
+            <label style={{ marginInlineStart: 20 }}>longitude
+                <input id='Lon2' type='number' onChange={(e: any) => this.updateLatLon(e)} />
+            </label>
+            <br />
+          </div>
+        </form>
+        }
+      
+        <DenseTable height={600} width={1300} hover={true} headers={["", "Site A","", "Site B"]} data={data}> </DenseTable>
+
+          
+
+      
+    </div>
+
+  }
+
+
+}
+
+export default connect(mapProps, mapDispatch)(LinkCalculation);
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/linkCalculationApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 0000000..43b072c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/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/linkCalculationApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/linkCalculationApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..8eb652e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/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="linkCalculationApp"/>
+        <property name="index" value="120"/>
+    </bean>
+</blueprint>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/linkCalculationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 0000000..c319bb1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*
+ * ============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.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+    @Test
+    public void test() {
+        OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+        MyOdluxBundle b = new MyOdluxBundle();
+        b.setLoader(loader);
+        b.setIndex(0);
+        b.setBundleName("abc");
+        b.initialize();
+        assertTrue(loader.getNumberOfBundles()==1);
+        assertNotNull(b.getLoader());
+        assertEquals("abc",b.getBundleName());
+        assertTrue(b.hasResource("test.js"));
+        assertNotNull(b.getResourceFileContent("test.js"));
+        b.clean();
+        assertTrue(loader.getNumberOfBundles()==0);
+    }
+
+}
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/linkCalculationApp/src2/test/resources/test.js
new file mode 100644
index 0000000..b47fdc3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad 
+as
+d 
+sad
+ sadfa
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/tsconfig.json b/sdnr/wt/odlux/apps/linkCalculationApp/tsconfig.json
new file mode 100644
index 0000000..a66b5d8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/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/linkCalculationApp/webpack.config.js b/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js
new file mode 100644
index 0000000..4f2bd2e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js
@@ -0,0 +1,159 @@
+/**
+ * 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: {
+      linkCalculationApp: ["./pluginLinkCalculation.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: {
+        "/oauth2/": {
+          target: "http://10.20.6.29:8181",
+          secure: false
+        },
+        "/database/": {
+          target: "http://10.20.6.29:8181",
+          secure: false
+        },
+        "/restconf/": {
+          target: "http://10.20.6.29:8181",
+          secure: false
+        },
+        "/topology/": {
+          target: "http://localhost:3001",
+          secure: false
+        },
+        "/help/": {
+          target: "http://10.20.6.29:8181",
+          secure: false
+        },
+        "/websocket/": {
+          target: "http://10.20.6.29:8181",
+          ws: true,
+          changeOrigin: true,
+          secure: false
+        }
+      }
+
+    }
+  }];
+}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
index 874d17c..e66404c 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
+++ b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
index 21d5d61..6accabe 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/pom.xml
+++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/minimumApp/pom.xml b/sdnr/wt/odlux/apps/minimumApp/pom.xml
index 55bdf97..8135426 100644
--- a/sdnr/wt/odlux/apps/minimumApp/pom.xml
+++ b/sdnr/wt/odlux/apps/minimumApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
index 819c742..5ace21f 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
@@ -43,6 +43,11 @@
         </license>
     </licenses>
 
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <checkstyle.skip>true</checkstyle.skip>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>