Add remove op policy option

Update the UI and backend code to be able to remove op policy for loop
instances.

Issue-ID: CLAMP-648
Change-Id: Ib3eab4977fe4f1b85e11f2373263197009bbc3e1
Signed-off-by: xuegao <xg353y@intl.att.com>
diff --git a/ui-react/src/components/dialogs/Loop/ModifyLoopModal.js b/ui-react/src/components/dialogs/Loop/ModifyLoopModal.js
index 4cd21fd..7c16b78 100644
--- a/ui-react/src/components/dialogs/Loop/ModifyLoopModal.js
+++ b/ui-react/src/components/dialogs/Loop/ModifyLoopModal.js
@@ -35,6 +35,8 @@
 import LastPage from '@material-ui/icons/LastPage';
 import Search from '@material-ui/icons/Search';
 import LoopService from '../../../api/LoopService';
+import Tabs from 'react-bootstrap/Tabs';
+import Tab from 'react-bootstrap/Tab';
 
 
 const ModalStyled = styled(Modal)`
@@ -61,6 +63,8 @@
 		content: 'Please select Tosca model to view the details',
 		selectedRowData: {},
 		toscaPolicyModelsData: [],
+		selectedPolicyModelsData: [],
+		key: 'add',
 		toscaColumns: [
 			{ title: "#", field: "index", render: rowData => rowData.tableData.id + 1,
 				cellStyle: cellStyle,
@@ -105,11 +109,12 @@
 	constructor(props, context) {
 		super(props, context);
 		this.handleClose = this.handleClose.bind(this);
-		this.getPolicyToscaModels = this.getToscaPolicyModels.bind(this);
+		this.initializeToscaPolicyModelsInfo = this.initializeToscaPolicyModelsInfo.bind(this);
 		this.handleYamlContent = this.handleYamlContent.bind(this);
 		this.getToscaPolicyModelYaml = this.getToscaPolicyModelYaml.bind(this);
 		this.handleAdd = this.handleAdd.bind(this);
-		this.getToscaPolicyModels();
+		this.handleRemove = this.handleRemove.bind(this);
+		this.initializeToscaPolicyModelsInfo();
 	}
 
 	componentWillReceiveProps(newProps) {
@@ -119,9 +124,16 @@
 		});
 	}
 
-	getToscaPolicyModels() {
-	    PolicyToscaService.getToscaPolicyModels().then(allToscaModels => {
-			this.setState({ toscaPolicyModelsData: allToscaModels});
+	initializeToscaPolicyModelsInfo() {
+		var operationalPolicies = this.state.loopCache.getOperationalPolicies();
+		var selectedPolicyModels = [];
+		for (var policy in operationalPolicies) {
+			selectedPolicyModels.push(operationalPolicies[policy]["policyModel"]);
+		}
+
+		PolicyToscaService.getToscaPolicyModels().then(allToscaModels => {
+			this.setState({ toscaPolicyModelsData: allToscaModels,
+							selectedPolicyModelsData: selectedPolicyModels});
 		});
 	}
 
@@ -149,38 +161,70 @@
 	}
 
 	handleAdd() {
-        LoopService.addOperationalPolicyType(this.state.loopCache.getLoopName(),this.state.selectedRowData.policyModelType,this.state.selectedRowData.version);
-        this.handleClose();
-        this.props.loadLoopFunction(this.state.loopCache.getLoopName());
+		LoopService.addOperationalPolicyType(this.state.loopCache.getLoopName(),this.state.selectedRowData.policyModelType,this.state.selectedRowData.version);
+		this.handleClose();
+		this.props.loadLoopFunction(this.state.loopCache.getLoopName());
+	}
+
+	handleRemove() {
+		LoopService.removeOperationalPolicyType(this.state.loopCache.getLoopName(),this.state.selectedRowData.policyModelType,this.state.selectedRowData.version);
+		this.handleClose();
+		this.props.loadLoopFunction(this.state.loopCache.getLoopName());
 	}
 
 	render() {
 		return (
 			<ModalStyled size="xl" show={this.state.show} onHide={this.handleClose}>
 				<Modal.Header closeButton>
+					<Modal.Title>Modify Loop Operational Policies</Modal.Title>
 				</Modal.Header>
-				<Modal.Body>
-					<MaterialTable
-					title={"View Tosca Policy Models"}
-					data={this.state.toscaPolicyModelsData}
-					columns={this.state.toscaColumns}
-					icons={this.state.tableIcons}
-					onRowClick={(event, rowData) => {this.getToscaPolicyModelYaml(rowData.policyModelType, rowData.version);this.setState({selectedRowData: rowData})}}
-					options={{
-						headerStyle: rowHeaderStyle,
-						rowStyle: rowData => ({
-							backgroundColor: (this.state.selectedRowData !== {} && this.state.selectedRowData.id === rowData.tableData.id) ? '#EEE' : '#FFF'
-						})
-					}}
-					/>
-					<div>
-						<TextModal value={this.state.content} onChange={this.handleYamlContent}/>
-					</div>
-				</Modal.Body>
+				<Tabs id="controlled-tab-example" activeKey={this.state.key} onSelect={key => this.setState({ key, selectedRowData: {} })}>
+					<Tab eventKey="add" title="Add Operational Policies">
+						<Modal.Body>
+							<MaterialTable
+							title={"View Tosca Policy Models"}
+							data={this.state.toscaPolicyModelsData}
+							columns={this.state.toscaColumns}
+							icons={this.state.tableIcons}
+							onRowClick={(event, rowData) => {this.getToscaPolicyModelYaml(rowData.policyModelType, rowData.version);this.setState({selectedRowData: rowData})}}
+							options={{
+								headerStyle: rowHeaderStyle,
+								rowStyle: rowData => ({
+									backgroundColor: (this.state.selectedRowData !== {} && this.state.selectedRowData.tableData !== undefined
+									&& this.state.selectedRowData.tableData.id === rowData.tableData.id) ? '#EEE' : '#FFF'
+								})
+							}}
+							/>
+							<div>
+								<TextModal value={this.state.content} onChange={this.handleYamlContent}/>
+							</div>
+						</Modal.Body>
+					</Tab>
+					<Tab eventKey="remove" title="Remove Operational Policies">
+						<Modal.Body>
+							<MaterialTable
+							title={"Already added Tosca Policy Models"}
+							data={this.state.selectedPolicyModelsData}
+							columns={this.state.toscaColumns}
+							icons={this.state.tableIcons}
+							onRowClick={(event, rowData) => {this.setState({selectedRowData: rowData})}}
+							options={{
+								headerStyle: rowHeaderStyle,
+								rowStyle: rowData => ({
+									backgroundColor: (this.state.selectedRowData !== {} && this.state.selectedRowData.tableData !== undefined
+									&& this.state.selectedRowData.tableData.id === rowData.tableData.id) ? '#EEE' : '#FFF'
+								})
+							}}
+							/>
+						</Modal.Body>
+					</Tab>
+				</Tabs>
 				<Modal.Footer>
 					<Button variant="secondary" type="null" onClick={this.handleClose}>Cancel</Button>
-					<Button variant="primary"  type="submit" onClick={this.handleAdd}>Add</Button>
+					<Button variant="primary" disabled={(this.state.key === "remove")} type="submit" onClick={this.handleAdd}>Add</Button>
+					<Button variant="primary" disabled={(this.state.key === "add")} type="submit" onClick={this.handleRemove}>Remove</Button>
 				</Modal.Footer>
+
 			</ModalStyled>
 		);
 	}
diff --git a/ui-react/src/components/dialogs/Loop/ModifyLoopModal.test.js b/ui-react/src/components/dialogs/Loop/ModifyLoopModal.test.js
new file mode 100644
index 0000000..055ad0e
--- /dev/null
+++ b/ui-react/src/components/dialogs/Loop/ModifyLoopModal.test.js
@@ -0,0 +1,109 @@
+/*-
+ * ============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 { mount } from 'enzyme';
+import ModifyLoopModal from './ModifyLoopModal';
+import LoopCache from '../../../api/LoopCache';
+import LoopService from '../../../api/LoopService';
+import PolicyToscaService from '../../../api/PolicyToscaService';
+
+describe('Verify ModifyLoopModal', () => {
+    beforeEach(() => {
+        PolicyToscaService.getToscaPolicyModels = jest.fn().mockImplementation(() => {
+            return Promise.resolve([{
+                "policyModelType":"test",
+                "policyAcronym":"test",
+                "version":"1.0.0",
+                "updatedBy":"",
+                "updatedDate":""
+            }]);
+        });
+        PolicyToscaService.getToscaPolicyModelYaml = jest.fn().mockImplementation(() => {
+            return Promise.resolve("OK");
+        });
+    })
+
+    const loopCache = new LoopCache({
+            "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca",
+            "microServicePolicies": [{
+                "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca",
+                "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app",
+                "properties": {"domain": "measurementsForVfScaling"},
+                "shared": false,
+                "jsonRepresentation": {"schema": {}}
+            }],
+            "globalPropertiesJson": {
+                "dcaeDeployParameters": {
+                    "testMs": {
+                    "location_id": "",
+                    "policy_id": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca"
+                }
+            }
+        }
+    });
+    const historyMock = { push: jest.fn() };
+    const flushPromises = () => new Promise(setImmediate);
+
+    it('Test handleClose', () => {
+        const handleClose = jest.spyOn(ModifyLoopModal.prototype,'handleClose');
+        const component = mount(<ModifyLoopModal history={historyMock} loopCache={loopCache}/>)
+
+        component.find('[variant="secondary"]').get(0).props.onClick();
+
+        expect(handleClose).toHaveBeenCalledTimes(1);
+        expect(component.state('show')).toEqual(false);
+        expect(historyMock.push.mock.calls[0]).toEqual([ '/']);
+    });
+
+    it('Test getToscaPolicyModelYaml',  async () => {
+        const flushPromises = () => new Promise(setImmediate);
+        const component = mount(<ModifyLoopModal history={historyMock} loopCache={loopCache}/>)
+        component.setState({ 
+                "selectedRowData": {"tableData":{"id":0}}
+        });
+        const instance = component.instance();
+
+        instance.getToscaPolicyModelYaml("","1.0.0");
+        expect(component.state('content')).toEqual("Please select Tosca model to view the details");
+
+        instance.getToscaPolicyModelYaml("test","1.0.0");
+        await flushPromises();
+        expect(component.state('content')).toEqual("OK");
+
+        PolicyToscaService.getToscaPolicyModelYaml = jest.fn().mockImplementation(() => {
+            return Promise.resolve("");
+        });
+        instance.getToscaPolicyModelYaml("test","1.0.0");
+        await flushPromises();
+        expect(component.state('content')).toEqual("No Tosca model Yaml available");
+    });
+
+    it('Test handleYamlContent',  async () => {
+        const component = mount(<ModifyLoopModal loopCache={loopCache}/>)
+        const instance = component.instance();
+
+        const event = {"target":{"value":"testValue"}}
+        instance.handleYamlContent(event);
+        expect(component.state('content')).toEqual("testValue");
+    });
+});
\ No newline at end of file