Update ConfigurationApp

Add grouping per yang module

Issue-ID: CCSDK-3023
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: I7fd15d0a7dc982c6d824e679b5a0d1eeaaa2e7a8
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
index 83134fc..d7babc1 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
@@ -8,8 +8,7 @@
 import { restService } from "../services/restServices";
 import { YangParser } from "../yang/yangParser";
 import { Module } from "../models/yang";
-import { ViewSpecification, ViewElement, isViewElementReference, isViewElementList, isViewElementObjectOrList, isViewElementRpc, isViewElementChoise, ViewElementChoiseCase } from "../models/uiModels";
-import { element } from 'prop-types';
+import { ViewSpecification, ViewElement, isViewElementReference, isViewElementList, isViewElementObjectOrList, isViewElementRpc, isViewElementChoise, ViewElementChoiseCase, ViewElementString } from "../models/uiModels";
 
 export class EnableValueSelector extends Action {
   constructor(public listSpecification: ViewSpecification, public listData: any[], public keyProperty: string, public onValueSelected : (value: any) => void ) {
@@ -52,22 +51,26 @@
   dispatch(new UpdateDeviceDescription("", {}, []));
   dispatch(new SetCollectingSelectionData(true));
   
-  const availableCapabilities = await restService.getCapabilitiesByMoutId(nodeId);
+  const { avaliableCapabilities, unavaliableCapabilities } = await restService.getCapabilitiesByMoutId(nodeId);
 
-  if (!availableCapabilities || availableCapabilities.length <= 0) {
+  if (!avaliableCapabilities || avaliableCapabilities.length <= 0) {
     throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
   }
-
-  const parser = new YangParser();
-
+  
   const capParser = /^\(.*\?revision=(\d{4}-\d{2}-\d{2})\)(\S+)$/i;
-  for (let i = 0; i < availableCapabilities.length; ++i){
-    const capRaw = availableCapabilities[i];
+  
+  const parser = new YangParser(unavaliableCapabilities?.map(cap => {
+      const capMatch = cap && capParser.exec(cap.capability);
+      return { capability:capMatch && capMatch[2] || '', failureReason: cap.failureReason };
+  }) || undefined);
+
+  for (let i = 0; i < avaliableCapabilities.length; ++i){
+    const capRaw = avaliableCapabilities[i];
     const capMatch = capRaw && capParser.exec(capRaw.capability);
     try {
       capMatch && await parser.addCapability(capMatch[2], capMatch[1]);
     } catch (err) {
-      console.error(err);
+      console.error(`Error in ${capMatch && capMatch[2]} ${capMatch && capMatch[1]}`, err);
     }
   }
 
@@ -75,6 +78,10 @@
 
   dispatch(new SetCollectingSelectionData(false));
 
+  if (process.env.NODE_ENV === "development" ) {
+      console.log(parser, parser.modules, parser.views);
+  }
+
   return dispatch(new UpdateDeviceDescription(nodeId, parser.modules, parser.views));
 }
 
@@ -317,8 +324,33 @@
               window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, "%2F")}]`)));
             }));
           } else {
+            // Found a list at root level of a module w/o a refenrece key.
+            dataPath += `?content=config&fields=${encodeURIComponent(viewElement.id)}(${encodeURIComponent(viewElement.key || '')})`; 
+            const restResult = (await restService.getConfigData(dataPath));
+            if (restResult && restResult.status === 200 && restResult.data && restResult.data[viewElement.id] ){
+                // spoof the not existing view here
+                const refData = restResult.data[viewElement.id];
+                const refView : ViewSpecification  = {
+                    id: "-1",
+                    canEdit: false,
+                    language: "en-US",
+                    elements: {
+                        [viewElement.key!] : { 
+                           uiType: "string",
+                           config: false,
+                           id: viewElement.key,
+                           label: viewElement.key,
+                           isList: true,
+                        } as ViewElementString
+                    }
+                };
+                dispatch(new EnableValueSelector(refView, refData, viewElement.key!, (refKey) => {
+                 window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, "%2F")}]`))); 
+                }));
+            } else {
+              throw new Error("Found a list at root level of a module and could not determine the keys.");
+            }
             dispatch(new SetCollectingSelectionData(false));
-            throw new Error("Found a list at root level of a module w/o a refenrece key.");
           }
           return;
         }
@@ -392,7 +424,7 @@
 
       // extract the list -> key: list
       data = extractList
