ConfigApp bugfix 14/113614/1
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>
Wed, 7 Oct 2020 14:36:59 +0000 (16:36 +0200)
committerAijana Schumann <aijana.schumann@highstreet-technologies.com>
Wed, 7 Oct 2020 14:36:59 +0000 (16:36 +0200)
Fix interface list is not visible

Issue-ID: CCSDK-2880
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: I090a298a925ada52eda603c8a24cf6d577a7b5e6

sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts

index 790d251..83134fc 100644 (file)
@@ -182,13 +182,25 @@ const resolveViewDescription = (defaultNS: string | null, vPath: string, view: V
   // check if-feature | when | and resolve all references.
   view = { ...view };
   view.elements = Object.keys(view.elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
-    const elm = view.elements[cur];
+    const resolveHistory : ViewElement[] = [];  
+    let elm = view.elements[cur];
     const key = defaultNS && cur.replace(new RegExp(`^${defaultNS}:`, "i"),"") || cur;
-    if (isViewElementReference(elm)) {
-      acc[key] = { ...(elm.ref(vPath) || elm), id: key };
-    } else {
-      acc[key] = { ...elm, id: key };
-    }
+    while (isViewElementReference(elm)) {
+      const result = (elm.ref(vPath));  
+      if (result) {
+        const [referencedElement, referencedPath] = result;
+        if (resolveHistory.some(hist => hist === referencedElement)) {
+            console.error(`Circle reference found at: ${vPath}`, resolveHistory);
+            break;
+        }
+        elm = referencedElement;
+        vPath = referencedPath;
+        resolveHistory.push(elm);
+      }
+    } 
+    
+    acc[key] = { ...elm, id: key };
+    
     return acc;
   }, {});
   return view;
index 73812a4..c08f5c9 100644 (file)
@@ -23,5 +23,6 @@ export type BaseProps<TValue = string> = {
     inputValue: TValue, 
     readOnly: boolean, 
     disabled: boolean, 
-    onChange(newValue: TValue): void 
-};
+    onChange(newValue: TValue): void,
+    isKey?: boolean 
+};
\ No newline at end of file
index 95841b7..122f715 100644 (file)
@@ -23,7 +23,7 @@ import { BaseProps } from "./baseProps";
 import { IfWhenTextInput } from "./ifWhenTextInput";
 import { checkRange, checkPattern } from "./verifyer";
 
