summaryrefslogtreecommitdiffstats
path: root/ui-react/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'ui-react/src/components')
-rw-r--r--ui-react/src/components/dialogs/PerformActions.js52
-rw-r--r--ui-react/src/components/dialogs/PerformActions.test.js8
-rw-r--r--ui-react/src/components/dialogs/Policy/PolicyModal.js63
-rw-r--r--ui-react/src/components/loop_viewer/svg/SvgGenerator.js16
4 files changed, 90 insertions, 49 deletions
diff --git a/ui-react/src/components/dialogs/PerformActions.js b/ui-react/src/components/dialogs/PerformActions.js
index cf5a3c20e..f6001e21f 100644
--- a/ui-react/src/components/dialogs/PerformActions.js
+++ b/ui-react/src/components/dialogs/PerformActions.js
@@ -22,24 +22,19 @@
*/
import React from 'react';
import LoopActionService from '../../api/LoopActionService';
-import Spinner from 'react-bootstrap/Spinner'
-import styled from 'styled-components';
-const StyledSpinnerDiv = styled.div`
- justify-content: center !important;
- display: flex !important;
-`;
export default class PerformActions extends React.Component {
state = {
loopName: this.props.loopCache.getLoopName(),
loopAction: this.props.loopAction
};
+
constructor(props, context) {
super(props, context);
-
this.refreshStatus = this.refreshStatus.bind(this);
}
+
componentWillReceiveProps(newProps) {
this.setState({
loopName: newProps.loopCache.getLoopName(),
@@ -51,35 +46,50 @@ export default class PerformActions extends React.Component {
const action = this.state.loopAction;
const loopName = this.state.loopName;
- LoopActionService.performAction(loopName, action).then(pars => {
+ if (action === 'delete') {
+ if (window.confirm('You are about to remove Control Loop Model "' + loopName +
+ '". Select OK to continue with deletion or Cancel to keep the model.') === false) {
+ return;
+ }
+ }
+
+ this.props.setBusyLoading(); // Alert top level to start block user clicks
+
+ LoopActionService.performAction(loopName, action)
+ .then(pars => {
this.props.showSucAlert("Action " + action + " successfully performed");
- // refresh status and update loop logs
- this.refreshStatus(loopName);
+ if (action === 'delete') {
+ this.props.updateLoopFunction(null);
+ this.props.history.push('/');
+ } else {
+ // refresh status and update loop logs
+ this.refreshStatus(loopName);
+ }
})
.catch(error => {
this.props.showFailAlert("Action " + action + " failed");
// refresh status and update loop logs
this.refreshStatus(loopName);
- });
-
+ })
+ .finally(() => this.props.clearBusyLoading());
}
refreshStatus(loopName) {
- LoopActionService.refreshStatus(loopName).then(data => {
+
+ this.props.setBusyLoading();
+
+ LoopActionService.refreshStatus(loopName)
+ .then(data => {
this.props.updateLoopFunction(data);
this.props.history.push('/');
})
- .catch(error => {
+ .catch(error => {
this.props.history.push('/');
- });
+ })
+ .finally(() => this.props.clearBusyLoading());
}
render() {
- return (
- <StyledSpinnerDiv>
- <Spinner animation="border" role="status">
- </Spinner>
- </StyledSpinnerDiv>
- );
+ return null;
}
}
diff --git a/ui-react/src/components/dialogs/PerformActions.test.js b/ui-react/src/components/dialogs/PerformActions.test.js
index b833a929d..c91c2f675 100644
--- a/ui-react/src/components/dialogs/PerformActions.test.js
+++ b/ui-react/src/components/dialogs/PerformActions.test.js
@@ -38,6 +38,8 @@ describe('Verify PerformActions', () => {
const updateLoopFunction = jest.fn();
const showSucAlert = jest.fn();
const showFailAlert = jest.fn();
+ const setBusyLoading = jest.fn();
+ const clearBusyLoading = jest.fn();
LoopActionService.refreshStatus = jest.fn().mockImplementation(() => {
return Promise.resolve({
@@ -47,7 +49,7 @@ describe('Verify PerformActions', () => {
});
});
const component = shallow(<PerformActions loopCache={loopCache}
- loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showSucAlert={showSucAlert} showFailAlert={showFailAlert} />)
+ loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showSucAlert={showSucAlert} showFailAlert={showFailAlert} setBusyLoading={setBusyLoading} clearBusyLoading={clearBusyLoading}/>)
await flushPromises();
component.update();
@@ -60,6 +62,8 @@ describe('Verify PerformActions', () => {
const updateLoopFunction = jest.fn();
const showSucAlert = jest.fn();
const showFailAlert = jest.fn();
+ const setBusyLoading = jest.fn();
+ const clearBusyLoading = jest.fn();
LoopActionService.performAction = jest.fn().mockImplementation(() => {
return Promise.resolve({
@@ -76,7 +80,7 @@ describe('Verify PerformActions', () => {
});
});
const component = shallow(<PerformActions loopCache={loopCache}
- loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showSucAlert={showSucAlert} showFailAlert={showFailAlert} />)
+ loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showSucAlert={showSucAlert} showFailAlert={showFailAlert} setBusyLoading={setBusyLoading} clearBusyLoading={clearBusyLoading}/>)
await flushPromises();
component.update();
diff --git a/ui-react/src/components/dialogs/Policy/PolicyModal.js b/ui-react/src/components/dialogs/Policy/PolicyModal.js
index d3b427396..6b1ebe178 100644
--- a/ui-react/src/components/dialogs/Policy/PolicyModal.js
+++ b/ui-react/src/components/dialogs/Policy/PolicyModal.js
@@ -34,11 +34,16 @@ import LoopCache from '../../../api/LoopCache';
import JSONEditor from '@json-editor/json-editor';
import Alert from 'react-bootstrap/Alert';
import OnapConstant from '../../../utils/OnapConstants';
+import OnapUtils from '../../../utils/OnapUtils';
const ModalStyled = styled(Modal)`
background-color: transparent;
`
+const DivWhiteSpaceStyled = styled.div`
+ white-space: pre;
+`
+
export default class PolicyModal extends React.Component {
state = {
@@ -70,42 +75,49 @@ export default class PolicyModal extends React.Component {
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;
}
handleSave() {
- var errors = this.state.jsonEditor.validate();
var editorData = this.state.jsonEditor.getValue();
+ var errors = this.state.jsonEditor.validate();
+ errors = errors.concat(this.customValidation(editorData, this.state.loopCache.getTemplateName()));
if (errors.length !== 0) {
console.error("Errors detected during policy data validation ", errors);
this.setState({
- showFailAlert: true,
- showMessage: "Errors detected during policy data validation " + errors
- });
+ 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());
- });
+ 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.history.push('/');
this.props.loadLoopFunction(this.state.loopCache.getLoopName());
});
}
}
}
+ customValidation(editorData, templateName) {
+ // method for sub-classes to override with customized validation
+ return [];
+ }
+
handleClose() {
this.setState({ show: false });
this.props.history.push('/');
@@ -115,6 +127,15 @@ export default class PolicyModal extends React.Component {
this.renderJsonEditor();
}
+ componentDidUpdate() {
+ if (this.state.showSucAlert === true || this.state.showFailAlert === true) {
+ let modalElement = document.getElementById("policyModal")
+ if (modalElement) {
+ modalElement.scrollTo(0, 0);
+ }
+ }
+ }
+
createJsonEditor(toscaModel, editorData) {
JSONEditor.defaults.themes.myBootstrap4 = JSONEditor.defaults.themes.bootstrap4.extend({
getTab: function(text,tabId) {
@@ -313,12 +334,16 @@ export default class PolicyModal extends React.Component {
<Modal.Header closeButton>
{this.renderModalTitle()}
</Modal.Header>
- <Alert variant="success" show={this.state.showSucAlert} onClose={this.disableAlert} dismissible>
- {this.state.showMessage}
- </Alert>
- <Alert variant="danger" show={this.state.showFailAlert} onClose={this.disableAlert} dismissible>
- {this.state.showMessage}
- </Alert>
+ <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" />
@@ -330,4 +355,4 @@ export default class PolicyModal extends React.Component {
</ModalStyled>
);
}
-} \ No newline at end of file
+}
diff --git a/ui-react/src/components/loop_viewer/svg/SvgGenerator.js b/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
index d718c2e44..7070455e7 100644
--- a/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
+++ b/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
@@ -70,13 +70,15 @@ class SvgGenerator extends React.Component {
}
handleSvgClick(event) {
- if (this.state.clickable) {
- console.debug("svg click event received");
- var elementName = event.target.parentNode.getAttribute('policyId');
- console.info("SVG element clicked", elementName);
- if (elementName !== null) {
- this.props.history.push("/policyModal/"+event.target.parentNode.getAttribute('policyType')+"/"+elementName);
- }
+ 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);
+ }
}
}