Added Tosca File Upload Functionality

Added 2 new components
One deals with the file upload to commissioning
Other deals with display of the ui elements

Issue-ID: POLICY-3222
Change-Id: I3b20489bb9e5c499f842cc8adde8147d3e3e8de0
Signed-off-by: saul.gill <saul.gill@est.tech>
diff --git a/gui-clamp/ui-react/package.json b/gui-clamp/ui-react/package.json
index 3826255..17f92d0 100644
--- a/gui-clamp/ui-react/package.json
+++ b/gui-clamp/ui-react/package.json
@@ -33,16 +33,13 @@
 		"@material-ui/pickers": "3.3.10",
 		"bootstrap-css-only": "4.3.1",
 		"js-yaml": "4.1.0",
-		"js-yaml-loader": "1.2.2",
 		"material-table": "1.68.1",
 		"react": "17.0.2",
 		"react-bootstrap": "1.5.2",
 		"react-dom": "17.0.2",
-		"react-native-fs": "2.18.0",
 		"react-router-dom": "5.2.0",
 		"react-scripts": "4.0.3",
 		"react-select": "4.2.1",
-		"react-uuid": "1.0.2",
 		"styled-components": "5.2.1"
 	},
 	"devDependencies": {
diff --git a/gui-clamp/ui-react/src/LoopUI.js b/gui-clamp/ui-react/src/LoopUI.js
index 9461871..6904122 100644
--- a/gui-clamp/ui-react/src/LoopUI.js
+++ b/gui-clamp/ui-react/src/LoopUI.js
@@ -51,6 +51,7 @@
 
 import { Link } from 'react-router-dom';
 import ReadAndConvertYaml from "./components/dialogs/ReadAndConvertYaml";
+import GetLocalToscaFileForUpload from "./components/dialogs/GetLocalToscaFileForUpload";
 
 const StyledMainDiv = styled.div`
   background-color: ${ props => props.theme.backgroundColor };
@@ -296,6 +297,7 @@
     return (
       <React.Fragment>
         <Route path="/readToscaTemplate" render={ (routeProps) => (<ReadAndConvertYaml { ...routeProps } />) }/>
+        <Route path="/uploadToscaFile" render={ (routeProps) => (<GetLocalToscaFileForUpload { ...routeProps } />) }/>
         <Route path="/viewLoopTemplatesModal" render={ (routeProps) => (<ViewLoopTemplatesModal { ...routeProps } />) }/>
         <Route path="/manageDictionaries" render={ (routeProps) => (<ManageDictionaries { ...routeProps } />) }/>
         <Route path="/viewAllPolicies" render={ (routeProps) => (<ViewAllPolicies { ...routeProps } />) }/>
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 f30a85d..e9ed817 100644
--- a/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap
+++ b/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap
@@ -10,6 +10,10 @@
     render={[Function]}
   />
   <Route
+    path="/uploadToscaFile"
+    render={[Function]}
+  />
+  <Route
     path="/viewLoopTemplatesModal"
     render={[Function]}
   />
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 9205eed..4488c7c 100644
--- a/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap
+++ b/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap
@@ -39,6 +39,10 @@
       render={[Function]}
     />
     <Route
+      path="/uploadToscaFile"
+      render={[Function]}
+    />
+    <Route
       path="/viewLoopTemplatesModal"
       render={[Function]}
     />
diff --git a/gui-clamp/ui-react/src/api/UploadToscaFile.js b/gui-clamp/ui-react/src/api/UploadToscaFile.js
new file mode 100644
index 0000000..1bde9e7
--- /dev/null
+++ b/gui-clamp/ui-react/src/api/UploadToscaFile.js
@@ -0,0 +1,63 @@
+/*
+ * -
+ *  * ============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 Button from "react-bootstrap/Button";
+import React, { useState } from "react";
+
+const UploadToscaFile = (props) => {
+  const [windowLocationPathName, setWindowLocationPathname] = useState('');
+
+  const postServiceTemplateHandler = async (event) => {
+
+    event.preventDefault();
+    setWindowLocationPathname(window.location.pathname);
+
+    const response = await fetch(windowLocationPathName +
+      '/restservices/clds/v2/toscaControlLoop/commissionToscaTemplate', {
+      method: 'POST',
+      headers: {
+        "Content-Type": "application/json"
+      },
+      credentials: 'same-origin',
+      body: JSON.stringify(props.toscaObject),
+    });
+
+    const responseObj = await response;
+    const responseMessage = await response.text();
+
+    props.onResponseReceived(responseObj, responseMessage);
+
+  }
+
+  return (
+    <React.Fragment>
+      <Button variant="primary"
+              block={ true }
+              type="submit"
+              onClick={ postServiceTemplateHandler }>
+        Upload Tosca Service Template
+      </Button>
+    </React.Fragment>
+  );
+
+};
+
+export default UploadToscaFile;
diff --git a/gui-clamp/ui-react/src/components/dialogs/GetLocalToscaFileForUpload.js b/gui-clamp/ui-react/src/components/dialogs/GetLocalToscaFileForUpload.js
new file mode 100644
index 0000000..f159280
--- /dev/null
+++ b/gui-clamp/ui-react/src/components/dialogs/GetLocalToscaFileForUpload.js
@@ -0,0 +1,150 @@
+/*
+ * -
+ *  * ============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 Button from "react-bootstrap/Button";
+import Modal from 'react-bootstrap/Modal';
+import Form from 'react-bootstrap/Form';
+import Row from 'react-bootstrap/Row';
+import styled from 'styled-components';
+import Alert from 'react-bootstrap/Alert';
+import * as yaml from "js-yaml";
+import UploadToscaFile from "../../api/UploadToscaFile";
+
+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 GetLocalToscaFileForUpload = (props) => {
+  const [selectedFile, setSelectedFile] = useState();
+  const [fileIsSelected, setFileIsSelected] = useState(false);
+  const [toscaJsonObject, setToscaJsonObject] = useState({});
+  const [show, setShow] = useState(true);
+  const [alertMessages, setAlertMessages] = useState();
+
+  const handleClose = () => {
+    setShow(false);
+    props.history.push('/');
+  }
+
+  const fileChangeHandler = (event) => {
+    event.preventDefault();
+
+    if (event.currentTarget.files[0] !== undefined) {
+      setSelectedFile(event.currentTarget.files[0]);
+      setFileIsSelected(true);
+
+      const file = event.currentTarget.files[0];
+
+      setAlertMessages([]);
+
+      const fileReader = new FileReader();
+
+      fileReader.onload = () => {
+        const jsonObj = yaml.load(fileReader.result, 'utf8');
+        setToscaJsonObject(jsonObj);
+      }
+
+      fileReader.readAsText(file);
+
+    } else {
+      return;
+    }
+  };
+
+  const receiveResponseFromUpload = (response, responseMessage) => {
+
+    if (response.ok) {
+      setAlertMessages(<Alert variant="success">
+        <Alert.Heading>Upload Success</Alert.Heading>
+        <p>Tosca Service Template 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 Service Template from { selectedFile.name } failed to upload</p>
+        <p>Status code: { response.status }: { response.statusText }</p>
+        <p>Response from CLAMP: { responseMessage }</p>
+        <hr/>
+        <p>Type: { selectedFile.type }</p><p>Size: { +selectedFile.size / 1000 }Kb</p>
+      </Alert>);
+    }
+  };
+
+  return (
+    <ModalStyled size="lg"
+                 show={ show }
+                 onHide={ handleClose }
+                 backdrop="static"
+                 keyboard={ false }>
+      <Modal.Header closeButton>
+        <Modal.Title>Upload Tosca to Commissioning API</Modal.Title>
+      </Modal.Header>
+      <br/>
+      <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={ fileChangeHandler }
+                custom
+                accept=".yaml,.yml,.json"
+                label={ fileIsSelected ? selectedFile.name : 'Please select a file' }
+              >
+              </Form.File>
+              <Form.Text>Only .yaml, .yml and .json files are supported</Form.Text>
+            </Form.Group>
+            <Form.Group as={ Row }>
+              <UploadToscaFile toscaObject={ toscaJsonObject }
+                               onResponseReceived={ receiveResponseFromUpload }/>
+            </Form.Group>
+            <Form.Group as={ Row }>
+              <StyledMessagesDiv>
+                { alertMessages }
+              </StyledMessagesDiv>
+            </Form.Group>
+          </Form>
+        </Modal.Body>
+      </div>
+      <Modal.Footer>
+        <Button variant="secondary"
+                onClick={ handleClose }>Close</Button>
+      </Modal.Footer>
+    </ModalStyled>
+  );
+}
+
+export default GetLocalToscaFileForUpload;
diff --git a/gui-clamp/ui-react/src/components/menu/MenuBar.js b/gui-clamp/ui-react/src/components/menu/MenuBar.js
index 75a56d7..978a87a 100644
--- a/gui-clamp/ui-react/src/components/menu/MenuBar.js
+++ b/gui-clamp/ui-react/src/components/menu/MenuBar.js
@@ -89,6 +89,7 @@
       <Navbar.Collapse>
         <StyledNavDropdown title="Tosca">
           <NavDropdown.Item as={ StyledLink } to="/readToscaTemplate">View Tosca Template</NavDropdown.Item>
+          <NavDropdown.Item as={ StyledLink } to="/uploadToscaFile">Upload Tosca to Commissioning</NavDropdown.Item>
         </StyledNavDropdown>
         <StyledNavDropdown title="POLICY Framework">
           <NavDropdown.Item as={ StyledLink } to="/viewAllPolicies">View All Policies</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 01f692b..2fef6c7 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
@@ -70,6 +70,71 @@
     >
       View Tosca Template
     </DropdownItem>
+    <DropdownItem
+      as={
+        Object {
+          "$$typeof": Symbol(react.forward_ref),
+          "attrs": Array [],
+          "componentStyle": e {
+            "baseHash": 1014106698,
+            "baseStyle": undefined,
+            "componentId": "sc-bdfBwQ",
+            "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-bdfBwQ",
+          "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="/uploadToscaFile"
+    >
+      Upload Tosca to Commissioning
+    </DropdownItem>
   </Styled(NavDropdown)>
   <Styled(NavDropdown)
     title="POLICY Framework"