-        ? data[viewElement!.label] || [] // if the list is empty, it does not exist
+        ? data[viewElement!.id] || data[viewElement!.label] || [] // if the list is empty, it does not exist
         : data;
 
     } else if (viewElement! && viewElement!.uiType === "rpc") {
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
index c08f5c9..26c3944 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
@@ -23,6 +23,6 @@
     inputValue: TValue, 
     readOnly: boolean, 
     disabled: boolean, 
-    onChange(newValue: TValue): void,
+    onChange(newValue: TValue): void;
     isKey?: boolean 
 };
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
index b95df1f..223c4cb 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
@@ -38,7 +38,7 @@
   const { element } = props;
   return (
     <FormControl key={element.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
-      <Tooltip title={element.description || ''}>
+      <Tooltip title={element.description || element.path || ''}>
         <Button className={classes.button} aria-label={element.label+'-button'} color="secondary" disabled={props.disabled} onClick={() => {
           props.onOpenReference(element);
         }}>{`${element.label}`}</Button>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
index 122f715..f87b94f 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
@@ -23,7 +23,7 @@
 import { IfWhenTextInput } from "./ifWhenTextInput";
 import { checkRange, checkPattern } from "./verifyer";
 
-type stringEntryProps = BaseProps;
+type stringEntryProps = BaseProps ;
 
 export const UiElementString = (props: stringEntryProps) => {
 
@@ -81,4 +81,4 @@
             />
         </Tooltip>
     );
-}
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
index a5a52fc..9c03bdf 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
@@ -19,6 +19,8 @@
 export type ViewElementBase = {
   "id": string;
   "label": string;
+  "module": string;
+  "path": string;
   "config": boolean;
   "ifFeature"?: string;
   "when"?: string;
@@ -52,6 +54,14 @@
   "invertMatch"?: true;
 }
 
+// special case derived from 
+export type ViewElementDate = ViewElementBase & {
+  "uiType": "date";
+  "pattern"?: Expression<RegExp>;
+  "length"?: Expression<YangRange>;
+  "invertMatch"?: true;
+}
+
 // https://tools.ietf.org/html/rfc7950#section-9.3
 export type ViewElementNumber = ViewElementBase & {
   "uiType": "number";
@@ -134,6 +144,7 @@
   | ViewElementBits
   | ViewElementBinary
   | ViewElementString
+  | ViewElementDate
   | ViewElementNumber
   | ViewElementBoolean
   | ViewElementObject
@@ -145,7 +156,11 @@
   | ViewElementRpc;
 
 export const isViewElementString = (viewElement: ViewElement): viewElement is ViewElementString => {
-  return viewElement && viewElement.uiType === "string";
+  return viewElement && (viewElement.uiType === "string" || viewElement.uiType === "date");
+}
+
+export const isViewElementDate = (viewElement: ViewElement): viewElement is ViewElementDate => {
+  return viewElement && (viewElement.uiType === "date");
 }
 
 export const isViewElementNumber = (viewElement: ViewElement): viewElement is ViewElementNumber => {
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
index 11eb44d..e4ab6f5 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
@@ -17,6 +17,13 @@
  */
 
 import { ViewElement, ViewSpecification } from "./uiModels";
+import { StepLabel } from "@material-ui/core";
+
+export enum ModuleState {
+  stable,
+  instable,
+  unabaliabe,
+}
 
 export type Token = {
   name: string;
@@ -50,6 +57,7 @@
   name: string;
   namespace?: string;
   prefix?: string;
+  state: ModuleState;
   identities: { [name: string]: Identity };
   revisions: { [version: string]: Revision };
   imports: { [prefix: string]: string };
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
index eb2c67c..239a8e4 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
@@ -21,12 +21,50 @@
 
 import { NetworkElementConnection } from "../models/networkElementConnection";
 
+type CapabilityResponse = {
+    "network-topology:node": {
+        "node-id": string, 
+        "netconf-node-topology:available-capabilities": { 
+            "available-capability": { 
+                "capability-origin": string, 
+                "capability": string,
+            }[] 
+        },
+        "netconf-node-topology:unavailable-capabilities": { 
+            "unavailable-capability": { 
+                "capability": string,
+                "failure-reason": string, 
+            }[] 
+        }
+    }[] 
+}
+
+type CapabilityAnswer = { 
+    avaliableCapabilities: { 
+        capabilityOrigin: string, 
+        capability: string 
+    }[] | null ,
+    unavaliableCapabilities: { 
+        failureReason: string, 
+        capability: string 
+    }[] | null ,
+}
+
 class RestService {
-  public async getCapabilitiesByMoutId(nodeId: string): Promise<{ "capabilityOrigin": string, "capability": string }[] | null> {
+  public async getCapabilitiesByMoutId(nodeId: string): Promise<CapabilityAnswer> {
     const path = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}`;
-    const capabilitiesResult = await requestRest<{"network-topology:node": {"node-id": string, "netconf-node-topology:available-capabilities": { "available-capability": { "capability-origin": string, "capability": string }[] }}[] }>(path, { method: "GET" });
-    return capabilitiesResult && capabilitiesResult["network-topology:node"] && capabilitiesResult["network-topology:node"].length > 0 &&
-      capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"]["available-capability"].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || null;
+    const capabilitiesResult = await requestRest<CapabilityResponse>(path, { method: "GET" });
+    const avaliableCapabilities = capabilitiesResult && capabilitiesResult["network-topology:node"] && capabilitiesResult["network-topology:node"].length > 0 &&
+       capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"] && 
+       capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"]["available-capability"] && 
+       capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"]["available-capability"].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [];
+   
+    const unavaliableCapabilities = capabilitiesResult && capabilitiesResult["network-topology:node"] && capabilitiesResult["network-topology:node"].length > 0 &&
+      capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"] &&
+      capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"]["unavailable-capability"] && 
+      capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"]["unavailable-capability"].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || []
+   
+    return { avaliableCapabilities, unavaliableCapabilities };
   }
 
   public async getMountedNetworkElementByMountId(nodeId: string): Promise<NetworkElementConnection | null> {
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
index 3b1df6f..45b3081 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -29,7 +29,7 @@
 
 import { DisplayModeType } from '../handlers/viewDescriptionHandler';
 import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator, updateViewActionAsyncCreator, removeElementActionAsyncCreator, executeRpcActionAsyncCreator } from "../actions/deviceActions";
-import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection, isViewElementChoise, ViewElement, ViewElementChoise, isViewElementUnion, isViewElementRpc, ViewElementRpc, isViewElementEmpty } from "../models/uiModels";
+import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection, isViewElementChoise, ViewElement, ViewElementChoise, isViewElementUnion, isViewElementRpc, ViewElementRpc, isViewElementEmpty, isViewElementDate } from "../models/uiModels";
 
 import Fab from '@material-ui/core/Fab';
 import AddIcon from '@material-ui/icons/Add';
@@ -45,8 +45,14 @@
 import Select from "@material-ui/core/Select";
 import MenuItem from "@material-ui/core/MenuItem";
 import Breadcrumbs from "@material-ui/core/Breadcrumbs";
-import { Button } from '@material-ui/core';
+import Button from '@material-ui/core/Button';
 import Link from "@material-ui/core/Link";
+import Accordion from '@material-ui/core/Accordion';
+import AccordionSummary from '@material-ui/core/AccordionSummary';
+import AccordionDetails from '@material-ui/core/AccordionDetails';
+import Typography from '@material-ui/core/Typography';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+
 
 import { BaseProps } from '../components/baseProps';
 import { UIElementReference } from '../components/uiElementReference';
@@ -60,93 +66,104 @@
 import { useConfirm } from 'material-ui-confirm';
 
 const styles = (theme: Theme) => createStyles({
-  header: {
-    "display": "flex",
-    "justifyContent": "space-between",
-  },
-  leftButton: {
-    "justifyContent": "left"
-  },
-  outer: {
-    "flex": "1",
-    "height": "100%",
-    "display": "flex",
-    "alignItems": "center",
-    "justifyContent": "center",
-  },
-  inner: {
+    header: {
+        "display": "flex",
+        "justifyContent": "space-between",
+    },
+    leftButton: {
+        "justifyContent": "left"
+    },
+    outer: {
+        "flex": "1",
+        "height": "100%",
+        "display": "flex",
+        "alignItems": "center",
+        "justifyContent": "center",
+    },
+    inner: {
 
-  },
-  container: {
-    "height": "100%",
-    "display": "flex",
-    "flexDirection": "column",
-  },
-  "icon": {
-    "marginRight": theme.spacing(0.5),
-    "width": 20,
-    "height": 20,
-  },
-  "fab": {
-    "margin": theme.spacing(1),
-  },
-  button: {
-    margin: 0,
-    padding: "6px 6px",
-    minWidth: 'unset'
-  },
-  readOnly: {
-    '& label.Mui-focused': {
-      color: 'green',
     },
-    '& .MuiInput-underline:after': {
-      borderBottomColor: 'green',
+    container: {
+        "height": "100%",
+        "display": "flex",
+        "flexDirection": "column",
     },
-    '& .MuiOutlinedInput-root': {
-      '& fieldset': {
-        borderColor: 'red',
-      },
-      '&:hover fieldset': {
-        borderColor: 'yellow',
-      },
-      '&.Mui-focused fieldset': {
-        borderColor: 'green',
-      },
+    "icon": {
+        "marginRight": theme.spacing(0.5),
+        "width": 20,
+        "height": 20,
     },
-  },
-  uiView: {
-    overflowY: "auto",
-  },
-  section: {
-    padding: "15px",
-    borderBottom: `2px solid ${theme.palette.divider}`,
-  },
-  viewElements: {
-    width: 485, marginLeft: 20, marginRight: 20
-  },
-  verificationElements: {
-    width: 485, marginLeft: 20, marginRight: 20
-  }
+    "fab": {
+        "margin": theme.spacing(1),
+    },
+    button: {
+        margin: 0,
+        padding: "6px 6px",
+        minWidth: 'unset'
+    },
+    readOnly: {
+        '& label.Mui-focused': {
+            color: 'green',
+        },
+        '& .MuiInput-underline:after': {
+            borderBottomColor: 'green',
+        },
+        '& .MuiOutlinedInput-root': {
+            '& fieldset': {
+                borderColor: 'red',
+            },
+            '&:hover fieldset': {
+                borderColor: 'yellow',
+            },
+            '&.Mui-focused fieldset': {
+                borderColor: 'green',
+            },
+        },
+    },
+    uiView: {
+        overflowY: "auto",
+    },
+    section: {
+        padding: "15px",
+        borderBottom: `2px solid ${theme.palette.divider}`,
+    },
+    viewElements: {
+        width: 485, marginLeft: 20, marginRight: 20
+    },
+    verificationElements: {
+        width: 485, marginLeft: 20, marginRight: 20
+    },
+    heading: {
+        fontSize: theme.typography.pxToRem(15),
+        fontWeight: theme.typography.fontWeightRegular,
+    },
+    moduleCollection: {
+       marginTop: "16px",
+       overflow: "auto", 
+    },
+    objectReult: {
+       overflow: "auto"    
+    }
 });
 
 const mapProps = (state: IApplicationStoreState) => ({
-  collectingData: state.configuration.valueSelector.collectingData,
-  listKeyProperty: state.configuration.valueSelector.keyProperty,
-  listSpecification: state.configuration.valueSelector.listSpecification,
-  listData: state.configuration.valueSelector.listData,
-  vPath: state.configuration.viewDescription.vPath,
-  nodeId: state.configuration.deviceDescription.nodeId,
-  viewData: state.configuration.viewDescription.viewData,
-  outputData: state.configuration.viewDescription.outputData,
-  displaySpecification: state.configuration.viewDescription.displaySpecification,
+    collectingData: state.configuration.valueSelector.collectingData,
+    listKeyProperty: state.configuration.valueSelector.keyProperty,
+    listSpecification: state.configuration.valueSelector.listSpecification,
+    listData: state.configuration.valueSelector.listData,
+    vPath: state.configuration.viewDescription.vPath,
+    nodeId: state.configuration.deviceDescription.nodeId,
+    viewData: state.configuration.viewDescription.viewData,
+    outputData: state.configuration.viewDescription.outputData,
+    displaySpecification: state.configuration.viewDescription.displaySpecification,
 });
 
 const mapDispatch = (dispatcher: IDispatcher) => ({
-  onValueSelected: (value: any) => dispatcher.dispatch(new SetSelectedValue(value)),
-  onUpdateData: (vPath: string, data: any) => dispatcher.dispatch(updateDataActionAsyncCreator(vPath, data)),
-  reloadView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
-  removeElement: (vPath: string) => dispatcher.dispatch(removeElementActionAsyncCreator(vPath)),
-  executeRpc: (vPath: string, data: any) => dispatcher.dispatch(executeRpcActionAsyncCreator(vPath, data)),
+    onValueSelected: (value: any) => dispatcher.dispatch(new SetSelectedValue(value)),
+    onUpdateData: (vPath: string, data: any) => dispatcher.dispatch(updateDataActionAsyncCreator(vPath, data)),
+    reloadView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
+    removeElement: (vPath: string) => dispatcher.dispatch(removeElementActionAsyncCreator(vPath)),
+    executeRpc: (vPath: string, data: any) => dispatcher.dispatch(executeRpcActionAsyncCreator(vPath, data)),
 });
 
 const SelectElementTable = MaterialTable as MaterialTableCtorType<{ [key: string]: any }>;
@@ -154,599 +171,653 @@
 type ConfigurationApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
 
 type ConfigurationApplicationComponentState = {
-  isNew: boolean;
-  editMode: boolean;
-  canEdit: boolean;
-  viewData: { [key: string]: any } | null;
-  choises: { [path: string]: { selectedCase: string, data: { [property: string]: any } } };
+    isNew: boolean;
+    editMode: boolean;
+    canEdit: boolean;
+    viewData: { [key: string]: any } | null;
+    choises: { [path: string]: { selectedCase: string, data: { [property: string]: any } } };
 }
 
 const OldProps = Symbol("OldProps");
 class ConfigurationApplicationComponent extends React.Component<ConfigurationApplicationComponentProps, ConfigurationApplicationComponentState> {
 
-  /**
-   *
-   */
-  constructor(props: ConfigurationApplicationComponentProps) {
-    super(props);
+    /**
+     *
+     */
+    constructor(props: ConfigurationApplicationComponentProps) {
+        super(props);
 
-    this.state = {
-      isNew: false,
-      canEdit: false,
-      editMode: false,
-      viewData: null,
-      choises: {},
+        this.state = {
+            isNew: false,
+            canEdit: false,
+            editMode: false,
+            viewData: null,
+            choises: {},
+        }
     }
-  }
 
-  private static getChoisesFromElements = (elements: { [name: string]: ViewElement }, viewData: any) => {
-    return Object.keys(elements).reduce((acc, cur) => {
-      const elm = elements[cur];
-      if (isViewElementChoise(elm)) {
-        const caseKeys = Object.keys(elm.cases);
+    private static getChoisesFromElements = (elements: { [name: string]: ViewElement }, viewData: any) => {
+        return Object.keys(elements).reduce((acc, cur) => {
+            const elm = elements[cur];
+            if (isViewElementChoise(elm)) {
+                const caseKeys = Object.keys(elm.cases);
 
-        // find the right case for this choise, use the first one with data, at least use index 0
-        const selectedCase = caseKeys.find(key => {
-          const caseElm = elm.cases[key];
-          return Object.keys(caseElm.elements).some(caseElmKey => {
-            const caseElmElm = caseElm.elements[caseElmKey];
-            return viewData[caseElmElm.label] !== undefined || viewData[caseElmElm.id] != undefined;
-          });
-        }) || caseKeys[0];
+                // find the right case for this choise, use the first one with data, at least use index 0
+                const selectedCase = caseKeys.find(key => {
+                    const caseElm = elm.cases[key];
+                    return Object.keys(caseElm.elements).some(caseElmKey => {
+                        const caseElmElm = caseElm.elements[caseElmKey];
+                        return viewData[caseElmElm.label] !== undefined || viewData[caseElmElm.id] != undefined;
+                    });
+                }) || caseKeys[0];
 
-        // extract all data of the active case
-        const caseElements = elm.cases[selectedCase].elements;
-        const data = Object.keys(caseElements).reduce((dataAcc, dataCur) => {
-          const dataElm = caseElements[dataCur];
-          if (isViewElementEmpty(dataElm)) {
-            dataAcc[dataElm.label] = null;
-          } else if (viewData[dataElm.label] !== undefined) {
-            dataAcc[dataElm.label] = viewData[dataElm.label];
-          } else if (viewData[dataElm.id] !== undefined) {
-            dataAcc[dataElm.id] = viewData[dataElm.id];
-          }
-          return dataAcc;
-        }, {} as { [name: string]: any });
+                // extract all data of the active case
+                const caseElements = elm.cases[selectedCase].elements;
+                const data = Object.keys(caseElements).reduce((dataAcc, dataCur) => {
+                    const dataElm = caseElements[dataCur];
+                    if (isViewElementEmpty(dataElm)) {
+                        dataAcc[dataElm.label] = null;
+                    } else if (viewData[dataElm.label] !== undefined) {
+                        dataAcc[dataElm.label] = viewData[dataElm.label];
+                    } else if (viewData[dataElm.id] !== undefined) {
+                        dataAcc[dataElm.id] = viewData[dataElm.id];
+                    }
+                    return dataAcc;
+                }, {} as { [name: string]: any });
 
-        acc[elm.id] = {
-          selectedCase,
-          data,
-        };
-      }
-      return acc;
-    }, {} as { [path: string]: { selectedCase: string, data: { [property: string]: any } } }) || {}
-  }
-
-  static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
-
-    if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
-      const isNew: boolean = nextProps.vPath?.endsWith("[]") || false;
-      const state = {
-        ...prevState,
-        isNew: isNew,
-        editMode: isNew,
-        viewData: nextProps.viewData || null,
-        [OldProps]: nextProps,
-        choises: nextProps.displaySpecification.displayMode === DisplayModeType.doNotDisplay
-          ? null
-          : nextProps.displaySpecification.displayMode === DisplayModeType.displayAsRPC
-            ? nextProps.displaySpecification.inputViewSpecification && ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.inputViewSpecification.elements, nextProps.viewData) || []
-            : ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.viewSpecification.elements, nextProps.viewData)
-      }
-      return state;
-    }
-    return null;
-  }
-
-  private navigate = (path: string) => {
-    this.props.history.push(`${this.props.match.url}${path}`);
-  }
-
-  private changeValueFor = (property: string, value: any) => {
-    this.setState({
-      viewData: {
-        ...this.state.viewData,
-        [property]: value
-      }
-    });
-  }
-
-  private collectData = (elements: { [name: string]: ViewElement }) => {
-    // ensure only active choises will be contained
-    const viewData : { [key: string]: any }= { ...this.state.viewData };
-    const choiseKeys = Object.keys(elements).filter(elmKey => isViewElementChoise(elements[elmKey]));
-    const elementsToRemove = choiseKeys.reduce((acc, curChoiceKey) => {
-      const currentChoice = elements[curChoiceKey] as ViewElementChoise;
-      const selectedCase = this.state.choises[curChoiceKey].selectedCase;
-      Object.keys(currentChoice.cases).forEach(caseKey => {
-        const caseElements = currentChoice.cases[caseKey].elements;
-        if (caseKey === selectedCase) {
-          Object.keys(caseElements).forEach(caseElementKey => {
-            const elm = caseElements[caseElementKey];
-            if (isViewElementEmpty(elm)) {
-              // insert null for all empty elements
-              viewData[elm.id] = null;
+                acc[elm.id] = {
+                    selectedCase,
+                    data,
+                };
             }
-          });
-          return;
-        };
-        Object.keys(caseElements).forEach(caseElementKey => {
-          acc.push(caseElements[caseElementKey]);
-        });
-      });
-      return acc;
-    }, [] as ViewElement[]);
-
-    return viewData && Object.keys(viewData).reduce((acc, cur) => {
-      if (!elementsToRemove.some(elm => elm.label === cur || elm.id === cur)) {
-        acc[cur] = viewData[cur];
-      }
-      return acc;
-    }, {} as { [key: string]: any });
-  }
-
-  private getEditorForViewElement = (uiElement: ViewElement) : (null | React.ComponentType<BaseProps<any>>) => { 
-  if (isViewElementEmpty(uiElement)) {
-     return null;
-  } else if (isViewElementSelection(uiElement)) {
-     return UiElementSelection;
-  } else if (isViewElementBoolean(uiElement)) {
-    return UiElementBoolean;
-  } else if (isViewElementString(uiElement)) {
-      return UiElementString;
-  } else if (isViewElementNumber(uiElement)) {
-     return UiElementNumber;
-  } else if (isViewElementUnion(uiElement)) {
-     return UIElementUnion;
-  } else {
-     if (process.env.NODE_ENV !== "production") {
-       console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
-     }
-    return null;
+            return acc;
+        }, {} as { [path: string]: { selectedCase: string, data: { [property: string]: any } } }) || {}
     }
-  }
 
-  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));
+    static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
 
-     // do not show elements w/o any value from the backend
-    if (viewData[uiElement.id] == null && !editMode) {
-      return null;
-    } else if (isViewElementEmpty(uiElement)) {
-      return null;  
-    } else if (uiElement.isList) {
-      /* element is a leaf-list */
-      return <UiElementLeafList
-         key={uiElement.id}
-         inputValue={viewData[uiElement.id] == null ? [] : viewData[uiElement.id]} 
-         value={uiElement}
-         readOnly={!canEdit}
-         disabled={editMode && !canEdit}
-         onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
-         getEditorForViewElement = { this.getEditorForViewElement }
-      />;  
-    } else {
-        const Element = this.getEditorForViewElement(uiElement);
-        return Element != null   
-          ? (
-            <Element
+        if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
+            const isNew: boolean = nextProps.vPath?.endsWith("[]") || false;
+            const state = {
+                ...prevState,
+                isNew: isNew,
+                editMode: isNew,
+                viewData: nextProps.viewData || null,
+                [OldProps]: nextProps,
+                choises: nextProps.displaySpecification.displayMode === DisplayModeType.doNotDisplay
+                    ? null
+                    : nextProps.displaySpecification.displayMode === DisplayModeType.displayAsRPC
+                        ? nextProps.displaySpecification.inputViewSpecification && ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.inputViewSpecification.elements, nextProps.viewData) || []
+                        : ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.viewSpecification.elements, nextProps.viewData)
+            }
+            return state;
+        }
+        return null;
+    }
+
+    private navigate = (path: string) => {
+        this.props.history.push(`${this.props.match.url}${path}`);
+    }
+
+    private changeValueFor = (property: string, value: any) => {
+        this.setState({
+            viewData: {
+                ...this.state.viewData,
+                [property]: value
+            }
+        });
+    }
+
+    private collectData = (elements: { [name: string]: ViewElement }) => {
+        // ensure only active choises will be contained
+        const viewData: { [key: string]: any } = { ...this.state.viewData };
+        const choiseKeys = Object.keys(elements).filter(elmKey => isViewElementChoise(elements[elmKey]));
+        const elementsToRemove = choiseKeys.reduce((acc, curChoiceKey) => {
+            const currentChoice = elements[curChoiceKey] as ViewElementChoise;
+            const selectedCase = this.state.choises[curChoiceKey].selectedCase;
+            Object.keys(currentChoice.cases).forEach(caseKey => {
+                const caseElements = currentChoice.cases[caseKey].elements;
+                if (caseKey === selectedCase) {
+                    Object.keys(caseElements).forEach(caseElementKey => {
+                        const elm = caseElements[caseElementKey];
+                        if (isViewElementEmpty(elm)) {
+                            // insert null for all empty elements
+                            viewData[elm.id] = null;
+                        }
+                    });
+                    return;
+                };
+                Object.keys(caseElements).forEach(caseElementKey => {
+                    acc.push(caseElements[caseElementKey]);
+                });
+            });
+            return acc;
+        }, [] as ViewElement[]);
+
+        return viewData && Object.keys(viewData).reduce((acc, cur) => {
+            if (!elementsToRemove.some(elm => elm.label === cur || elm.id === cur)) {
+                acc[cur] = viewData[cur];
+            }
+            return acc;
+        }, {} as { [key: string]: any });
+    }
+
+    private getEditorForViewElement = (uiElement: ViewElement): (null | React.ComponentType<BaseProps<any>>) => {
+        if (isViewElementEmpty(uiElement)) {
+            return null;
+        } else if (isViewElementSelection(uiElement)) {
+            return UiElementSelection;
+        } else if (isViewElementBoolean(uiElement)) {
+            return UiElementBoolean;
+        } else if (isViewElementString(uiElement)) {
+            return UiElementString;
+        } else if (isViewElementDate(uiElement)) {
+            return UiElementString;
+        } else if (isViewElementNumber(uiElement)) {
+            return UiElementNumber;
+        } else if (isViewElementUnion(uiElement)) {
+            return UIElementUnion;
+        } else {
+            if (process.env.NODE_ENV !== "production") {
+                console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+            }
+            return null;
+        }
+    }
+
+    private renderUIElement = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+        const isKey = (uiElement.label === keyProperty);
+        const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+
+        // do not show elements w/o any value from the backend
+        if (viewData[uiElement.id] == null && !editMode) {
+            return null;
+        } else if (isViewElementEmpty(uiElement)) {
+            return null;
+        } else if (uiElement.isList) {
+            /* element is a leaf-list */
+            return <UiElementLeafList
                 key={uiElement.id}
-                isKey={isKey}
-                inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
+                inputValue={viewData[uiElement.id] == null ? [] : viewData[uiElement.id]}
                 value={uiElement}
                 readOnly={!canEdit}
                 disabled={editMode && !canEdit}
                 onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
-            /> )
-          : null ;
-    }
-  };
-
-  // private renderUIReference = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
-  //   const isKey = (uiElement.label === keyProperty);
-  //   const canEdit = editMode && (isNew || (uiElement.config && !isKey));
-  //   if (isViewElementObjectOrList(uiElement)) {
-  //     return (
-  //       <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
-  //         <Tooltip title={uiElement.description || ''}>
-  //           <Button className={this.props.classes.leftButton} color="secondary" disabled={this.state.editMode} onClick={() => {
-  //             this.navigate(`/${uiElement.id}`);
-  //           }}>{uiElement.label}</Button>
-  //         </Tooltip>
-  //       </FormControl>
-  //     );
-  //   } else {
-  //     if (process.env.NODE_ENV !== "production") {
-  //       console.error(`Unknown reference type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
-  //     }
-  //     return null;
-  //   }
-  // };
-
-  private renderUIChoise = (uiElement: ViewElementChoise, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
-    const isKey = (uiElement.label === keyProperty);
-
-    const currentChoise = this.state.choises[uiElement.id];
-    const currentCase = currentChoise && uiElement.cases[currentChoise.selectedCase];
-
-    const canEdit = editMode && (isNew || (uiElement.config && !isKey));
-    if (isViewElementChoise(uiElement)) {
-      const subElements = currentCase ?.elements;
-      return (
-        <>
-          <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
-            <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
-            <Select
-              required={!!uiElement.mandatory}
-              onChange={(e) => {
-                if (currentChoise.selectedCase === e.target.value) {
-                  return; // nothing changed
-                }
-                this.setState({ choises: { ...this.state.choises, [uiElement.id]: { ...this.state.choises[uiElement.id], selectedCase: e.target.value as string } } });
-              }}
-              readOnly={!canEdit}
-              disabled={editMode && !canEdit}
-              value={this.state.choises[uiElement.id].selectedCase}
-              inputProps={{
-                name: uiElement.id,
-                id: `select-${uiElement.id}`,
-              }}
-            >
-              {
-                Object.keys(uiElement.cases).map(caseKey => {
-                  const caseElm = uiElement.cases[caseKey];
-                  return (
-                    <MenuItem key={caseElm.id} value={caseKey}><Tooltip title={caseElm.description || ''}><div style={{width:"100%"}}>{caseElm.label}</div></Tooltip></MenuItem>
-                  );
-                })
-              }
-            </Select>
-          </FormControl>
-          {subElements
-            ? Object.keys(subElements).map(elmKey => {
-              const elm = subElements[elmKey];
-              return this.renderUIElement(elm, viewData, keyProperty, editMode, isNew);
-            })
-            : <h3>Invalid Choise</h3>
-          }
-        </>
-      );
-    } else {
-      if (process.env.NODE_ENV !== "production") {
-        console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
-      }
-      return null;
-    }
-  };
-
-  private renderUIView = (viewSpecification: ViewSpecification, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
-    const { classes } = this.props;
-
-    const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
-      if (keyProperty) {
-        // if (vsA.label === vsB.label) return 0;
-        if (vsA.label === keyProperty) return -1;
-        if (vsB.label === keyProperty) return +1;
-      }
-
-      // if (vsA.uiType === vsB.uiType) return 0;
-      // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
-      // if (vsA.uiType === "object") return +1;
-      return -1;
+                getEditorForViewElement={this.getEditorForViewElement}
+            />;
+        } else {
+            const Element = this.getEditorForViewElement(uiElement);
+            return Element != null
+                ? (
+                    <Element
+                        key={uiElement.id}
+                        isKey={isKey}
+                        inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
+                        value={uiElement}
+                        readOnly={!canEdit}
+                        disabled={editMode && !canEdit}
+                        onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
+                    />)
+                : null;
+        }
     };
 
-    const sections = Object.keys(viewSpecification.elements).reduce((acc, cur) => {
-      const elm = viewSpecification.elements[cur];
-      if (isViewElementObjectOrList(elm)) {
-        acc.references.push(elm);
-      } else if (isViewElementChoise(elm)) {
-        acc.choises.push(elm);
-      } else if (isViewElementRpc(elm)) {
-        acc.rpcs.push(elm);
-      } else {
-        acc.elements.push(elm);
-      }
-      return acc;
-    }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] });
+    // private renderUIReference = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+    //   const isKey = (uiElement.label === keyProperty);
+    //   const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+    //   if (isViewElementObjectOrList(uiElement)) {
+    //     return (
+    //       <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+    //         <Tooltip title={uiElement.description || ''}>
+    //           <Button className={this.props.classes.leftButton} color="secondary" disabled={this.state.editMode} onClick={() => {
+    //             this.navigate(`/${uiElement.id}`);
+    //           }}>{uiElement.label}</Button>
+    //         </Tooltip>
+    //       </FormControl>
+    //     );
+    //   } else {
+    //     if (process.env.NODE_ENV !== "production") {
+    //       console.error(`Unknown reference type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+    //     }
+    //     return null;
+    //   }
+    // };
 
-    sections.elements = sections.elements.sort(orderFunc);
+    private renderUIChoise = (uiElement: ViewElementChoise, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+        const isKey = (uiElement.label === keyProperty);
 
-    return (
-      <div className={classes.uiView}>
-        <div className={classes.section} />
-        {sections.elements.length > 0
-          ? (
-            <div className={classes.section}>
-              {sections.elements.map(element => this.renderUIElement(element, viewData, keyProperty, editMode, isNew))}
-            </div>
-          ) : null
-        }
-        {sections.references.length > 0
-          ? (
-            <div className={classes.section}>
-              {sections.references.map(element => (
-                <UIElementReference key={element.id} element={element} disabled={editMode} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
-              ))}
-            </div>
-          ) : null
-        }
-        {sections.choises.length > 0
-          ? (
-            <div className={classes.section}>
-              {sections.choises.map(element => this.renderUIChoise(element, viewData, keyProperty, editMode, isNew))}
-            </div>
-          ) : null
-        }
-        {sections.rpcs.length > 0
-          ? (
-            <div className={classes.section}>
-              {sections.rpcs.map(element => (
-                <UIElementReference key={element.id} element={element} disabled={editMode} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
-              ))}
-            </div>
-          ) : null
-        }
-      </div>
-    );
-  };
+        const currentChoise = this.state.choises[uiElement.id];
+        const currentCase = currentChoise && uiElement.cases[currentChoise.selectedCase];
 
-  private renderUIViewList(listSpecification: ViewSpecification, listKeyProperty: string, listData: { [key: string]: any }[]) {
-    const listElements = listSpecification.elements;
-
-    const navigate = (path: string) => {
-      this.props.history.push(`${this.props.match.url}${path}`);
+        const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+        if (isViewElementChoise(uiElement)) {
+            const subElements = currentCase?.elements;
+            return (
+                <>
+                    <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+                        <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
+                        <Select
+                            aria-label={uiElement.label+'-selection'}
+                            required={!!uiElement.mandatory}
+                            onChange={(e) => {
+                                if (currentChoise.selectedCase === e.target.value) {
+                                    return; // nothing changed
+                                }
+                                this.setState({ choises: { ...this.state.choises, [uiElement.id]: { ...this.state.choises[uiElement.id], selectedCase: e.target.value as string } } });
+                            }}
+                            readOnly={!canEdit}
+                            disabled={editMode && !canEdit}
+                            value={this.state.choises[uiElement.id].selectedCase}
+                            inputProps={{
+                                name: uiElement.id,
+                                id: `select-${uiElement.id}`,
+                            }}
+                        >
+                            {
+                                Object.keys(uiElement.cases).map(caseKey => {
+                                    const caseElm = uiElement.cases[caseKey];
+                                    return (
+                                        <MenuItem key={caseElm.id} value={caseKey} aria-label={caseKey}><Tooltip title={caseElm.description || ''}><div style={{ width: "100%" }}>{caseElm.label}</div></Tooltip></MenuItem>
+                                    );
+                                })
+                            }
+                        </Select>
+                    </FormControl>
+                    {subElements
+                        ? Object.keys(subElements).map(elmKey => {
+                            const elm = subElements[elmKey];
+                            return this.renderUIElement(elm, viewData, keyProperty, editMode, isNew);
+                        })
+                        : <h3>Invalid Choise</h3>
+                    }
+                </>
+            );
+        } else {
+            if (process.env.NODE_ENV !== "production") {
+                console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+            }
+            return null;
+        }
     };
 
-    const addNewElementAction = {
-      icon: AddIcon, tooltip: 'Add', onClick: () => {
-        navigate("[]"); // empty key means new element
-      }
-    };
+    private renderUIView = (viewSpecification: ViewSpecification, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+        const { classes } = this.props;
 
-    const { classes, removeElement } = this.props;
+        const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
+            if (keyProperty) {
+                // if (vsA.label === vsB.label) return 0;
+                if (vsA.label === keyProperty) return -1;
+                if (vsB.label === keyProperty) return +1;
+            }
 
-    const DeleteIconWithConfirmation : React.FC<{rowData: {[key:string]:any}, onReload: () => void} > = (props) => {
-        const confirm = useConfirm();
+            // if (vsA.uiType === vsB.uiType) return 0;
+            // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+            // if (vsA.uiType === "object") return +1;
+            return -1;
+        };
+
+        const sections = Object.keys(viewSpecification.elements).reduce((acc, cur) => {
+            const elm = viewSpecification.elements[cur];
+            if (isViewElementObjectOrList(elm)) {
+                acc.references.push(elm);
+            } else if (isViewElementChoise(elm)) {
+                acc.choises.push(elm);
+            } else if (isViewElementRpc(elm)) {
+                acc.rpcs.push(elm);
+            } else {
+                acc.elements.push(elm);
+            }
+            return acc;
+        }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] });
+
+        sections.elements = sections.elements.sort(orderFunc);
 
         return (
-              <Tooltip title={"Remove"} >
-                <IconButton className={classes.button} onClick={async (e) => {
-                  e.stopPropagation();
-                  e.preventDefault();
-                  confirm({title: "Do you really want to delete this element ?", description: "This action is permanent!", confirmationButtonProps: { color: "secondary" }})
-                    .then(() => removeElement(`${this.props.vPath}[${props.rowData[listKeyProperty]}]`))
-                    .then( props.onReload );
-                }} >
-                  <RemoveIcon />
-                </IconButton>
-              </Tooltip>
+            <div className={classes.uiView}>
+                <div className={classes.section} />
+                {sections.elements.length > 0
+                    ? (
+                        <div className={classes.section}>
+                            {sections.elements.map(element => this.renderUIElement(element, viewData, keyProperty, editMode, isNew))}
+                        </div>
+                    ) : null
+                }
+                {sections.references.length > 0
+                    ? (
+                        <div className={classes.section}>
+                            {sections.references.map(element => (
+                                <UIElementReference key={element.id} element={element} disabled={editMode} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
+                            ))}
+                        </div>
+                    ) : null
+                }
+                {sections.choises.length > 0
+                    ? (
+                        <div className={classes.section}>
+                            {sections.choises.map(element => this.renderUIChoise(element, viewData, keyProperty, editMode, isNew))}
+                        </div>
+                    ) : null
+                }
+                {sections.rpcs.length > 0
+                    ? (
+                        <div className={classes.section}>
+                            {sections.rpcs.map(element => (
+                                <UIElementReference key={element.id} element={element} disabled={editMode} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
+                            ))}
+                        </div>
+                    ) : null
+                }
+            </div>
+        );
+    };
+
+    private renderUIViewSelector = (viewSpecification: ViewSpecification, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+        const { classes } = this.props;
+
+        // group by module name
+        const modules = Object.keys(viewSpecification.elements).reduce<{ [key: string]: ViewSpecification }>((acc, cur) => {
+            const elm = viewSpecification.elements[cur];
+            const moduleView = (acc[elm.module] = acc[elm.module] || { ...viewSpecification, elements: {} });
+            moduleView.elements[cur] = elm;
+            return acc;
+        }, {});
+
+        const moduleKeys = Object.keys(modules).sort(); 
+
+        return (
+            <div className={classes.moduleCollection}>
+                {
+                   moduleKeys.map(key => {
+                        const moduleView = modules[key];
+                        return (
+                            <Accordion key={key} defaultExpanded={ moduleKeys.length < 4 } aria-label={key+'-panel'} >
+                                <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls={`content-${key}`} id={`header-${key}`} >
+                                    <Typography className={classes.heading}>{key}</Typography>
+                                </AccordionSummary>
+                                <AccordionDetails>
+                                    {this.renderUIView(moduleView, viewData, keyProperty, editMode, isNew)}
+                                </AccordionDetails>
+                            </Accordion>
+                        );
+                    })
+                }
+            </div>
+           );
+    };
+
+    private renderUIViewList(listSpecification: ViewSpecification, listKeyProperty: string, listData: { [key: string]: any }[]) {
+        const listElements = listSpecification.elements;
+
+        const navigate = (path: string) => {
+            this.props.history.push(`${this.props.match.url}${path}`);
+        };
+
+        const addNewElementAction = {
+            icon: AddIcon, tooltip: 'Add', onClick: () => {
+                navigate("[]"); // empty key means new element
+            }
+        };
+
+        const { classes, removeElement } = this.props;
+
+        const DeleteIconWithConfirmation: React.FC<{ rowData: { [key: string]: any }, onReload: () => void }> = (props) => {
+            const confirm = useConfirm();
+
+            return (
+                <Tooltip title={"Remove"} >
+                    <IconButton className={classes.button} aria-label="remove-element-button"
+                     onClick={async (e) => {
+                        e.stopPropagation();
+                        e.preventDefault();
+                        confirm({ title: "Do you really want to delete this element ?", description: "This action is permanent!", confirmationButtonProps: { color: "secondary" } })
+                            .then(() => removeElement(`${this.props.vPath}[${props.rowData[listKeyProperty]}]`))
+                            .then(props.onReload);
+                    }} >
+                        <RemoveIcon />
+                    </IconButton>
+                </Tooltip>
+            );
+        }
+
+        return (
+            <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} customActionButtons={[addNewElementAction]} columns={
+                Object.keys(listElements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
+                    const elm = listElements[cur];
+                    if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
+                        if (elm.label !== listKeyProperty) {
+                            acc.push(elm.uiType === "boolean" 
+                            ? { property: elm.label, type: ColumnType.boolean } 
+                            :  elm.uiType === "date" 
+                               ? { property: elm.label, type: ColumnType.date } 
+                               : { property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+                        } else {
+                            acc.unshift(elm.uiType === "boolean" 
+                            ? { property: elm.label, type: ColumnType.boolean } 
+                            : elm.uiType === "date" 
+                               ? { property: elm.label, type: ColumnType.date } 
+                               : { property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+                        }
+                    }
+                    return acc;
+                }, []).concat([{
+                    property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (({ rowData }) => {
+                        return (
+                            <DeleteIconWithConfirmation rowData={rowData} onReload={() => this.props.vPath && this.props.reloadView(this.props.vPath)} />
+                        );
+                    })
+                }])
+            } onHandleClick={(ev, row) => {
+                ev.preventDefault();
+                navigate(`[${encodeURIComponent(row[listKeyProperty])}]`);
+            }} ></SelectElementTable>
         );
     }
 
-    return (
-      <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} customActionButtons={[addNewElementAction]} columns={
-        Object.keys(listElements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
-          const elm = listElements[cur];
-          if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
-            if (elm.label !== listKeyProperty) {
-              acc.push(elm.uiType === "boolean" ? { property: elm.label, type: ColumnType.boolean } : { property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+    private renderUIViewRPC(inputViewSpecification: ViewSpecification | undefined, inputViewData: { [key: string]: any }, outputViewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) {
+        const { classes } = this.props;
+
+        const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
+            if (keyProperty) {
+                // if (vsA.label === vsB.label) return 0;
+                if (vsA.label === keyProperty) return -1;
+                if (vsB.label === keyProperty) return +1;
+            }
+
+            // if (vsA.uiType === vsB.uiType) return 0;
+            // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+            // if (vsA.uiType === "object") return +1;
+            return -1;
+        };
+
+        const sections = inputViewSpecification && Object.keys(inputViewSpecification.elements).reduce((acc, cur) => {
+            const elm = inputViewSpecification.elements[cur];
+            if (isViewElementObjectOrList(elm)) {
+                console.error("Object should not appear in RPC view !");
+            } else if (isViewElementChoise(elm)) {
+                acc.choises.push(elm);
+            } else if (isViewElementRpc(elm)) {
+                console.error("RPC should not appear in RPC view !");
             } else {
-              acc.unshift(elm.uiType === "boolean" ? { property: elm.label, type: ColumnType.boolean } : { property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
-            }
-          }
-          return acc;
-        }, []).concat([{
-          property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: ( ({ rowData })=> {
-            return (
-              <DeleteIconWithConfirmation rowData={rowData} onReload={() => this.props.vPath && this.props.reloadView(this.props.vPath) } />
-            );
-          })
-        }])
-      } onHandleClick={(ev, row) => {
-        ev.preventDefault();
-        navigate(`[${row[listKeyProperty]}]`);
-      }} ></SelectElementTable>
-    );
-  }
-
-  private renderUIViewRPC(inputViewSpecification: ViewSpecification | undefined, inputViewData: { [key: string]: any }, outputViewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) {
-    const { classes } = this.props;
-
-    const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
-      if (keyProperty) {
-        // if (vsA.label === vsB.label) return 0;
-        if (vsA.label === keyProperty) return -1;
-        if (vsB.label === keyProperty) return +1;
-      }
-
-      // if (vsA.uiType === vsB.uiType) return 0;
-      // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
-      // if (vsA.uiType === "object") return +1;
-      return -1;
-    };
-
-    const sections = inputViewSpecification && Object.keys(inputViewSpecification.elements).reduce((acc, cur) => {
-      const elm = inputViewSpecification.elements[cur];
-      if (isViewElementObjectOrList(elm)) {
-        console.error("Object should not appear in RPC view !");
-      } else if (isViewElementChoise(elm)) {
-        acc.choises.push(elm);
-      } else if (isViewElementRpc(elm)) {
-        console.error("RPC should not appear in RPC view !");
-      } else {
-        acc.elements.push(elm);
-      }
-      return acc;
-    }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] })
-      || { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] };
-
-    sections.elements = sections.elements.sort(orderFunc);
-
-    return (
-      <>
-        <div className={classes.section} />
-        {sections.elements.length > 0
-          ? (
-            <div className={classes.section}>
-              {sections.elements.map(element => this.renderUIElement(element, inputViewData, keyProperty, editMode, isNew))}
-            </div>
-          ) : null
-        }
-        {sections.choises.length > 0
-          ? (
-            <div className={classes.section}>
-              {sections.choises.map(element => this.renderUIChoise(element, inputViewData, keyProperty, editMode, isNew))}
-            </div>
-          ) : null
-        }
-        <Button onClick={() => {
-          const resultingViewData = inputViewSpecification && this.collectData(inputViewSpecification.elements);
-          this.props.executeRpc(this.props.vPath!, resultingViewData);
-        }} >Exec</Button>
-        {outputViewData !== undefined
-          ? (
-            renderObject(outputViewData)          )
-          : null
-        }
-        </>
-    );
-  };
-
-  private renderBreadCrumps() {
-    const { editMode } = this.state;
-    const { displaySpecification } = this.props;
-    const { vPath, nodeId } = this.props;
-    const pathParts = splitVPath(vPath!, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
-    let lastPath = `/configuration`;
-    let basePath = `/configuration/${nodeId}`;
-    return (
-      <div className={this.props.classes.header}>
-        <div>
-          <Breadcrumbs aria-label="breadcrumb">
-            <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
-              ev.preventDefault();
-              this.props.history.push(lastPath);
-            }}>Back</Link>
-            <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
-              ev.preventDefault();
-              this.props.history.push(`/configuration/${nodeId}`);
-            }}><span>{nodeId}</span></Link>
-            {
-              pathParts.map(([prop, key], ind) => {
-                const path = `${basePath}/${prop}`;
-                const keyPath = key && `${basePath}/${prop}[${key}]`;
-                const ret = (
-                  <span key={ind}>
-                    <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
-                      ev.preventDefault();
-                      this.props.history.push(path);
-                    }}><span>{prop.replace(/^[^:]+:/, "")}</span></Link>
-                    {
-                      keyPath && <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
-                        ev.preventDefault();
-                        this.props.history.push(keyPath);
-                      }}>{`[${key}]`}</Link> || null
-                    }
-                  </span>
-                );
-                lastPath = basePath;
-                basePath = keyPath || path;
-                return ret;
-              })
-            }
-          </Breadcrumbs>
-        </div>
-        {this.state.editMode && (
-          <Fab color="secondary" aria-label="edit" className={this.props.classes.fab} onClick={async () => {
-            this.props.vPath && await this.props.reloadView(this.props.vPath);
-            this.setState({ editMode: false });
-          }} ><ArrowBack /></Fab>
-        ) || null}
-        { /* do not show edit if this is a list or it can't be edited */
-          displaySpecification.displayMode === DisplayModeType.displayAsObject && displaySpecification.viewSpecification.canEdit && (<div>
-            <Fab color="secondary" aria-label="edit" className={this.props.classes.fab} onClick={() => {
-              if (this.state.editMode) {
-                // ensure only active choises will be contained
-                const resultingViewData = this.collectData(displaySpecification.viewSpecification.elements);
-                this.props.onUpdateData(this.props.vPath!, resultingViewData);
-              }
-              this.setState({ editMode: !editMode });
-            }}>
-              {editMode
-                ? <SaveIcon />
-                : <EditIcon />
-              }
-            </Fab>
-          </div> || null)
-        }
-      </div>
-    );
-  }
-
-  private renderValueSelector() {
-    const { listKeyProperty, listSpecification, listData, onValueSelected } = this.props;
-    if (!listKeyProperty || !listSpecification) {
-      throw new Error("ListKex ot view not specified.");
-    }
-
-    return (
-      <div className={this.props.classes.container}>
-        <SelectElementTable stickyHeader  idProperty={listKeyProperty} rows={listData} columns={
-          Object.keys(listSpecification.elements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
-            const elm = listSpecification.elements[cur];
-            if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
-              if (elm.label !== listKeyProperty) {
-                acc.push({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
-              } else {
-                acc.unshift({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
-              }
+                acc.elements.push(elm);
             }
             return acc;
-          }, [])
-        } onHandleClick={(ev, row) => { ev.preventDefault(); onValueSelected(row); }} ></SelectElementTable>
-      </div>
-    );
-  }
+        }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] })
+            || { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] };
 
