MERGE Clamp UI-React repo to Policy Gui Repo 03/121703/1
authorbrunomilitzer <bruno.militzer@est.tech>
Fri, 4 Jun 2021 13:40:46 +0000 (14:40 +0100)
committerbrunomilitzer <bruno.militzer@est.tech>
Fri, 4 Jun 2021 15:06:28 +0000 (16:06 +0100)
According to a Diff differences from one repo to the other, there was some missing changes from the original clamp repo to the policy gui repo.

Issue-ID: POLICY-3267
Change-Id: I9a71841732dc5c3d9623bca9c1384866f4c826a6
Signed-off-by: brunomilitzer <bruno.militzer@est.tech>
33 files changed:
gui-clamp/ui-react-lib/libIndex.js
gui-clamp/ui-react/package.json
gui-clamp/ui-react/src/api/PoliciesListCache.js [deleted file]
gui-clamp/ui-react/src/api/PolicyService.js
gui-clamp/ui-react/src/api/PolicyToscaService.js
gui-clamp/ui-react/src/components/dialogs/Loop/CreateLoopModal.test.js
gui-clamp/ui-react/src/components/dialogs/Loop/DeployLoopModal.js
gui-clamp/ui-react/src/components/dialogs/Loop/ModifyLoopModal.js
gui-clamp/ui-react/src/components/dialogs/Loop/__snapshots__/DeployLoopModal.test.js.snap
gui-clamp/ui-react/src/components/dialogs/Policy/PoliciesTreeViewer.js [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/PolicyEditor.js
gui-clamp/ui-react/src/components/dialogs/Policy/PolicyEditor.test.js [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/PolicyModal.js
gui-clamp/ui-react/src/components/dialogs/Policy/PolicyModal.test.js
gui-clamp/ui-react/src/components/dialogs/Policy/PolicyToscaFileSelector.js [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/ToscaViewer.js
gui-clamp/ui-react/src/components/dialogs/Policy/ToscaViewer.test.js [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js
gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyEditor.test.js.snap [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyModal.test.js.snap [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/ToscaViewer.test.js.snap [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/toscaData.test.json [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Policy/toscaData.test.yaml [new file with mode: 0644]
gui-clamp/ui-react/src/components/dialogs/Tosca/ViewLoopTemplatesModal.js
gui-clamp/ui-react/src/components/dialogs/UserInfoModal.js
gui-clamp/ui-react/src/components/dialogs/__snapshots__/UserInfoModal.test.js.snap
gui-clamp/ui-react/src/components/loop_viewer/logs/LoopLogs.js
gui-clamp/ui-react/src/components/loop_viewer/logs/__snapshots__/LoopLogs.test.js.snap
gui-clamp/ui-react/src/components/loop_viewer/status/LoopStatus.js
gui-clamp/ui-react/src/components/loop_viewer/status/__snapshots__/LoopStatus.test.js.snap
gui-clamp/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
gui-clamp/ui-react/src/setupTests.js

index 46c331f..2a91ebf 100644 (file)
@@ -26,7 +26,6 @@ export { default as CreateLoopModal } from './src/components/dialogs/Loop/Create
 export { default as DeployLoopModal } from './src/components/dialogs/Loop/DeployLoopModal';
 export { default as LoopActionService } from './src/api/LoopActionService';
 export { default as LoopCache } from './src/api/LoopCache';
-export { default as PoliciesListCache } from './src/api/PoliciesListCache';
 export { default as LoopLogs } from './src/components/loop_viewer/logs/LoopLogs';
 export { default as LoopPropertiesModal } from './src/components/dialogs/Loop/LoopPropertiesModal';
 export { default as LoopService } from './src/api/LoopService';
@@ -52,3 +51,6 @@ export { default as UserInfoModal } from './src/components/dialogs/UserInfoModal
 export { default as UserService } from './src/api/UserService';
 export { default as ViewLoopTemplatesModal } from './src/components/dialogs/Tosca/ViewLoopTemplatesModal';
 export { default as ViewAllPolicies } from './src/components/dialogs/Policy/ViewAllPolicies';
+export { default as PolicyDeploymentEditor } from './src/components/dialogs/Policy/PolicyDeploymentEditor';
+export { default as PoliciesTreeViewer } from './src/components/dialogs/Policy/PoliciesTreeViewer';
+export { default as PolicyToscaFileSelector } from './src/components/dialogs/Policy/PolicyToscaFileSelector';
index 8d11044..fd3dc0a 100644 (file)
@@ -27,8 +27,8 @@
        "dependencies": {
                "@json-editor/json-editor": "2.5.2",
                "@fortawesome/fontawesome-free": "5.15.2",
-               "react": "17.0.1",
-               "react-dom": "17.0.1",
+               "react": "17.0.2",
+               "react-dom": "17.0.2",
                "react-scripts": "4.0.3",
                "react-bootstrap": "1.5.2",
                "bootstrap-css-only": "4.3.1",
                "react-router-dom": "5.2.0",
                "@material-ui/core": "4.11.3",
                "@material-ui/icons": "4.11.2",
+               "@material-ui/pickers": "3.3.10",
+               "@material-ui/lab": "4.0.0-alpha.57",
                "material-table": "1.68.1",
-               "react-select": "4.2.1",
-               "react-uuid": "1.0.2"
+               "react-select": "4.2.1"
        },
        "devDependencies": {
                "jest": "26.6.0",
                "@babel/preset-react": "7.12.13",
                "@babel/plugin-proposal-class-properties": "7.13.0",
                "enzyme": "3.11.0",
-               "enzyme-adapter-react-17-updated": "1.0.2",
+               "@wojtekmaj/enzyme-adapter-react-17": "0.6.1",
                "enzyme-to-json": "3.6.1",
-               "jest-fetch-mock": "3.0.3"
+               "jest-fetch-mock": "3.0.3",
+               "jest-canvas-mock": "2.3.1"
        },
        "browserslist": [
                ">0.2%",
@@ -71,7 +73,8 @@
                        "\\.(css|png)$": "identity-obj-proxy"
                },
                "setupFiles": [
-                       "./src/setupTests.js"
+                       "./src/setupTests.js",
+                       "jest-canvas-mock"
                ],
                "snapshotSerializers": [
                        "enzyme-to-json/serializer"
@@ -95,4 +98,3 @@
                ]
        }
 }
-
diff --git a/gui-clamp/ui-react/src/api/PoliciesListCache.js b/gui-clamp/ui-react/src/api/PoliciesListCache.js
deleted file mode 100644 (file)
index 265dab4..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2021 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-export default class PoliciesListCache {
-  policiesJsonCache;
-
-  constructor(policiesJson) {
-    this.policiesJsonCache = policiesJson;
-  }
-
-  getAllPolicies() {
-    return this.policiesJsonCache["policies"];
-  }
-}
index 046f789..cf4f0fd 100644 (file)
@@ -41,7 +41,7 @@ export default class PolicyService {
         console.error("getPoliciesList error occurred ", error);
         alert("getPoliciesList error occurred " + error);
         return undefined;
-      })
+      });
   }
 
   static createNewPolicy(policyModelType, policyModelVersion, policyName, policyVersion, policyJson) {
@@ -95,4 +95,58 @@ export default class PolicyService {
         return undefined;
       });
   }
+
+  static updatePdpDeployment(pdpOperationsList) {
+    return fetch(window.location.pathname + 'restservices/clds/v2/policies/pdpDeployment', {
+      method: 'PUT',
+      credentials: 'same-origin',
+      headers: {
+        "Content-Type": "application/json"
+      },
+      body: JSON.stringify(pdpOperationsList)
+    })
+      .then(function (response) {
+        console.debug("updatePdpDeployment response received: ", response.status);
+        if (response.ok) {
+          console.info("updatePdpDeployment query successful");
+          return response.text();
+        } else {
+          return response.text().then(responseBody => {
+            throw new Error("HTTP " + response.status + "," + responseBody);
+          })
+        }
+      })
+      .catch(function (error) {
+        console.error("updatePdpDeployment error occurred ", error);
+        alert("updatePdpDeployment error occurred " + error);
+        return undefined;
+      });
+  }
+
+  static sendNewPolicyModel(newPolicyModel) {
+    return fetch(window.location.pathname + 'restservices/clds/v2/policies/policytype', {
+      method: 'POST',
+      credentials: 'same-origin',
+      headers: {
+        "Content-Type": "plain/text"
+      },
+      body: newPolicyModel
+    })
+      .then(function (response) {
+        console.debug("sendNewPolicyModel response received: ", response.status);
+        if (response.ok) {
+          console.info("sendNewPolicyModel query successful");
+          return response.text();
+        } else {
+          return response.text().then(responseBody => {
+            throw new Error("HTTP " + response.status + "," + responseBody);
+          })
+        }
+      })
+      .catch(function (error) {
+        console.error("sendNewPolicyModel error occurred ", error);
+        alert("sendNewPolicyModel error occurred " + error);
+        return undefined;
+      });
+  }
 }
index b5282f9..6c74149 100644 (file)
@@ -77,60 +77,4 @@ export default class PolicyToscaService {
         return {};
       });
   }
-
-  static createPolicyModelFromToscaModel(jsonData) {
-    return fetch(window.location.pathname + 'restservices/clds/v2/policyToscaModels', {
-      method: 'POST',
-      credentials: 'same-origin',
-      headers: {
-        "Content-Type": "a",
-      },
-      body: JSON.stringify(jsonData)
-    })
-      .then(function (response) {
-        console.debug("createPolicyModelFromToscaModel response received: ", response.status);
-        if (response.ok) {
-          var message = {
-            status: response.status,
-            message: 'Tosca Policy Model successfully uploaded'
-          };
-          return message;
-        } else {
-          console.error("createPolicyModelFromToscaModel failed");
-          return response.text();
-        }
-      })
-      .catch(function (error) {
-        console.error("createPolicyModelFromToscaModel error received", error);
-        return "";
-      });
-  }
-
-  static updatePolicyModelTosca(policyModelType, policyModelVersion, jsonData) {
-    return fetch(window.location.pathname + 'restservices/clds/v2/policyToscaModels/' + policyModelType + '/' + policyModelVersion, {
-      method: 'PUT',
-      credentials: 'same-origin',
-      headers: {
-        "Content-Type": "a",
-      },
-      body: JSON.stringify(jsonData)
-    })
-      .then(function (response) {
-        console.debug("updatePolicyModelTosca response received: ", response.status);
-        if (response.ok) {
-          var message = {
-            status: response.status,
-            message: 'Tosca Policy Model successfully uploaded'
-          };
-          return message;
-        } else {
-          console.error("updatePolicyModelTosca failed");
-          return response.text();
-        }
-      })
-      .catch(function (error) {
-        console.error("updatePolicyModelTosca error received", error);
-        return "";
-      });
-  }
 }
index 401bb6a..3d94833 100644 (file)
@@ -26,6 +26,13 @@ import CreateLoopModal from './CreateLoopModal';
 import LoopService from '../../../api/LoopService';
 import TemplateService from '../../../api/TemplateService';
 