-type stringEntryProps = BaseProps & { isKey: boolean };
+type stringEntryProps = BaseProps;
 
 export const UiElementString = (props: stringEntryProps) => {
 
@@ -71,7 +71,7 @@ export const UiElementString = (props: stringEntryProps) => {
         <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
             <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
                 spellCheck={false} autoFocus margin="dense"
-                id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+                id={element.id} label={props?.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
                 style={{ width: 485, marginLeft: 20, marginRight: 20 }}
                 onChange={(e: any) => { verifyValues(e.target.value) }}
                 error={isError}
@@ -81,4 +81,4 @@ export const UiElementString = (props: stringEntryProps) => {
             />
         </Tooltip>
     );
-}
\ No newline at end of file
+}
index f0391ee..a5a52fc 100644 (file)
@@ -101,7 +101,7 @@ export type ViewElementList = (ViewElementBase & {
 export type ViewElementReference = ViewElementBase & {
   "uiType": "reference";
   "referencePath": string;
-  "ref": (currentPath: string) => ViewElement | null;
+  "ref": (currentPath: string) => [ViewElement , string] | undefined;
 }
 
 export type ViewElementUnion = ViewElementBase & {
@@ -196,13 +196,14 @@ export const ResolveFunction = Symbol("IsResolved");
 
 export type ViewSpecification = {
   "id": string;
+  "ns"?: string;
   "name"?: string;
   "title"?: string;
   "parentView"?: string;
   "language": string;
   "ifFeature"?: string;
   "when"?: string;
-  "uses"?: (string[]) & { [ResolveFunction]?: () => void };
+  "uses"?: (string[]) & { [ResolveFunction]?: (parent: string) => void };
   "elements": { [name: string]: ViewElement };
   readonly "canEdit": boolean;
 }
index fc3c68e..7b92778 100644 (file)
@@ -332,6 +332,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
           ? (
             <Element
                 key={uiElement.id}
+                isKey={isKey}
                 inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
                 value={uiElement}
                 readOnly={!canEdit}
@@ -340,75 +341,6 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
             /> )
           : null ;
     }
-    
-    // // 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] || ''}
-    //     value={uiElement}
-    //     readOnly={!canEdit}
-    //     disabled={editMode && !canEdit}
-    //     onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
-    //   />;  
-    // } else if (isViewElementSelection(uiElement)) {
-
-    //   return <UiElementSelection
-    //     key={uiElement.id}
-    //     inputValue={viewData[uiElement.id] || ''}
-    //     value={uiElement}
-    //     readOnly={!canEdit}
-    //     disabled={editMode && !canEdit}
-    //     onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
-    //   />
-
-    // } else if (isViewElementBoolean(uiElement)) {
-    //   return <UiElementBoolean
-    //     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) }} />
-
-    // } else if (isViewElementString(uiElement)) {
-    //   return <UiElementString
-    //     key={uiElement.id}
-    //     inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
-    //     value={uiElement}
-    //     isKey={isKey}
-    //     readOnly={!canEdit}
-    //     disabled={editMode && !canEdit}
-    //     onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
-
-    // } else if (isViewElementNumber(uiElement)) {
-    //   return <UiElementNumber
-    //     key={uiElement.id}
-    //     value={uiElement}
-    //     inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
-    //     readOnly={!canEdit}
-    //     disabled={editMode && !canEdit}
-    //     onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
-    // } else if (isViewElementUnion(uiElement)) {
-    //   return <UIElementUnion
-    //     key={uiElement.id}
-    //     isKey={false}
-    //     value={uiElement}
-    //     inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
-    //     readOnly={!canEdit}
-    //     disabled={editMode && !canEdit}
-    //     onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
-    // } else {
-    //   if (process.env.NODE_ENV !== "production") {
-    //     console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
-    //   }
-    //   return null;
-    // }
   };
 
   // private renderUIReference = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
@@ -817,4 +749,4 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
 }
 
 export const ConfigurationApplication = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(ConfigurationApplicationComponent)));
-export default ConfigurationApplication;
\ No newline at end of file
+export default ConfigurationApplication;
index b1c1e74..0f74297 100644 (file)
@@ -437,8 +437,8 @@ export class YangParser {
 
     // process all groupings
     this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => {
-      try { vs.uses![ResolveFunction]!(); } catch (error) {
-        console.warn(`Error resolving: [${error.message}]`);
+      try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!("|"); } catch (error) {
+        console.warn(`Error resolving: [${vs.name}] [${error.message}]`);
       }
     });
 