-  private renderValueEditor() {
-    const { displaySpecification: ds, outputData } = this.props;
-    const { viewData, editMode, isNew } = this.state;
+        sections.elements = sections.elements.sort(orderFunc);
 
-    return (
-      <div className={this.props.classes.container}>
-        {this.renderBreadCrumps()}
-        {ds.displayMode === DisplayModeType.doNotDisplay
-          ? null
-          : ds.displayMode === DisplayModeType.displayAsList && viewData instanceof Array
-            ? this.renderUIViewList(ds.viewSpecification, ds.keyProperty!, viewData)
-            : ds.displayMode === DisplayModeType.displayAsRPC
-              ? this.renderUIViewRPC(ds.inputViewSpecification, viewData!, outputData, undefined, true, false)
-              : this.renderUIView(ds.viewSpecification, viewData!, ds.keyProperty, editMode, isNew)
+        return (
+            <>
+                <div className={classes.section} />
+                { sections.elements.length > 0
+                    ? (
+                        <div className={classes.section}>
+                            {sections.elements.map(element => this.renderUIElement(element, inputViewData, keyProperty, editMode, isNew))}
+                        </div>
+                    ) : null
+                }
+                { sections.choises.length > 0
+                    ? (
+                        <div className={classes.section}>
+                            {sections.choises.map(element => this.renderUIChoise(element, inputViewData, keyProperty, editMode, isNew))}
+                        </div>
+                    ) : null
+                }
+                <Button onClick={() => {
+                    const resultingViewData = inputViewSpecification && this.collectData(inputViewSpecification.elements);
+                    this.props.executeRpc(this.props.vPath!, resultingViewData);
+                }} >Exec</Button>
+                <div className={classes.objectReult}>
+                { outputViewData !== undefined
+                    ? renderObject(outputViewData)
+                    : null
+                }
+                </div>
+            </>
+        );
+    };
+
+    private renderBreadCrumps() {
+        const { editMode } = this.state;
+        const { displaySpecification, vPath, nodeId } = this.props;
+        const pathParts = splitVPath(vPath!, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+        let lastPath = `/configuration`;
+        let basePath = `/configuration/${nodeId}`;
+        return (
+            <div className={this.props.classes.header}>
+                <div>
+                    <Breadcrumbs aria-label="breadcrumbs">
+                        <Link color="inherit" href="#" aria-label="back-breadcrumb"
+                         onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                            ev.preventDefault();
+                            this.props.history.push(lastPath);
+                        }}>Back</Link>
+                        <Link color="inherit" href="#" 
+                        aria-label={nodeId+'-breadcrumb'}
+                        onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                            ev.preventDefault();
+                            this.props.history.push(`/configuration/${nodeId}`);
+                        }}><span>{nodeId}</span></Link>
+                        {
+                            pathParts.map(([prop, key], ind) => {
+                                const path = `${basePath}/${prop}`;
+                                const keyPath = key && `${basePath}/${prop}[${key}]`;
+                                const propTitle= prop.replace(/^[^:]+:/, "");
+                                const ret = (
+                                    <span key={ind}>
+                                        <Link color="inherit" href="#" 
+                                        aria-label={propTitle+'-breadcrumb'}
+                                        onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                                            ev.preventDefault();
+                                            this.props.history.push(path);
+                                        }}><span>{propTitle}</span></Link>
+                                        {
+                                            keyPath && <Link color="inherit" href="#" 
+                                            aria-label={key+'-breadcrumb'}
+                                            onClick={(ev: React.MouseEvent<HTMLElement>) => {
+                                                ev.preventDefault();
+                                                this.props.history.push(keyPath);
+                                            }}>{`[${key}]`}</Link> || null
+                                        }
+                                    </span>
+                                );
+                                lastPath = basePath;
+                                basePath = keyPath || path;
+                                return ret;
+                            })
+                        }
+                    </Breadcrumbs>
+                </div>
+                {this.state.editMode && (
+                    <Fab color="secondary" aria-label="back-button" className={this.props.classes.fab} onClick={async () => {
+                        this.props.vPath && await this.props.reloadView(this.props.vPath);
+                        this.setState({ editMode: false });
+                    }} ><ArrowBack /></Fab>
+                ) || null}
+                { /* do not show edit if this is a list or it can't be edited */
+                    displaySpecification.displayMode === DisplayModeType.displayAsObject && displaySpecification.viewSpecification.canEdit && (<div>
+                        <Fab color="secondary" aria-label={editMode ? 'save-button' : 'edit-button'} className={this.props.classes.fab} onClick={() => {
+                            if (this.state.editMode) {
+                                // ensure only active choises will be contained
+                                const resultingViewData = this.collectData(displaySpecification.viewSpecification.elements);
+                                this.props.onUpdateData(this.props.vPath!, resultingViewData);
+                            }
+                            this.setState({ editMode: !editMode });
+                        }}>
+                            {editMode
+                                ? <SaveIcon />
+                                : <EditIcon />
+                            }
+                        </Fab>
+                    </div> || null)
+                }
+            </div>
+        );
+    }
+
+    private renderValueSelector() {
+        const { listKeyProperty, listSpecification, listData, onValueSelected } = this.props;
+        if (!listKeyProperty || !listSpecification) {
+            throw new Error("ListKex ot view not specified.");
         }
-      </div >
-    );
-  }
 
