Add new dialog for policy

Add a new dialog component for tosca based policy, config/op should use that dialog now.

Issue-ID: CLAMP-653

Change-Id: I57523bc2d4bfbf5ca5a3acf5c59823df06fd4cd9
Signed-off-by: sebdet <sebastien.determe@intl.att.com>
diff --git a/ui-react/src/LoopUI.js b/ui-react/src/LoopUI.js
index 7f07f34..9510670 100644
--- a/ui-react/src/LoopUI.js
+++ b/ui-react/src/LoopUI.js
@@ -255,7 +255,8 @@
 				<Route path="/ViewLoopTemplatesModal" render={(routeProps) => (<ViewLoopTemplatesModal {...routeProps} />)} />
 				<Route path="/operationalPolicyModal"
 					render={(routeProps) => (<OperationalPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} />
-				<Route path="/configurationPolicyModal/:componentName" render={(routeProps) => (<ConfigurationPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} />
+				<Route path="/policyModal/:policyInstanceType/:policyName" render={(routeProps) => (<PolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} />
+				<Route path="/configurationPolicyModal/:policyName" render={(routeProps) => (<ConfigurationPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} />
 				<Route path="/openLoop" render={(routeProps) => (<OpenLoopModal {...routeProps} loadLoopFunction={this.loadLoop} />)} />
 				<Route path="/loopProperties" render={(routeProps) => (<LoopPropertiesModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} />
 				<Route path="/modifyLoop" render={(routeProps) => (<ModifyLoopModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} />
diff --git a/ui-react/src/__snapshots__/LoopUI.test.js.snap b/ui-react/src/__snapshots__/LoopUI.test.js.snap
index 98f802d..3d0137c 100644
--- a/ui-react/src/__snapshots__/LoopUI.test.js.snap
+++ b/ui-react/src/__snapshots__/LoopUI.test.js.snap
@@ -21,7 +21,11 @@
     render={[Function]}
   />
   <Route
-    path="/configurationPolicyModal/:componentName"
+    path="/policyModal/:policyInstanceType/:policyName"
+    render={[Function]}
+  />
+  <Route
+    path="/configurationPolicyModal/:policyName"
     render={[Function]}
   />
   <Route
diff --git a/ui-react/src/__snapshots__/OnapClamp.test.js.snap b/ui-react/src/__snapshots__/OnapClamp.test.js.snap
index 35951ca..1c456e1 100644
--- a/ui-react/src/__snapshots__/OnapClamp.test.js.snap
+++ b/ui-react/src/__snapshots__/OnapClamp.test.js.snap
@@ -46,7 +46,11 @@
       render={[Function]}
     />
     <Route
-      path="/configurationPolicyModal/:componentName"
+      path="/policyModal/:policyInstanceType/:policyName"
+      render={[Function]}
+    />
+    <Route
+      path="/configurationPolicyModal/:policyName"
       render={[Function]}
     />
     <Route
diff --git a/ui-react/src/api/LoopCache.js b/ui-react/src/api/LoopCache.js
index c73ed62..b177230 100644
--- a/ui-react/src/api/LoopCache.js
+++ b/ui-react/src/api/LoopCache.js
@@ -78,6 +78,33 @@
 		return this.loopJsonCache["microServicePolicies"];
 	}
 
+	getOperationalPolicyForName(name) {
+		var opProperties=this.getOperationalPolicies();
+		for (var policy in opProperties) {
+			if (opProperties[policy]["name"] === name) {
+				return opProperties[policy];
+			}
+		}
+		return null;
+	}
+
+	getOperationalPolicyPropertiesForName(name) {
+		var opConfig = this.getOperationalPolicyForName(name);
+		if (opConfig !== null) {
+			return opConfig["properties"];
+		}
+		return null;
+	}
+
+	getOperationalPolicyJsonRepresentationForName(name) {
+    	var opConfig = this.getOperationalPolicyForName(name);
+    	if (opConfig !== null) {
+    		return opConfig["jsonRepresentation"];
+    	}
+    	return null;
+    }
+
+
 	getMicroServiceForName(name) {
 		var msProperties=this.getMicroServicePolicies();
 		for (var policy in msProperties) {
diff --git a/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.js b/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.js
index b0f601e..3fa0c0c 100644
--- a/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.js
+++ b/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.js
@@ -38,7 +38,7 @@
 		show: true,
 		loopCache: this.props.loopCache,
 		jsonEditor: null,
-		componentName: this.props.match.params.componentName
+		policyName: this.props.match.params.policyName
 	};
 
 	constructor(props, context) {
@@ -59,8 +59,8 @@
 		}
 		else {
 			console.info("NO validation errors found in config policy data");
-			this.state.loopCache.updateMicroServiceProperties(this.state.componentName, editorData[0]);
-			LoopService.setMicroServiceProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getMicroServiceForName(this.state.componentName)).then(resp => {
+			this.state.loopCache.updateMicroServiceProperties(this.state.policyName, editorData[0]);
+			LoopService.setMicroServiceProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getMicroServiceForName(this.state.policyName)).then(resp => {
 				this.setState({ show: false });
 				this.props.history.push('/');
 				this.props.loadLoopFunction(this.state.loopCache.getLoopName());
@@ -78,12 +78,12 @@
 	}
 
 	renderJsonEditor() {
-		console.debug("Rendering ConfigurationPolicyModal ", this.state.componentName);
-		var toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.componentName);
+		console.debug("Rendering ConfigurationPolicyModal ", this.state.policyName);
+		var toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.policyName);
 		if (toscaModel == null) {
 			return;
 		}
-		var editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.componentName);
+		var editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.policyName);
 
 		JSONEditor.defaults.options.theme = 'bootstrap4';
 		//JSONEditor.defaults.options.iconlib = 'bootstrap2';
diff --git a/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.test.js b/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.test.js
index 4fa08e6..4d527b7 100644
--- a/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.test.js
+++ b/ui-react/src/components/dialogs/ConfigurationPolicy/ConfigurationPolicyModal.test.js
@@ -48,7 +48,7 @@
         }]
     });
     const historyMock = { push: jest.fn() };
-    const matchMock = { params:{ componentName: "TCA_h2NMX_v1_0_ResourceInstanceName1_tca" } } 
+    const matchMock = { params:{ policyName: "TCA_h2NMX_v1_0_ResourceInstanceName1_tca" } } 
     const flushPromises = () => new Promise(setImmediate);
 	
     it('Test handleClose', () => {
@@ -73,7 +73,7 @@
 
         expect(handleSave).toHaveBeenCalledTimes(1);
         expect(component.state('show')).toEqual(false);
-        expect(component.state('componentName')).toEqual("TCA_h2NMX_v1_0_ResourceInstanceName1_tca");
+        expect(component.state('policyName')).toEqual("TCA_h2NMX_v1_0_ResourceInstanceName1_tca");
         expect(historyMock.push.mock.calls[0]).toEqual([ '/']);
     });
 });