@@ -660,7 +660,7 @@ export class YangParser {
         }
         const key = this.extractValue(cur, "key") || undefined;
         if (elmConfig && !key) {
-          console.error(new Error(`Module: [${context.name}]${currentPath}. Found configurable list without key.`));
+          console.warn(`Module: [${context.name}]${currentPath}. Found configurable list without key. Assume config shell be false.`);
           elmConfig = false;
         }
         const [currentView, subViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
@@ -821,6 +821,7 @@ export class YangParser {
     const viewSpec: ViewSpecification = {
       id: String(currentId),
       parentView: String(parentId),
+      ns: context.name,
       name: statement.arg != null ? statement.arg : undefined,
       title: statement.arg != null ? statement.arg : undefined,
       language: "en-us",
@@ -848,7 +849,7 @@ export class YangParser {
     if (usesRefs && usesRefs.length > 0) {
 
       viewSpec.uses = (viewSpec.uses || []);
-      const resolveFunctions : (()=>void)[] = [];
+      const resolveFunctions : ((parentElementPath: string)=>void)[] = [];
 
       for (let i = 0; i < usesRefs.length; ++i) {
         const groupingName = usesRefs[i].arg;
@@ -857,14 +858,14 @@ export class YangParser {
         }
 
         viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
-
-        resolveFunctions.push(() => {
+        
+        resolveFunctions.push((parentElementPath: string) => {
           const groupingViewSpec = this.resolveGrouping(groupingName, context);
           if (groupingViewSpec) {
 
             // resolve recursive
             const resolveFunc = groupingViewSpec.uses && groupingViewSpec.uses[ResolveFunction];
-            resolveFunc && resolveFunc();
+            resolveFunc && resolveFunc(parentElementPath);
 
             Object.keys(groupingViewSpec.elements).forEach(key => {
               const elm = groupingViewSpec.elements[key];
@@ -878,14 +879,16 @@ export class YangParser {
         });
       }
 
-      viewSpec.uses[ResolveFunction] = () => {
-        resolveFunctions.forEach(res => {
-          try {
-            res();
-          } catch (error) {
-            console.error(error);
-          }
+      viewSpec.uses[ResolveFunction] = (parentElementPath: string) => {
+        const currentElementPath = `${parentElementPath} -> ${viewSpec.ns}:${viewSpec.name}`;  
+        resolveFunctions.forEach(resolve => {
+            try {
+                resolve(currentElementPath);
+            } catch (error) {
+                console.error(error);
+            }
         });
+        // console.log("Resolved "+currentElementPath, viewSpec);
         viewSpec?.uses![ResolveFunction] = undefined;
       }
 
@@ -1136,9 +1139,14 @@ export class YangParser {
         uiType: "reference",
         referencePath: refPath,
         ref(this: ViewElement, currentPath: string) {
-          const resolved = resolve(refPath, currentPath);
-          return resolved && {
-            ...resolved,
+          const elementPath = `${currentPath}/${cur.arg}`;  
+          
+          const result = resolve(refPath, elementPath);
+          if (!result) return undefined;
+
+          const [resolvedElement, resolvedPath] = result;
+          return resolvedElement && [{
+            ...resolvedElement,
             id: this.id,
             label: this.label,
             config: this.config,
@@ -1146,7 +1154,7 @@ export class YangParser {
             isList: this.isList,
             default: this.default,
             description: this.description,
-          } as ViewElement;
+          } as ViewElement , resolvedPath] || undefined;
         }
       };
       return res;
@@ -1309,7 +1317,7 @@ export class YangParser {
 
     const vPathParts = splitVPath(vPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }));
     const resultPathParts = !vPath.startsWith("/")
-      ? splitVPath(currentPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }))
+      ? splitVPath(currentPath, vPathParser).map(p => { moduleName = p[1] || moduleName ; return { ns: moduleName, property: p[2], ind: p[3] } })
       : [];
 
     for (let i = 0; i < vPathParts.length; ++i) {
@@ -1333,17 +1341,16 @@ export class YangParser {
         const view: ViewSpecification = this._views[+element.viewId];
         if (moduleName !== pathPart.ns) {
           moduleName = pathPart.ns;
-          element = view.elements[`${moduleName}:${pathPart.property}`];
-        } else {
-          element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
-        }
+        }   
+        element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
       } else {
         throw new Error("Could not resolve reference.\r\n" + vPath);
       }
       if (!element) throw new Error("Could not resolve path [" + pathPart.property + "] in [" + currentPath + "] \r\n" + vPath);
     }
 
-    return element;
+    moduleName = ""; // create the vPath for the resolved element, do not add the element itself this will be done later in the res(...) function
+    return [element, resultPathParts.slice(0,-1).map(p => `${moduleName !== p.ns ? `${moduleName=p.ns}:` : ""}${p.property}${p.ind || ''}`).join("/")];
   }
 
   private resolveView(vPath: string) {