-  private renderCollectingData() {
-    return (
-      <div className={this.props.classes.outer}>
-        <div className={this.props.classes.inner}>
-          <Loader />
-          <h3>Processing ...</h3>
-        </div>
-      </div>
-    );
-  }
+        return (
+            <div className={this.props.classes.container}>
+                <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} columns={
+                    Object.keys(listSpecification.elements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
+                        const elm = listSpecification.elements[cur];
+                        if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
+                            if (elm.label !== listKeyProperty) {
+                                acc.push({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+                            } else {
+                                acc.unshift({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+                            }
+                        }
+                        return acc;
+                    }, [])
+                } onHandleClick={(ev, row) => { ev.preventDefault(); onValueSelected(row); }} ></SelectElementTable>
+            </div>
+        );
+    }
 
-  render() {
-    return this.props.collectingData || !this.state.viewData
-      ? this.renderCollectingData()
-      : this.props.listSpecification
-        ? this.renderValueSelector()
-        : this.renderValueEditor();
-  }
+    private renderValueEditor() {
+        const { displaySpecification: ds, outputData } = this.props;
+        const { viewData, editMode, isNew } = this.state;
+
+        return (
+            <div className={this.props.classes.container}>
+                {this.renderBreadCrumps()}
+                {ds.displayMode === DisplayModeType.doNotDisplay
+                    ? null
+                    : ds.displayMode === DisplayModeType.displayAsList && viewData instanceof Array
+                        ? this.renderUIViewList(ds.viewSpecification, ds.keyProperty!, viewData)
+                        : ds.displayMode === DisplayModeType.displayAsRPC
+                            ? this.renderUIViewRPC(ds.inputViewSpecification, viewData!, outputData, undefined, true, false)
+                            : this.renderUIViewSelector(ds.viewSpecification, viewData!, ds.keyProperty, editMode, isNew)
+                }
+            </div >
+        );
+    }
+
+    private renderCollectingData() {
+        return (
+            <div className={this.props.classes.outer}>
+                <div className={this.props.classes.inner}>
+                    <Loader />
+                    <h3>Processing ...</h3>
+                </div>
+            </div>
+        );
+    }
+
+    render() {
+        return this.props.collectingData || !this.state.viewData
+            ? this.renderCollectingData()
+            : this.props.listSpecification
+                ? this.renderValueSelector()
+                : this.renderValueEditor();
+    }
 }
 
 export const ConfigurationApplication = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(ConfigurationApplicationComponent)));