\ No newline at end of file
diff --git a/ui-react/src/components/dialogs/Policy/PolicyModal.js b/ui-react/src/components/dialogs/Policy/PolicyModal.js
new file mode 100644
index 0000000..75ac2c4
--- /dev/null
+++ b/ui-react/src/components/dialogs/Policy/PolicyModal.js
@@ -0,0 +1,145 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+import React from 'react'
+import Button from 'react-bootstrap/Button';
+import Modal from 'react-bootstrap/Modal';
+import styled from 'styled-components';
+import LoopService from '../../../api/LoopService';
+import JSONEditor from '@json-editor/json-editor';
+
+const ModalStyled = styled(Modal)`
+	background-color: transparent;
+`
+
+export default class PolicyModal extends React.Component {
+
+	state = {
+		show: true,
+		loopCache: this.props.loopCache,
+		jsonEditor: null,
+		policyName: this.props.match.params.policyName,
+		// This is to indicate whether it's an operational or config policy (in terms of loop instance)
+		policyInstanceType: this.props.match.params.policyInstanceType
+	};
+
+	constructor(props, context) {
+		super(props, context);
+		this.handleClose = this.handleClose.bind(this);
+		this.handleSave = this.handleSave.bind(this);
+		this.renderJsonEditor = this.renderJsonEditor.bind(this);
+	}
+
+	handleSave() {
+		var errors = this.state.jsonEditor.validate();
+		var editorData = this.state.jsonEditor.getValue();
+
+		if (errors.length !== 0) {
+			console.error("Errors detected during policy data validation ", errors);
+			this.setState({ show: false });
+			this.props.history.push('/');
+		}
+		else {
+			console.info("NO validation errors found in policy data");
+			if (policyInstanceType === 'MICRO-SERVICE-POLICY') {
+                this.state.loopCache.updateMicroServiceProperties(this.state.policyName, editorData[0]);
+                LoopService.setMicroServiceProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getMicroServiceForName(this.state.policyName)).then(resp => {
+                    this.setState({ show: false });
+                    this.props.history.push('/');
+                    this.props.loadLoopFunction(this.state.loopCache.getLoopName());
+                });
+			} else if (policyInstanceType === 'OPERATIONAL-POLICY') {
+			    this.state.loopCache.updateOperationalPolicyProperties(editorData);
+            	LoopService.setOperationalPolicyProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getOperationalPolicyForName(this.state.policyName)).then(resp => {
+            		this.setState({ show: false });
+            		this.props.history.push('/');
+            		this.props.loadLoopFunction(this.state.loopCache.getLoopName());
+            	});
+			}
+		}
+	}
+
+	handleClose() {
+		this.setState({ show: false });
+		this.props.history.push('/');
+	}
+
+	componentDidMount() {
+		this.renderJsonEditor();
+	}
+
+	renderJsonEditor() {
+		console.debug("Rendering PolicyModal ", this.state.policyName);
+		var toscaModel = {};
+	    var editorData = {};
+	    if (policyInstanceType === 'MICRO-SERVICE-POLICY') {
+            toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.policyName);
+            editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.policyName);
+        } else if (policyInstanceType === 'OPERATIONAL-POLICY') {
+            toscaModel = this.state.loopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName);
+            editorData = this.state.loopCache.getOperationalPolicyPropertiesForName(this.state.policyName);
+        }
+
+		if (toscaModel == null) {
+			return;
+		}
+
+		JSONEditor.defaults.options.theme = 'bootstrap4';
+		//JSONEditor.defaults.options.iconlib = 'bootstrap2';
+		JSONEditor.defaults.options.object_layout = 'grid';
+		JSONEditor.defaults.options.disable_properties = true;
+		JSONEditor.defaults.options.disable_edit_json = false;
+		JSONEditor.defaults.options.disable_array_reorder = true;
+		JSONEditor.defaults.options.disable_array_delete_last_row = true;
+		JSONEditor.defaults.options.disable_array_delete_all_rows = false;
+		JSONEditor.defaults.options.show_errors = 'always';
+
+		this.setState({
+			jsonEditor: new JSONEditor(document.getElementById("editor"),
+				{ schema: toscaModel.schema, startval: editorData })
+		})
+	}
+
+	render() {
+		return (
+			<ModalStyled size="xl" show={this.state.show} onHide={this.handleClose}>
+				<Modal.Header closeButton>
+					<Modal.Title>Configuration policies</Modal.Title>
+				</Modal.Header>
+				<Modal.Body>
+					<div id="editor" />
+
+				</Modal.Body>
+				<Modal.Footer>
+					<Button variant="secondary" onClick={this.handleClose}>
+						Close
+				</Button>
+					<Button variant="primary" onClick={this.handleSave}>
+						Save Changes
+	            </Button>
+				</Modal.Footer>
+			</ModalStyled>
+
+		);
+	}
+}
\ No newline at end of file
diff --git a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js b/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
index a409d2c..5b0dc1e 100644
--- a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
+++ b/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
@@ -4,15 +4,18 @@
 		var componentsMap = new Map([]);
 		if (typeof (loopCache.getMicroServicePolicies()) !== "undefined") {
 			loopCache.getMicroServicePolicies().forEach(ms => {
-				componentsMap.set(ms.name, "/configurationPolicyModal/"+ms.name);
+				componentsMap.set(ms.name, "/policyModal/MICRO-SERVICE-POLICY/"+ms.name);
 			})
 		}
 		if (typeof (loopCache.getOperationalPolicies()) !== "undefined") {
 			loopCache.getOperationalPolicies().forEach(op => {
-				componentsMap.set(op.name, "/operationalPolicyModal");
+				if (op.name.includes("legacy")) {
+					componentsMap.set(op.name,"/operationalPolicyModal");
+				} else {
+					componentsMap.set(op.name, "/policyModal/OPERATIONAL-POLICY/"+op.name);
+				}
 			})
 		}
