diff --git a/package-lock.json b/package-lock.json index 62f082a2..97208ff9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3235,6 +3235,11 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "attr-accept": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz", + "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==" + }, "autoprefixer": { "version": "10.4.4", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", @@ -5626,6 +5631,21 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, + "file-selector": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz", + "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==", + "requires": { + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + } + } + }, "filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -10112,6 +10132,16 @@ "scheduler": "^0.19.1" } }, + "react-dropzone": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz", + "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==", + "requires": { + "attr-accept": "^2.2.2", + "file-selector": "^0.6.0", + "prop-types": "^15.8.1" + } + }, "react-error-overlay": { "version": "6.0.10", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz", diff --git a/package.json b/package.json index 2ee8e622..0de75ea1 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "react-cytoscapejs": "^1.2.1", "react-datetime-picker": "^3.5.0", "react-dom": "^16.14.0", + "react-dropzone": "^14.2.3", "react-helmet": "^6.1.0", "react-router-dom": "^5.2.0", "react-scripts": "^5.0.0", diff --git a/src/components/SliceViewer/DetailForm.jsx b/src/components/SliceViewer/DetailForm.jsx index 3558267d..8db22e2d 100644 --- a/src/components/SliceViewer/DetailForm.jsx +++ b/src/components/SliceViewer/DetailForm.jsx @@ -1,5 +1,4 @@ import React, { Component } from 'react' -import { CopyToClipboard } from 'react-copy-to-clipboard'; import CopyButton from "../common/CopyButton"; import { default as portalData } from "../../services/portalData.json"; @@ -82,15 +81,30 @@ export default class DetailForm extends Component { }
- + 0? data.capacities.core : "configuring"} + disabled + />
- + 0? data.capacities.ram : "configuring"} + disabled + />
- + 0? data.capacities.disk : "configuring"} + disabled + />
} diff --git a/src/components/SliceViewer/Graph.jsx b/src/components/SliceViewer/Graph.jsx index 654e0a20..9f3a794d 100644 --- a/src/components/SliceViewer/Graph.jsx +++ b/src/components/SliceViewer/Graph.jsx @@ -9,6 +9,7 @@ import IconLink from '../../imgs/SliceComponentIcons/Link.png'; import IconSharedNIC from '../../imgs/SliceComponentIcons/SharedNIC.png'; import IconSmartNIC from '../../imgs/SliceComponentIcons/SmartNIC.png'; import IconNVME from '../../imgs/SliceComponentIcons/NVME.png'; +import IconStorage from '../../imgs/SliceComponentIcons/RotatingStorage.png'; import IconNS from '../../imgs/SliceComponentIcons/NetworkService.png'; import _ from "lodash"; import { OverlayTrigger, Tooltip } from 'react-bootstrap'; @@ -76,11 +77,6 @@ export default class Graph extends Component { } - saveJSON = () => { - var jsonBlob = new Blob([ JSON.stringify( this.cy.json() ) ], { type: 'application/javascript;charset=utf-8' }); - saveAs( jsonBlob, `${this.props.sliceName}.json` ); - } - savePNG = () => { var png64 = this.cy.png({ 'bg': 'white', @@ -105,15 +101,18 @@ export default class Graph extends Component { Reset Layout
- - - + { + this.props.isNewSlice && + + + + } { this.props.isNewSlice && @@ -219,6 +218,16 @@ export default class Graph extends Component { "width": 100, } }, + { + "selector": ".graphStorage", + "style": { + "background-image": `${IconStorage}`, + "background-fit": "contain", + "background-color": "#fff", + "height": 70, + "width": 100, + } + }, { "selector": ".graphLink", "style": { diff --git a/src/components/SliceViewer/NewSliceDetailForm.jsx b/src/components/SliceViewer/NewSliceDetailForm.jsx index bfb4d963..2406f6d8 100644 --- a/src/components/SliceViewer/NewSliceDetailForm.jsx +++ b/src/components/SliceViewer/NewSliceDetailForm.jsx @@ -1,6 +1,7 @@ import React, { Component } from 'react' import SingleComponent from './SingleComponent'; import validator from "../../utils/sliceValidator"; +import Dropfile from "../common/Dropfile"; export default class NewSliceDetailForm extends Component { state = { @@ -12,6 +13,8 @@ export default class NewSliceDetailForm extends Component { isRamChanged: false, disk: 0, isDiskChanged: false, + BootScript: "", + isBootScriptChanged: false, showVMComponent: false, validationResult: { isValid: true, @@ -62,6 +65,11 @@ export default class NewSliceDetailForm extends Component { this.setState({ disk, validationResult, isDiskChanged: true }); } + handleBootScriptChange = (e) => { + const BootScript = e.target.value; + this.setState({ BootScript, isBootScriptChanged: true }); + } + handleShowVMComponent = () => { const showOrNot = this.state.showVMComponent; this.setState({ showVMComponent: !showOrNot }); @@ -70,13 +78,15 @@ export default class NewSliceDetailForm extends Component { handleVMUpdate = (e) => { e.preventDefault(); const data = this.props.data; - const { nodeName, core, ram, disk, isNameChanged, isCoreChanged, isRamChanged, isDiskChanged } = this.state; + const { nodeName, core, ram, disk, BootScript, isNameChanged, isCoreChanged, + isRamChanged, isDiskChanged, isBootScriptChanged } = this.state; const newName = isNameChanged ? nodeName : data.properties.name; const newCore = isCoreChanged ? core : JSON.parse(data.capacities).core; const newRam = isRamChanged ? ram : JSON.parse(data.capacities).ram; const newDisk = isDiskChanged ? disk : JSON.parse(data.capacities).disk; + const newBootScript = isBootScriptChanged ? BootScript : data.BootScript; const capacities = JSON.stringify({"core": newCore, "ram": newRam, "disk": newDisk}); - this.props.onVMUpdate({ vm_id: this.props.data.id, new_name: newName, new_capacities: capacities }); + this.props.onVMUpdate({ vm_id: this.props.data.id, new_name: newName, new_capacities: capacities, new_boot_script: newBootScript }); } isCPAvailable = () => { @@ -114,6 +124,10 @@ export default class NewSliceDetailForm extends Component { this.props.onSingleComponentAdd(data); } + handleFileDrop = (textStr) => { + this.props.onJsonUpload(textStr); + } + getVMComponents = () => { const vm_component_ids = []; @@ -154,7 +168,21 @@ export default class NewSliceDetailForm extends Component {
{ (!data || !data.properties) && ( -
Click an element on the topology to view details or make changes.
+
+ { + this.props.nodes.length > 0 && + + + Click an element on the topology to view details or make changes. + + } + { + this.props.nodes.length === 0 && + + } +
) } @@ -225,6 +253,16 @@ export default class NewSliceDetailForm extends Component { { this.state.showVMComponent &&
+
+ +