-export default ConfigurationApplication;
+export default ConfigurationApplication;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
index 0f74297..c5cb8fb 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -15,14 +15,15 @@
  * the License.
  * ============LICENSE_END==========================================================================
  */
-import { Token, Statement, Module, Identity } from "../models/yang";
+import { Token, Statement, Module, Identity, ModuleState } from "../models/yang";
 import {
   ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase,
   isViewElementReference, ViewElementChoise, ViewElementBinary, ViewElementString, isViewElementString,
-  isViewElementNumber, ViewElementNumber, Expression, YangRange, ViewElementUnion, ViewElementRpc, isViewElementRpc, ResolveFunction
+  isViewElementNumber, ViewElementNumber, Expression, YangRange, ViewElementUnion, ViewElementRpc, isViewElementRpc, ResolveFunction, ViewElementDate
 } from "../models/uiModels";
 import { yangService } from "../services/yangService";
 
+
 export const splitVPath = (vPath: string, vPathParser: RegExp): RegExpMatchArray[] => {
   const pathParts: RegExpMatchArray[] = [];
   let partMatch: RegExpExecArray | null;
@@ -284,8 +285,8 @@
 
   public static ResolveStack = Symbol("ResolveStack");
 
-  constructor() {
-
+  constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = []) {
+   
   }
 
   public get modules() {
@@ -299,9 +300,16 @@
   public async addCapability(capability: string, version?: string) {
     // do not add twice
     if (this._modules[capability]) {
+      // console.warn(`Skipped capability: ${capability} since allready contained.` );
       return;
     }
 
+    // // do not add unavaliabe capabilities
+    // if (this._unavailableCapabilities.some(c => c.capability === capability)) {
+    //   // console.warn(`Skipped capability: ${capability} since it is marked as unavaliable.` );
+    //   return;
+    // }
+
     const data = await yangService.getCapability(capability, version);
     if (!data) {
       throw new Error(`Could not load yang file for ${capability}.`);
@@ -316,6 +324,8 @@
       throw new Error(`Root element capability ${rootStatement.arg} does not requested ${capability}.`);
     }
 
+    const isUnavaliabe = this._unavailableCapabilities.some(c => c.capability === capability);
+    
     const module = this._modules[capability] = {
       name: rootStatement.arg,
       revisions: {},
@@ -326,7 +336,10 @@
       groupings: {},
       typedefs: {},
       views: {},
-      elements: {}
+      elements: {},
+      state: isUnavaliabe
+           ? ModuleState.unabaliabe 
+           : ModuleState.stable,
     };
 
     await this.handleModule(module, rootStatement, capability);
@@ -389,9 +402,14 @@
       }, {})
     };
 