+let errorMessage = '';
+window.alert = jest.fn().mockImplementation((mesg) => {
+  errorMessage = mesg;
+  return
+});
+
+
 describe('Verify CreateLoopModal', () => {
 
   it('Test the render method', async () => {
index b7ab8a5..5fff586 100644 (file)
@@ -1,8 +1,8 @@
 /*-
  * ============LICENSE_START=======================================================
- * ONAP CLAMP
+ * ONAP POLICY-CLAMP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -44,6 +44,7 @@ const FormStyled = styled(Form.Group)`
 `
 export default class DeployLoopModal extends React.Component {
 
+
   constructor(props, context) {
     super(props, context);
 
@@ -65,13 +66,7 @@ export default class DeployLoopModal extends React.Component {
 
   getInitialKeyValue(temporaryPropertiesJson) {
     const deployJsonList = temporaryPropertiesJson["dcaeDeployParameters"];
-    let initialKey;
-    Object.keys(deployJsonList)
-      .filter((obj) => Object.keys(deployJsonList).indexOf(obj) === 0)
-      .map(obj =>
-        initialKey = obj
-      );
-    return initialKey;
+    return Object.keys(deployJsonList).find((obj) => Object.keys(deployJsonList).indexOf(obj) === 0);
   }
 
   componentWillReceiveProps(newProps) {
@@ -145,8 +140,8 @@ export default class DeployLoopModal extends React.Component {
 
     const deployJsonList = this.state.temporaryPropertiesJson["dcaeDeployParameters"];
     var indents = [];
-    Object.keys(deployJsonList).map((item, key) =>
-      indents.push(<Tab eventKey={ item } title={ item }>
+    Object.keys(deployJsonList).forEach(item =>
+      indents.push(<Tab key={ item } eventKey={ item } title={ item }>
         { this.renderDeployParam(deployJsonList[item]) }
       </Tab>)
     );
@@ -155,8 +150,8 @@ export default class DeployLoopModal extends React.Component {
 
   renderDeployParam(deployJson) {
     var indents = [];
-    Object.keys(deployJson).map((item, key) =>
-      indents.push(<FormStyled>
+    Object.keys(deployJson).forEach(item =>
+      indents.push(<FormStyled key={ item }>
         <Form.Label>{ item }</Form.Label>
         <Form.Control type="text" name={ item } onChange={ this.handleChange } defaultValue={ deployJson[item] }></Form.Control>
       </FormStyled>));
index 8f8b74d..0d20341 100644 (file)
@@ -130,13 +130,6 @@ export default class ModifyLoopModal extends React.Component {
     this.initializeToscaPolicyModelsInfo();
   }
 
-  componentWillReceiveProps(newProps) {
-    this.setState({
-      loopCache: newProps.loopCache,
-      temporaryPropertiesJson: JSON.parse(JSON.stringify(newProps.loopCache.getGlobalProperties()))
-    });
-  }
-
   initializeToscaPolicyModelsInfo() {
     var operationalPolicies = this.state.loopCache.getOperationalPolicies();
     var selectedPolicyModels = [];
index 4779ced..33f8faa 100644 (file)
@@ -26,9 +26,12 @@ exports[`Verify DeployLoopModal Test the render method 1`] = `
   >
     <Tab
       eventKey="testMs"
+      key="testMs"
       title="testMs"
     >
-      <Styled(FormGroup)>
+      <Styled(FormGroup)
+        key="location_id"
+      >
         <FormLabel
           column={false}
           srOnly={false}
@@ -42,7 +45,9 @@ exports[`Verify DeployLoopModal Test the render method 1`] = `
           type="text"
         />
       </Styled(FormGroup)>
-      <Styled(FormGroup)>
+      <Styled(FormGroup)
+        key="policy_id"
+      >
         <FormLabel
           column={false}
           srOnly={false}
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/PoliciesTreeViewer.js b/gui-clamp/ui-react/src/components/dialogs/Policy/PoliciesTreeViewer.js
new file mode 100644 (file)
index 0000000..5bca4e6
--- /dev/null
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+import React, { forwardRef } from 'react'
+import TreeView from '@material-ui/lab/TreeView';
+import TreeItem from '@material-ui/lab/TreeItem';
+import FolderIcon from '@material-ui/icons/Folder';
+import FolderOpenIcon from '@material-ui/icons/FolderOpen';
+import DescriptionIcon from '@material-ui/icons/Description';
+
+
+export default class PoliciesTreeViewer extends React.Component {
+
+  separator = ".";
+
+  nodesList = new Map();
+
+  constructor(props, context) {
+    super(props, context);
+    this.createPoliciesTree = this.createPoliciesTree.bind(this);
+    this.handleTreeItemClick = this.handleTreeItemClick.bind(this);
+    this.buildNameWithParent = this.buildNameWithParent.bind(this);
+
+  }
+
+  state = {
+    policiesTreeData: this.createPoliciesTree(this.props.policiesData),
+  }
+
+  componentDidUpdate(prevProps) {
+    if (prevProps.policiesData !== this.props.policiesData) {
+      this.setState({ policiesTreeData: this.createPoliciesTree(this.props.policiesData) })
+    }
+  }
+
+  createPoliciesTree(policiesArray) {
+    // put my policies array in a Json
+    let nodeId = 1;
+    let root = { id: nodeId, policyCount: 0, name: "ROOT", children: [], parent: undefined };
+    this.nodesList.set(nodeId++, root);
+
+    policiesArray.forEach(policy => {
+      let currentTreeNode = root;
+      policy[this.props.valueForTreeCreation].split(this.separator).forEach((policyNamePart, index, policyNamePartsArray) => {
+        let node = currentTreeNode["children"].find(element => element.name === policyNamePart);
+        if (typeof (node) === "undefined") {
+          node = { id: nodeId, policyCount: 0, children: [], name: policyNamePart, parent: currentTreeNode };
+          this.nodesList.set(nodeId++, node);
+          currentTreeNode["children"].push(node);
+        }
+        if ((index + 1) === policyNamePartsArray.length) {
+          ++currentTreeNode["policyCount"];
+        }
+        currentTreeNode = node;
+      })
+    })
+    return root;
+  }
+
+  buildNameWithParent(node) {
+    let nameToBuild = node.name;
+    if (node.parent !== undefined) {
+      nameToBuild = this.buildNameWithParent(node.parent) + this.separator + node.name;
+    }
+    return nameToBuild;
+  }
+
+  handleTreeItemClick(event, value) {
+    let fullName = this.buildNameWithParent(this.nodesList.get(value[0])).substring(5);
+    this.props.policiesFilterFunction(fullName);
+  }
+
+  renderTreeItems(nodes) {
+    return (<TreeItem key={ nodes.id } nodeId={ nodes.id } label={ nodes.name + "(" + nodes.policyCount + ")" } onNodeSelect={ this.handleTreeItemClick }>
+      {
+        Array.isArray(nodes.children) ? nodes.children.map((node) => this.renderTreeItems(node)) : null
+      }
+    </TreeItem>);
+  };
+
+  render() {
+    return (
+      <TreeView defaultExpanded={ ['root'] } defaultCollapseIcon={ <FolderOpenIcon/> }
+                defaultExpandIcon={ <FolderIcon/> } defaultEndIcon={ <DescriptionIcon/> } onNodeSelect={ this.handleTreeItemClick } multiSelect>
+        { this.renderTreeItems(this.state.policiesTreeData) }
+      </TreeView>
+    );
+  }
+}
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js b/gui-clamp/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js
new file mode 100644 (file)
index 0000000..de29947
--- /dev/null
@@ -0,0 +1,178 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+import React, { forwardRef } from 'react';
+import Modal from 'react-bootstrap/Modal';
+import styled from 'styled-components';
+import Button from 'react-bootstrap/Button';
+import Alert from 'react-bootstrap/Alert';
+import PolicyService from '../../../api/PolicyService';
+import FormGroup from '@material-ui/core/FormGroup';
+import Checkbox from '@material-ui/core/Checkbox';
+import FormControlLabel from '@material-ui/core/FormControlLabel';
+
+const DivWhiteSpaceStyled = styled.div`
+  white-space: pre;
+`
+
+const PanelDiv = styled.div`
+  text-align: justify;
+  font-size: ${ props => props.theme.policyEditorFontSize };
+  background-color: ${ props => props.theme.loopViewerBackgroundColor };
+`
+
+export default class PolicyDeploymentEditor extends React.Component {
+
+  state = {
+    policyData: this.props.policyData,
+    showSuccessAlert: false,
+    showFailAlert: false,
+    checkboxesState: this.createPdpStructure(this.props.policyData),
+    checkboxesInitialState: this.createPdpStructure(this.props.policyData),
+  };
+
+  constructor(props, context) {
+    super(props, context);
+    this.handleClose = this.handleClose.bind(this);
+    this.handleUpdatePdpDeployment = this.handleUpdatePdpDeployment.bind(this);
+    this.disableAlert = this.disableAlert.bind(this);
+    this.renderPdpDeploymentCheckboxes = this.renderPdpDeploymentCheckboxes.bind(this);
+    this.createPdpStructure = this.createPdpStructure.bind(this);
+    this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
+    this.createPdpGroupOperations = this.createPdpGroupOperations.bind(this);
+  }
+
+  handleClose() {
+    this.setState({ show: false });
+
+  }
+
+  disableAlert() {
+    this.setState({ showSuccessAlert: false, showFailAlert: false });
+  }
+
+  createPdpGroupOperations(initialStates, newStates) {
+    let commandsArray = [];
+    initialStates.forEach(initElem => {
+      let newStateFound = newStates.find(newElement => newElement.name === initElem.name);
+      if (initElem.value !== newStateFound.value) {
+        let newPdpGroupsArray = newStateFound.name.split("/");
+        let operation = "POST/";
+        if (initElem.value) {
+          operation = "DELETE/";
+        }
+        commandsArray.push(operation + newPdpGroupsArray[0] + "/" + newPdpGroupsArray[1] + "/"
+          + this.state.policyData.name + "/" + this.state.policyData.version);
+      }
+    });
+    return commandsArray.length > 0 ? { "PdpActions": commandsArray } : undefined;
+  }
+
+  handleUpdatePdpDeployment() {
+    let operationsList = this.createPdpGroupOperations(this.state.checkboxesInitialState,
+      this.state.checkboxesState);
+    if (typeof (operationsList) !== "undefined") {
+      PolicyService.updatePdpDeployment(operationsList).then(respPdpDeploymentUpdate => {
+        if (typeof (respPdpDeploymentUpdate) === "undefined") {
+          //it indicates a failure
+          this.setState({
+            showFailAlert: true,
+            showMessage: 'Pdp Deployment update Failure'
+          });
+        } else {
+          this.setState({
+            showSuccessAlert: true,
+            showMessage: 'Pdp Deployment Update successful'
+          });
+          this.props.policiesTableUpdateFunction();
+        }
+      })
+    } else {
+      this.setState({
+        showSuccessAlert: true,
+        showMessage: 'Pdp Deployment: Nothing to change'
+      });
+    }
+  }
+
+  createPdpStructure(policyData) {
+    // Create map with data for all group/subgroup where the policy is deployed
+    let infoPdpMap = new Map();
+    if (typeof policyData.pdpGroupInfo !== "undefined") {
+      policyData["pdpGroupInfo"].forEach(pdpGroupElem => {
+        let pdpGroupName = Object.keys(pdpGroupElem)[0];
+        pdpGroupElem[pdpGroupName]["pdpSubgroups"].forEach(pdpSubGroupElem => {
+          infoPdpMap.set(pdpGroupName + "/" + pdpSubGroupElem["pdpType"], true);
+        });
+      });
+    }
+    // Create the possible values for pdpgroup/subgroup and tick the ones where policy is deployed
+    let pdpStates = [];
+    if (typeof policyData.supportedPdpGroups !== "undefined") {
+      for (const pdpGroup of policyData["supportedPdpGroups"]) {
+        let pdpGroupName = Object.keys(pdpGroup)[0];
+        for (const pdpSubGroup of Object.values(pdpGroup)[0]) {
+          let fullName = pdpGroupName + "/" + pdpSubGroup;
+          pdpStates.push({
+            name: fullName,
+            value: infoPdpMap.get(fullName) !== undefined
+          });
+        }
+      }
+    }
+    return pdpStates;
+  }
+
+  handleCheckboxChange(event) {
+    const checkboxesArray = this.state.checkboxesState;
+    checkboxesArray.find(element => element.name === event.target.name).value = event.target.checked;
+    this.setState({ checkboxesState: checkboxesArray });
+  }
+
+  renderPdpDeploymentCheckboxes() {
+    return this.state.checkboxesState.map(item => {
+      return <FormControlLabel control={ <Checkbox checked={ item.value } onChange={ this.handleCheckboxChange }
+                                                   name={ item.name }/> } label={ item.name }/>;
+    });
+  }
+
+  render() {
+    return (
+      <PanelDiv>
+        <Alert variant="success" show={ this.state.showSuccessAlert } onClose={ this.disableAlert } dismissible>
+          <DivWhiteSpaceStyled>
+            { this.state.showMessage }
+          </DivWhiteSpaceStyled>
+        </Alert>
+        <Alert variant="danger" show={ this.state.showFailAlert } onClose={ this.disableAlert } dismissible>
+          <DivWhiteSpaceStyled>
+            { this.state.showMessage }
+          </DivWhiteSpaceStyled>
+        </Alert>
+        <Button variant="secondary" title="Update the policy to the specified PDP Groups/Subgroups"
+                onClick={ this.handleUpdatePdpDeployment }>Update PDP</Button>
+        <FormGroup>{ this.renderPdpDeploymentCheckboxes() }</FormGroup>
+      </PanelDiv>
+    );
+  }
+}
index 525d66b..1e27541 100644 (file)
@@ -31,9 +31,7 @@ import TextField from '@material-ui/core/TextField';
 import Alert from 'react-bootstrap/Alert';
 import PolicyService from '../../../api/PolicyService';
 import OnapUtils from '../../../utils/OnapUtils';
-import uuid from 'react-uuid';
 
-//const JSONEditor = require("@json-editor/json-editor").JSONEditor;
 const DivWhiteSpaceStyled = styled.div`
   white-space: pre;
 `
@@ -46,7 +44,6 @@ const JsonEditorDiv = styled.div`
   border: 1px solid #C0C0C0;
 `
 const PanelDiv = styled.div`
-  margin-top: 20px;
   text-align: justify;
   font-size: ${ props => props.theme.policyEditorFontSize };
   background-color: ${ props => props.theme.loopViewerBackgroundColor };
@@ -63,7 +60,7 @@ export default class PolicyEditor extends React.Component {
     showSuccessAlert: false,
     showFailAlert: false,
     jsonEditor: null,
-    jsonEditorDivId: uuid(),
+    jsonEditorDivId: this.props.policyModelType + "_" + this.props.policyModelTypeVersion + "_" + this.props.policyName + "_" + this.props.policyVersion,
   }
 
   constructor(props, context) {
@@ -112,17 +109,12 @@ export default class PolicyEditor extends React.Component {
             showSuccessAlert: true,
             showMessage: 'Policy ' + this.state.policyName + '/' + this.state.policyVersion + ' created successfully'
           });
-          this.props.policyUpdateFunction();
+          this.props.policiesTableUpdateFunction();
         }
       })
     }
   }
 
-  bumpVersion(versionToBump) {
-    let semVer = versionToBump.split(".");
-    return parseInt(semVer[0]) + 1 + "." + semVer[1] + "." + semVer[2];
-  }
-
   getToscaModelForPolicy() {
     PolicyToscaService.getToscaPolicyModel(this.state.policyModelType, this.state.policyModelTypeVersion).then(respJsonPolicyTosca => {
       if (respJsonPolicyTosca !== {}) {
@@ -139,27 +131,10 @@ export default class PolicyEditor extends React.Component {
   }
 
   createJsonEditor(toscaModel, editorData) {
-    /*JSONEditor.defaults.themes.myBootstrap4 = JSONEditor.defaults.themes.bootstrap4.extend({
-            getTab: function(text,tabId) {
-                var liel = document.createElement('li');
-                liel.classList.add('nav-item');
-                var ael = document.createElement("a");
-                ael.classList.add("nav-link");
-                ael.setAttribute("style",'padding:10px;max-width:160px;');
-                ael.setAttribute("href", "#" + tabId);
-                ael.setAttribute('data-toggle', 'tab');
-                text.setAttribute("style",'word-wrap:break-word;');
-                ael.appendChild(text);
-                liel.appendChild(ael);
-                return liel;
-            }
-        });*/
-
     return new JSONEditor(document.getElementById(this.state.jsonEditorDivId),
       {
         schema: toscaModel,
         startval: editorData,
-        //theme: 'myBootstrap4',
         theme: 'bootstrap4',
         iconlib: 'fontawesome5',
         object_layout: 'grid',
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/PolicyEditor.test.js b/gui-clamp/ui-react/src/components/dialogs/Policy/PolicyEditor.test.js
new file mode 100644 (file)
index 0000000..111f2c6
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+import React from 'react';
+import PolicyEditor from './PolicyEditor';
+import { shallow, mount } from 'enzyme';
+import PolicyToscaService from '../../../api/PolicyToscaService';
+
+describe('Verify PolicyEditor', () => {
+  const fs = require('fs');
+
+  let toscaJson = fs.readFileSync('src/components/dialogs/Policy/toscaData.test.json', { encoding: 'utf8', flag: 'r' })
+
+  const policyProperties = {
+    "tca.policy": {
+      "domain": "measurementsForVfScaling",
+      "metricsPerEventName": [
+        {
+          "policyScope": "DCAE",
+          "thresholds": [
+            {
+              "version": "1.0.2",
+              "severity": "MAJOR",
+              "thresholdValue": 200,
+              "closedLoopEventStatus": "ONSET",
+              "closedLoopControlName": "LOOP_test",
+              "direction": "LESS_OR_EQUAL",
+              "fieldPath": "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta"
+            }
+          ],
+          "eventName": "vLoadBalancer",
+          "policyVersion": "v0.0.1",
+          "controlLoopSchemaType": "VM",
+          "policyName": "DCAE.Config_tca-hi-lo"
+        }
+      ]
+    }
+  };
+
+
+  it('Test the render method', async () => {
+    PolicyToscaService.getToscaPolicyModel = jest.fn().mockImplementation(() => {
+      return Promise.resolve(toscaJson);
+    });
+
+    const component = mount(<PolicyEditor policyModelType="onap.policies.monitoring.tcagen2" policyModelTypeVersion="1.0.0"
+                                          policyName="org.onap.new" policyVersion="1.0.0" policyProperties={ policyProperties }
+                                          policiesTableUpdateFunction={ () => {
+                                          } }/>);
+    await PolicyToscaService.getToscaPolicyModel();
+    expect(component).toMatchSnapshot();
+  });
+});
index 105b2c5..0c7637c 100644 (file)
@@ -137,21 +137,6 @@ export default class PolicyModal extends React.Component {
   }
 
   createJsonEditor(toscaModel, editorData) {
-    /*JSONEditor.defaults.themes.myBootstrap4 = JSONEditor.defaults.themes.bootstrap4.extend({
-            getTab: function(text,tabId) {
-                var liel = document.createElement('li');
-                liel.classList.add('nav-item');
-                var ael = document.createElement("a");
-                ael.classList.add("nav-link");
-                ael.setAttribute("style",'padding:10px;max-width:160px;');
-                ael.setAttribute("href", "#" + tabId);
-                ael.setAttribute('data-toggle', 'tab');
-                text.setAttribute("style",'word-wrap:break-word;');
-                ael.appendChild(text);
-                liel.appendChild(ael);
-                return liel;
-            }
-        });*/
     return new JSONEditor(document.getElementById("editor"),
       {
         schema: toscaModel,
@@ -316,17 +301,17 @@ export default class PolicyModal extends React.Component {
   }
 
   renderButton() {
-    var allElement = [(<Button variant="secondary" onClick={ this.handleClose }>
+    var allElement = [(<Button key="close" variant="secondary" onClick={ this.handleClose }>
       Close
     </Button>)];
     if (this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) {
       allElement.push((
-        <Button variant="primary" disabled={ this.readOnly } onClick={ this.handleSave }>
+        <Button key="save" variant="primary" disabled={ this.readOnly } onClick={ this.handleSave }>
           Save Changes
         </Button>
       ));
       allElement.push((
-        <Button variant="primary" disabled={ this.readOnly } onClick={ this.handleRefresh }>
+        <Button key="refresh" variant="primary" disabled={ this.readOnly } onClick={ this.handleRefresh }>
           Refresh
         </Button>
       ));
index 734f22e..658b19e 100644 (file)
@@ -1,8 +1,8 @@
 /*-
  * ============LICENSE_START=======================================================
- * ONAP CLAMP
+ * ONAP POLICY-CLAMP
  * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,6 +26,7 @@ import PolicyModal from './PolicyModal';
 import LoopCache from '../../../api/LoopCache';
 import LoopService from '../../../api/LoopService';
 import OnapConstant from '../../../utils/OnapConstants';
+import { shallow } from 'enzyme';
 
 describe('Verify PolicyModal', () => {
   beforeEach(() => {
@@ -52,6 +53,7 @@ describe('Verify PolicyModal', () => {
       "jsonRepresentation": { "schema": {} }
     }]
   };
+
   const loopCache = new LoopCache(loopCacheStr);
   const historyMock = { push: jest.fn() };
   const flushPromises = () => new Promise(setImmediate);
@@ -125,4 +127,9 @@ describe('Verify PolicyModal', () => {
     instance.handlePdpSubgroupChange(event);
     expect(component.state('chosenPdpSubgroup')).toEqual("option1");
   });
+
+  it('Test the render method', () => {
+    const component = shallow(<PolicyModal loopCache={ loopCache } match={ match }/>)
+    expect(component).toMatchSnapshot();
+  });
 });
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/PolicyToscaFileSelector.js b/gui-clamp/ui-react/src/components/dialogs/Policy/PolicyToscaFileSelector.js
new file mode 100644 (file)
index 0000000..8093b7e
--- /dev/null
@@ -0,0 +1,133 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+import React from 'react'
+import Modal from 'react-bootstrap/Modal';
+import Form from 'react-bootstrap/Form';
+import Row from 'react-bootstrap/Row';
+import Col from 'react-bootstrap/Col';
+import styled from 'styled-components';
+import Alert from 'react-bootstrap/Alert';
+import { Input, InputLabel, Button, SvgIcon } from "@material-ui/core";
+import PublishIcon from '@material-ui/icons/Publish';
+import PolicyService from '../../../api/PolicyService';
+
+const ModalStyled = styled(Modal)`
+  background-color: transparent;
+`
+
+const StyledMessagesDiv = styled.div`
+  overflow: auto;
+  max-height: 300px;
+`
+
+
+export default class PolicyToscaFileSelector extends React.Component {
+
+  state = {
+    show: this.props.show,
+    alertMessages: [],
+  }
+
+  constructor(props, context) {
+    super(props, context);
+    this.handleClose = this.handleClose.bind(this);
+    this.onFileChange = this.onFileChange.bind(this);
+  }
+
+  componentDidUpdate(prevProps) {
+    if (this.props.show !== this.state.show) {
+      this.setState({ show: this.props.show });
+    }
+  }
+
+  handleClose() {
+    this.props.disableFunction();
+    this.setState({ alertMessages: [] });
+  }
+
+  onFileChange(target) {
+    this.setState({ alertMessages: [] });
+    target.currentTarget.files.forEach(file => {
+      const fileReader = new FileReader();
+      fileReader.readAsDataURL(file);
+      fileReader.onload = (content) => {
+        PolicyService.sendNewPolicyModel(atob(content.target.result.split(",")[1])).then(respModelCreate => {
+          if (typeof (respModelCreate) === "undefined") {
+            //it indicates a failure
+            this.setState(state => {
+              return {
+                alertMessages: [...state.alertMessages, (<Alert variant="danger"><Alert.Heading>{ file.name }</Alert.Heading><p>Policy Tosca Model Creation Failure</p>
+                  <hr/>
+                  <p>Type: { file.type }</p><p>Size: { file.size }</p></Alert>)]
+              };
+            });
+          } else {
+            this.props.toscaTableUpdateFunction();
+            this.setState(state => {
+              return {
+                alertMessages: [...state.alertMessages, (<Alert variant="success"><Alert.Heading>{ file.name }</Alert.Heading><p>Policy Tosca Model Created Successfully</p>
+                  <hr/>
+                  <p>Type: { file.type }</p><p>Size: { file.size }</p></Alert>)]
+              };
+            });
+          }
+        });
+      };
+    });
+
+  }
+
+  render() {
+    return (
+      <ModalStyled size="lg" show={ this.state.show } onHide={ this.handleClose } backdrop="static" keyboard={ false }>
+        <Modal.Header closeButton>
+          <Modal.Title>Create New Policy Tosca Model</Modal.Title>
+        </Modal.Header>
+        <Modal.Body>
+          <Form.Group as={ Row } controlId="formPlaintextEmail">
+            <Col sm="10">
+              <input type="file" multiple accept=".yaml,.yml" id="fileUploadButton" style={ { display: 'none' } } onChange={ this.onFileChange }/>
+              <label htmlFor={ 'fileUploadButton' }>
+                <Button color="primary" variant="contained" component="span"
+                        startIcon={
+                          <SvgIcon fontSize="small">
+                            <PublishIcon/>
+                          </SvgIcon>
+                        }>
+                  Upload Files
+                </Button>
+                <p>(Only YAML files are supported)</p>
+              </label>
+              <StyledMessagesDiv>
+                { this.state.alertMessages }
+              </StyledMessagesDiv>
+            </Col>
+          </Form.Group>
+        </Modal.Body>
+        <Modal.Footer>
+          <Button variant="secondary" onClick={ this.handleClose }>Close</Button>
+        </Modal.Footer>
+      </ModalStyled>
+    );
+  }
+}
index ce4edce..fc69a63 100644 (file)
@@ -26,8 +26,7 @@ import PolicyToscaService from '../../../api/PolicyToscaService';
 import styled from 'styled-components';
 import Button from 'react-bootstrap/Button';
 
-const JsonEditorDiv = styled.div`
-  margin-top: 20px;
+const ToscaDiv = styled.div`
   background-color: ${ props => props.theme.toscaTextareaBackgroundColor };
   text-align: justify;
   font-size: ${ props => props.theme.toscaTextareaFontSize };
@@ -57,11 +56,11 @@ export default class ToscaViewer extends React.Component {
 
   render() {
     return (
-      <JsonEditorDiv>
+      <ToscaDiv>
         <pre>{ this.state.yamlPolicyTosca }</pre>
         <Button variant="secondary" title="Create a new policy version from the defined parameters"
                 onClick={ this.handleCreateNewVersion }>Create New Version</Button>
-      </JsonEditorDiv>
+      </ToscaDiv>
     );
   }
 }
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/ToscaViewer.test.js b/gui-clamp/ui-react/src/components/dialogs/Policy/ToscaViewer.test.js
new file mode 100644 (file)
index 0000000..5b59760
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+import React from 'react';
+import ToscaViewer from './ToscaViewer';
+import { shallow, mount } from 'enzyme';
+import PolicyToscaService from '../../../api/PolicyToscaService';
+
+describe('Verify ToscaViewer', () => {
+  const fs = require('fs');
+
+  let toscaYaml = fs.readFileSync('src/components/dialogs/Policy/toscaData.test.yaml', { encoding: 'utf8', flag: 'r' })
+
+  const toscaData = {
+    "policyModelType": "onap.policies.controlloop.Guard",
+    "version": "1.0.0",
+    "policyAcronym": "Guard",
+    "createdDate": "2021-04-09T02:29:31.407356Z",
+    "updatedDate": "2021-04-09T02:29:31.407356Z",
+    "updatedBy": "Not found",
+    "createdBy": "Not found",
+    "tableData": {
+      "id": 0
+    }
+  };
+
+  it('Test the render method', async () => {
+    PolicyToscaService.getToscaPolicyModelYaml = jest.fn().mockImplementation(() => {
+      return Promise.resolve(toscaYaml);
+    });
+    const component = shallow(<ToscaViewer toscaData={ toscaData }/>);
+    await PolicyToscaService.getToscaPolicyModelYaml();
+    expect(component).toMatchSnapshot();
+  });
+});
index a97deea..f571bc1 100644 (file)
@@ -43,24 +43,27 @@ import ViewColumn from '@material-ui/icons/ViewColumn';
 import DehazeIcon from '@material-ui/icons/Dehaze';
 import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';
 import AddIcon from '@material-ui/icons/Add';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
+import PublishIcon from '@material-ui/icons/Publish';
 import Switch from '@material-ui/core/Switch';
 import MaterialTable from "material-table";
 import PolicyService from '../../../api/PolicyService';
 import PolicyToscaService from '../../../api/PolicyToscaService';
-import Select from 'react-select';
+import Select from '@material-ui/core/Select';
 import Alert from 'react-bootstrap/Alert';
 import Tabs from 'react-bootstrap/Tabs';
 import Tab from 'react-bootstrap/Tab';
 import PolicyEditor from './PolicyEditor';
 import ToscaViewer from './ToscaViewer';
+import PolicyDeploymentEditor from './PolicyDeploymentEditor';
+import PoliciesTreeViewer from './PoliciesTreeViewer';
+import PolicyToscaFileSelector from './PolicyToscaFileSelector';
 
 const DivWhiteSpaceStyled = styled.div`
   white-space: pre;
 `
 
 const ModalStyled = styled(Modal)`
-  @media (min-width: 1000px) {
+  @media (min-width: 800px) {
     .modal-xl {
       max-width: 96%;
     }
@@ -73,26 +76,38 @@ const DetailedRow = styled.div`
   font-size: ${ props => props.theme.policyEditorFontSize };
   width: 97%;
   margin-left: auto;
-  margin-right: 0;
+  margin-right: auto;
+  margin-top: 20px;
 `
 
+const PoliciesTreeViewerDiv = styled.div`
+  width: 20%;
+  float: left;
+  left: 0;
+  overflow: auto;
+`
+
+const MaterialTableDiv = styled.div`
+  float: right;
+  width: 80%;
+  left: 20%;
+`
 
 const standardCellStyle = { backgroundColor: '#039be5', color: '#FFF', border: '1px solid black' };
-const cellPdpGroupStyle = { backgroundColor: '#039be5', color: '#FFF', border: '1px solid black' };
 const headerStyle = { backgroundColor: '#ddd', border: '2px solid black' };
 const rowHeaderStyle = { backgroundColor: '#ddd', fontSize: '15pt', text: 'bold', border: '1px solid black' };
 
 export default class ViewAllPolicies extends React.Component {
   state = {
     show: true,
-    content: 'Please select a policy to display it',
-    selectedRowId: -1,
     policiesListData: [],
+    policiesListDataFiltered: [],
     toscaModelsListData: [],
+    toscaModelsListDataFiltered: [],
     jsonEditorForPolicy: new Map(),
-    prefixGrouping: false,
     showSuccessAlert: false,
     showFailAlert: false,
+    showFileSelector: false,
     policyColumnsDefinition: [
       {
         title: "Policy Name", field: "name",
@@ -102,7 +117,7 @@ export default class ViewAllPolicies extends React.Component {
       {
         title: "Policy Version", field: "version",
         cellStyle: standardCellStyle,
-        headerStyle: headerStyle
+        headerStyle: headerStyle,
       },
       {
         title: "Policy Type", field: "type",
@@ -115,20 +130,13 @@ export default class ViewAllPolicies extends React.Component {
         headerStyle: headerStyle
       },
       {
-        title: "Deployed in PDP", field: "pdpGroupInfo.pdpGroup",
-        cellStyle: cellPdpGroupStyle,
-        headerStyle: headerStyle,
-        render: rowData => this.renderPdpGroupDropBox(rowData),
-        grouping: false
-      },
-      {
-        title: "PDP Group", field: "pdpGroupInfo.pdpGroup",
-        cellStyle: cellPdpGroupStyle,
+        title: "Deployable in PDP Group", field: "supportedPdpGroupsString",
+        cellStyle: standardCellStyle,
         headerStyle: headerStyle
       },
       {
-        title: "PDP SubGroup", field: "pdpGroupInfo.pdpSubGroup",
-        cellStyle: cellPdpGroupStyle,
+        title: "Deployed in PDP Group", field: "pdpGroupInfoString",
+        cellStyle: standardCellStyle,
         headerStyle: headerStyle
       }
     ],
@@ -183,62 +191,63 @@ export default class ViewAllPolicies extends React.Component {
   constructor(props, context) {
     super(props, context);
     this.handleClose = this.handleClose.bind(this);
-    this.renderPdpGroupDropBox = this.renderPdpGroupDropBox.bind(this);
-    this.handlePdpGroupChange = this.handlePdpGroupChange.bind(this);
-    this.handlePrefixGrouping = this.handlePrefixGrouping.bind(this);
     this.handleDeletePolicy = this.handleDeletePolicy.bind(this);
     this.disableAlert = this.disableAlert.bind(this);
     this.getAllPolicies = this.getAllPolicies.bind(this);
     this.getAllToscaModels = this.getAllToscaModels.bind(this);
+    this.generateAdditionalPolicyColumns = this.generateAdditionalPolicyColumns.bind(this);
+    this.filterPolicies = this.filterPolicies.bind(this);
+    this.filterTosca = this.filterTosca.bind(this);
+    this.showFileSelector = this.showFileSelector.bind(this);
+    this.disableFileSelector = this.disableFileSelector.bind(this);
     this.getAllPolicies();
     this.getAllToscaModels();
   }
 
-  getAllToscaModels() {
-    PolicyToscaService.getToscaPolicyModels().then(toscaModelsList => {
-      this.setState({ toscaModelsListData: toscaModelsList });
-    });
-  }
-
-  handlePdpGroupChange(e) {
-    let pdpSplit = e.value.split("/");
-    let selectedPdpGroup = pdpSplit[0];
-    let selectedSubPdpGroup = pdpSplit[1];
-    if (typeof selectedSubPdpGroup !== "undefined") {
-      let temp = this.state.policiesListData;
-      temp[this.state.selectedRowId]["pdpGroupInfo"] = { "pdpGroup": selectedPdpGroup, "pdpSubGroup": selectedSubPdpGroup };
-      this.setState({ policiesListData: temp });
-    } else {
-      delete this.state.policiesListData[this.state.selectedRowId]["pdpGroupInfo"];
-    }
-  }
+  generateAdditionalPolicyColumns(policiesData) {
+    policiesData.forEach(policy => {
+      let supportedPdpGroupsString = "";
+      if (typeof policy.supportedPdpGroups !== "undefined") {
+        for (const pdpGroup of policy["supportedPdpGroups"]) {
+          for (const pdpSubGroup of Object.values(pdpGroup)[0]) {
+            supportedPdpGroupsString += (Object.keys(pdpGroup)[0] + "/" + pdpSubGroup + "\r\n");
+          }
+        }
+        policy["supportedPdpGroupsString"] = supportedPdpGroupsString;
+      }
 
-  renderPdpGroupDropBox(dataRow) {
-    let optionItems = [{ label: "NOT DEPLOYED", value: "NOT DEPLOYED" }];
-    let selectedItem = { label: "NOT DEPLOYED", value: "NOT DEPLOYED" };
-    if (typeof dataRow.supportedPdpGroups !== "undefined") {
-      for (const pdpGroup of dataRow["supportedPdpGroups"]) {
-        for (const pdpSubGroup of Object.values(pdpGroup)[0]) {
-          optionItems.push({
-            label: Object.keys(pdpGroup)[0] + "/" + pdpSubGroup,
-            value: Object.keys(pdpGroup)[0] + "/" + pdpSubGroup
+      let infoPdpGroup = "";
+      if (typeof policy.pdpGroupInfo !== "undefined") {
+        policy["pdpGroupInfo"].forEach(pdpGroupElem => {
+          let groupName = Object.keys(pdpGroupElem)[0];
+          pdpGroupElem[groupName]["pdpSubgroups"].forEach(pdpSubGroupElem => {
+            infoPdpGroup += (groupName + "/" + pdpSubGroupElem["pdpType"] + " ("
+              + pdpGroupElem[groupName]["pdpGroupState"] + ")" + "\r\n");
           });
-        }
+          policy["pdpGroupInfoString"] = infoPdpGroup;
+        });
       }
-    }
-    if (typeof dataRow.pdpGroupInfo !== "undefined") {
-      selectedItem = {
-        label: dataRow["pdpGroupInfo"]["pdpGroup"] + "/" + dataRow["pdpGroupInfo"]["pdpSubGroup"],
-        value: dataRow["pdpGroupInfo"]["pdpGroup"] + "/" + dataRow["pdpGroupInfo"]["pdpSubGroup"]
-      };
-    }
-    return (<div style={ { width: '250px' } }><Select value={ selectedItem } options={ optionItems } onChange={ this.handlePdpGroupChange }/></div>);
+    });
+  }
+
+  getAllToscaModels() {
+    PolicyToscaService.getToscaPolicyModels().then(toscaModelsList => {
+      this.setState({
+        toscaModelsListData: toscaModelsList,
+        toscaModelsListDataFiltered: toscaModelsList
+      });
+    });
   }
 
   getAllPolicies() {
     PolicyService.getPoliciesList().then(allPolicies => {
-      this.setState({ policiesListData: allPolicies["policies"] })
+      this.generateAdditionalPolicyColumns(allPolicies["policies"])
+      this.setState({
+        policiesListData: allPolicies["policies"],
+        policiesListDataFiltered: allPolicies["policies"],
+      })
     });
+
   }
 
   handleClose() {
@@ -246,10 +255,6 @@ export default class ViewAllPolicies extends React.Component {
     this.props.history.push('/')
   }
 
-  handlePrefixGrouping(event) {
-    this.setState({ prefixGrouping: event.target.checked });
-  }
-
   handleDeletePolicy(event, rowData) {
     PolicyService.deletePolicy(rowData["type"], rowData["type_version"], rowData["name"], rowData["version"]).then(
       respPolicyDeletion => {
@@ -264,8 +269,8 @@ export default class ViewAllPolicies extends React.Component {
             showSuccessAlert: true,
             showMessage: 'Policy successfully Deleted'
           });
+          this.getAllPolicies();
         }
-        this.getAllPolicies();
       }
     )
   }
@@ -274,62 +279,92 @@ export default class ViewAllPolicies extends React.Component {
     this.setState({ showSuccessAlert: false, showFailAlert: false });
   }
 
+  filterPolicies(prefixForFiltering) {
+    this.setState({ policiesListDataFiltered: this.state.policiesListData.filter(element => element.name.startsWith(prefixForFiltering)) });
+  }
+
+  filterTosca(prefixForFiltering) {
+    this.setState({ toscaModelsListDataFiltered: this.state.toscaModelsListData.filter(element => element.policyModelType.startsWith(prefixForFiltering)) });
+  }
+
+  showFileSelector() {
+    this.setState({ showFileSelector: true });
+  }
+
+  disableFileSelector() {
+    this.setState({ showFileSelector: false });
+  }
+
   renderPoliciesTab() {
     return (
       <Tab eventKey="policies" title="Policies in Policy Framework">
         <Modal.Body>
-          <FormControlLabel
-            control={ <Switch checked={ this.state.prefixGrouping } onChange={ this.handlePrefixGrouping }/> }
-            label="Group by prefix"
-          />
-          <MaterialTable
-            title={ "Policies" }
-            data={ this.state.policiesListData }
-            columns={ this.state.policyColumnsDefinition }
-            icons={ this.state.tableIcons }
-            onRowClick={ (event, rowData, togglePanel) => togglePanel() }
-            options={ {
-              grouping: true,
-              exportButton: true,
-              headerStyle: rowHeaderStyle,
-              rowStyle: rowData => ({
-                backgroundColor: (this.state.selectedRowId !== -1 && this.state.selectedRowId === rowData.tableData.id) ? '#EEE' : '#FFF'
-              }),
-              actionsColumnIndex: -1
-            } }
-            detailPanel={ [
-              {
-                icon: ArrowForwardIosIcon,
-                tooltip: 'Show Configuration',
-                render: rowData => {
-                  return (
-                    <DetailedRow>
-                      <PolicyEditor policyModelType={ rowData["type"] } policyModelTypeVersion={ rowData["type_version"] } policyName={ rowData["name"] } policyVersion={ rowData["version"] }
-                                    policyProperties={ rowData["properties"] } policyUpdateFunction={ this.getAllPolicies }/>
-                    </DetailedRow>
-                  )
-                },
-              },
-              {
-                icon: DehazeIcon,
-                tooltip: 'Show Raw Data',
-                render: rowData => {
-                  return (
-                    <DetailedRow>
-                      <pre>{ JSON.stringify(rowData, null, 2) }</pre>
-                    </DetailedRow>
-                  )
-                },
-              },
-            ] }
-            actions={ [
-              {
-                icon: forwardRef((props, ref) => <DeleteRoundedIcon { ...props } ref={ ref }/>),
-                tooltip: 'Delete Policy',
-                onClick: (event, rowData) => this.handleDeletePolicy(event, rowData)
-              }
-            ] }
-          />
+          <div>
+            <PoliciesTreeViewerDiv>
+              <PoliciesTreeViewer policiesData={ this.state.policiesListData } valueForTreeCreation="name" policiesFilterFunction={ this.filterPolicies }/>
+            </PoliciesTreeViewerDiv>
+            <MaterialTableDiv>
+              <MaterialTable
+                title={ "Policies" }
+                data={ this.state.policiesListDataFiltered }
+                columns={ this.state.policyColumnsDefinition }
+                icons={ this.state.tableIcons }
+                onRowClick={ (event, rowData, togglePanel) => togglePanel() }
+                options={ {
+                  grouping: true,
+                  exportButton: true,
+                  headerStyle: rowHeaderStyle,
+                  actionsColumnIndex: -1
+                } }
+                detailPanel={ [
+                  {
+                    icon: ArrowForwardIosIcon,
+                    tooltip: 'Show Configuration',
+                    render: rowData => {
+                      return (
+                        <DetailedRow>
+                          <PolicyEditor policyModelType={ rowData["type"] } policyModelTypeVersion={ rowData["type_version"] }
+                                        policyName={ rowData["name"] } policyVersion={ rowData["version"] } policyProperties={ rowData["properties"] }
+                                        policiesTableUpdateFunction={ this.getAllPolicies }/>
+                        </DetailedRow>
+                      )
+                    },
+                  },
+                  {
+                    icon: DehazeIcon,
+                    openIcon: DehazeIcon,
+                    tooltip: 'Show Raw Data',
+                    render: rowData => {
+                      return (
+                        <DetailedRow>
+                          <pre>{ JSON.stringify(rowData, null, 2) }</pre>
+                        </DetailedRow>
+                      )
+                    },
+                  },
+                  {
+                    icon: PublishIcon,
+                    openIcon: PublishIcon,
+                    tooltip: 'PDP Group Deployment',
+                    render: rowData => {
+                      return (
+                        <DetailedRow>
+                          <PolicyDeploymentEditor policyData={ rowData } policiesTableUpdateFunction={ this.getAllPolicies }/>
+                        </DetailedRow>
+                      )
+                    },
+                  }
+                ] }
+                actions={ [
+                  {
+                    icon: DeleteRoundedIcon,
+                    tooltip: 'Delete Policy',
+                    onClick: (event, rowData) => this.handleDeletePolicy(event, rowData)
+                  }
+                ] }
+              />
+            </MaterialTableDiv>
+          </div>
         </Modal.Body>
       </Tab>
     );
@@ -339,61 +374,71 @@ export default class ViewAllPolicies extends React.Component {
     return (
       <Tab eventKey="tosca models" title="Tosca Models in Policy Framework">
         <Modal.Body>
-          <FormControlLabel
-            control={ <Switch checked={ this.state.prefixGrouping } onChange={ this.handlePrefixGrouping }/> }
-            label="Group by prefix"
-          />
-          <MaterialTable
-            title={ "Tosca Models" }
-            data={ this.state.toscaModelsListData }
-            columns={ this.state.toscaColumnsDefinition }
-            icons={ this.state.tableIcons }
-            onRowClick={ (event, rowData, togglePanel) => togglePanel() }
-            options={ {
-              grouping: true,
-              exportButton: true,
-              headerStyle: rowHeaderStyle,
-              rowStyle: rowData => ({
-                backgroundColor: (this.state.selectedRowId !== -1 && this.state.selectedRowId === rowData.tableData.id) ? '#EEE' : '#FFF'
-              }),
-              actionsColumnIndex: -1
-            } }
-            detailPanel={ [
-              {
-                icon: ArrowForwardIosIcon,
-                tooltip: 'Show Tosca',
-                render: rowData => {
-                  return (
-                    <DetailedRow>
-                      <ToscaViewer toscaData={ rowData }/>
-                    </DetailedRow>
-                  )
-                },
-              },
-              {
-                icon: DehazeIcon,
-                tooltip: 'Show Raw Data',
-                render: rowData => {
-                  return (
-                    <DetailedRow>
-                      <pre>{ JSON.stringify(rowData, null, 2) }</pre>
-                    </DetailedRow>
-                  )
-                },
-              },
-              {
-                icon: AddIcon,
-                tooltip: 'Create a policy from this model',
-                render: rowData => {
-                  return (
-                    <DetailedRow>
-                      <PolicyEditor policyModelType={ rowData["policyModelType"] } policyModelTypeVersion={ rowData["version"] } policyProperties={ {} } policyUpdateFunction={ this.getAllPolicies }/>
-                    </DetailedRow>
-                  )
-                },
-              },
-            ] }
-          />
+          <div>
+            <PoliciesTreeViewerDiv>
+              <PoliciesTreeViewer policiesData={ this.state.toscaModelsListData } valueForTreeCreation="policyModelType" policiesFilterFunction={ this.filterTosca }/>
+            </PoliciesTreeViewerDiv>
+            <MaterialTableDiv>
+              <MaterialTable
+                title={ "Tosca Models" }
+                data={ this.state.toscaModelsListDataFiltered }
+                columns={ this.state.toscaColumnsDefinition }
+                icons={ this.state.tableIcons }
+                onRowClick={ (event, rowData, togglePanel) => togglePanel() }
+                options={ {
+                  grouping: true,
+                  exportButton: true,
+                  headerStyle: rowHeaderStyle,
+                  actionsColumnIndex: -1
+                } }
+                actions={ [
+                  {
+                    icon: AddIcon,
+                    tooltip: 'Add New Tosca Model',
+                    isFreeAction: true,
+                    onClick: () => this.showFileSelector()
+                  }
+                ] }
+                detailPanel={ [
+                  {
+                    icon: ArrowForwardIosIcon,
+                    tooltip: 'Show Tosca',
+                    render: rowData => {
+                      return (
+                        <DetailedRow>
+                          <ToscaViewer toscaData={ rowData }/>
+                        </DetailedRow>
+                      )
+                    },
+                  },
+                  {
+                    icon: DehazeIcon,
+                    openIcon: DehazeIcon,
+                    tooltip: 'Show Raw Data',
+                    render: rowData => {
+                      return (
+                        <DetailedRow>
+                          <pre>{ JSON.stringify(rowData, null, 2) }</pre>
+                        </DetailedRow>
+                      )
+                    },
+                  },
+                  {
+                    icon: AddIcon,
+                    openIcon: AddIcon,
+                    tooltip: 'Create a policy from this model',
+                    render: rowData => {
+                      return (
+                        <DetailedRow>
+                          <PolicyEditor policyModelType={ rowData["policyModelType"] } policyModelTypeVersion={ rowData["version"] } policyProperties={ {} } policiesTableUpdateFunction={ this.getAllPolicies }/>
+                        </DetailedRow>
+                      )
+                    },
+                  },
+                ] }
+              />
+            </MaterialTableDiv>
+          </div>
         </Modal.Body>
       </Tab>
     );
@@ -401,27 +446,30 @@ export default class ViewAllPolicies extends React.Component {
 
   render() {
     return (
-      <ModalStyled size="xl" show={ this.state.show } onHide={ this.handleClose } backdrop="static" keyboard={ false }>
-        <Modal.Header closeButton>
-        </Modal.Header>
-        <Tabs id="controlled-tab-example" activeKey={ this.state.key } onSelect={ key => this.setState({ key, selectedRowData: {} }) }>
-          { this.renderPoliciesTab() }
-          { this.renderToscaTab() }
-        </Tabs>
-        <Alert variant="success" show={ this.state.showSuccessAlert } onClose={ this.disableAlert } dismissible>
-          <DivWhiteSpaceStyled>
-            { this.state.showMessage }
-          </DivWhiteSpaceStyled>
-        </Alert>
-        <Alert variant="danger" show={ this.state.showFailAlert } onClose={ this.disableAlert } dismissible>
-          <DivWhiteSpaceStyled>
-            { this.state.showMessage }
-          </DivWhiteSpaceStyled>
-        </Alert>
-        <Modal.Footer>
-          <Button variant="secondary" onClick={ this.handleClose }>Close</Button>
-        </Modal.Footer>
-      </ModalStyled>
+      <React.Fragment>
+        <ModalStyled size="xl" show={ this.state.show } onHide={ this.handleClose } backdrop="static" keyboard={ false }>
+          <Modal.Header closeButton>
+          </Modal.Header>
+          <Tabs id="controlled-tab-example" activeKey={ this.state.key } onSelect={ key => this.setState({ key, selectedRowData: {} }) }>
+            { this.renderPoliciesTab() }
+            { this.renderToscaTab() }
+          </Tabs>
+          <Alert variant="success" show={ this.state.showSuccessAlert } onClose={ this.disableAlert } dismissible>
+            <DivWhiteSpaceStyled>
+              { this.state.showMessage }
+            </DivWhiteSpaceStyled>
+          </Alert>
+          <Alert variant="danger" show={ this.state.showFailAlert } onClose={ this.disableAlert } dismissible>
+            <DivWhiteSpaceStyled>
+              { this.state.showMessage }
+            </DivWhiteSpaceStyled>
+          </Alert>
+          <Modal.Footer>
+            <Button variant="secondary" onClick={ this.handleClose }>Close</Button>
+          </Modal.Footer>
+        </ModalStyled>
+        <PolicyToscaFileSelector show={ this.state.showFileSelector } disableFunction={ this.disableFileSelector } toscaTableUpdateFunction={ this.getAllToscaModels }/>
+      </React.Fragment>
     );
   }
 }
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyEditor.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyEditor.test.js.snap
new file mode 100644 (file)
index 0000000..bf84e91
--- /dev/null
@@ -0,0 +1,788 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify PolicyEditor Test the render method 1`] = `
+<PolicyEditor
+  policiesTableUpdateFunction={[Function]}
+  policyModelType="onap.policies.monitoring.tcagen2"
+  policyModelTypeVersion="1.0.0"
+  policyName="org.onap.new"
+  policyProperties={
+    Object {
+      "tca.policy": Object {
+        "domain": "measurementsForVfScaling",
+        "metricsPerEventName": Array [
+          Object {
+            "controlLoopSchemaType": "VM",
+            "eventName": "vLoadBalancer",
+            "policyName": "DCAE.Config_tca-hi-lo",
+            "policyScope": "DCAE",
+            "policyVersion": "v0.0.1",
+            "thresholds": Array [
+              Object {
+                "closedLoopControlName": "LOOP_test",
+                "closedLoopEventStatus": "ONSET",
+                "direction": "LESS_OR_EQUAL",
+                "fieldPath": "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta",
+                "severity": "MAJOR",
+                "thresholdValue": 200,
+                "version": "1.0.2",
+              },
+            ],
+          },
+        ],
+      },
+    }
+  }
+  policyVersion="1.0.0"
+>
+  <styled.div>
+    <div
+      className="sc-dlfnbm eVKaeY"
+    >
+      <Alert
+        closeLabel="Close alert"
+        dismissible={true}
+        onClose={[Function]}
+        show={false}
+        transition={
+          Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "defaultProps": Object {
+              "appear": false,
+              "in": false,
+              "mountOnEnter": false,
+              "timeout": 300,
+              "unmountOnExit": false,
+            },
+            "render": [Function],
+          }
+        }
+        variant="success"
+      >
+        <Fade
+          appear={false}
+          in={false}
+          mountOnEnter={false}
+          timeout={300}
+          unmountOnExit={true}
+        >
+          <Transition
+            addEndListener={[Function]}
+            appear={false}
+            enter={true}
+            exit={true}
+            in={false}
+            mountOnEnter={false}
+            onEnter={[Function]}
+            onEntered={[Function]}
+            onEntering={[Function]}
+            onExit={[Function]}
+            onExited={[Function]}
+            onExiting={[Function]}
+            timeout={300}
+            unmountOnExit={true}
+          />
+        </Fade>
+      </Alert>
+      <Alert
+        closeLabel="Close alert"
+        dismissible={true}
+        onClose={[Function]}
+        show={false}
+        transition={
+          Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "defaultProps": Object {
+              "appear": false,
+              "in": false,
+              "mountOnEnter": false,
+              "timeout": 300,
+              "unmountOnExit": false,
+            },
+            "render": [Function],
+          }
+        }
+        variant="danger"
+      >
+        <Fade
+          appear={false}
+          in={false}
+          mountOnEnter={false}
+          timeout={300}
+          unmountOnExit={true}
+        >
+          <Transition
+            addEndListener={[Function]}
+            appear={false}
+            enter={true}
+            exit={true}
+            in={false}
+            mountOnEnter={false}
+            onEnter={[Function]}
+            onEntered={[Function]}
+            onEntering={[Function]}
+            onExit={[Function]}
+            onExited={[Function]}
+            onExiting={[Function]}
+            timeout={300}
+            unmountOnExit={true}
+          />
+        </Fade>
+      </Alert>
+      <WithStyles(ForwardRef(TextField))
+        defaultValue="org.onap.new"
+        id="policyName"
+        label="Required"
+        onChange={[Function]}
+        required={true}
+        size="small"
+        variant="outlined"
+      >
+        <ForwardRef(TextField)
+          classes={
+            Object {
+              "root": "MuiTextField-root",
+            }
+          }
+          defaultValue="org.onap.new"
+          id="policyName"
+          label="Required"
+          onChange={[Function]}
+          required={true}
+          size="small"
+          variant="outlined"
+        >
+          <WithStyles(ForwardRef(FormControl))
+            className="MuiTextField-root"
+            color="primary"
+            disabled={false}
+            error={false}
+            fullWidth={false}
+            required={true}
+            size="small"
+            variant="outlined"
+          >
+            <ForwardRef(FormControl)
+              className="MuiTextField-root"
+              classes={
+                Object {
+                  "fullWidth": "MuiFormControl-fullWidth",
+                  "marginDense": "MuiFormControl-marginDense",
+                  "marginNormal": "MuiFormControl-marginNormal",
+                  "root": "MuiFormControl-root",
+                }
+              }
+              color="primary"
+              disabled={false}
+              error={false}
+              fullWidth={false}
+              required={true}
+              size="small"
+              variant="outlined"
+            >
+              <div
+                className="MuiFormControl-root MuiTextField-root"
+              >
+                <WithStyles(ForwardRef(InputLabel))
+                  htmlFor="policyName"
+                  id="policyName-label"
+                >
+                  <ForwardRef(InputLabel)
+                    classes={
+                      Object {
+                        "animated": "MuiInputLabel-animated",
+                        "asterisk": "MuiInputLabel-asterisk",
+                        "disabled": "Mui-disabled",
+                        "error": "Mui-error",
+                        "filled": "MuiInputLabel-filled",
+                        "focused": "Mui-focused",
+                        "formControl": "MuiInputLabel-formControl",
+                        "marginDense": "MuiInputLabel-marginDense",
+                        "outlined": "MuiInputLabel-outlined",
+                        "required": "Mui-required",
+                        "root": "MuiInputLabel-root",
+                        "shrink": "MuiInputLabel-shrink",
+                      }
+                    }
+                    htmlFor="policyName"
+                    id="policyName-label"
+                  >
+                    <WithStyles(ForwardRef(FormLabel))
+                      className="MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-marginDense MuiInputLabel-outlined"
+                      classes={
+                        Object {
+                          "asterisk": "MuiInputLabel-asterisk",
+                          "disabled": "Mui-disabled",
+                          "error": "Mui-error",
+                          "focused": "Mui-focused",
+                          "required": "Mui-required",
+                        }
+                      }
+                      data-shrink={true}
+                      htmlFor="policyName"
+                      id="policyName-label"
+                    >
+                      <ForwardRef(FormLabel)
+                        className="MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-marginDense MuiInputLabel-outlined"
+                        classes={
+                          Object {
+                            "asterisk": "MuiFormLabel-asterisk MuiInputLabel-asterisk",
+                            "colorSecondary": "MuiFormLabel-colorSecondary",
+                            "disabled": "Mui-disabled Mui-disabled",
+                            "error": "Mui-error Mui-error",
+                            "filled": "MuiFormLabel-filled",
+                            "focused": "Mui-focused Mui-focused",
+                            "required": "Mui-required Mui-required",
+                            "root": "MuiFormLabel-root",
+                          }
+                        }
+                        data-shrink={true}
+                        htmlFor="policyName"
+                        id="policyName-label"
+                      >
+                        <label
+                          className="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-marginDense MuiInputLabel-outlined MuiFormLabel-filled Mui-required Mui-required"
+                          data-shrink={true}
+                          htmlFor="policyName"
+                          id="policyName-label"
+                        >
+                          Required
+                          <span
+                            aria-hidden={true}
+                            className="MuiFormLabel-asterisk MuiInputLabel-asterisk"
+                          >
+                            â€‰
+                            *
+                          </span>
+                        </label>
+                      </ForwardRef(FormLabel)>
+                    </WithStyles(ForwardRef(FormLabel))>
+                  </ForwardRef(InputLabel)>
+                </WithStyles(ForwardRef(InputLabel))>
+                <WithStyles(ForwardRef(OutlinedInput))
+                  autoFocus={false}
+                  defaultValue="org.onap.new"
+                  fullWidth={false}
+                  id="policyName"
+                  label={
+                    <React.Fragment>
+                      Required
+                      Â *
+                    </React.Fragment>
+                  }
+                  multiline={false}
+                  onChange={[Function]}
+                >
+                  <ForwardRef(OutlinedInput)
+                    autoFocus={false}
+                    classes={
+                      Object {
+                        "adornedEnd": "MuiOutlinedInput-adornedEnd",
+                        "adornedStart": "MuiOutlinedInput-adornedStart",
+                        "colorSecondary": "MuiOutlinedInput-colorSecondary",
+                        "disabled": "Mui-disabled",
+                        "error": "Mui-error",
+                        "focused": "Mui-focused",
+                        "input": "MuiOutlinedInput-input",
+                        "inputAdornedEnd": "MuiOutlinedInput-inputAdornedEnd",
+                        "inputAdornedStart": "MuiOutlinedInput-inputAdornedStart",
+                        "inputMarginDense": "MuiOutlinedInput-inputMarginDense",
+                        "inputMultiline": "MuiOutlinedInput-inputMultiline",
+                        "marginDense": "MuiOutlinedInput-marginDense",
+                        "multiline": "MuiOutlinedInput-multiline",
+                        "notchedOutline": "MuiOutlinedInput-notchedOutline",
+                        "root": "MuiOutlinedInput-root",
+                      }
+                    }
+                    defaultValue="org.onap.new"
+                    fullWidth={false}
+                    id="policyName"
+                    label={
+                      <React.Fragment>
+                        Required
+                        Â *
+                      </React.Fragment>
+                    }
+                    multiline={false}
+                    onChange={[Function]}
+                  >
+                    <WithStyles(ForwardRef(InputBase))
+                      autoFocus={false}
+                      classes={
+                        Object {
+                          "adornedEnd": "MuiOutlinedInput-adornedEnd",
+                          "adornedStart": "MuiOutlinedInput-adornedStart",
+                          "colorSecondary": "MuiOutlinedInput-colorSecondary",
+                          "disabled": "Mui-disabled",
+                          "error": "Mui-error",
+                          "focused": "Mui-focused",
+                          "input": "MuiOutlinedInput-input",
+                          "inputAdornedEnd": "MuiOutlinedInput-inputAdornedEnd",
+                          "inputAdornedStart": "MuiOutlinedInput-inputAdornedStart",
+                          "inputMarginDense": "MuiOutlinedInput-inputMarginDense",
+                          "inputMultiline": "MuiOutlinedInput-inputMultiline",
+                          "marginDense": "MuiOutlinedInput-marginDense",
+                          "multiline": "MuiOutlinedInput-multiline",
+                          "notchedOutline": null,
+                          "root": "MuiOutlinedInput-root",
+                        }
+                      }
+                      defaultValue="org.onap.new"
+                      fullWidth={false}
+                      id="policyName"
+                      inputComponent="input"
+                      multiline={false}
+                      onChange={[Function]}
+                      renderSuffix={[Function]}
+                      type="text"
+                    >
+                      <ForwardRef(InputBase)
+                        autoFocus={false}
+                        classes={
+                          Object {
+                            "adornedEnd": "MuiInputBase-adornedEnd MuiOutlinedInput-adornedEnd",
+                            "adornedStart": "MuiInputBase-adornedStart MuiOutlinedInput-adornedStart",
+                            "colorSecondary": "MuiInputBase-colorSecondary MuiOutlinedInput-colorSecondary",
+                            "disabled": "Mui-disabled Mui-disabled",
+                            "error": "Mui-error Mui-error",
+                            "focused": "Mui-focused Mui-focused",
+                            "formControl": "MuiInputBase-formControl",
+                            "fullWidth": "MuiInputBase-fullWidth",
+                            "input": "MuiInputBase-input MuiOutlinedInput-input",
+                            "inputAdornedEnd": "MuiInputBase-inputAdornedEnd MuiOutlinedInput-inputAdornedEnd",
+                            "inputAdornedStart": "MuiInputBase-inputAdornedStart MuiOutlinedInput-inputAdornedStart",
+                            "inputHiddenLabel": "MuiInputBase-inputHiddenLabel",
+                            "inputMarginDense": "MuiInputBase-inputMarginDense MuiOutlinedInput-inputMarginDense",
+                            "inputMultiline": "MuiInputBase-inputMultiline MuiOutlinedInput-inputMultiline",
+                            "inputTypeSearch": "MuiInputBase-inputTypeSearch",
+                            "marginDense": "MuiInputBase-marginDense MuiOutlinedInput-marginDense",
+                            "multiline": "MuiInputBase-multiline MuiOutlinedInput-multiline",
+                            "root": "MuiInputBase-root MuiOutlinedInput-root",
+                          }
+                        }
+                        defaultValue="org.onap.new"
+                        fullWidth={false}
+                        id="policyName"
+                        inputComponent="input"
+                        multiline={false}
+                        onChange={[Function]}
+                        renderSuffix={[Function]}
+                        type="text"
+                      >
+                        <div
+                          className="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl MuiInputBase-marginDense MuiOutlinedInput-marginDense"
+                          onClick={[Function]}
+                        >
+                          <input
+                            aria-invalid={false}
+                            autoFocus={false}
+                            className="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMarginDense MuiOutlinedInput-inputMarginDense"
+                            defaultValue="org.onap.new"
+                            disabled={false}
+                            id="policyName"
+                            onAnimationStart={[Function]}
+                            onBlur={[Function]}
+                            onChange={[Function]}
+                            onFocus={[Function]}
+                            required={true}
+                            type="text"
+                          />
+                          <WithStyles(ForwardRef(NotchedOutline))
+                            className="MuiOutlinedInput-notchedOutline"
+                            label={
+                              <React.Fragment>
+                                Required
+                                Â *
+                              </React.Fragment>
+                            }
+                            labelWidth={0}
+                            notched={true}
+                          >
+                            <ForwardRef(NotchedOutline)
+                              className="MuiOutlinedInput-notchedOutline"
+                              classes={
+                                Object {
+                                  "legend": "PrivateNotchedOutline-legend-2",
+                                  "legendLabelled": "PrivateNotchedOutline-legendLabelled-3",
+                                  "legendNotched": "PrivateNotchedOutline-legendNotched-4",
+                                  "root": "PrivateNotchedOutline-root-1",
+                                }
+                              }
+                              label={
+                                <React.Fragment>
+                                  Required
+                                  Â *
+                                </React.Fragment>
+                              }
+                              labelWidth={0}
+                              notched={true}
+                            >
+                              <fieldset
+                                aria-hidden={true}
+                                className="PrivateNotchedOutline-root-1 MuiOutlinedInput-notchedOutline"
+                              >
+                                <legend
+                                  className="PrivateNotchedOutline-legendLabelled-3 PrivateNotchedOutline-legendNotched-4"
+                                >
+                                  <span>
+                                    Required
+                                    Â *
+                                  </span>
+                                </legend>
+                              </fieldset>
+                            </ForwardRef(NotchedOutline)>
+                          </WithStyles(ForwardRef(NotchedOutline))>
+                        </div>
+                      </ForwardRef(InputBase)>
+                    </WithStyles(ForwardRef(InputBase))>
+                  </ForwardRef(OutlinedInput)>
+                </WithStyles(ForwardRef(OutlinedInput))>
+              </div>
+            </ForwardRef(FormControl)>
+          </WithStyles(ForwardRef(FormControl))>
+        </ForwardRef(TextField)>
+      </WithStyles(ForwardRef(TextField))>
+      <WithStyles(ForwardRef(TextField))
+        defaultValue="1.0.0"
+        id="policyVersion"
+        label="Required"
+        onChange={[Function]}
+        required={true}
+        size="small"
+        variant="outlined"
+      >
+        <ForwardRef(TextField)
+          classes={
+            Object {
+              "root": "MuiTextField-root",
+            }
+          }
+          defaultValue="1.0.0"
+          id="policyVersion"
+          label="Required"
+          onChange={[Function]}
+          required={true}
+          size="small"
+          variant="outlined"
+        >
+          <WithStyles(ForwardRef(FormControl))
+            className="MuiTextField-root"
+            color="primary"
+            disabled={false}
+            error={false}
+            fullWidth={false}
+            required={true}
+            size="small"
+            variant="outlined"
+          >
+            <ForwardRef(FormControl)
+              className="MuiTextField-root"
+              classes={
+                Object {
+                  "fullWidth": "MuiFormControl-fullWidth",
+                  "marginDense": "MuiFormControl-marginDense",
+                  "marginNormal": "MuiFormControl-marginNormal",
+                  "root": "MuiFormControl-root",
+                }
+              }
+              color="primary"
+              disabled={false}
+              error={false}
+              fullWidth={false}
+              required={true}
+              size="small"
+              variant="outlined"
+            >
+              <div
+                className="MuiFormControl-root MuiTextField-root"
+              >
+                <WithStyles(ForwardRef(InputLabel))
+                  htmlFor="policyVersion"
+                  id="policyVersion-label"
+                >
+                  <ForwardRef(InputLabel)
+                    classes={
+                      Object {
+                        "animated": "MuiInputLabel-animated",
+                        "asterisk": "MuiInputLabel-asterisk",
+                        "disabled": "Mui-disabled",
+                        "error": "Mui-error",
+                        "filled": "MuiInputLabel-filled",
+                        "focused": "Mui-focused",
+                        "formControl": "MuiInputLabel-formControl",
+                        "marginDense": "MuiInputLabel-marginDense",
+                        "outlined": "MuiInputLabel-outlined",
+                        "required": "Mui-required",
+                        "root": "MuiInputLabel-root",
+                        "shrink": "MuiInputLabel-shrink",
+                      }
+                    }
+                    htmlFor="policyVersion"
+                    id="policyVersion-label"
+                  >
+                    <WithStyles(ForwardRef(FormLabel))
+                      className="MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-marginDense MuiInputLabel-outlined"
+                      classes={
+                        Object {
+                          "asterisk": "MuiInputLabel-asterisk",
+                          "disabled": "Mui-disabled",
+                          "error": "Mui-error",
+                          "focused": "Mui-focused",
+                          "required": "Mui-required",
+                        }
+                      }
+                      data-shrink={true}
+                      htmlFor="policyVersion"
+                      id="policyVersion-label"
+                    >
+                      <ForwardRef(FormLabel)
+                        className="MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-marginDense MuiInputLabel-outlined"
+                        classes={
+                          Object {
+                            "asterisk": "MuiFormLabel-asterisk MuiInputLabel-asterisk",
+                            "colorSecondary": "MuiFormLabel-colorSecondary",
+                            "disabled": "Mui-disabled Mui-disabled",
+                            "error": "Mui-error Mui-error",
+                            "filled": "MuiFormLabel-filled",
+                            "focused": "Mui-focused Mui-focused",
+                            "required": "Mui-required Mui-required",
+                            "root": "MuiFormLabel-root",
+                          }
+                        }
+                        data-shrink={true}
+                        htmlFor="policyVersion"
+                        id="policyVersion-label"
+                      >
+                        <label
+                          className="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-marginDense MuiInputLabel-outlined MuiFormLabel-filled Mui-required Mui-required"
+                          data-shrink={true}
+                          htmlFor="policyVersion"
+                          id="policyVersion-label"
+                        >
+                          Required
+                          <span
+                            aria-hidden={true}
+                            className="MuiFormLabel-asterisk MuiInputLabel-asterisk"
+                          >
+                            â€‰
+                            *
+                          </span>
+                        </label>
+                      </ForwardRef(FormLabel)>
+                    </WithStyles(ForwardRef(FormLabel))>
+                  </ForwardRef(InputLabel)>
+                </WithStyles(ForwardRef(InputLabel))>
+                <WithStyles(ForwardRef(OutlinedInput))
+                  autoFocus={false}
+                  defaultValue="1.0.0"
+                  fullWidth={false}
+                  id="policyVersion"
+                  label={
+                    <React.Fragment>
+                      Required
+                      Â *
+                    </React.Fragment>
+                  }
+                  multiline={false}
+                  onChange={[Function]}
+                >
+                  <ForwardRef(OutlinedInput)
+                    autoFocus={false}
+                    classes={
+                      Object {
+                        "adornedEnd": "MuiOutlinedInput-adornedEnd",
+                        "adornedStart": "MuiOutlinedInput-adornedStart",
+                        "colorSecondary": "MuiOutlinedInput-colorSecondary",
+                        "disabled": "Mui-disabled",
+                        "error": "Mui-error",
+                        "focused": "Mui-focused",
+                        "input": "MuiOutlinedInput-input",
+                        "inputAdornedEnd": "MuiOutlinedInput-inputAdornedEnd",
+                        "inputAdornedStart": "MuiOutlinedInput-inputAdornedStart",
+                        "inputMarginDense": "MuiOutlinedInput-inputMarginDense",
+                        "inputMultiline": "MuiOutlinedInput-inputMultiline",
+                        "marginDense": "MuiOutlinedInput-marginDense",
+                        "multiline": "MuiOutlinedInput-multiline",
+                        "notchedOutline": "MuiOutlinedInput-notchedOutline",
+                        "root": "MuiOutlinedInput-root",
+                      }
+                    }
+                    defaultValue="1.0.0"
+                    fullWidth={false}
+                    id="policyVersion"
+                    label={
+                      <React.Fragment>
+                        Required
+                        Â *
+                      </React.Fragment>
+                    }
+                    multiline={false}
+                    onChange={[Function]}
+                  >
+                    <WithStyles(ForwardRef(InputBase))
+                      autoFocus={false}
+                      classes={
+                        Object {
+                          "adornedEnd": "MuiOutlinedInput-adornedEnd",
+                          "adornedStart": "MuiOutlinedInput-adornedStart",
+                          "colorSecondary": "MuiOutlinedInput-colorSecondary",
+                          "disabled": "Mui-disabled",
+                          "error": "Mui-error",
+                          "focused": "Mui-focused",
+                          "input": "MuiOutlinedInput-input",
+                          "inputAdornedEnd": "MuiOutlinedInput-inputAdornedEnd",
+                          "inputAdornedStart": "MuiOutlinedInput-inputAdornedStart",
+                          "inputMarginDense": "MuiOutlinedInput-inputMarginDense",
+                          "inputMultiline": "MuiOutlinedInput-inputMultiline",
+                          "marginDense": "MuiOutlinedInput-marginDense",
+                          "multiline": "MuiOutlinedInput-multiline",
+                          "notchedOutline": null,
+                          "root": "MuiOutlinedInput-root",
+                        }
+                      }
+                      defaultValue="1.0.0"
+                      fullWidth={false}
+                      id="policyVersion"
+                      inputComponent="input"
+                      multiline={false}
+                      onChange={[Function]}
+                      renderSuffix={[Function]}
+                      type="text"
+                    >
+                      <ForwardRef(InputBase)
+                        autoFocus={false}
+                        classes={
+                          Object {
+                            "adornedEnd": "MuiInputBase-adornedEnd MuiOutlinedInput-adornedEnd",
+                            "adornedStart": "MuiInputBase-adornedStart MuiOutlinedInput-adornedStart",
+                            "colorSecondary": "MuiInputBase-colorSecondary MuiOutlinedInput-colorSecondary",
+                            "disabled": "Mui-disabled Mui-disabled",
+                            "error": "Mui-error Mui-error",
+                            "focused": "Mui-focused Mui-focused",
+                            "formControl": "MuiInputBase-formControl",
+                            "fullWidth": "MuiInputBase-fullWidth",
+                            "input": "MuiInputBase-input MuiOutlinedInput-input",
+                            "inputAdornedEnd": "MuiInputBase-inputAdornedEnd MuiOutlinedInput-inputAdornedEnd",
+                            "inputAdornedStart": "MuiInputBase-inputAdornedStart MuiOutlinedInput-inputAdornedStart",
+                            "inputHiddenLabel": "MuiInputBase-inputHiddenLabel",
+                            "inputMarginDense": "MuiInputBase-inputMarginDense MuiOutlinedInput-inputMarginDense",
+                            "inputMultiline": "MuiInputBase-inputMultiline MuiOutlinedInput-inputMultiline",
+                            "inputTypeSearch": "MuiInputBase-inputTypeSearch",
+                            "marginDense": "MuiInputBase-marginDense MuiOutlinedInput-marginDense",
+                            "multiline": "MuiInputBase-multiline MuiOutlinedInput-multiline",
+                            "root": "MuiInputBase-root MuiOutlinedInput-root",
+                          }
+                        }
+                        defaultValue="1.0.0"
+                        fullWidth={false}
+                        id="policyVersion"
+                        inputComponent="input"
+                        multiline={false}
+                        onChange={[Function]}
+                        renderSuffix={[Function]}
+                        type="text"
+                      >
+                        <div
+                          className="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl MuiInputBase-marginDense MuiOutlinedInput-marginDense"
+                          onClick={[Function]}
+                        >
+                          <input
+                            aria-invalid={false}
+                            autoFocus={false}
+                            className="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMarginDense MuiOutlinedInput-inputMarginDense"
+                            defaultValue="1.0.0"
+                            disabled={false}
+                            id="policyVersion"
+                            onAnimationStart={[Function]}
+                            onBlur={[Function]}
+                            onChange={[Function]}
+                            onFocus={[Function]}
+                            required={true}
+                            type="text"
+                          />
+                          <WithStyles(ForwardRef(NotchedOutline))
+                            className="MuiOutlinedInput-notchedOutline"
+                            label={
+                              <React.Fragment>
+                                Required
+                                Â *
+                              </React.Fragment>
+                            }
+                            labelWidth={0}
+                            notched={true}
+                          >
+                            <ForwardRef(NotchedOutline)
+                              className="MuiOutlinedInput-notchedOutline"
+                              classes={
+                                Object {
+                                  "legend": "PrivateNotchedOutline-legend-2",
+                                  "legendLabelled": "PrivateNotchedOutline-legendLabelled-3",
+                                  "legendNotched": "PrivateNotchedOutline-legendNotched-4",
+                                  "root": "PrivateNotchedOutline-root-1",
+                                }
+                              }
+                              label={
+                                <React.Fragment>
+                                  Required
+                                  Â *
+                                </React.Fragment>
+                              }
+                              labelWidth={0}
+                              notched={true}
+                            >
+                              <fieldset
+                                aria-hidden={true}
+                                className="PrivateNotchedOutline-root-1 MuiOutlinedInput-notchedOutline"
+                              >
+                                <legend
+                                  className="PrivateNotchedOutline-legendLabelled-3 PrivateNotchedOutline-legendNotched-4"
+                                >
+                                  <span>
+                                    Required
+                                    Â *
+                                  </span>
+                                </legend>
+                              </fieldset>
+                            </ForwardRef(NotchedOutline)>
+                          </WithStyles(ForwardRef(NotchedOutline))>
+                        </div>
+                      </ForwardRef(InputBase)>
+                    </WithStyles(ForwardRef(InputBase))>
+                  </ForwardRef(OutlinedInput)>
+                </WithStyles(ForwardRef(OutlinedInput))>
+              </div>
+            </ForwardRef(FormControl)>
+          </WithStyles(ForwardRef(FormControl))>
+        </ForwardRef(TextField)>
+      </WithStyles(ForwardRef(TextField))>
+      <Button
+        active={false}
+        disabled={false}
+        onClick={[Function]}
+        title="Create a new policy version from the defined parameters"
+        variant="secondary"
+      >
+        <button
+          className="btn btn-secondary"
+          disabled={false}
+          onClick={[Function]}
+          title="Create a new policy version from the defined parameters"
+          type="button"
+        >
+          Create New Version
+        </button>
+      </Button>
+      <styled.div
+        id="onap.policies.monitoring.tcagen2_1.0.0_org.onap.new_1.0.0"
+        title="Policy Properties"
+      >
+        <div
+          className="sc-gsTCUz hXXDCR"
+          id="onap.policies.monitoring.tcagen2_1.0.0_org.onap.new_1.0.0"
+          title="Policy Properties"
+        />
+      </styled.div>
+    </div>
+  </styled.div>
+</PolicyEditor>
+`;
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyModal.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyModal.test.js.snap
new file mode 100644 (file)
index 0000000..8b1261b
--- /dev/null
@@ -0,0 +1,159 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify PolicyModal Test the render method 1`] = `
+<Styled(Modal)
+  backdrop="static"
+  keyboard={false}
+  onHide={[Function]}
+  show={true}
+  size="xl"
+>
+  <ModalHeader
+    closeButton={true}
+    closeLabel="Close"
+  >
+    <ModalTitle>
+      Edit the policy
+    </ModalTitle>
+  </ModalHeader>
+  <Alert
+    closeLabel="Close alert"
+    dismissible={true}
+    onClose={[Function]}
+    show={false}
+    transition={
+      Object {
+        "$$typeof": Symbol(react.forward_ref),
+        "defaultProps": Object {
+          "appear": false,
+          "in": false,
+          "mountOnEnter": false,
+          "timeout": 300,
+          "unmountOnExit": false,
+        },
+        "render": [Function],
+      }
+    }
+    variant="success"
+  >
+    <styled.div />
+  </Alert>
+  <Alert
+    closeLabel="Close alert"
+    dismissible={true}
+    onClose={[Function]}
+    show={false}
+    transition={
+      Object {
+        "$$typeof": Symbol(react.forward_ref),
+        "defaultProps": Object {
+          "appear": false,
+          "in": false,
+          "mountOnEnter": false,
+          "timeout": 300,
+          "unmountOnExit": false,
+        },
+        "render": [Function],
+      }
+    }
+    variant="danger"
+  >
+    <styled.div />
+  </Alert>
+  <ModalBody>
+    <div
+      id="editor"
+    />
+    <FormGroup
+      as={
+        Object {
+          "$$typeof": Symbol(react.forward_ref),
+          "defaultProps": Object {
+            "noGutters": false,
+          },
+          "render": [Function],
+        }
+      }
+      controlId="formPlaintextEmail"
+    >
+      <FormLabel
+        column={true}
+        sm="2"
+        srOnly={false}
+      >
+        Pdp Group Info
+      </FormLabel>
+      <Col
+        sm="3"
+      >
+        <StateManager
+          defaultInputValue=""
+          defaultMenuIsOpen={false}
+          defaultValue={null}
+          onChange={[Function]}
+          options={
+            Array [
+              Object {
+                "label": "monitoring",
+                "value": "monitoring",
+              },
+            ]
+          }
+          value={
+            Object {
+              "label": undefined,
+              "value": undefined,
+            }
+          }
+        />
+      </Col>
+      <Col
+        sm="3"
+      >
+        <StateManager
+          defaultInputValue=""
+          defaultMenuIsOpen={false}
+          defaultValue={null}
+          onChange={[Function]}
+          options={Array []}
+          value={
+            Object {
+              "label": undefined,
+              "value": undefined,
+            }
+          }
+        />
+      </Col>
+    </FormGroup>
+  </ModalBody>
+  <ModalFooter>
+    <Button
+      active={false}
+      disabled={false}
+      key="close"
+      onClick={[Function]}
+      variant="secondary"
+    >
+      Close
+    </Button>
+    <Button
+      active={false}
+      disabled={false}
+      key="save"
+      onClick={[Function]}
+      variant="primary"
+    >
+      Save Changes
+    </Button>
+    <Button
+      active={false}
+      disabled={false}
+      key="refresh"
+      onClick={[Function]}
+      variant="primary"
+    >
+      Refresh
+    </Button>
+  </ModalFooter>
+</Styled(Modal)>
+`;
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/ToscaViewer.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/Policy/__snapshots__/ToscaViewer.test.js.snap
new file mode 100644 (file)
index 0000000..61fb485
--- /dev/null
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify ToscaViewer Test the render method 1`] = `
+<styled.div>
+  <pre>
+    tosca_definitions_version: tosca_simple_yaml_1_1_0
+policy_types:
+  onap.policies.controlloop.Guard:
+    properties: {
+    }
+    name: onap.policies.controlloop.Guard
+    version: 1.0.0
+    derived_from: tosca.policies.Root
+    metadata: {
+    }
+    description: Guard Policies for Control Loop Operational Policies
+name: ToscaServiceTemplateSimple
+version: 1.0.0
+
+  </pre>
+  <Button
+    active={false}
+    disabled={false}
+    title="Create a new policy version from the defined parameters"
+    variant="secondary"
+  >
+    Create New Version
+  </Button>
+</styled.div>
+`;
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/toscaData.test.json b/gui-clamp/ui-react/src/components/dialogs/Policy/toscaData.test.json
new file mode 100644 (file)
index 0000000..3b001b3
--- /dev/null
@@ -0,0 +1,179 @@
+{
+  "title": "onap.policies.monitoring.tcagen2",
+  "type": "object",
+  "required": [
+    "tca.policy"
+  ],
+  "properties": {
+    "tca.policy": {
+      "title": "onap.datatypes.monitoring.tca_policy",
+      "type": "object",
+      "required": [
+        "domain",
+        "metricsPerEventName"
+      ],
+      "properties": {
+        "domain": {
+          "type": "string",
+          "description": "Domain name to which TCA needs to be applied",
+          "default": "measurementsForVfScaling",
+          "const": "measurementsForVfScaling"
+        },
+        "metricsPerEventName": {
+          "type": "array",
+          "description": "Contains eventName and threshold details that need to be applied to given eventName",
+          "items": {
+            "title": "onap.datatypes.monitoring.metricsPerEventName",
+            "type": "object",
+            "required": [
+              "controlLoopSchemaType",
+              "eventName",
+              "policyName",
+              "policyScope",
+              "policyVersion",
+              "thresholds"
+            ],
+            "properties": {
+              "controlLoopSchemaType": {
+                "type": "string",
+                "description": "Specifies Control Loop Schema Type for the event Name e.g. VNF, VM",
+                "enum": [
+                  "VM",
+                  "VNF"
+                ]
+              },
+              "eventName": {
+                "type": "string",
+                "description": "Event name to which thresholds need to be applied"
+              },
+              "policyName": {
+                "type": "string",
+                "description": "TCA Policy Scope Name"
+              },
+              "policyScope": {
+                "type": "string",
+                "description": "TCA Policy Scope"
+              },
+              "policyVersion": {
+                "type": "string",
+                "description": "TCA Policy Scope Version"
+              },
+              "thresholds": {
+                "type": "array",
+                "description": "Thresholds associated with eventName",
+                "items": {
+                  "title": "onap.datatypes.monitoring.thresholds",
+                  "type": "object",
+                  "required": [
+                    "closedLoopControlName",
+                    "closedLoopEventStatus",
+                    "direction",
+                    "fieldPath",
+                    "severity",
+                    "thresholdValue",
+                    "version"
+                  ],
+                  "properties": {
+                    "closedLoopControlName": {
+                      "type": "string",
+                      "description": "Closed Loop Control Name associated with the threshold"
+                    },
+                    "closedLoopEventStatus": {
+                      "type": "string",
+                      "description": "Closed Loop Event Status of the threshold",
+                      "enum": [
+                        "ONSET",
+                        "ABATED"
+                      ]
+                    },
+                    "direction": {
+                      "type": "string",
+                      "description": "Direction of the threshold",
+                      "enum": [
+                        "LESS",
+                        "LESS_OR_EQUAL",
+                        "GREATER",
+                        "GREATER_OR_EQUAL",
+                        "EQUAL"
+                      ]
+                    },
+                    "fieldPath": {
+                      "type": "string",
+                      "description": "Json field Path as per CEF message which needs to be analyzed for TCA",
+                      "enum": [
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait",
+                        "$.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage",
+                        "$.event.measurementsForVfScalingFields.meanRequestLatency",
+                        "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered",
+                        "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached",
+                        "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured",
+                        "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree",
+                        "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed",
+                        "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value"
+                      ]
+                    },
+                    "severity": {
+                      "type": "string",
+                      "description": "Threshold Event Severity",
+                      "enum": [
+                        "CRITICAL",
+                        "MAJOR",
+                        "MINOR",
+                        "WARNING",
+                        "NORMAL"
+                      ]
+                    },
+                    "thresholdValue": {
+                      "type": "integer",
+                      "description": "Threshold value for the field Path inside CEF message"
+                    },
+                    "version": {
+                      "type": "string",
+                      "description": "Version number associated with the threshold"
+                    }
+                  }
+                },
+                "format": "tabs-top"
+              }
+            }
+          },
+          "format": "tabs-top"
+        }
+      }
+    }
+  }
+}
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/toscaData.test.yaml b/gui-clamp/ui-react/src/components/dialogs/Policy/toscaData.test.yaml
new file mode 100644 (file)
index 0000000..15a3cec
--- /dev/null
@@ -0,0 +1,13 @@
+tosca_definitions_version: tosca_simple_yaml_1_1_0
+policy_types:
+  onap.policies.controlloop.Guard:
+    properties: {
+    }
+    name: onap.policies.controlloop.Guard
+    version: 1.0.0
+    derived_from: tosca.policies.Root
+    metadata: {
+    }
+    description: Guard Policies for Control Loop Operational Policies
+name: ToscaServiceTemplateSimple
+version: 1.0.0
index 7257337..e7be984 100644 (file)
@@ -1,8 +1,8 @@
 /*-
  * ============LICENSE_START=======================================================
- * ONAP CLAMP
+ * ONAP POLICY-CLAMP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
index e58c61a..d452f6d 100644 (file)
@@ -60,7 +60,7 @@ export default class UserInfoModal extends React.Component {
   renderPermissions() {
     if (this.state.userInfo["allPermissions"]) {
       var listOfPermissions = this.state.userInfo["allPermissions"].map(function (perm) {
-        return <Form.Control plaintext readOnly defaultValue={ perm }/>;
+        return <Form.Control key={ perm } plaintext readOnly defaultValue={ perm }/>;
       })
       return listOfPermissions;
     } else {
index 7c725bc..548a2d9 100644 (file)
@@ -91,11 +91,13 @@ exports[`Verify UserInfoModal Test the render method full permission 1`] = `
       <Col>
         <FormControl
           defaultValue="permission1"
+          key="permission1"
           plaintext={true}
           readOnly={true}
         />
         <FormControl
           defaultValue="permission2"
+          key="permission2"
           plaintext={true}
           readOnly={true}
         />
index b03b740..3435ba3 100644 (file)
@@ -67,10 +67,9 @@ export default class LoopLogs extends React.Component {
   }
 
   renderLogs() {
-    if (this.state.loopCache.getLoopLogsArray() != null) {
-      return (
-        this.state.loopCache.getLoopLogsArray().map(row => <TableRow logRow={ row }/>)
-      )
+    let logsArray = this.state.loopCache.getLoopLogsArray();
+    if (logsArray != null) {
+      return (logsArray.map(row => <TableRow key={ row.id } logRow={ row }/>));
     }
   }
 
index 75b817b..996c674 100644 (file)
@@ -45,6 +45,7 @@ exports[`Verify LoopLogs Test the render method 1`] = `
     </thead>
     <tbody>
       <TableRow
+        key="1"
         logRow={
           Object {
             "id": 1,
index 2994c84..f539ad4 100644 (file)
@@ -57,12 +57,13 @@ export default class LoopStatus extends React.Component {
 
 
   renderStatus() {
-    if (this.state.loopCache.getComponentStates() != null) {
-      return Object.keys(this.state.loopCache.getComponentStates()).map((key) => {
+    let componentStates = this.state.loopCache.getComponentStates();
+    if (componentStates != null) {
+      return Object.keys(componentStates).map((key) => {
         console.debug("Adding status for: ", key);
         var res = {}
         res[key] = this.state.loopCache.getComponentStates()[key];
-        return (<TableRow statusRow={ {
+        return (<TableRow key={ key } statusRow={ {
           'componentName': key,
           'stateName': this.state.loopCache.getComponentStates()[key].componentState.stateName,
           'description': this.state.loopCache.getComponentStates()[key].componentState.description
index 73da5ff..24d879d 100644 (file)
@@ -40,6 +40,7 @@ exports[`Verify LoopStatus Test the render method 1`] = `
       </thead>
       <tbody>
         <TableRow
+          key="POLICY"
           statusRow={
             Object {
               "componentName": "POLICY",
@@ -49,6 +50,7 @@ exports[`Verify LoopStatus Test the render method 1`] = `
           }
         />
         <TableRow
+          key="DCAE"
           statusRow={
             Object {
               "componentName": "DCAE",
index f5f5047..2692aef 100644 (file)
@@ -27,220 +27,222 @@ import LoopCache from '../../../api/LoopCache';
 import OnapConstant from '../../../utils/OnapConstants';
 
 const DivStyled = styled.div`
-       overflow-x: scroll;
-         display: flex;
-    width: 100%;
-    height: 100%;
+  overflow-x: scroll;
+  display: flex;
+  width: 100%;
+  height: 100%;
 `
 
-const emptySvg = (<svg> <text x="60" y="40">No LOOP (SVG)</text> </svg>);
+const emptySvg = (<svg>
+  <text x="60" y="40">No LOOP (SVG)</text>
+</svg>);
 
 class SvgGenerator extends React.Component {
-    boxWidth = 200;
-    boxHeight = 100;
-    boxSpace = 50;
-
-    static GENERATED_FROM_INSTANCE = "INSTANCE";
-    static GENERATED_FROM_TEMPLATE = "TEMPLATE";
-
-       state = {
-               loopCache: new LoopCache({}),
-               clickable: false,
-               generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE
-       }
-
-       constructor(props) {
-               super(props);
-               this.state.loopCache = props.loopCache;
-               this.state.clickable = props.clickable;
-               this.state.generatedFrom = props.generatedFrom;
-               this.handleSvgClick = this.handleSvgClick.bind(this);
-               this.renderSvg = this.renderSvg.bind(this);
-       }
-
-       shouldComponentUpdate(nextProps, nextState) {
-               return this.state.loopCache !== nextState.loopCache;
-       }
-
-       componentWillReceiveProps(newProps) {
-               if (this.state.loopCache !== newProps.loopCache) {
-                       this.setState({
-                               loopCache: newProps.loopCache,
-                       });
-               }
-       }
-
-       handleSvgClick(event) {
-               console.debug("svg click event received");
-               if (this.state.clickable) {
-                       var elementName = event.target.parentNode.getAttribute('policyId');
-                       console.info("SVG element clicked", elementName);
-                       // Only allow movement to policy editing IF there busyLoadingCOunt is 0,
-                       // meaning we are not waiting for refreshStatus to complete, for example
-                       if (elementName !== null && !this.props.isBusyLoading()) {
-                               this.props.history.push("/policyModal/"+event.target.parentNode.getAttribute('policyType')+"/"+elementName);
-                       }
-               }
-       }
-
-    createVesBox (xPos) {
-        return this.createOneBox(xPos,null,null,'VES Collector','VES',null);
+  boxWidth = 200;
+  boxHeight = 100;
+  boxSpace = 50;
+
+  static GENERATED_FROM_INSTANCE = "INSTANCE";
+  static GENERATED_FROM_TEMPLATE = "TEMPLATE";
+
+  state = {
+    loopCache: new LoopCache({}),
+    clickable: false,
+    generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE
+  }
+
+  constructor(props) {
+    super(props);
+    this.state.loopCache = props.loopCache;
+    this.state.clickable = props.clickable;
+    this.state.generatedFrom = props.generatedFrom;
+    this.handleSvgClick = this.handleSvgClick.bind(this);
+    this.renderSvg = this.renderSvg.bind(this);
+  }
+
+  shouldComponentUpdate(nextProps, nextState) {
+    return this.state.loopCache !== nextProps.loopCache;
+  }
+
+  componentDidUpdate(prevProps) {
+    if (prevProps.loopCache !== this.props.loopCache) {
+      this.setState({
+        loopCache: this.props.loopCache,
+      });
     }
-
-    createOneArrow(xPos) {
-        return (
-         <svg width={this.boxSpace} height={this.boxHeight} x={xPos}>
-           <defs>
-                       <marker viewBox="0 0 20 20" markerWidth="20" markerHeight="20" orient="auto" refX="8.5" refY="5" id="arrow">
-                               <path d="m 1 5 l 0 -3 l 7 3 l -7 3 z"
-                                       stroke-width= "1" stroke-linecap= "butt" stroke-dasharray= "10000, 1"
-                                       fill="#000000" stroke="#000000" />
-                       </marker>
-           </defs>
-           <line x1="0" y1="50%" x2="100%" y2="50%" stroke-width="2" color="black" stroke="black" marker-end="url(#arrow)"/>
-         </svg>
-        );
-    }
-
-    createBeginCircle(xPos, text) {
-            return (
-            <svg width={this.boxWidth} height={this.boxHeight} x={xPos}>
-                <circle cx={this.boxWidth-30} cy="50%" r="30" stroke-width="1" color="black" stroke="black" fill="#27ae60"/>
-                <text x={this.boxWidth-30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text>
-            </svg>
-            );
+  }
+
+  handleSvgClick(event) {
+    console.debug("svg click event received");
+    if (this.state.clickable) {
+      var elementName = event.target.parentNode.getAttribute('policyId');
+      console.info("SVG element clicked", elementName);
+      // Only allow movement to policy editing IF there busyLoadingCOunt is 0,
+      // meaning we are not waiting for refreshStatus to complete, for example
+      if (elementName !== null && !this.props.isBusyLoading()) {
+        this.props.history.push("/policyModal/" + event.target.parentNode.getAttribute('policyType') + "/" + elementName);
+      }
     }
-
-    createEndCircle(xPos, text) {
-            return (
-            <svg width={this.boxWidth} height={this.boxHeight} x={xPos}>
-                <circle cx={30} cy="50%" r="30" stroke-width="2" color="black" stroke="black" fill="#27ae60"/>
-                <text x={30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text>
-            </svg>
-            );
+  }
+
+  createVesBox(xPos) {
+    return this.createOneBox(xPos, null, null, 'VES Collector', 'VES', null);
+  }
+
+  createOneArrow(xPos) {
+    return (
+      <svg width={ this.boxSpace } height={ this.boxHeight } x={ xPos }>
+        <defs>
+          <marker viewBox="0 0 20 20" markerWidth="20" markerHeight="20" orient="auto" refX="8.5" refY="5" id="arrow">
+            <path d="m 1 5 l 0 -3 l 7 3 l -7 3 z"
+                  stroke-width="1" stroke-linecap="butt" stroke-dasharray="10000, 1"
+                  fill="#000000" stroke="#000000"/>
+          </marker>
+        </defs>
+        <line x1="0" y1="50%" x2="100%" y2="50%" stroke-width="2" color="black" stroke="black" marker-end="url(#arrow)"/>
+      </svg>
+    );
+  }
+
+  createBeginCircle(xPos, text) {
+    return (
+      <svg width={ this.boxWidth } height={ this.boxHeight } x={ xPos }>
+        <circle cx={ this.boxWidth - 30 } cy="50%" r="30" stroke-width="1" color="black" stroke="black" fill="#27ae60"/>
+        <text x={ this.boxWidth - 30 } y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs">{ text }</text>
+      </svg>
+    );
+  }
+
+  createEndCircle(xPos, text) {
+    return (
+      <svg width={ this.boxWidth } height={ this.boxHeight } x={ xPos }>
+        <circle cx={ 30 } cy="50%" r="30" stroke-width="2" color="black" stroke="black" fill="#27ae60"/>
+        <text x={ 30 } y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs">{ text }</text>
+      </svg>
+    );
+  }
+
+  createOneBox(xPos, policyId, loopElementModelId, name, title, policyType) {
+    return (
+      <svg width={ this.boxWidth } height={ this.boxHeight } x={ xPos } title="test">
+        <g policyId={ policyId } loopElementModelId={ loopElementModelId } policyType={ policyType }>
+          <rect width="100%" height="100%" stroke-width="2" color="black" stroke="black" fill="#1abc9c"/>
+          <text x="50%" y="15%" color="white" fill="white" dominant-baseline="middle" text-anchor="middle" textLength="50%" lengthAdjust="spacingAndGlyphs">{ title }</text>
+          <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" textLength="80%" lengthAdjust="spacingAndGlyphs">{ name }</text>
+          <text x="50%" y="80%" text-anchor="middle" dominant-baseline="middle" textLength="110%" lengthAdjust="spacingAndGlyphs">{ policyId }</text>
+        </g>
+      </svg>
+    );
+  }
+
+  createSvgFromTemplate() {
+    const allElements = [];
+    var xPos = 0;
+
+    allElements.push(this.createBeginCircle(xPos, "Start"))
+    xPos += (this.boxWidth + this.boxSpace);
+
+    allElements.push(this.createOneArrow(xPos - this.boxSpace));
+
+    allElements.push(this.createVesBox(xPos));
+    xPos += (this.boxWidth + this.boxSpace);
+
+    allElements.push(this.createOneArrow(xPos - this.boxSpace));
+    //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType)
+    for (var loopElement of this.state.loopCache.getAllLoopElementModels()) {
+
+      allElements.push(this.createOneBox(xPos,
+        loopElement['name'],
+        loopElement['name'],
+        loopElement['shortName'],
+        loopElement['loopElementType'],
+        loopElement['loopElementType']))
+      xPos += (this.boxWidth + this.boxSpace);
+      allElements.push(this.createOneArrow(xPos - this.boxSpace));
     }
 
-    createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) {
-        return (
-        <svg width={this.boxWidth} height={this.boxHeight} x={xPos} title="test">
-            <g policyId={policyId} loopElementModelId={loopElementModelId} policyType={policyType}>
-                <rect width="100%" height="100%" stroke-width="2" color="black" stroke="black" fill="#1abc9c"/>
-                <text x="50%" y="15%" color="white" fill="white" dominant-baseline="middle" text-anchor="middle" textLength="50%" lengthAdjust="spacingAndGlyphs">{title}</text>
-                <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" textLength="80%" lengthAdjust="spacingAndGlyphs" >{name}</text>
-                <text x="50%" y="80%" text-anchor="middle" dominant-baseline="middle" textLength="110%" lengthAdjust="spacingAndGlyphs" >{policyId}</text>
-            </g>
-        </svg>
-        );
-    }
+    allElements.push(this.createEndCircle(xPos, "End"))
+    xPos += (this.boxWidth + this.boxSpace);
 
-    createSvgFromTemplate() {
-        const allElements = [];
-        var xPos = 0;
+    return allElements;
+  }
 
-        allElements.push(this.createBeginCircle(xPos,"Start"))
-        xPos+=(this.boxWidth+this.boxSpace);
+  createSvgFromInstance() {
+    const allElements = [];
+    var xPos = 0;
 
-        allElements.push(this.createOneArrow(xPos-this.boxSpace));
+    allElements.push(this.createBeginCircle(xPos, "Start"))
+    xPos += (this.boxWidth + this.boxSpace);
 
-        allElements.push(this.createVesBox(xPos));
-        xPos+=(this.boxWidth+this.boxSpace);
+    allElements.push(this.createOneArrow(xPos - this.boxSpace));
 
-        allElements.push(this.createOneArrow(xPos-this.boxSpace));
-        //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType)
-        for (var loopElement of this.state.loopCache.getAllLoopElementModels()) {
+    allElements.push(this.createVesBox(xPos));
+    xPos += (this.boxWidth + this.boxSpace);
 
-            allElements.push(this.createOneBox(xPos,
-                loopElement['name'],
-                loopElement['name'],
-                loopElement['shortName'],
-                loopElement['loopElementType'],
-                loopElement['loopElementType']))
-            xPos+=(this.boxWidth+this.boxSpace);
-            allElements.push(this.createOneArrow(xPos-this.boxSpace));
-        }
+    allElements.push(this.createOneArrow(xPos - this.boxSpace));
 
-        allElements.push(this.createEndCircle(xPos, "End"))
-        xPos+=(this.boxWidth+this.boxSpace);
-
-        return allElements;
+    for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) {
+      var loopElementModelName = this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel'];
+      if (loopElementModelName !== undefined) {
+        loopElementModelName = loopElementModelName['name'];
+      }
+      allElements.push(this.createOneBox(xPos,
+        this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'],
+        loopElementModelName,
+        this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'],
+        'microservice',
+        OnapConstant.microServiceType))
+      xPos += (this.boxWidth + this.boxSpace);
+      allElements.push(this.createOneArrow(xPos - this.boxSpace));
     }
 
-    createSvgFromInstance() {
-        const allElements = [];
-        var xPos = 0;
-
-        allElements.push(this.createBeginCircle(xPos,"Start"))
-        xPos+=(this.boxWidth+this.boxSpace);
-
-        allElements.push(this.createOneArrow(xPos-this.boxSpace));
-
-        allElements.push(this.createVesBox(xPos));
-        xPos+=(this.boxWidth+this.boxSpace);
-
-        allElements.push(this.createOneArrow(xPos-this.boxSpace));
-
-        for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) {
-            var loopElementModelName =  this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel'];
-            if (loopElementModelName !== undefined) {
-                loopElementModelName = loopElementModelName['name'];
-            }
-            allElements.push(this.createOneBox(xPos,
-                this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'],
-                loopElementModelName,
-                this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'],
-                'microservice',
-                OnapConstant.microServiceType))
-            xPos+=(this.boxWidth+this.boxSpace);
-            allElements.push(this.createOneArrow(xPos-this.boxSpace));
-        }
-
-        for (var opPolicy in this.state.loopCache.getOperationalPolicies()) {
-            loopElementModelName =  this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel'];
-            if (loopElementModelName !== undefined) {
-                loopElementModelName = loopElementModelName['name'];
-            }
-            allElements.push(this.createOneBox(xPos,
-                this.state.loopCache.getOperationalPolicies()[opPolicy]['name'],
-                loopElementModelName,
-                this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'],
-                'operational',
-                OnapConstant.operationalPolicyType))
-            xPos+=(this.boxWidth+this.boxSpace);
-            allElements.push(this.createOneArrow(xPos-this.boxSpace));
-        }
-
-        allElements.push(this.createEndCircle(xPos, "End"))
-        xPos+=(this.boxWidth+this.boxSpace);
-
-        return allElements;
+    for (var opPolicy in this.state.loopCache.getOperationalPolicies()) {
+      loopElementModelName = this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel'];
+      if (loopElementModelName !== undefined) {
+        loopElementModelName = loopElementModelName['name'];
+      }
+      allElements.push(this.createOneBox(xPos,
+        this.state.loopCache.getOperationalPolicies()[opPolicy]['name'],
+        loopElementModelName,
+        this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'],
+        'operational',
+        OnapConstant.operationalPolicyType))
+      xPos += (this.boxWidth + this.boxSpace);
+      allElements.push(this.createOneArrow(xPos - this.boxSpace));
     }
 
-    renderSvg() {
-        if (this.state.loopCache.getLoopName() === undefined) {
-            return [emptySvg];
-        }
-        if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) {
-            return this.createSvgFromInstance();
-        } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) {
-            return this.createSvgFromTemplate();
-        }
-    }
+    allElements.push(this.createEndCircle(xPos, "End"))
+    xPos += (this.boxWidth + this.boxSpace);
+
+    return allElements;
+  }
 
-    render() {
-        var allTheElements = this.renderSvg();
-        var svgWidth = this.boxWidth*allTheElements.length;
-        var svgHeight = this.boxHeight+50;
-        return (
-
-            <DivStyled onClick={this.handleSvgClick} >
-                <svg height={svgHeight} width={svgWidth}  viewBox="0,0,{svgWidth},{svgHeight}" preserveAspectRatio="none">
-                                                                       <svg x="-50" y="25">
-                    {allTheElements}
-                                                                       </svg>
-                </svg>
-            </DivStyled>
-        );
+  renderSvg() {
+    if (this.state.loopCache.getLoopName() === undefined) {
+      return [emptySvg];
     }
+    if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) {
+      return this.createSvgFromInstance();
+    } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) {
+      return this.createSvgFromTemplate();
+    }
+  }
+
+  render() {
+    var allTheElements = this.renderSvg();
+    var svgWidth = this.boxWidth * allTheElements.length;
+    var svgHeight = this.boxHeight + 50;
+    return (
+
+      <DivStyled onClick={ this.handleSvgClick }>
+        <svg key="main" height={ svgHeight } width={ svgWidth } viewBox="0,0,{svgWidth},{svgHeight}" preserveAspectRatio="none">
+          <svg key="content" x="-50" y="25">
+            { allTheElements }
+          </svg>
+        </svg>
+      </DivStyled>
+    );
+  }
 }
 
 export default withRouter(SvgGenerator);
index f553583..30ce019 100644 (file)
@@ -22,7 +22,7 @@
  */
 
 import { configure } from 'enzyme';
-import Adapter from 'enzyme-adapter-react-17-updated';
+import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
 
 configure({ adapter: new Adapter() });
-global.fetch = require('jest-fetch-mock');
\ No newline at end of file
+global.fetch = require('jest-fetch-mock');