aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml8
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java96
-rw-r--r--runtime/src/test/resources/http-cache/third_party_proxy.py2
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js248
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js544
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js202
-rw-r--r--runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js388
7 files changed, 799 insertions, 689 deletions
diff --git a/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml b/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml
index ac83ffd7a..200eac780 100644
--- a/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml
+++ b/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml
@@ -98,10 +98,16 @@
<setHeader name="Content-Type">
<constant>application/json</constant>
</setHeader>
+ <setProperty name="name">
+ <simple>${header.name}</simple>
+ </setProperty>
+ <setProperty name="version">
+ <simple>${header.version}</simple>
+ </setProperty>
<log loggingLevel="INFO"
message="Endpoint to get Tosca Instantiation: {{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/instantiation"></log>
<toD
- uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/instantiation?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.controlloop.runtime.userName}}&amp;authPassword={{clamp.config.controlloop.runtime.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/instantiation?name=${exchangeProperty[name]}&amp;version=${exchangeProperty[version]}&amp;bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.controlloop.runtime.userName}}&amp;authPassword={{clamp.config.controlloop.runtime.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
<convertBodyTo type="java.lang.String"/>
<doFinally>
<to uri="direct:reset-raise-http-exception-flag"/>
diff --git a/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java b/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java
new file mode 100644
index 000000000..ae80d0498
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java
@@ -0,0 +1,96 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.runtime;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class RuntimeInstantiationResponseItTestCase {
+ @Autowired
+ CamelContext camelContext;
+
+ private static final String DIRECT_GET_TOSCA_INSTANTIATION = "direct:get-tosca-instantiation";
+
+ private static final String SERVICE_TEMPLATE_NAME = "name";
+
+ private static final String SERVICE_TEMPLATE_VERSION = "version";
+
+ private static final String RAISE_HTTP_EXCEPTION_FLAG = "raiseHttpExceptionFlag";
+
+ private static final String SAMPLE_CONTROL_LOOP_LIST = "{\"controlLoopList\": [{\"name\": \"PMSHInstance0\","
+ + "\"version\": \"1.0.1\",\"definition\": {},\"state\": \"UNINITIALISED\",\"orderedState\": \"UNINITIALISED\","
+ + "\"description\": \"PMSH control loop instance 0\",\"elements\": {}}]}";
+
+ @Test
+ public void testToscaServiceTemplateStatus() {
+ ProducerTemplate prodTemplate = camelContext.createProducerTemplate();
+
+ Exchange exchangeResponse =
+ prodTemplate.send(DIRECT_GET_TOSCA_INSTANTIATION, ExchangeBuilder.anExchange(camelContext)
+ .withProperty(SERVICE_TEMPLATE_NAME, "ToscaServiceTemplate")
+ .withProperty(SERVICE_TEMPLATE_VERSION, "1.0.0")
+ .withProperty(RAISE_HTTP_EXCEPTION_FLAG, "true")
+ .build());
+
+ assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()).isTrue();
+ }
+
+ @Test
+ public void testToscaInstantiationGetResponseBody() {
+ ProducerTemplate prodTemplate = camelContext.createProducerTemplate();
+
+ Exchange exchangeResponse =
+ prodTemplate.send(DIRECT_GET_TOSCA_INSTANTIATION, ExchangeBuilder.anExchange(camelContext)
+ .withProperty(SERVICE_TEMPLATE_NAME, "ToscaServiceTemplate")
+ .withProperty(SERVICE_TEMPLATE_VERSION, "1.0.0")
+ .withProperty(RAISE_HTTP_EXCEPTION_FLAG, "true")
+ .build());
+
+ assertThat(exchangeResponse.getIn().getBody()).hasToString(SAMPLE_CONTROL_LOOP_LIST);
+ }
+
+ @Test
+ public void testToscaInstantiationStatus() {
+ ProducerTemplate prodTemplate = camelContext.createProducerTemplate();
+
+ Exchange exchangeResponse =
+ prodTemplate.send(DIRECT_GET_TOSCA_INSTANTIATION, ExchangeBuilder.anExchange(camelContext)
+ .withBody(SAMPLE_CONTROL_LOOP_LIST)
+ .withProperty(RAISE_HTTP_EXCEPTION_FLAG, "true")
+ .build());
+
+ assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()).isTrue();
+ }
+}
diff --git a/runtime/src/test/resources/http-cache/third_party_proxy.py b/runtime/src/test/resources/http-cache/third_party_proxy.py
index d6628535d..5c80cdda4 100644
--- a/runtime/src/test/resources/http-cache/third_party_proxy.py
+++ b/runtime/src/test/resources/http-cache/third_party_proxy.py
@@ -328,7 +328,7 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
return True
elif (self.path.startswith("/onap/controlloop/v2/instantiation")) and http_type == "GET":
print("self.path start with /instantiation Retrieving Instantiation, generating response json...")
- jsonGenerated = "{\"errorDetails\": null,\"affectedControlLoopDefinitions\": [{ \"name\": \"ToscaServiceTemplateSimple\", \"version\": \"1.0.0\" }]}"
+ jsonGenerated = "{\"controlLoopList\": [{\"name\": \"PMSHInstance0\",\"version\": \"1.0.1\",\"definition\": {},\"state\": \"UNINITIALISED\",\"orderedState\": \"UNINITIALISED\",\"description\": \"PMSH control loop instance 0\",\"elements\": {}}]}";
self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content)
return True
else:
diff --git a/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js b/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js
index 57d61600a..de29947fe 100644
--- a/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js
+++ b/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js
@@ -32,145 +32,147 @@ import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
const DivWhiteSpaceStyled = styled.div`
- white-space: pre;
+ white-space: pre;
`
const PanelDiv = styled.div`
- text-align: justify;
- font-size: ${props => props.theme.policyEditorFontSize};
- background-color: ${props => props.theme.loopViewerBackgroundColor};
+ 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),
- };
+ 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);
- }
+ 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 });
+ handleClose() {
+ this.setState({ show: false });
- }
+ }
- disableAlert() {
- this.setState ({ showSuccessAlert: false, showFailAlert: 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;
- }
+ 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'
- });
- }
+ 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;
+ 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);
+ });
+ });
}
-
- handleCheckboxChange(event) {
- const checkboxesArray = this.state.checkboxesState;
- checkboxesArray.find(element => element.name === event.target.name).value = event.target.checked;
- this.setState({checkboxesState:checkboxesArray});
+ // 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;
+ }
- renderPdpDeploymentCheckboxes() {
- return this.state.checkboxesState.map(item => {
- return <FormControlLabel control={<Checkbox checked={item.value} onChange={this.handleCheckboxChange}
- name={item.name} />} label={item.name} />;
- });
- }
+ handleCheckboxChange(event) {
+ const checkboxesArray = this.state.checkboxesState;
+ checkboxesArray.find(element => element.name === event.target.name).value = event.target.checked;
+ this.setState({ checkboxesState: checkboxesArray });
+ }
- 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>
- );
- }
- } \ No newline at end of file
+ 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>
+ );
+ }
+}
diff --git a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js
index 4a883fffa..0c7637c44 100644
--- a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js
+++ b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js
@@ -31,315 +31,319 @@ import Modal from 'react-bootstrap/Modal';
import styled from 'styled-components';
import LoopService from '../../../api/LoopService';
import LoopCache from '../../../api/LoopCache';
-import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor.js';
+import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor.js';
import "@fortawesome/fontawesome-free/css/all.css"
import Alert from 'react-bootstrap/Alert';
import OnapConstant from '../../../utils/OnapConstants';
import OnapUtils from '../../../utils/OnapUtils';
const ModalStyled = styled(Modal)`
- background-color: transparent;
+ background-color: transparent;
`
const DivWhiteSpaceStyled = styled.div`
- white-space: pre;
+ white-space: pre;
`
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,
- pdpGroup: null,
- pdpGroupList: [],
- pdpSubgroupList: [],
- chosenPdpGroup: '',
- chosenPdpSubgroup: '',
- showSucAlert: false,
- showFailAlert: false
- };
-
- constructor(props, context) {
- super(props, context);
- this.handleClose = this.handleClose.bind(this);
- this.handleSave = this.handleSave.bind(this);
- this.renderJsonEditor = this.renderJsonEditor.bind(this);
- this.handlePdpGroupChange = this.handlePdpGroupChange.bind(this);
- this.handlePdpSubgroupChange = this.handlePdpSubgroupChange.bind(this);
- this.createJsonEditor = this.createJsonEditor.bind(this);
- this.handleRefresh = this.handleRefresh.bind(this);
- this.disableAlert = this.disableAlert.bind(this);
- this.renderPdpGroupDropDown = this.renderPdpGroupDropDown.bind(this);
- this.renderOpenLoopMessage = this.renderOpenLoopMessage.bind(this);
- this.renderModalTitle = this.renderModalTitle.bind(this);
- this.readOnly = props.readOnly !== undefined ? props.readOnly : false;
- }
+ 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,
+ pdpGroup: null,
+ pdpGroupList: [],
+ pdpSubgroupList: [],
+ chosenPdpGroup: '',
+ chosenPdpSubgroup: '',
+ showSucAlert: false,
+ showFailAlert: false
+ };
- handleSave() {
- var editorData = this.state.jsonEditor.getValue();
- var errors = this.state.jsonEditor.validate();
- errors = errors.concat(this.customValidation(editorData, this.state.loopCache.getTemplateName()));
+ constructor(props, context) {
+ super(props, context);
+ this.handleClose = this.handleClose.bind(this);
+ this.handleSave = this.handleSave.bind(this);
+ this.renderJsonEditor = this.renderJsonEditor.bind(this);
+ this.handlePdpGroupChange = this.handlePdpGroupChange.bind(this);
+ this.handlePdpSubgroupChange = this.handlePdpSubgroupChange.bind(this);
+ this.createJsonEditor = this.createJsonEditor.bind(this);
+ this.handleRefresh = this.handleRefresh.bind(this);
+ this.disableAlert = this.disableAlert.bind(this);
+ this.renderPdpGroupDropDown = this.renderPdpGroupDropDown.bind(this);
+ this.renderOpenLoopMessage = this.renderOpenLoopMessage.bind(this);
+ this.renderModalTitle = this.renderModalTitle.bind(this);
+ this.readOnly = props.readOnly !== undefined ? props.readOnly : false;
+ }
- if (errors.length !== 0) {
- console.error("Errors detected during policy data validation ", errors);
- this.setState({
- showFailAlert: true,
- showMessage: 'Errors detected during policy data validation:\n' + OnapUtils.jsonEditorErrorFormatter(errors)
- });
- return;
- }
- else {
- console.info("NO validation errors found in policy data");
- if (this.state.policyInstanceType === OnapConstant.microServiceType) {
- this.state.loopCache.updateMicroServiceProperties(this.state.policyName, editorData);
- this.state.loopCache.updateMicroServicePdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup);
- 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 (this.state.policyInstanceType === OnapConstant.operationalPolicyType) {
- this.state.loopCache.updateOperationalPolicyProperties(this.state.policyName, editorData);
- this.state.loopCache.updateOperationalPolicyPdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup);
- LoopService.setOperationalPolicyProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getOperationalPolicies()).then(resp => {
- this.setState({ show: false });
- this.props.history.push('/');
- this.props.loadLoopFunction(this.state.loopCache.getLoopName());
- });
- }
- }
- }
+ handleSave() {
+ var editorData = this.state.jsonEditor.getValue();
+ var errors = this.state.jsonEditor.validate();
+ errors = errors.concat(this.customValidation(editorData, this.state.loopCache.getTemplateName()));
- customValidation(editorData, templateName) {
- // method for sub-classes to override with customized validation
- return [];
+ if (errors.length !== 0) {
+ console.error("Errors detected during policy data validation ", errors);
+ this.setState({
+ showFailAlert: true,
+ showMessage: 'Errors detected during policy data validation:\n' + OnapUtils.jsonEditorErrorFormatter(errors)
+ });
+ return;
+ } else {
+ console.info("NO validation errors found in policy data");
+ if (this.state.policyInstanceType === OnapConstant.microServiceType) {
+ this.state.loopCache.updateMicroServiceProperties(this.state.policyName, editorData);
+ this.state.loopCache.updateMicroServicePdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup);
+ 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 (this.state.policyInstanceType === OnapConstant.operationalPolicyType) {
+ this.state.loopCache.updateOperationalPolicyProperties(this.state.policyName, editorData);
+ this.state.loopCache.updateOperationalPolicyPdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup);
+ LoopService.setOperationalPolicyProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getOperationalPolicies()).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('/');
- }
+ customValidation(editorData, templateName) {
+ // method for sub-classes to override with customized validation
+ return [];
+ }
- componentDidMount() {
- this.renderJsonEditor();
- }
+ handleClose() {
+ this.setState({ show: false });
+ this.props.history.push('/');
+ }
- componentDidUpdate() {
- if (this.state.showSucAlert === true || this.state.showFailAlert === true) {
- let modalElement = document.getElementById("policyModal")
- if (modalElement) {
- modalElement.scrollTo(0, 0);
- }
- }
- }
+ componentDidMount() {
+ this.renderJsonEditor();
+ }
- createJsonEditor(toscaModel, editorData) {
- return new JSONEditor(document.getElementById("editor"),
- { schema: toscaModel,
- startval: editorData,
- theme: 'bootstrap4',
- iconlib: 'fontawesome5',
- object_layout: 'grid',
- disable_properties: false,
- disable_edit_json: false,
- disable_array_reorder: true,
- disable_array_delete_last_row: true,
- disable_array_delete_all_rows: false,
- array_controls_top: true,
- keep_oneof_values: false,
- collapsed:true,
- show_errors: 'always',
- display_required_only: false,
- show_opt_in: false,
- prompt_before_delete: true,
- required_by_default: false
- })
+ componentDidUpdate() {
+ if (this.state.showSucAlert === true || this.state.showFailAlert === true) {
+ let modalElement = document.getElementById("policyModal")
+ if (modalElement) {
+ modalElement.scrollTo(0, 0);
+ }
}
+ }
- renderJsonEditor() {
- console.debug("Rendering PolicyModal ", this.state.policyName);
- var toscaModel = {};
- var editorData = {};
- var pdpGroupValues = {};
- var chosenPdpGroupValue, chosenPdpSubgroupValue;
- if (this.state.policyInstanceType === OnapConstant.microServiceType) {
- toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.policyName);
- editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.policyName);
- pdpGroupValues = this.state.loopCache.getMicroServiceSupportedPdpGroup(this.state.policyName);
- chosenPdpGroupValue = this.state.loopCache.getMicroServicePdpGroup(this.state.policyName);
- chosenPdpSubgroupValue = this.state.loopCache.getMicroServicePdpSubgroup(this.state.policyName);
- } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) {
- toscaModel = this.state.loopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName);
- editorData = this.state.loopCache.getOperationalPolicyPropertiesForName(this.state.policyName);
- pdpGroupValues = this.state.loopCache.getOperationalPolicySupportedPdpGroup(this.state.policyName);
- chosenPdpGroupValue = this.state.loopCache.getOperationalPolicyPdpGroup(this.state.policyName);
- chosenPdpSubgroupValue = this.state.loopCache.getOperationalPolicyPdpSubgroup(this.state.policyName);
- }
-
- if (toscaModel == null) {
- return;
- }
+ createJsonEditor(toscaModel, editorData) {
+ return new JSONEditor(document.getElementById("editor"),
+ {
+ schema: toscaModel,
+ startval: editorData,
+ theme: 'bootstrap4',
+ iconlib: 'fontawesome5',
+ object_layout: 'grid',
+ disable_properties: false,
+ disable_edit_json: false,
+ disable_array_reorder: true,
+ disable_array_delete_last_row: true,
+ disable_array_delete_all_rows: false,
+ array_controls_top: true,
+ keep_oneof_values: false,
+ collapsed: true,
+ show_errors: 'always',
+ display_required_only: false,
+ show_opt_in: false,
+ prompt_before_delete: true,
+ required_by_default: false
+ })
+ }
- var pdpSubgroupValues = [];
- if (typeof(chosenPdpGroupValue) !== "undefined") {
- var selectedPdpGroup = pdpGroupValues.filter(entry => (Object.keys(entry)[0] === chosenPdpGroupValue));
- pdpSubgroupValues = selectedPdpGroup[0][chosenPdpGroupValue].map((pdpSubgroup) => { return { label: pdpSubgroup, value: pdpSubgroup } });
- }
- this.setState({
- jsonEditor: this.createJsonEditor(toscaModel,editorData),
- pdpGroup: pdpGroupValues,
- pdpGroupList: pdpGroupValues.map(entry => {
- return { label: Object.keys(entry)[0], value: Object.keys(entry)[0] };
- }),
- pdpSubgroupList: pdpSubgroupValues,
- chosenPdpGroup: chosenPdpGroupValue,
- chosenPdpSubgroup: chosenPdpSubgroupValue
- })
+ renderJsonEditor() {
+ console.debug("Rendering PolicyModal ", this.state.policyName);
+ var toscaModel = {};
+ var editorData = {};
+ var pdpGroupValues = {};
+ var chosenPdpGroupValue, chosenPdpSubgroupValue;
+ if (this.state.policyInstanceType === OnapConstant.microServiceType) {
+ toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.policyName);
+ editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.policyName);
+ pdpGroupValues = this.state.loopCache.getMicroServiceSupportedPdpGroup(this.state.policyName);
+ chosenPdpGroupValue = this.state.loopCache.getMicroServicePdpGroup(this.state.policyName);
+ chosenPdpSubgroupValue = this.state.loopCache.getMicroServicePdpSubgroup(this.state.policyName);
+ } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) {
+ toscaModel = this.state.loopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName);
+ editorData = this.state.loopCache.getOperationalPolicyPropertiesForName(this.state.policyName);
+ pdpGroupValues = this.state.loopCache.getOperationalPolicySupportedPdpGroup(this.state.policyName);
+ chosenPdpGroupValue = this.state.loopCache.getOperationalPolicyPdpGroup(this.state.policyName);
+ chosenPdpSubgroupValue = this.state.loopCache.getOperationalPolicyPdpSubgroup(this.state.policyName);
}
- handlePdpGroupChange(e) {
- var selectedPdpGroup = this.state.pdpGroup.filter(entry => (Object.keys(entry)[0] === e.value));
- const pdpSubgroupValues = selectedPdpGroup[0][e.value].map((pdpSubgroup) => { return { label: pdpSubgroup, value: pdpSubgroup } });
- if (this.state.chosenPdpGroup !== e.value) {
- this.setState({
- chosenPdpGroup: e.value,
- chosenPdpSubgroup: '',
- pdpSubgroupList: pdpSubgroupValues
- });
- }
+ if (toscaModel == null) {
+ return;
}
- handlePdpSubgroupChange(e) {
- this.setState({ chosenPdpSubgroup: e.value });
+ var pdpSubgroupValues = [];
+ if (typeof (chosenPdpGroupValue) !== "undefined") {
+ var selectedPdpGroup = pdpGroupValues.filter(entry => (Object.keys(entry)[0] === chosenPdpGroupValue));
+ pdpSubgroupValues = selectedPdpGroup[0][chosenPdpGroupValue].map((pdpSubgroup) => {
+ return { label: pdpSubgroup, value: pdpSubgroup }
+ });
}
+ this.setState({
+ jsonEditor: this.createJsonEditor(toscaModel, editorData),
+ pdpGroup: pdpGroupValues,
+ pdpGroupList: pdpGroupValues.map(entry => {
+ return { label: Object.keys(entry)[0], value: Object.keys(entry)[0] };
+ }),
+ pdpSubgroupList: pdpSubgroupValues,
+ chosenPdpGroup: chosenPdpGroupValue,
+ chosenPdpSubgroup: chosenPdpSubgroupValue
+ })
+ }
- handleRefresh() {
- var newLoopCache, toscaModel, editorData;
- if (this.state.policyInstanceType === OnapConstant.microServiceType) {
- LoopService.refreshMicroServicePolicyJson(this.state.loopCache.getLoopName(),this.state.policyName).then(data => {
- newLoopCache = new LoopCache(data);
- toscaModel = newLoopCache.getMicroServiceJsonRepresentationForName(this.state.policyName);
- editorData = newLoopCache.getMicroServicePropertiesForName(this.state.policyName);
- document.getElementById("editor").innerHTML = "";
- this.setState({
- loopCache: newLoopCache,
- jsonEditor: this.createJsonEditor(toscaModel,editorData),
- showSucAlert: true,
- showMessage: "Successfully refreshed"
- });
- })
- .catch(error => {
- console.error("Error while refreshing the Operational Policy Json Representation");
- this.setState({
- showFailAlert: true,
- showMessage: "Refreshing of UI failed"
- });
- });
- } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) {
- LoopService.refreshOperationalPolicyJson(this.state.loopCache.getLoopName(),this.state.policyName).then(data => {
- var newLoopCache = new LoopCache(data);
- toscaModel = newLoopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName);
- editorData = newLoopCache.getOperationalPolicyPropertiesForName(this.state.policyName);
- document.getElementById("editor").innerHTML = "";
- this.setState({
- loopCache: newLoopCache,
- jsonEditor: this.createJsonEditor(toscaModel,editorData),
- showSucAlert: true,
- showMessage: "Successfully refreshed"
- });
- })
- .catch(error => {
- console.error("Error while refreshing the Operational Policy Json Representation");
- this.setState({
- showFailAlert: true,
- showMessage: "Refreshing of UI failed"
- });
- });
- }
+ handlePdpGroupChange(e) {
+ var selectedPdpGroup = this.state.pdpGroup.filter(entry => (Object.keys(entry)[0] === e.value));
+ const pdpSubgroupValues = selectedPdpGroup[0][e.value].map((pdpSubgroup) => {
+ return { label: pdpSubgroup, value: pdpSubgroup }
+ });
+ if (this.state.chosenPdpGroup !== e.value) {
+ this.setState({
+ chosenPdpGroup: e.value,
+ chosenPdpSubgroup: '',
+ pdpSubgroupList: pdpSubgroupValues
+ });
}
+ }
- disableAlert() {
- this.setState ({ showSucAlert: false, showFailAlert: false });
- }
+ handlePdpSubgroupChange(e) {
+ this.setState({ chosenPdpSubgroup: e.value });
+ }
- renderPdpGroupDropDown() {
- if(this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) {
- return (
- <Form.Group as={Row} controlId="formPlaintextEmail">
- <Form.Label column sm="2">Pdp Group Info</Form.Label>
- <Col sm="3">
- <Select value={{ label: this.state.chosenPdpGroup, value: this.state.chosenPdpGroup }} onChange={this.handlePdpGroupChange} options={this.state.pdpGroupList} />
- </Col>
- <Col sm="3">
- <Select value={{ label: this.state.chosenPdpSubgroup, value: this.state.chosenPdpSubgroup }} onChange={this.handlePdpSubgroupChange} options={this.state.pdpSubgroupList} />
- </Col>
- </Form.Group>
- );
- }
+ handleRefresh() {
+ var newLoopCache, toscaModel, editorData;
+ if (this.state.policyInstanceType === OnapConstant.microServiceType) {
+ LoopService.refreshMicroServicePolicyJson(this.state.loopCache.getLoopName(), this.state.policyName).then(data => {
+ newLoopCache = new LoopCache(data);
+ toscaModel = newLoopCache.getMicroServiceJsonRepresentationForName(this.state.policyName);
+ editorData = newLoopCache.getMicroServicePropertiesForName(this.state.policyName);
+ document.getElementById("editor").innerHTML = "";
+ this.setState({
+ loopCache: newLoopCache,
+ jsonEditor: this.createJsonEditor(toscaModel, editorData),
+ showSucAlert: true,
+ showMessage: "Successfully refreshed"
+ });
+ })
+ .catch(error => {
+ console.error("Error while refreshing the Operational Policy Json Representation");
+ this.setState({
+ showFailAlert: true,
+ showMessage: "Refreshing of UI failed"
+ });
+ });
+ } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) {
+ LoopService.refreshOperationalPolicyJson(this.state.loopCache.getLoopName(), this.state.policyName).then(data => {
+ var newLoopCache = new LoopCache(data);
+ toscaModel = newLoopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName);
+ editorData = newLoopCache.getOperationalPolicyPropertiesForName(this.state.policyName);
+ document.getElementById("editor").innerHTML = "";
+ this.setState({
+ loopCache: newLoopCache,
+ jsonEditor: this.createJsonEditor(toscaModel, editorData),
+ showSucAlert: true,
+ showMessage: "Successfully refreshed"
+ });
+ })
+ .catch(error => {
+ console.error("Error while refreshing the Operational Policy Json Representation");
+ this.setState({
+ showFailAlert: true,
+ showMessage: "Refreshing of UI failed"
+ });
+ });
}
+ }
- renderOpenLoopMessage() {
- if(this.state.policyInstanceType === OnapConstant.operationalPolicyType && this.state.loopCache.isOpenLoopTemplate()) {
- return (
- "Operational Policy cannot be configured as only Open Loop is supported for this Template!"
- );
- }
- }
+ disableAlert() {
+ this.setState({ showSucAlert: false, showFailAlert: false });
+ }
- renderModalTitle() {
- return (
- <Modal.Title>Edit the policy</Modal.Title>
- );
+ renderPdpGroupDropDown() {
+ if (this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) {
+ return (
+ <Form.Group as={ Row } controlId="formPlaintextEmail">
+ <Form.Label column sm="2">Pdp Group Info</Form.Label>
+ <Col sm="3">
+ <Select value={ { label: this.state.chosenPdpGroup, value: this.state.chosenPdpGroup } } onChange={ this.handlePdpGroupChange } options={ this.state.pdpGroupList }/>
+ </Col>
+ <Col sm="3">
+ <Select value={ { label: this.state.chosenPdpSubgroup, value: this.state.chosenPdpSubgroup } } onChange={ this.handlePdpSubgroupChange } options={ this.state.pdpSubgroupList }/>
+ </Col>
+ </Form.Group>
+ );
}
+ }
- renderButton() {
- 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 key="save" variant="primary" disabled={this.readOnly} onClick={this.handleSave}>
- Save Changes
- </Button>
- ));
- allElement.push((
- <Button key="refresh" variant="primary" disabled={this.readOnly} onClick={this.handleRefresh}>
- Refresh
- </Button>
- ));
- }
- return allElement;
+ renderOpenLoopMessage() {
+ if (this.state.policyInstanceType === OnapConstant.operationalPolicyType && this.state.loopCache.isOpenLoopTemplate()) {
+ return (
+ "Operational Policy cannot be configured as only Open Loop is supported for this Template!"
+ );
}
+ }
- render() {
- return (
- <ModalStyled size="xl" backdrop="static" keyboard={false} show={this.state.show} onHide={this.handleClose}>
- <Modal.Header closeButton>
- {this.renderModalTitle()}
- </Modal.Header>
- <Alert variant="success" show={this.state.showSucAlert} 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.Body>
- {this.renderOpenLoopMessage()}
- <div id="editor" />
- {this.renderPdpGroupDropDown()}
- </Modal.Body>
- <Modal.Footer>
- {this.renderButton()}
- </Modal.Footer>
- </ModalStyled>
- );
+ renderModalTitle() {
+ return (
+ <Modal.Title>Edit the policy</Modal.Title>
+ );
+ }
+
+ renderButton() {
+ 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 key="save" variant="primary" disabled={ this.readOnly } onClick={ this.handleSave }>
+ Save Changes
+ </Button>
+ ));
+ allElement.push((
+ <Button key="refresh" variant="primary" disabled={ this.readOnly } onClick={ this.handleRefresh }>
+ Refresh
+ </Button>
+ ));
}
+ return allElement;
+ }
+
+ render() {
+ return (
+ <ModalStyled size="xl" backdrop="static" keyboard={ false } show={ this.state.show } onHide={ this.handleClose }>
+ <Modal.Header closeButton>
+ { this.renderModalTitle() }
+ </Modal.Header>
+ <Alert variant="success" show={ this.state.showSucAlert } 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.Body>
+ { this.renderOpenLoopMessage() }
+ <div id="editor"/>
+ { this.renderPdpGroupDropDown() }
+ </Modal.Body>
+ <Modal.Footer>
+ { this.renderButton() }
+ </Modal.Footer>
+ </ModalStyled>
+ );
+ }
}
diff --git a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js
index 1e6fac0a0..658b19e26 100644
--- a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js
+++ b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js
@@ -29,107 +29,107 @@ import OnapConstant from '../../../utils/OnapConstants';
import { shallow } from 'enzyme';
describe('Verify PolicyModal', () => {
- beforeEach(() => {
- fetch.resetMocks();
- fetch.mockImplementation(() => {
- return Promise.resolve({
- ok: true,
- status: 200,
- text: () => "OK"
- });
- });
- })
- const loopCacheStr = {
- "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca",
- "operationalPolicies": [{
- "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca",
- "configurationsJson": {
- "operational_policy": {
- "controlLoop": {},
- "policies": []
- }
- },
- "policyModel": {"policyPdpGroup": {"supportedPdpGroups":[{"monitoring": ["xacml"]}]}},
- "jsonRepresentation" : {"schema": {}}
- }]
- };
-
- const loopCache = new LoopCache(loopCacheStr);
- const historyMock = { push: jest.fn() };
- const flushPromises = () => new Promise(setImmediate);
- const match = {params: {policyName:"OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", policyInstanceType: OnapConstant.operationalPolicyType}}
-
- it('Test handleClose', () => {
- const handleClose = jest.spyOn(PolicyModal.prototype,'handleClose');
- const component = mount(<PolicyModal history={historyMock} match={match} loopCache={loopCache}/>)
-
- component.find('[variant="secondary"]').prop('onClick')();
-
- expect(handleClose).toHaveBeenCalledTimes(1);
- expect(component.state('show')).toEqual(false);
- expect(historyMock.push.mock.calls[0]).toEqual([ '/']);
+ beforeEach(() => {
+ fetch.resetMocks();
+ fetch.mockImplementation(() => {
+ return Promise.resolve({
+ ok: true,
+ status: 200,
+ text: () => "OK"
+ });
});
-
- it('Test handleSave', async () => {
- const loadLoopFunction = jest.fn();
- const handleSave = jest.spyOn(PolicyModal.prototype,'handleSave');
- const component = mount(<PolicyModal history={historyMock}
- loopCache={loopCache} match={match} loadLoopFunction={loadLoopFunction} />)
-
- component.find('[variant="primary"]').get(0).props.onClick();
- await flushPromises();
- component.update();
-
- expect(handleSave).toHaveBeenCalledTimes(1);
- expect(component.state('show')).toEqual(false);
- expect(historyMock.push.mock.calls[0]).toEqual([ '/']);
+ })
+ const loopCacheStr = {
+ "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca",
+ "operationalPolicies": [{
+ "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca",
+ "configurationsJson": {
+ "operational_policy": {
+ "controlLoop": {},
+ "policies": []
+ }
+ },
+ "policyModel": { "policyPdpGroup": { "supportedPdpGroups": [{ "monitoring": ["xacml"] }] } },
+ "jsonRepresentation": { "schema": {} }
+ }]
+ };
+
+ const loopCache = new LoopCache(loopCacheStr);
+ const historyMock = { push: jest.fn() };
+ const flushPromises = () => new Promise(setImmediate);
+ const match = { params: { policyName: "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", policyInstanceType: OnapConstant.operationalPolicyType } }
+
+ it('Test handleClose', () => {
+ const handleClose = jest.spyOn(PolicyModal.prototype, 'handleClose');
+ const component = mount(<PolicyModal history={ historyMock } match={ match } loopCache={ loopCache }/>)
+
+ component.find('[variant="secondary"]').prop('onClick')();
+
+ expect(handleClose).toHaveBeenCalledTimes(1);
+ expect(component.state('show')).toEqual(false);
+ expect(historyMock.push.mock.calls[0]).toEqual(['/']);
+ });
+
+ it('Test handleSave', async () => {
+ const loadLoopFunction = jest.fn();
+ const handleSave = jest.spyOn(PolicyModal.prototype, 'handleSave');
+ const component = mount(<PolicyModal history={ historyMock }
+ loopCache={ loopCache } match={ match } loadLoopFunction={ loadLoopFunction }/>)
+
+ component.find('[variant="primary"]').get(0).props.onClick();
+ await flushPromises();
+ component.update();
+
+ expect(handleSave).toHaveBeenCalledTimes(1);
+ expect(component.state('show')).toEqual(false);
+ expect(historyMock.push.mock.calls[0]).toEqual(['/']);
+ });
+
+ it('Test handleRefresh', async () => {
+ LoopService.refreshOperationalPolicyJson = jest.fn().mockImplementation(() => {
+ return Promise.resolve(loopCacheStr);
});
-
- it('Test handleRefresh', async () => {
- LoopService.refreshOperationalPolicyJson = jest.fn().mockImplementation(() => {
- return Promise.resolve(loopCacheStr);
- });
- const updateLoopFunction = jest.fn();
- const handleRefresh = jest.spyOn(PolicyModal.prototype,'handleRefresh');
- const component = mount(<PolicyModal loopCache={loopCache} match={match} updateLoopFunction={updateLoopFunction} />)
-
- component.find('[variant="primary"]').get(1).props.onClick();
- await flushPromises();
- component.update();
-
- expect(handleRefresh).toHaveBeenCalledTimes(1);
- expect(component.state('show')).toEqual(true);
- expect(component.state('showSucAlert')).toEqual(true);
- expect(component.state('showMessage')).toEqual("Successfully refreshed");
- });
-
- it('Test handlePdpGroupChange', () => {
- const component = mount(<PolicyModal loopCache={loopCache} match={match} />)
- component.setState({
- "pdpGroup": [{"option1":["subPdp1","subPdp2"]}],
- "chosenPdpGroup": "option2"
- });
- expect(component.state('chosenPdpGroup')).toEqual("option2");
-
- const instance = component.instance();
- const event = {label:"option1", value:"option1"}
- instance.handlePdpGroupChange(event);
- expect(component.state('chosenPdpGroup')).toEqual("option1");
- expect(component.state('chosenPdpSubgroup')).toEqual("");
- expect(component.state('pdpSubgroupList')).toEqual([{label:"subPdp1", value:"subPdp1"}, {label:"subPdp2", value:"subPdp2"}]);
- });
-
- it('Test handlePdpSubgroupChange', () => {
- const component = mount(<PolicyModal loopCache={loopCache} match={match} />)
-
- const instance = component.instance();
- const event = {label:"option1", value:"option1"}
- 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();
+ const updateLoopFunction = jest.fn();
+ const handleRefresh = jest.spyOn(PolicyModal.prototype, 'handleRefresh');
+ const component = mount(<PolicyModal loopCache={ loopCache } match={ match } updateLoopFunction={ updateLoopFunction }/>)
+
+ component.find('[variant="primary"]').get(1).props.onClick();
+ await flushPromises();
+ component.update();
+
+ expect(handleRefresh).toHaveBeenCalledTimes(1);
+ expect(component.state('show')).toEqual(true);
+ expect(component.state('showSucAlert')).toEqual(true);
+ expect(component.state('showMessage')).toEqual("Successfully refreshed");
+ });
+
+ it('Test handlePdpGroupChange', () => {
+ const component = mount(<PolicyModal loopCache={ loopCache } match={ match }/>)
+ component.setState({
+ "pdpGroup": [{ "option1": ["subPdp1", "subPdp2"] }],
+ "chosenPdpGroup": "option2"
});
-}); \ No newline at end of file
+ expect(component.state('chosenPdpGroup')).toEqual("option2");
+
+ const instance = component.instance();
+ const event = { label: "option1", value: "option1" }
+ instance.handlePdpGroupChange(event);
+ expect(component.state('chosenPdpGroup')).toEqual("option1");
+ expect(component.state('chosenPdpSubgroup')).toEqual("");
+ expect(component.state('pdpSubgroupList')).toEqual([{ label: "subPdp1", value: "subPdp1" }, { label: "subPdp2", value: "subPdp2" }]);
+ });
+
+ it('Test handlePdpSubgroupChange', () => {
+ const component = mount(<PolicyModal loopCache={ loopCache } match={ match }/>)
+
+ const instance = component.instance();
+ const event = { label: "option1", value: "option1" }
+ 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/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js b/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
index 6d3cd7a21..2692aefa0 100644
--- a/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
+++ b/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
@@ -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 !== nextProps.loopCache;
- }
-
- componentDidUpdate(prevProps) {
- if (prevProps.loopCache !== this.props.loopCache) {
- this.setState({
- loopCache: this.props.loopCache,
- });
- }
+ 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,
+ });
}
-
- 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);
+ }
+
+ 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);
+ }
}
-
- 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>
- );
+ }
+
+ 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));
}
- 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>
- );
- }
+ allElements.push(this.createEndCircle(xPos, "End"))
+ xPos += (this.boxWidth + this.boxSpace);
- 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>
- );
- }
+ return allElements;
+ }
- createSvgFromTemplate() {
- const allElements = [];
- var xPos = 0;
+ createSvgFromInstance() {
+ const allElements = [];
+ var xPos = 0;
- allElements.push(this.createBeginCircle(xPos,"Start"))
- xPos+=(this.boxWidth+this.boxSpace);
+ allElements.push(this.createBeginCircle(xPos, "Start"))
+ xPos += (this.boxWidth + this.boxSpace);
- allElements.push(this.createOneArrow(xPos-this.boxSpace));
+ allElements.push(this.createOneArrow(xPos - this.boxSpace));
- allElements.push(this.createVesBox(xPos));
- xPos+=(this.boxWidth+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.createOneArrow(xPos - 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.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);
- 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>
- );
+ return allElements;
+ }
+
+ 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);