-    // import all required files
+    // import all required files and set module state 
     if (imports) for (let ind = 0; ind < imports.length; ++ind) {
-      await this.addCapability(imports[ind].arg!);
+      const moduleName = imports[ind].arg!; 
+      await this.addCapability(moduleName);
+      const importedModule = this._modules[imports[ind].arg!];
+      if (importedModule && importedModule.state > ModuleState.stable) {
+          module.state = Math.max(module.state, ModuleState.instable);
+      }
     }
 
     this.extractTypeDefinitions(rootStatement, module, "");
@@ -420,7 +438,9 @@
           const viewIdIndex = Number(viewElement.viewId);
           module.views[key] = this._views[viewIdIndex];
         }
-        this._views[0].elements[key] = module.elements[key];
+        
+        // add only the UI View if the module is avliable
+        if (module.state !== ModuleState.unabaliabe) this._views[0].elements[key] = module.elements[key];
       });
     });
     return module;
@@ -442,10 +462,30 @@
       }
     });
 
-    // process all augmentations
+    // process all augmentations / sort by namespace changes to ensure propper order 
     Object.keys(this.modules).forEach(modKey => {
       const module = this.modules[modKey];
-      Object.keys(module.augments).forEach(augKey => {
+      const augmentKeysWithCounter = Object.keys(module.augments).map((key) => {
+        const pathParts = splitVPath(key, /(?:(?:([^\/\:]+):)?([^\/]+))/g);  // 1 = opt: namespace / 2 = property 
+        let nameSpaceChangeCounter = 0;
+        let currentNS = module.name; // init namespace
+        pathParts.forEach(([ns, _])=> {
+          if (ns === currentNS){
+            currentNS = ns;
+            nameSpaceChangeCounter++;
+          }
+        });
+        return {
+          key,
+          nameSpaceChangeCounter,
+        }
+      });
+      
+      const augmentKeys = augmentKeysWithCounter
+        .sort((a,b) => a.nameSpaceChangeCounter > b.nameSpaceChangeCounter ? 1 : a.nameSpaceChangeCounter === b.nameSpaceChangeCounter ? 0 : -1 )
+        .map((a) => a.key);
+
+      augmentKeys.forEach(augKey => {
         const augments = module.augments[augKey];
         const viewSpec = this.resolveView(augKey);
         if (!viewSpec) console.warn(`Could not find view to augment [${augKey}] in [${module.name}].`);
@@ -454,6 +494,7 @@
             const elm = augment.elements[key];
             viewSpec.elements[key] = {
               ...augment.elements[key],
+              
               when: elm.when ? `(${augment.when}) and (${elm.when})` : augment.when,
               ifFeature: elm.ifFeature ? `(${augment.ifFeature}) and (${elm.ifFeature})` : augment.ifFeature,
             };
@@ -546,7 +587,7 @@
         const grouping = cur.arg;
 
         // the default for config on module level is config = true;
-        const [currentView, subViews] = this.extractSubViews(cur, parentId, module, currentPath);
+        const [currentView, subViews] = this.extractSubViews(cur, /* parentId */ -1, module, currentPath);
         grouping && (module.groupings[grouping] = currentView);
         acc.push(currentView, ...subViews);
         return acc;
@@ -600,6 +641,7 @@
     }, {});
   }
 
+   // Hint: use 0 as parentId for rootElements and -1 for rootGroupings.
   private extractSubViews(statement: Statement, parentId: number, module: Module, currentPath: string): [ViewSpecification, ViewSpecification[]] {
     // used for scoped definitions
     const context: Module = {
@@ -640,6 +682,8 @@
         elements.push({
           id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
           label: cur.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
           uiType: "object",
           viewId: currentView.id,
           config: config
@@ -667,6 +711,8 @@
         elements.push({
           id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
           label: cur.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
           isList: true,
           uiType: "object",
           viewId: currentView.id,
@@ -755,6 +801,8 @@
           uiType: "choise",
           id: parentId === 0 ? `${context.name}:${curChoise.arg}` : curChoise.arg,
           label: curChoise.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
           config: config,
           mandatory: mandatory,
           description: description,
@@ -802,6 +850,8 @@
           uiType: "rpc",
           id: parentId === 0 ? `${context.name}:${curRpc.arg}` : curRpc.arg,
           label: curRpc.arg,
+          path: currentPath,
+          module: context.name || module.name || '',
           config: config,
           description: description,
           inputViewId: inputViewId,
@@ -869,7 +919,8 @@
 
             Object.keys(groupingViewSpec.elements).forEach(key => {
               const elm = groupingViewSpec.elements[key];
-              viewSpec.elements[key] = {
+              // a useRef on root level need a namespace
+              viewSpec.elements[parentId === 0 ? `${module.name}:${key}` : key] = {
                 ...groupingViewSpec.elements[key],
                 when: elm.when ? `(${groupingViewSpec.when}) and (${elm.when})` : groupingViewSpec.when,
                 ifFeature: elm.ifFeature ? `(${groupingViewSpec.ifFeature}) and (${elm.ifFeature})` : groupingViewSpec.ifFeature,
@@ -889,7 +940,9 @@
             }
         });
         // console.log("Resolved "+currentElementPath, viewSpec);
-        viewSpec?.uses![ResolveFunction] = undefined;
+        if (viewSpec?.uses) {
+          viewSpec.uses[ResolveFunction] = undefined;
+        }
       }
 
       this._groupingsToResolve.push(viewSpec);
@@ -934,9 +987,19 @@
     const extractRange = (min: number, max: number, property: string = "range"): { expression: Expression<YangRange> | undefined, min: number, max: number } => {
       const ranges = this.extractValue(this.extractNodes(cur, "type")[0]!, property) || undefined;
       const range = ranges ?.replace(/min/i, String(min)).replace(/max/i, String(max)).split("|").map(r => {
-        const [minStr, maxStr] = r.split('..');
-        const minValue = Number(minStr);
-        const maxValue = Number(maxStr);
+        let minValue: number;
+        let maxValue: number;
+        
+        if (r.indexOf('..') > -1) {
+            const [minStr, maxStr] = r.split('..');
+            minValue = Number(minStr);
+            maxValue = Number(maxStr);
+        } else if (!isNaN(maxValue = Number(r && r.trim() )) ) {
+            minValue = maxValue;
+        } else {
+            minValue = min,
+            maxValue = max;
+        }
 
         if (minValue > min) min = minValue;
         if (maxValue < max) max = maxValue;
@@ -978,7 +1041,9 @@
 
     const element: ViewElementBase = {
       id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
-      label: cur.arg,
+      label: cur.arg, 
+      path: currentPath,
+      module: module.name || "",
       config: config,
       mandatory: mandatory,
       isList: isList,
@@ -1254,17 +1319,27 @@
         length: extractRange(0, +18446744073709551615, "length"),
       };
     } else {
-      // not a build in type, have to resolve type
+      // not a build in type, need to resolve type
       let typeRef = this.resolveType(type, module);
       if (typeRef == null) console.error(new Error(`Could not resolve type ${type} in [${module.name}][${currentPath}].`));
 
+
       if (isViewElementString(typeRef)) {
         typeRef = this.resolveStringType(typeRef, extractPattern(), extractRange(0, +18446744073709551615));
-
       } else if (isViewElementNumber(typeRef)) {
         typeRef = this.resolveNumberType(typeRef, extractRange(typeRef.min, typeRef.max));
       }
 
+      // spoof date type here from special string type
+      if ((type === 'date-and-time' || type.endsWith(':date-and-time') ) && typeRef.module === "ietf-yang-types") {
+          return {
+             ...typeRef,
+             ...element,
+             description: description,
+             uiType: "date", 
+          };
+      }
+
       return ({
         ...typeRef,
         ...element,
diff --git a/sdnr/wt/odlux/apps/configurationApp/webpack.config.js b/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
index 329eb00..6349305 100644
--- a/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
@@ -129,36 +129,46 @@
         colors: true
       },
        proxy: {
+        "/about": {
+          // target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
+          secure: false
+        }, 
         "/yang-schema/": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
           secure: false
         },   
         "/oauth2/": {
-          target: "http://10.20.6.29:48181",
+          // target: "https://10.20.35.188:30205",
+          target: "http://localhost:8181",
           secure: false
         },
         "/database/": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
           secure: false
         },
         "/restconf/": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
           secure: false
         },
         "/rests/": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
           secure: false
         },
         "/help/": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
+          secure: false
+        },
+         "/about/": {
+          target: "http://localhost:8181",
           secure: false
         },
         "/tree/": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
           secure: false
         },
         "/websocket": {
-          target: "http://10.20.6.29:48181",
+          target: "http://localhost:8181",
           ws: true,
           changeOrigin: true,
           secure: false
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml
index 732b4fe..c849c19 100644
--- a/sdnr/wt/odlux/framework/pom.xml
+++ b/sdnr/wt/odlux/framework/pom.xml
@@ -46,7 +46,7 @@
     <properties>
         <buildtime>${maven.build.timestamp}</buildtime>
         <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
-        <buildno>68.d7886ce(20/09/04)</buildno>
+        <buildno>86.51a94bd(20/11/17)</buildno>
         <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
     </properties>
 
diff --git a/sdnr/wt/odlux/framework/src/assets/version.json b/sdnr/wt/odlux/framework/src/assets/version.json
index 6311e10..7720cb9 100644
--- a/sdnr/wt/odlux/framework/src/assets/version.json
+++ b/sdnr/wt/odlux/framework/src/assets/version.json
@@ -1,4 +1,5 @@
 {
-    "version":"68.d7886ce(20/09/04)",
-    "build":"2020-09-04T12:31:19Z"
+    "version":"86.51a94bd(20/11/17)",
+    "build":"2020-11-17T11:13:24Z"
+
 }
\ No newline at end of file