Rework Loop properties window

Rework the loop properties window with React libraries.

Issue-ID: CLAMP-447
Change-Id: I5eba63aab39aeefe23d5fdc4732ce0d3d4a1682a
Signed-off-by: xuegao <xg353y@intl.att.com>
diff --git a/ui-react/src/api/LoopService.js b/ui-react/src/api/LoopService.js
index 020a3bf..031ec63 100644
--- a/ui-react/src/api/LoopService.js
+++ b/ui-react/src/api/LoopService.js
@@ -104,4 +104,28 @@
 				return "";
 			});
 	}
+
+	static updateGlobalProperties(loopName, jsonData) {
+		return fetch('/restservices/clds/v2/loop/updateGlobalProperties/' + loopName, {
+			method: 'POST',
+			credentials: 'same-origin',
+			headers: {
+				"Content-Type": "application/json",
+			},
+			body: JSON.stringify(jsonData),
+		})
+			.then(function (response) {
+				console.debug("updateGlobalProperties response received: ", response.status);
+				if (response.ok) {
+					return response.text();
+				} else {
+					console.error("updateGlobalProperties query failed");
+					return "";
+				}
+			})
+			.catch(function (error) {
+				console.error("updateGlobalProperties error received", error);
+				return "";
+			});
+	}
 }
diff --git a/ui-react/src/components/dialogs/LoopProperties.js b/ui-react/src/components/dialogs/LoopProperties.js
new file mode 100644
index 0000000..2cde8d4
--- /dev/null
+++ b/ui-react/src/components/dialogs/LoopProperties.js
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 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 Form from 'react-bootstrap/Form';
+import styled from 'styled-components';
+import LoopService from '../../api/LoopService';
+
+const ModalStyled = styled(Modal)`
+	background-color: transparent;
+`
+
+export default class LoopProperties extends React.Component {
+
+	formProps = {dcaeDeployParameters: {
+			"location_id": "",
+			"service_id": "",
+			"policy_id": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca"
+	}};
+
+	constructor(props, context) {
+		super(props, context);
+
+		this.handleClose = this.handleClose.bind(this);
+		this.handleChange = this.handleChange.bind(this);
+		this.saveProperties =  this.saveProperties.bind(this);
+		this.initialValues = this.initialValues.bind(this);
+		this.state = {
+			show: true,
+			loopName: 'LOOP_h2NMX_v1_0_ResourceInstanceName1_tca',
+			form: this.formProps
+		};
+
+	}
+	initialValues() {
+			const updatedForm = this.state.form;
+			Object.keys(updatedForm).forEach((key) => {
+			if (key === 'dcaeDeployParameters') {
+				updatedForm[key] = JSON.stringify(this.state.form[key]);
+			} else {
+				updatedForm[key] = this.state.form[key];
+			}
+			this.setState({ form: updatedForm });
+		});
+	}
+	handleClose() {
+			this.props.history.push('/');
+	}
+	handleChange(e) {
+			const formUpdated =  this.state.form;
+			formUpdated[e.target.name] = e.target.value;
+			this.setState({ form: formUpdated });
+   };
+	saveProperties(event) {
+		// translate the deploymentParameter into jsonFormat at submit time
+		const updatedForm = this.state.form;
+		Object.keys(updatedForm).forEach((key) => {
+			if (key === 'dcaeDeployParameters') {
+				try {
+				  let value = JSON.parse(updatedForm[key]);
+					updatedForm[key] = value;
+					// save Properties
+					this.setState( {form: updatedForm} );
+					LoopService.updateGlobalProperties(this.state.loopName, this.state.form);
+					this.props.history.push('/');
+				} catch (error) {
+				  alert("Deployment Parameters is not in good Json format. Please correct it.");
+				}
+			}
+		});
+	}
+	render() {
+		return (
+			<ModalStyled size="lg"  show={this.state.show} onHide={this.handleClose} onEntered={this.initialValues}>
+				<Modal.Header closeButton>
+					<Modal.Title>Model Properties</Modal.Title>
+				</Modal.Header>
+				<Modal.Body>
+					<Form.Group controlId="exampleForm.ControlTextarea1">
+					<Form.Label>Deploy Parameters</Form.Label>
+					<Form.Control as="textarea" rows="3" name="dcaeDeployParameters" onChange={this.handleChange} defaultValue={this.state.form["dcaeDeployParameters"]}/>
+					</Form.Group>
+				</Modal.Body>
+				<Modal.Footer>
+					<Button variant="secondary" type="null" onClick={this.handleClose}>Cacel</Button>
+					<Button variant="primary" type="submit" onClick={this.saveProperties}>Save</Button>
+				</Modal.Footer>
+			</ModalStyled>
+		);
+	}
+}
diff --git a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js b/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
index b737f3e..a409d2c 100644
--- a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
+++ b/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
@@ -3,16 +3,16 @@
 	static buildMapOfComponents(loopCache) {
 		var componentsMap = new Map([]);
 		if (typeof (loopCache.getMicroServicePolicies()) !== "undefined") {
-			loopCache.getMicroServicePolicies().map(ms => {
+			loopCache.getMicroServicePolicies().forEach(ms => {
 				componentsMap.set(ms.name, "/configurationPolicyModal/"+ms.name);
 			})
 		}
 		if (typeof (loopCache.getOperationalPolicies()) !== "undefined") {
-			loopCache.getOperationalPolicies().map(op => {
+			loopCache.getOperationalPolicies().forEach(op => {
 				componentsMap.set(op.name, "/operationalPolicyModal");
 			})
 		}
 		componentsMap.set("OperationalPolicy","/operationalPolicyModal");
 		return componentsMap;
 	}
-}
\ No newline at end of file
+}
diff --git a/ui-react/src/components/menu/MenuBar.js b/ui-react/src/components/menu/MenuBar.js
index 64aa6bc..491cc67 100644
--- a/ui-react/src/components/menu/MenuBar.js
+++ b/ui-react/src/components/menu/MenuBar.js
@@ -35,13 +35,12 @@
 `;
 
 export default class MenuBar extends React.Component {
-
 	render () {
 	   return (
 		  <Navbar.Collapse id="basic-navbar-nav" className="justify-content-center">
 		      <NavDropdown title="Closed Loop" id="basic-nav-dropdown">
 		        <StyledNavDropdownItem href="/openLoop">Open CL</StyledNavDropdownItem>
-		        <StyledNavDropdownItem href="#action/3.2">Properties CL</StyledNavDropdownItem>
+		        <StyledNavDropdownItem href="/loopProperties">Properties CL</StyledNavDropdownItem>
 		        <StyledNavDropdownItem href="/closeLoop">Close Model</StyledNavDropdownItem>
 		      </NavDropdown>
 					<NavDropdown title="Manage" id="basic-nav-dropdown">