aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrunomilitzer <bruno.militzer@est.tech>2021-07-08 15:33:55 +0100
committerbrunomilitzer <bruno.militzer@est.tech>2021-07-13 15:20:41 +0100
commit71d6358a8f787c5d2688a485d42ff9514dc58a56 (patch)
tree091e1bf68ecff15267d7c1c14f68cca9d04f38a8
parent9752dad7c9ad8f970fb87b92c06c7ae8d8121280 (diff)
Add Upload Control Loop Instantiation
Created Functionality to Upload JSON file to Control Loop Instantiation. Issue-ID: POLICY-3436 Change-Id: Iefd538c91154b7e61615ab63b440378e2feea502 Signed-off-by: brunomilitzer <bruno.militzer@est.tech>
-rw-r--r--gui-clamp/ui-react-lib/libIndex.js6
-rw-r--r--gui-clamp/ui-react/package.json2
-rw-r--r--gui-clamp/ui-react/src/LoopUI.js6
-rw-r--r--gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap6
-rw-r--r--gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap6
-rw-r--r--gui-clamp/ui-react/src/api/ControlLoopService.js24
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationElementItem.js (renamed from gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopElementItem.js)4
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationElements.js (renamed from gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopElements.js)8
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationItem.js (renamed from gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopItem.js)4
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js (renamed from gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitoringControlLoopModal.js)21
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.test.js64
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.js136
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.test.js102
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.js52
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.test.js61
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/MonitorInstantiation.test.js.snap32
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiation.test.js.snap91
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiationFile.test.js.snap16
-rw-r--r--gui-clamp/ui-react/src/components/dialogs/Policy/toscaInstantiationData.test.json59
-rw-r--r--gui-clamp/ui-react/src/components/menu/MenuBar.js4
-rw-r--r--gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap74
21 files changed, 746 insertions, 32 deletions
diff --git a/gui-clamp/ui-react-lib/libIndex.js b/gui-clamp/ui-react-lib/libIndex.js
index 179b882..b0981b0 100644
--- a/gui-clamp/ui-react-lib/libIndex.js
+++ b/gui-clamp/ui-react-lib/libIndex.js
@@ -55,7 +55,11 @@ export { default as ViewAllPolicies } from '../ui-react/src/components/dialogs/P
export { default as PolicyDeploymentEditor } from '../ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor';
export { default as PoliciesTreeViewer } from '../ui-react/src/components/dialogs/Policy/PoliciesTreeViewer';
export { default as PolicyToscaFileSelector } from '../ui-react/src/components/dialogs/Policy/PolicyToscaFileSelector';
-export { default as MonitoringControlLoopModal } from '../ui-react/src/components/dialogs/ControlLoop/MonitoringControlLoopModal';
+export { default as MonitorInstantiation } from '../ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation';
+export { default as InstantiationItem } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationItem';
+export { default as InstantiationElements } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationElements';
+export { default as InstantiationElementItem } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationElementItem';
+export { default as UploadToscaInstantiation } from '../ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation';
export { default as ControlLoopService } from '../ui-react/src/api/ControlLoopService';
export { default as GetLocalToscaFileForUpload } from '../ui-react/src/components/dialogs/ControlLoop/GetLocalToscaFileForUpload';
export { default as ReadAndConvertYaml } from '../ui-react/src/components/dialogs/ControlLoop/ReadAndConvertYaml';
diff --git a/gui-clamp/ui-react/package.json b/gui-clamp/ui-react/package.json
index 5754d44..6b67e3f 100644
--- a/gui-clamp/ui-react/package.json
+++ b/gui-clamp/ui-react/package.json
@@ -47,7 +47,7 @@
"@babel/preset-env": "7.14.7",
"@babel/preset-react": "7.14.5",
"@wojtekmaj/enzyme-adapter-react-17": "0.6.2",
- "babel-jest": "27.0.6",
+ "babel-jest": "26.6.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-17-updated": "1.0.2",
"enzyme-to-json": "3.6.2",
diff --git a/gui-clamp/ui-react/src/LoopUI.js b/gui-clamp/ui-react/src/LoopUI.js
index 752c89d..109a0b3 100644
--- a/gui-clamp/ui-react/src/LoopUI.js
+++ b/gui-clamp/ui-react/src/LoopUI.js
@@ -52,8 +52,9 @@ import Spinner from 'react-bootstrap/Spinner';
import { Link } from 'react-router-dom';
import ReadAndConvertYaml from "./components/dialogs/ControlLoop/ReadAndConvertYaml";
-import MonitoringControlLoopModal from "./components/dialogs/ControlLoop/MonitoringControlLoopModal";
+import MonitorInstantiation from "./components/dialogs/ControlLoop/MonitorInstantiation";
import GetLocalToscaFileForUpload from "./components/dialogs/ControlLoop/GetLocalToscaFileForUpload";
+import UploadToscaInstantiation from "./components/dialogs/ControlLoop/UploadToscaInstantiation";
const StyledMainDiv = styled.div`
background-color: ${ props => props.theme.backgroundColor };
@@ -382,7 +383,8 @@ export default class LoopUI extends React.Component {
showSucAlert={ this.showSucAlert }
showFailAlert={ this.showFailAlert }/>) }
/>
- <Route path="/monitoring" render={ (routeProps) => (<MonitoringControlLoopModal { ...routeProps } />) }/>
+ <Route path="/monitorInstantiation" render={ (routeProps) => (<MonitorInstantiation { ...routeProps } />) }/>
+ <Route path="/uploadToscaInstantiation" render={ (routeProps) => (<UploadToscaInstantiation { ...routeProps } />) }/>
</React.Fragment>
);
}
diff --git a/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap b/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap
index 6d25823..040fdaa 100644
--- a/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap
+++ b/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap
@@ -82,7 +82,11 @@ exports[`Verify LoopUI Test the render method 1`] = `
render={[Function]}
/>
<Route
- path="/monitoring"
+ path="/monitorInstantiation"
+ render={[Function]}
+ />
+ <Route
+ path="/uploadToscaInstantiation"
render={[Function]}
/>
<div />
diff --git a/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap b/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap
index f5680b1..5d8a207 100644
--- a/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap
+++ b/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap
@@ -111,7 +111,11 @@ exports[`Verify OnapClamp Test the render method 1`] = `
render={[Function]}
/>
<Route
- path="/monitoring"
+ path="/monitorInstantiation"
+ render={[Function]}
+ />
+ <Route
+ path="/uploadToscaInstantiation"
render={[Function]}
/>
<div />
diff --git a/gui-clamp/ui-react/src/api/ControlLoopService.js b/gui-clamp/ui-react/src/api/ControlLoopService.js
index 1882f78..30b0522 100644
--- a/gui-clamp/ui-react/src/api/ControlLoopService.js
+++ b/gui-clamp/ui-react/src/api/ControlLoopService.js
@@ -19,7 +19,7 @@
export default class ControlLoopService {
- static async getControlLoopList(windowLocationPathname) {
+ static async fetchControlLoopInstantiation(windowLocationPathname) {
return await fetch(windowLocationPathname + '/restservices/clds/v2/toscaControlLoop/getToscaInstantiation', {
method: 'GET',
@@ -28,10 +28,10 @@ export default class ControlLoopService {
},
credentials: 'same-origin',
}).then(response => {
- console.log("getControlLoopList received " + response.status);
+ console.log("fetchControlLoopInstantiation received " + response.status);
if (response.ok) {
- console.info("getControlLoopList query successful");
+ console.info("fetchControlLoopInstantiation query successful");
return response.json();
} else {
return response.text().then(responseBody => {
@@ -39,12 +39,26 @@ export default class ControlLoopService {
});
}
}).catch(error => {
- console.error("getControlLoopList error occurred ", error);
- alert("getControlLoopList error occurred " + error);
+ console.error("fetchControlLoopInstantiation error occurred ", error);
+ alert("fetchControlLoopInstantiation error occurred " + error);
return undefined;
});
}
+ static async uploadToscaInstantiation(toscaObject, windowLocationPathname) {
+
+ const response = await fetch(windowLocationPathname + '/restservices/clds/v2/toscaControlLoop/postToscaInstantiation', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'same-origin',
+ body: JSON.stringify(toscaObject)
+ });
+
+ return response;
+ }
+
static async getToscaTemplate(name, version, windowLocationPathname) {
const params = {
name: name,
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopElementItem.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationElementItem.js
index 632cacd..0e2c407 100644
--- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopElementItem.js
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationElementItem.js
@@ -65,7 +65,7 @@ const ButtonStyle = styled(Button)`
}
`
-const ControlLoopElementItem = (props) => {
+const InstantiationElementItem = (props) => {
const [title, setTitle] = useState("");
useEffect(() => {
@@ -121,4 +121,4 @@ const ControlLoopElementItem = (props) => {
);
}
-export default ControlLoopElementItem;
+export default InstantiationElementItem;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopElements.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationElements.js
index 57bdf40..d8e6348 100644
--- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopElements.js
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationElements.js
@@ -18,9 +18,9 @@
*/
import React, { useEffect, useState } from "react";
-import ControlLoopElementItem from "./ControlLoopElementItem";
+import InstantiationElementItem from "./InstantiationElementItem";
-const ControlLoopElements = (props) => {
+const InstantiationElements = (props) => {
const [clElements, setClElements] = useState([]);
useEffect(() => {
@@ -31,11 +31,11 @@ const ControlLoopElements = (props) => {
<React.Fragment>
{
clElements.map((clEl, index) => (
- <ControlLoopElementItem title={ clEl["definition"]["name"] } orderedState={ clEl["orderedState"] } key={ index } />
+ <InstantiationElementItem title={ clEl["definition"]["name"] } orderedState={ clEl["orderedState"] } key={ index } />
))
}
</React.Fragment>
);
}
-export default ControlLoopElements;
+export default InstantiationElements;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopItem.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationItem.js
index f149517..a59770b 100644
--- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ControlLoopItem.js
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationItem.js
@@ -71,7 +71,7 @@ const ToggleButton = styled(Button)`
}
`
-const ControlLoopItem = (props) => {
+const InstantiationItem = (props) => {
const toggleState = () => {
switch (props.orderedState) {
case 'UNINITIALISED':
@@ -125,4 +125,4 @@ const ControlLoopItem = (props) => {
);
}
-export default ControlLoopItem;
+export default InstantiationItem;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitoringControlLoopModal.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js
index 03fb64b..428defa 100644
--- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitoringControlLoopModal.js
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js
@@ -21,15 +21,15 @@ import React, { useEffect, useState } from "react";
import styled from "styled-components";
import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";
-import ControlLoopItem from "./ControlLoopItem";
+import InstantiationItem from "./InstantiationItem";
import ControlLoopService from "../../../api/ControlLoopService";
-import ControlLoopElements from "./ControlLoopElements";
+import InstantiationElements from "./InstantiationElements";
const ModalStyled = styled(Modal)`
background-color: transparent;
`
-const MonitoringControlLoopModal = (props) => {
+const MonitorInstantiation = (props) => {
const [show, setShow] = useState(true);
const [controlLoopList, setControlLoopList] = useState([]);
const [windowLocationPathname, setWindowLocationPathname] = useState('');
@@ -37,12 +37,13 @@ const MonitoringControlLoopModal = (props) => {
useEffect(() => {
setWindowLocationPathname(window.location.pathname);
- ControlLoopService.getControlLoopList(windowLocationPathname).then(controlLoopList => {
+ ControlLoopService.fetchControlLoopInstantiation(windowLocationPathname).then(controlLoopList => {
setControlLoopList(controlLoopList['controlLoopList']);
});
}, [])
const handleClose = () => {
+ console.log('handleClose called');
setShow(false);
props.history.push('/');
}
@@ -50,22 +51,22 @@ const MonitoringControlLoopModal = (props) => {
return (
<ModalStyled size="xl" show={ show } onHide={ handleClose } backdrop="static" keyboard={ false }>
<Modal.Header closeButton>
- <Modal.Title>Tosca Control Loop - Monitoring</Modal.Title>
+ <Modal.Title>Tosca Instantiation - Monitoring</Modal.Title>
</Modal.Header>
<Modal.Body>
{
controlLoopList.map((clList, index) => (
- <ControlLoopItem title={ clList["name"] } orderedState={ clList["orderedState"] } index={ index } key={ index }>
- <ControlLoopElements elements={ clList["elements"] } />
- </ControlLoopItem>
+ <InstantiationItem title={ clList["name"] } orderedState={ clList["orderedState"] } index={ index } key={ index }>
+ <InstantiationElements elements={ clList["elements"] } />
+ </InstantiationItem>
))
}
</Modal.Body>
<Modal.Footer>
- <Button variant="secondary" type="null" onClick={ handleClose }>Cancel</Button>
+ <Button variant="secondary" type="null" onClick={ handleClose }>Close</Button>
</Modal.Footer>
</ModalStyled>
)
}
-export default MonitoringControlLoopModal;
+export default MonitorInstantiation;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.test.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.test.js
new file mode 100644
index 0000000..5e30924
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.test.js
@@ -0,0 +1,64 @@
+/*
+ * ============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=========================================================
+ */
+
+import { mount, shallow } from "enzyme";
+import toJson from "enzyme-to-json";
+import { createMemoryHistory } from "history";
+import React from "react";
+import MonitorInstantiation from "./MonitorInstantiation";
+import { act } from "react-dom/test-utils";
+
+describe('Verify MonitoringInstantiation', () => {
+
+ it("renders without crashing", () => {
+ shallow(<MonitorInstantiation/>);
+ });
+
+ it("renders correctly", () => {
+ const tree = shallow(<MonitorInstantiation/>);
+ expect(toJson(tree)).toMatchSnapshot();
+ });
+
+ it('should have a Button element', () => {
+ const container = shallow(<MonitorInstantiation/>)
+ expect(container.find('Button').length).toEqual(1);
+ });
+
+ it('handleClose called when bottom button clicked', () => {
+ const history = createMemoryHistory();
+ const component = mount(<MonitorInstantiation history={ history }/>)
+ const logSpy = jest.spyOn(console, 'log');
+
+ act(() => {
+ component.find('[variant="secondary"]').simulate('click');
+ expect(logSpy).toHaveBeenCalledWith('handleClose called');
+ });
+ });
+
+ it('handleClose called when top-right button clicked', () => {
+ const history = createMemoryHistory();
+ const component = mount(<MonitorInstantiation history={ history }/>)
+ const logSpy = jest.spyOn(console, 'log');
+
+ act(() => {
+ component.find('[size="xl"]').get(0).props.onHide();
+ expect(logSpy).toHaveBeenCalledWith('handleClose called');
+ });
+ });
+});
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.js
new file mode 100644
index 0000000..d9bbe8b
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.js
@@ -0,0 +1,136 @@
+/*
+ * ============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=========================================================
+ */
+
+import React, { useState } from "react";
+import Modal from "react-bootstrap/Modal";
+import Button from "react-bootstrap/Button";
+import styled from "styled-components";
+import Row from "react-bootstrap/Row";
+import Form from "react-bootstrap/Form";
+import UploadToscaInstantiationFile from "./UploadToscaInstantiationFile";
+import jsYaml from "js-yaml";
+import Alert from "react-bootstrap/Alert";
+
+const ModalStyled = styled(Modal)`
+ background-color: transparent;
+`
+const StyledMessagesDiv = styled.div`
+ overflow: auto;
+ min-width: 100%;
+ max-height: 300px;
+ padding: 5px 5px 0px 5px;
+ text-align: center;
+`
+
+const UploadToscaInstantiation = (props) => {
+ const [show, setShow] = useState(true);
+ const [fileIsSelected, setFileIsSelected] = useState(false);
+ const [selectedFile, setSelectedFile] = useState();
+ const [jsonObject, setJsonObject] = useState([]);
+ const [alertMessages, setAlertMessages] = useState();
+
+ const fileUploadHandler = (event) => {
+ event.preventDefault();
+ console.log('fileUploadHandler called');
+
+ const file = event.currentTarget.files[0];
+
+ if (file !== undefined) {
+ console.log('fileDefined called');
+ setSelectedFile(file);
+ setFileIsSelected(true);
+
+ const fileReader = new FileReader();
+ fileReader.onload = () => {
+ const jsonFile = jsYaml.load(fileReader.result, 'utf8')
+ setJsonObject(jsonFile)
+ }
+
+ fileReader.readAsText(file);
+ } else {
+ console.log('fileUndefined called');
+ }
+ }
+
+ const onResponseReceivedHandler = async (response) => {
+ console.log('onResponseReceivedHandler called');
+
+ if (await response.ok) {
+ setAlertMessages(<Alert variant="success">
+ <Alert.Heading>Upload Success</Alert.Heading>
+ <p>Tosca Instantiation from { selectedFile.name } was Successfully Uploaded</p>
+ <hr/>
+ <p>Type: { selectedFile.type }</p><p>Size: { +selectedFile.size / 1000 }Kb</p>
+ </Alert>);
+ } else {
+ setAlertMessages(<Alert variant="danger">
+ <Alert.Heading>Upload Failure</Alert.Heading>
+ <p>Tosca Instantiation from { selectedFile.name } failed to upload</p>
+ <p>Status code: { await response.status }: { response.statusText }</p>
+ <p>Response Text: { await response.text() }</p>
+ <hr/>
+ <p>Type: { selectedFile.type }</p><p>Size: { +selectedFile.size / 1000 }Kb</p>
+ </Alert>);
+ }
+ }
+
+ const handleClose = () => {
+ console.log('handleClose called');
+ setShow(false);
+ props.history.push('/');
+ }
+
+ return (
+ <ModalStyled size="lg" show={ show } onHide={ handleClose } backdrop="static" keyboard={ false }>
+ <Modal.Header closeButton>
+ <Modal.Title>Tosca Control Loop - Create Instantiation</Modal.Title>
+ </Modal.Header>
+ <div style={ { padding: '5px 5px 0px 5px' } }>
+ <Modal.Body>
+ <Form style={ { paddingTop: '20px' } }>
+ <Form.Group as={ Row }>
+ <Form.File
+ type="file"
+ className="custom-file-label"
+ id="inputGroupFile01"
+ onChange={ fileUploadHandler }
+ custom
+ accept=".yaml,.yml,.json"
+ label={ fileIsSelected ? selectedFile.name : 'Please select a file' }></Form.File>
+ <UploadToscaInstantiationFile
+ jsonObject={jsonObject}
+ onResponseReceived={onResponseReceivedHandler}/>
+ <Form.Text>Only .yaml, .yml and .json files are supported</Form.Text>
+ </Form.Group>
+ <Form.Group as={ Row }>
+ <StyledMessagesDiv>
+ { alertMessages }
+ </StyledMessagesDiv>
+ </Form.Group>
+ </Form>
+ </Modal.Body>
+ </div>
+ <Modal.Footer>
+ <Button variant="secondary" type="null" onClick={ handleClose }>Close</Button>
+ </Modal.Footer>
+ </ModalStyled>
+ )
+}
+
+export default UploadToscaInstantiation;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.test.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.test.js
new file mode 100644
index 0000000..79daafb
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiation.test.js
@@ -0,0 +1,102 @@
+/*
+ * ============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=========================================================
+ */
+
+import { mount, shallow } from "enzyme";
+import React from "react";
+import toJson from "enzyme-to-json";
+import UploadToscaInstantiation from "./UploadToscaInstantiation";
+import { createMemoryHistory } from "history";
+import { act } from "react-dom/test-utils";
+
+describe("Verify UploadToscaInstantiation", () => {
+ const fs = require("fs");
+ const jsonFile = fs.readFileSync("src/components/dialogs/Policy/toscaInstantiationData.test.json");
+ const file = new Blob([jsonFile], { type: 'file' });
+
+ it("renders without crashing", () => {
+ shallow(<UploadToscaInstantiation/>);
+ });
+
+ it("renders correctly", () => {
+ const tree = shallow(<UploadToscaInstantiation/>);
+ expect(toJson(tree)).toMatchSnapshot();
+ });
+
+ it('should have a Button element', () => {
+ const container = shallow(<UploadToscaInstantiation/>)
+ expect(container.find('Button').length).toEqual(1);
+ });
+
+ it('handleClose called when bottom button clicked', () => {
+ const history = createMemoryHistory();
+ const component = mount(<UploadToscaInstantiation history={ history }/>)
+ const logSpy = jest.spyOn(console, 'log');
+
+
+ act(() => {
+ component.find('[variant="secondary"]').simulate('click');
+ expect(logSpy).toHaveBeenCalledWith('handleClose called');
+ });
+ });
+
+ it('handleClose called when top-right button clicked', () => {
+ const history = createMemoryHistory();
+ const component = mount(<UploadToscaInstantiation history={ history }/>)
+ const logSpy = jest.spyOn(console, 'log');
+
+
+ act(() => {
+ component.find('[size="lg"]').get(0).props.onHide();
+ expect(logSpy).toHaveBeenCalledWith('handleClose called');
+ });
+ });
+
+ it('fileUploadHandler called when uploading a defined file', () => {
+ const component = mount(<UploadToscaInstantiation/>)
+ const logSpy = jest.spyOn(console, 'log');
+
+ const event = {
+ preventDefault() {
+ },
+ currentTarget: { files: [file] }
+ };
+
+ act(() => {
+ component.find('[type="file"]').get(0).props.onChange(event);
+ expect(logSpy).toHaveBeenCalledWith('fileUploadHandler called');
+ expect(logSpy).toHaveBeenCalledWith('fileDefined called');
+ });
+ });
+
+ it('fileUploadHandler called when uploading a undefined file', () => {
+ const component = mount(<UploadToscaInstantiation/>)
+ const logSpy = jest.spyOn(console, 'log');
+
+ const event = {
+ preventDefault() {
+ },
+ currentTarget: { files: [] }
+ };
+
+ act(() => {
+ component.find('[type="file"]').get(0).props.onChange(event);
+ expect(logSpy).toHaveBeenCalledWith('fileUndefined called');
+ });
+ });
+});
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.js
new file mode 100644
index 0000000..5329bc0
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.js
@@ -0,0 +1,52 @@
+/*
+ * ============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=========================================================
+ */
+
+import React, { useEffect, useState } from "react";
+import Button from "react-bootstrap/Button";
+import ControlLoopService from "../../../api/ControlLoopService";
+
+const UploadToscaInstantiationFile = (props) => {
+ const [windowLocationPathName, setWindowLocationPathname] = useState('');
+
+ const postToscaInstantiationHandler = async (event) => {
+ event.preventDefault();
+ console.log('postToscaInstantiationHandler called');
+
+ setWindowLocationPathname(window.location.pathname);
+
+ const response = await ControlLoopService.uploadToscaInstantiation(props.jsonObject, windowLocationPathName)
+ .catch(error => error.message);
+
+ props.onResponseReceived(response);
+ }
+
+ return (
+ <React.Fragment>
+ <Button variant="primary"
+ block={ true }
+ type="submit"
+ onClick={ postToscaInstantiationHandler }>
+ Upload Tosca Instantiation
+ </Button>
+ </React.Fragment>
+ );
+}
+
+export default UploadToscaInstantiationFile;
+
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.test.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.test.js
new file mode 100644
index 0000000..83ab8d5
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaInstantiationFile.test.js
@@ -0,0 +1,61 @@
+/*
+ * ============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=========================================================
+ */
+
+import { mount, shallow } from "enzyme";
+import React from "react";
+import UploadToscaInstantiationFile from "./UploadToscaInstantiationFile";
+import toJson from "enzyme-to-json";
+import { act } from "react-dom/test-utils";
+
+describe('Verify UploadToscaInstantiationFile', () => {
+
+ it("renders without crashing", () => {
+ shallow(<UploadToscaInstantiationFile />);
+ });
+
+ it("renders correctly", () => {
+ const tree = shallow(<UploadToscaInstantiationFile />);
+ expect(toJson(tree)).toMatchSnapshot();
+ });
+
+ it('should have a Button element', () => {
+ const container = shallow(<UploadToscaInstantiationFile />)
+ expect(container.find('Button').length).toEqual(1);
+ });
+
+ it('Button should have a specific text', () => {
+ const container = shallow(<UploadToscaInstantiationFile />)
+ expect(container.find('Button').text()).toBe('Upload Tosca Instantiation');
+ });
+
+ it('button should call postToscaInstantiationHandler when clicked', async () => {
+ const mockFunction = jest.fn(() => 'default');
+ const component = mount(<UploadToscaInstantiationFile onResponseReceived={mockFunction}/>)
+ const logSpy = jest.spyOn(console, 'log');
+ const event = {
+ preventDefault() {
+ }
+ };
+
+ await act(async () => {
+ component.find('[variant="primary"]').get(0).props.onClick(event);
+ expect(logSpy).toHaveBeenCalledWith('postToscaInstantiationHandler called');
+ });
+ });
+});
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/MonitorInstantiation.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/MonitorInstantiation.test.js.snap
new file mode 100644
index 0000000..6504b54
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/MonitorInstantiation.test.js.snap
@@ -0,0 +1,32 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify MonitoringInstantiation renders correctly 1`] = `
+<Styled(Modal)
+ backdrop="static"
+ keyboard={false}
+ onHide={[Function]}
+ show={true}
+ size="xl"
+>
+ <ModalHeader
+ closeButton={true}
+ closeLabel="Close"
+ >
+ <ModalTitle>
+ Tosca Instantiation - Monitoring
+ </ModalTitle>
+ </ModalHeader>
+ <ModalBody />
+ <ModalFooter>
+ <Button
+ active={false}
+ disabled={false}
+ onClick={[Function]}
+ type="null"
+ variant="secondary"
+ >
+ Close
+ </Button>
+ </ModalFooter>
+</Styled(Modal)>
+`;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiation.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiation.test.js.snap
new file mode 100644
index 0000000..77e4b99
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiation.test.js.snap
@@ -0,0 +1,91 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify UploadToscaInstantiation renders correctly 1`] = `
+<Styled(Modal)
+ backdrop="static"
+ keyboard={false}
+ onHide={[Function]}
+ show={true}
+ size="lg"
+>
+ <ModalHeader
+ closeButton={true}
+ closeLabel="Close"
+ >
+ <ModalTitle>
+ Tosca Control Loop - Create Instantiation
+ </ModalTitle>
+ </ModalHeader>
+ <div
+ style={
+ Object {
+ "padding": "5px 5px 0px 5px",
+ }
+ }
+ >
+ <ModalBody>
+ <Form
+ inline={false}
+ style={
+ Object {
+ "paddingTop": "20px",
+ }
+ }
+ >
+ <FormGroup
+ as={
+ Object {
+ "$$typeof": Symbol(react.forward_ref),
+ "defaultProps": Object {
+ "noGutters": false,
+ },
+ "render": [Function],
+ }
+ }
+ >
+ <FormFile
+ accept=".yaml,.yml,.json"
+ className="custom-file-label"
+ custom={true}
+ id="inputGroupFile01"
+ label="Please select a file"
+ onChange={[Function]}
+ type="file"
+ />
+ <UploadToscaInstantiationFile
+ jsonObject={Array []}
+ onResponseReceived={[Function]}
+ />
+ <FormText>
+ Only .yaml, .yml and .json files are supported
+ </FormText>
+ </FormGroup>
+ <FormGroup
+ as={
+ Object {
+ "$$typeof": Symbol(react.forward_ref),
+ "defaultProps": Object {
+ "noGutters": false,
+ },
+ "render": [Function],
+ }
+ }
+ >
+ <styled.div />
+ </FormGroup>
+ </Form>
+ </ModalBody>
+ </div>
+ <ModalFooter>
+ <Button
+ active={false}
+ disabled={false}
+ onClick={[Function]}
+ type="null"
+ variant="secondary"
+ >
+ Close
+ </Button>
+ </ModalFooter>
+</Styled(Modal)>
+`;
diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiationFile.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiationFile.test.js.snap
new file mode 100644
index 0000000..3ac5087
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/UploadToscaInstantiationFile.test.js.snap
@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify UploadToscaInstantiationFile renders correctly 1`] = `
+<Fragment>
+ <Button
+ active={false}
+ block={true}
+ disabled={false}
+ onClick={[Function]}
+ type="submit"
+ variant="primary"
+ >
+ Upload Tosca Instantiation
+ </Button>
+</Fragment>
+`;
diff --git a/gui-clamp/ui-react/src/components/dialogs/Policy/toscaInstantiationData.test.json b/gui-clamp/ui-react/src/components/dialogs/Policy/toscaInstantiationData.test.json
new file mode 100644
index 0000000..d740203
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/Policy/toscaInstantiationData.test.json
@@ -0,0 +1,59 @@
+{
+ "controlLoopList": [
+ {
+ "name": "PMSHInstance0",
+ "version": "1.0.1",
+ "definition": {
+ "name": "org.onap.domain.pmsh.PMSHControlLoopDefinition",
+ "version": "1.2.3"
+ },
+ "state": "UNINITIALISED",
+ "orderedState": "UNINITIALISED",
+ "description": "PMSH control loop instance 0",
+ "elements": {
+ "709c62b3-8918-41b9-a747-d21eb79c6c20": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c20",
+ "definition": {
+ "name": "org.onap.domain.pmsh.PMSH_DCAEMicroservice",
+ "version": "1.2.3"
+ },
+ "participantType": {
+ "name": "org.onap.dcae.controlloop.DCAEMicroserviceControlLoopParticipant",
+ "version": "2.3.4"
+ },
+ "state": "UNINITIALISED",
+ "orderedState": "UNINITIALISED",
+ "description": "DCAE Control Loop Element for the PMSH instance 0 control loop"
+ },
+ "709c62b3-8918-41b9-a747-d21eb79c6c21": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c21",
+ "definition": {
+ "name": "org.onap.domain.pmsh.PMSH_MonitoringPolicyControlLoopElement",
+ "version": "1.2.3"
+ },
+ "participantType": {
+ "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+ "version": "2.3.1"
+ },
+ "state": "UNINITIALISED",
+ "orderedState": "UNINITIALISED",
+ "description": "Monitoring Policy Control Loop Element for the PMSH instance 0 control loop"
+ },
+ "709c62b3-8918-41b9-a747-d21eb79c6c22": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c22",
+ "definition": {
+ "name": "org.onap.domain.pmsh.PMSH_OperationalPolicyControlLoopElement",
+ "version": "1.2.3"
+ },
+ "participantType": {
+ "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+ "version": "2.3.1"
+ },
+ "state": "UNINITIALISED",
+ "orderedState": "UNINITIALISED",
+ "description": "Operational Policy Control Loop Element for the PMSH instance 0 control loop"
+ }
+ }
+ }
+ ]
+}
diff --git a/gui-clamp/ui-react/src/components/menu/MenuBar.js b/gui-clamp/ui-react/src/components/menu/MenuBar.js
index 4574a2a..f32d6c8 100644
--- a/gui-clamp/ui-react/src/components/menu/MenuBar.js
+++ b/gui-clamp/ui-react/src/components/menu/MenuBar.js
@@ -114,7 +114,9 @@ export default class MenuBar extends React.Component {
<NavDropdown.Item as={ StyledLink } to="/undeploy" disabled={ this.state.disabled }>UnDeploy to DCAE (UNDEPLOY)</NavDropdown.Item>
</StyledNavDropdown>
<StyledNavDropdown title="TOSCA Control Loop">
- <NavDropdown.Item as={ StyledLink } to="/monitoring">Monitoring Control Loop</NavDropdown.Item>
+ <NavDropdown.Header>Instantiation</NavDropdown.Header>
+ <NavDropdown.Item as={ StyledLink } to="/monitorInstantiation">Monitor Instantiation</NavDropdown.Item>
+ <NavDropdown.Item as={ StyledLink } to="/uploadToscaInstantiation">Upload Tosca Instantiation</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Header>Commissioning</NavDropdown.Header>
<NavDropdown.Item as={ StyledLink } to="/readToscaTemplate">View Tosca Template</NavDropdown.Item>
diff --git a/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap b/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap
index 2712218..9543c12 100644
--- a/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap
+++ b/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap
@@ -1005,6 +1005,76 @@ exports[`Verify MenuBar Test the render method 1`] = `
<Styled(NavDropdown)
title="TOSCA Control Loop"
>
+ <DropdownHeader
+ role="heading"
+ >
+ Instantiation
+ </DropdownHeader>
+ <DropdownItem
+ as={
+ Object {
+ "$$typeof": Symbol(react.forward_ref),
+ "attrs": Array [],
+ "componentStyle": e {
+ "baseHash": -715527839,
+ "baseStyle": undefined,
+ "componentId": "sc-bdnxRM",
+ "isStatic": false,
+ "rules": Array [
+ "
+ color: ",
+ [Function],
+ ";
+ background-color: ",
+ [Function],
+ ";
+ font-weight: normal;
+ display: block;
+ width: 100%;
+ padding: .25rem 1.5rem;
+ clear: both;
+ text-align: inherit;
+ white-space: nowrap;
+ border: 0;
+
+ :hover {
+ text-decoration: none;
+ background-color: ",
+ [Function],
+ ";
+ color: ",
+ [Function],
+ ";
+ }
+",
+ ],
+ "staticRulesId": "",
+ },
+ "foldedComponentIds": Array [],
+ "render": [Function],
+ "shouldForwardProp": undefined,
+ "styledComponentId": "sc-bdnxRM",
+ "target": Object {
+ "$$typeof": Symbol(react.forward_ref),
+ "propTypes": Object {
+ "innerRef": [Function],
+ "onClick": [Function],
+ "replace": [Function],
+ "target": [Function],
+ "to": [Function],
+ },
+ "render": [Function],
+ },
+ "toString": [Function],
+ "warnTooManyClasses": [Function],
+ "withComponent": [Function],
+ }
+ }
+ disabled={false}
+ to="/monitorInstantiation"
+ >
+ Monitor Instantiation
+ </DropdownItem>
<DropdownItem
as={
Object {
@@ -1066,9 +1136,9 @@ exports[`Verify MenuBar Test the render method 1`] = `
}
}
disabled={false}
- to="/monitoring"
+ to="/uploadToscaInstantiation"
>
- Monitoring Control Loop
+ Upload Tosca Instantiation
</DropdownItem>
<DropdownDivider
role="separator"