-		componentsMap.set("OperationalPolicy","/operationalPolicyModal");
 		return componentsMap;
 	}
 }
diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js
index 6351854..17f4b35 100644
--- a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js
+++ b/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js
@@ -99,7 +99,7 @@
         component.simulate('click', event);
         component.update();
 
-        expect(historyMock.push.mock.calls[0]).toEqual([ '/configurationPolicyModal/TCA_h2NMX_v1_0_ResourceInstanceName1_tca']);
+        expect(historyMock.push.mock.calls[0]).toEqual([ '/policyModal/MICRO-SERVICE-POLICY/TCA_h2NMX_v1_0_ResourceInstanceName1_tca']);
 
         //click operational policy
         dummyElement.setAttribute("data-element-id","OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca");
@@ -108,7 +108,7 @@
         component.simulate('click', event2);
         component.update();
 
-        expect(historyMock.push.mock.calls[1]).toEqual([ '/operationalPolicyModal']);
+        expect(historyMock.push.mock.calls[1]).toEqual([ '/policyModal/OPERATIONAL-POLICY/OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca']);
     });
 
     it('Test componentWillReceiveProps method', () => {
@@ -125,9 +125,9 @@
             <LoopSvg.WrappedComponent loopCache={localLoopCache}/>
         );
 
-        expect(component.state('componentModalMapping').size).toEqual(2);
+        expect(component.state('componentModalMapping').size).toEqual(1);
 
         component.setProps({loopCache: loopCache});
-        expect(component.state('componentModalMapping').size).toEqual(3);
+        expect(component.state('componentModalMapping').size).toEqual(2);
     });
 });