Update ODLUX
[ccsdk/features.git] / sdnr / wt / odlux / apps / configurationApp / src / actions / deviceActions.ts
index d7babc1..0dd42e3 100644 (file)
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
 import { Action } from '../../../../framework/src/flux/action';
 import { Dispatch } from '../../../../framework/src/flux/store';
 import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
@@ -10,6 +28,7 @@ import { YangParser } from "../yang/yangParser";
 import { Module } from "../models/yang";
 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 ) {
     super();
@@ -35,7 +54,7 @@ export class UpdateDeviceDescription extends Action {
 }
 
 export class UpdatViewDescription extends Action {
-  constructor (public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay } ) {
+  constructor (public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay }) {
     super();
   }
 }
@@ -51,26 +70,26 @@ export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatc
   dispatch(new UpdateDeviceDescription("", {}, []));
   dispatch(new SetCollectingSelectionData(true));
   
-  const { avaliableCapabilities, unavaliableCapabilities } = await restService.getCapabilitiesByMoutId(nodeId);
-
-  if (!avaliableCapabilities || avaliableCapabilities.length <= 0) {
+  const { availableCapabilities, unavailableCapabilities, importOnlyModules } = await restService.getCapabilitiesByMountId(nodeId);
+  
+  if (!availableCapabilities || availableCapabilities.length <= 0) {
+    dispatch(new SetCollectingSelectionData(false));
+    dispatch(new UpdateDeviceDescription(nodeId, {}, []));
+    dispatch(new UpdatViewDescription("", [], {
+      displayMode: DisplayModeType.displayAsMessage,
+      renderMessage: `NetworkElement : "${nodeId}" has no capabilities.`
+    }));
     throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
   }
-  
-  const capParser = /^\(.*\?revision=(\d{4}-\d{2}-\d{2})\)(\S+)$/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);
+    
+  const parser = new YangParser(unavailableCapabilities || undefined, importOnlyModules || undefined);
+
+  for (let i = 0; i < availableCapabilities.length; ++i){
+    const capRaw = availableCapabilities[i];
     try {
-      capMatch && await parser.addCapability(capMatch[2], capMatch[1]);
+      await parser.addCapability(capRaw.capability, capRaw.version);
     } catch (err) {
-      console.error(`Error in ${capMatch && capMatch[2]} ${capMatch && capMatch[1]}`, err);
+      console.error(`Error in ${capRaw.capability} ${capRaw.version}`, err);
     }
   }
 
@@ -333,6 +352,7 @@ export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch:
                 const refView : ViewSpecification  = {
                     id: "-1",
                     canEdit: false,
+                    config: false,
                     language: "en-US",
                     elements: {
                         [viewElement.key!] : { 
@@ -437,18 +457,21 @@ export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch:
         }
       });
     }
-
+    
     // create display specification
     const ds: DisplaySpecification = viewElement! && viewElement!.uiType === "rpc"
       ? {
+        dataPath,
         displayMode: DisplayModeType.displayAsRPC,
         inputViewSpecification: inputViewSpecification && resolveViewDescription(defaultNS, vPath, inputViewSpecification),
         outputViewSpecification: outputViewSpecification && resolveViewDescription(defaultNS, vPath, outputViewSpecification),
       }
       : {
+        dataPath,
         displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
         viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
         keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
+        apidocPath:  isViewElementList(viewElement!) &&  `/apidoc/explorer/index.html?urls.primaryName=$$$standard$$$#/mounted%20${nodeId}%20${viewElement!.module || 'MODULE_NOT_DEFINED'}/$$$action$$$_${dataPath.replace(/^\//,'').replace(/[\/=\-\:]/g,'_')}_${viewElement! != null ? `${viewElement.id.replace(/[\/=\-\:]/g,'_')}_` : '' }` || undefined,
       };
 
     // update display specification
@@ -516,6 +539,35 @@ export const updateDataActionAsyncCreator = (vPath: string, data: any) => async
       }
     }
 
+    // remove read-only elements
+    const removeReadOnlyElements = (viewSpecification: ViewSpecification, isList: boolean, data: any) => {
+      if (isList) {
+        return data.map((elm : any) => removeReadOnlyElements(viewSpecification, false, elm));
+      } else {
+        return Object.keys(data).reduce<{[key: string]: any}>((acc, cur)=>{
+          const [nsOrName, name] = cur.split(':',1);
+          const element = viewSpecification.elements[cur] || viewSpecification.elements[nsOrName] || viewSpecification.elements[name];
+          if (!element && process.env.NODE_ENV === "development" ) {
+            throw new Error("removeReadOnlyElements: Could not determine elment for data.");
+          }
+          if (element && element.config) {
+            if (element.uiType==="object") {
+              const view = views[+element.viewId];
+              if (!view) {
+                throw new Error("removeReadOnlyElements: Internal Error could not determine viewId: "+element.viewId);
+              }
+              acc[cur] = removeReadOnlyElements(view, element.isList != null && element.isList, data[cur]);
+            } else {
+              acc[cur] = data[cur];
+            }
+          }
+          return acc;
+        }, {});
+      }
+    };
+    data = removeReadOnlyElements(viewSpecification, embedList, data);
+
+
     // embed the list -> key: list
     data = embedList
       ? { [viewElement!.label]: data }
@@ -528,7 +580,7 @@ export const updateDataActionAsyncCreator = (vPath: string, data: any) => async
 
     // do not extract root member (0)
     if (viewSpecification && viewSpecification.id !== "0") {
-      const updateResult = await restService.setConfigData(dataPath, { [`${defaultNS}:${dataMember!}`]: data }); // addDataMember using defaultNS
+      const updateResult = await restService.setConfigData(dataPath, { [`${currentNS}:${dataMember!}`]: data }); // addDataMember using currentNS
       if (updateResult.status < 200 || updateResult.status > 299) {
         const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]["error-message"] || "";
         throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
@@ -536,7 +588,7 @@ export const updateDataActionAsyncCreator = (vPath: string, data: any) => async
     }
 
     if (isNew) {
-      return dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i, `[${isNew}]`)}`)) // navigate to new element
+      return dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i, `[${isNew}]`)}`)); // navigate to new element
     }
 
     // create display specification