From b8a45447109dfed0517c5c2976078af58befa433 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Wed, 24 Jun 2020 15:32:07 +0200 Subject: [PATCH 01/17] Querying VILLASnode API works, API endpoint hardcoded for now, processing of response missing #224 --- src/scenario/scenario.js | 36 ++++++++++++++++++++++++++++++ src/signal/signal-store.js | 27 ++++++++++++++++++++-- src/signal/signals-data-manager.js | 20 +++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 8d3495e..ee54a36 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -392,6 +392,37 @@ class Scenario extends React.Component { } } + signalsAutoConf(index){ + let componentConfig = this.state.configs[index]; + console.log("Signal AutoConf for CC: ", componentConfig); + + // determine host of infrastructure component + let ic = this.state.ics.filter(ic => ic.id === componentConfig.icID) + console.log("Signal AutoConf for IC: ", ic); + + let request = {}; + request["id"] = this.uuidv4(); + request["action"] = "config" + + // TODO add parameter for API host in data model of infrastructure component + let api = 'https://villas.k8s.eonerc.rwth-aachen.de/ws/api/v1' + + AppDispatcher.dispatch({ + type: 'signals/start-autoconfig', + data: request, + url: api + }); + + } + + uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + // eslint-disable-next-line + var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + /* ############################################## * File modification methods ############################################## */ @@ -441,6 +472,11 @@ class Scenario extends React.Component { editButton onEdit={index => this.setState({ editInputSignalsModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })} /> + this.signalsAutoConf(index)} + /> this.getICName(icID)} /> { + AppDispatcher.dispatch({ + type: 'signals/autoconfig-loaded', + data: response + }); + }).catch(error => { + AppDispatcher.dispatch({ + type: 'signals/autoconfig-error', + error: error + }) + }) + } + } export default new SignalsDataManager() From c00c16ddb540ab5a3305cbe9c6f5a43ce2a6c88f Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Wed, 1 Jul 2020 13:10:46 +0200 Subject: [PATCH 02/17] receive config of VILLASnode based on apihost parameter of IC --- src/scenario/scenario.js | 11 ++--------- src/signal/signals-data-manager.js | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index ee54a36..6f93ed7 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -394,23 +394,16 @@ class Scenario extends React.Component { signalsAutoConf(index){ let componentConfig = this.state.configs[index]; - console.log("Signal AutoConf for CC: ", componentConfig); - // determine host of infrastructure component - let ic = this.state.ics.filter(ic => ic.id === componentConfig.icID) - console.log("Signal AutoConf for IC: ", ic); - + let ic = this.state.ics.find(ic => ic.id === componentConfig.icID) let request = {}; request["id"] = this.uuidv4(); request["action"] = "config" - // TODO add parameter for API host in data model of infrastructure component - let api = 'https://villas.k8s.eonerc.rwth-aachen.de/ws/api/v1' - AppDispatcher.dispatch({ type: 'signals/start-autoconfig', data: request, - url: api + url: ic.apihost }); } diff --git a/src/signal/signals-data-manager.js b/src/signal/signals-data-manager.js index 653d051..94fa1b4 100644 --- a/src/signal/signals-data-manager.js +++ b/src/signal/signals-data-manager.js @@ -42,7 +42,6 @@ class SignalsDataManager extends RestDataManager{ // data contains the request data: { action, id, (request)} // See documentation of VILLASnode API: https://villas.fein-aachen.org/doc/node-dev-api-node.html - console.log("startAutoConfig: POST to ", url, ": ", data); RestAPI.post(url, data).then(response => { AppDispatcher.dispatch({ type: 'signals/autoconfig-loaded', From f038cfe0c87f3736a4f55bf285af34d7c16dac77 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Wed, 1 Jul 2020 13:56:06 +0200 Subject: [PATCH 03/17] Add notifications, auto conf only for VILLASnode ICs #224 --- src/scenario/scenario.js | 14 ++++++++++++++ src/signal/signal-store.js | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 6f93ed7..8c91c95 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -42,6 +42,7 @@ import EditConfigDialog from "../componentconfig/edit-config"; import EditSignalMapping from "../signal/edit-signal-mapping"; import FileStore from "../file/file-store" import WidgetStore from "../widget/widget-store"; +import NotificationsDataManager from "../common/data-managers/notifications-data-manager"; class Scenario extends React.Component { @@ -396,6 +397,19 @@ class Scenario extends React.Component { let componentConfig = this.state.configs[index]; // determine host of infrastructure component let ic = this.state.ics.find(ic => ic.id === componentConfig.icID) + if(!ic.type.includes("VILLASnode") && !ic.type.includes("villasnode") && !ic.type.includes("VILLASNODE")){ + let message = "Cannot autoconfigure signals for IC type " + ic.type + " of category " + ic.category + ". This is only possible for gateway ICs of type 'VILLASnode'." + console.warn(message); + + const SIGNAL_AUTOCONF_WARN_NOTIFICATION = { + title: 'Failed to load signal config for IC ' + ic.name, + message: message, + level: 'warning' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_WARN_NOTIFICATION); + return; + } + let request = {}; request["id"] = this.uuidv4(); request["action"] = "config" diff --git a/src/signal/signal-store.js b/src/signal/signal-store.js index c947e56..e41b10c 100644 --- a/src/signal/signal-store.js +++ b/src/signal/signal-store.js @@ -40,6 +40,14 @@ class SignalStore extends ArrayStore{ case 'signals/autoconfig-loaded': console.log("AutoConfig Loaded: ", action.data) // TODO save signal config contained in action.data + + const SIGNAL_AUTOCONF_INFO_NOTIFICATION = { + title: 'Signal configuration loaded successfully.', + message: '', + level: 'info' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_INFO_NOTIFICATION); + return super.reduce(state, action); case 'signals/autoconfig-error': From cc156d751bcb6e880ed35a272eb31778021c2f05 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Mon, 6 Jul 2020 11:33:11 +0200 Subject: [PATCH 04/17] implement signal auto config functionality based on response from VILLASnode API (to be tested) #224 --- src/scenario/scenario.js | 8 +- src/signal/signal-store.js | 10 +-- src/signal/signals-data-manager.js | 129 ++++++++++++++++++++++++++++- 3 files changed, 135 insertions(+), 12 deletions(-) diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 8c91c95..d509e52 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -410,14 +410,18 @@ class Scenario extends React.Component { return; } + let splitHost = ic.host.split("/") let request = {}; request["id"] = this.uuidv4(); - request["action"] = "config" + request["action"] = "nodes" AppDispatcher.dispatch({ type: 'signals/start-autoconfig', data: request, - url: ic.apihost + url: ic.apihost, + socketname: splitHost[splitHost.length -1], + token: this.state.sessionToken, + configID: componentConfig.id }); } diff --git a/src/signal/signal-store.js b/src/signal/signal-store.js index e41b10c..ff4d228 100644 --- a/src/signal/signal-store.js +++ b/src/signal/signal-store.js @@ -34,19 +34,13 @@ class SignalStore extends ArrayStore{ return super.reduce(state, action); case 'signals/start-autoconfig': - this.dataManager.startAutoConfig(action.data, action.url) + this.dataManager.startAutoConfig(action.data, action.url, action.socketname, action.token, action.configID) return super.reduce(state, action); case 'signals/autoconfig-loaded': console.log("AutoConfig Loaded: ", action.data) // TODO save signal config contained in action.data - - const SIGNAL_AUTOCONF_INFO_NOTIFICATION = { - title: 'Signal configuration loaded successfully.', - message: '', - level: 'info' - }; - NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_INFO_NOTIFICATION); + this.dataManager.saveSignals(action.data, action.token, action.configID, action.socketname); return super.reduce(state, action); diff --git a/src/signal/signals-data-manager.js b/src/signal/signals-data-manager.js index 94fa1b4..c8f7127 100644 --- a/src/signal/signals-data-manager.js +++ b/src/signal/signals-data-manager.js @@ -18,6 +18,7 @@ import RestDataManager from '../common/data-managers/rest-data-manager'; import RestAPI from "../common/api/rest-api"; import AppDispatcher from "../common/app-dispatcher"; +import NotificationsDataManager from "../common/data-managers/notifications-data-manager"; class SignalsDataManager extends RestDataManager{ @@ -36,7 +37,7 @@ class SignalsDataManager extends RestDataManager{ } - startAutoConfig(data, url){ + startAutoConfig(data, url, socketname, token, configID){ // This function queries the VILLASnode API to obtain the configuration of the VILLASnode located at url // Endpoint: http[s]://server:port/api/v1 (to be generated based on IC host, port 4000) // data contains the request data: { action, id, (request)} @@ -45,7 +46,10 @@ class SignalsDataManager extends RestDataManager{ RestAPI.post(url, data).then(response => { AppDispatcher.dispatch({ type: 'signals/autoconfig-loaded', - data: response + data: response, + token: token, + socketname: socketname, + configID: configID }); }).catch(error => { AppDispatcher.dispatch({ @@ -55,6 +59,127 @@ class SignalsDataManager extends RestDataManager{ }) } + saveSignals(data, token, configID, socketname){ + // data.response contains the response from the VILLASnode API, an array of node configurations + + if(!data.hasOwnProperty("response")){ + const SIGNAL_AUTOCONF_ERROR_NOTIFICATION = { + title: 'Failed to load signal config ', + message: 'VILLASnode returned no response field.', + level: 'error' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_ERROR_NOTIFICATION); + return; + } + + let configured = false; + let error = false; + for(let nodeConfig of data.response){ + if(!nodeConfig.hasOwnProperty("name")){ + console.warn("Could not parse the following node config because it lacks a name parameter:", nodeConfig); + } else if(nodeConfig.name === socketname){ + if(configured){ + const SIGNAL_AUTOCONF_WARNING_NOTIFICATION = { + title: 'There might be a problem with the signal auto-config', + message: 'VILLASnode returned multiple node configurations for the websocket ' + socketname + '. This is a problem of the VILLASnode.', + level: 'warning' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_WARNING_NOTIFICATION); + continue; + } + // signals are not yet configured: + console.log("Adding signals of websocket: ", nodeConfig); + let index_in = 1 + let index_out = 1 + + if(!nodeConfig.in.hasOwnProperty("signals")){ + const SIGNAL_AUTOCONF_ERROR_NOTIFICATION = { + title: 'Failed to load in signal config ', + message: 'No field for in signals contained in response.', + level: 'error' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_ERROR_NOTIFICATION); + error = true; + } else{ + + // add all in signals + for(let inSig of nodeConfig.in.signals) { + console.log("adding input signal:", inSig); + + if (inSig.enabled) { + let newSignal = { + configID: configID, + direction: 'in', + name: inSig.hasOwnProperty("name") ? inSig.name : "in_" + String(index_in), + unit: inSig.hasOwnProperty("unit") ? inSig.unit : '-', + index: index_in, + scalingFactor: 1.0 + }; + + AppDispatcher.dispatch({ + type: 'signals/start-add', + data: newSignal, + token: token + }); + + index_in++; + } + } + } + + if(!nodeConfig.out.hasOwnProperty("signals")){ + const SIGNAL_AUTOCONF_ERROR_NOTIFICATION = { + title: 'Failed to load out signal config ', + message: 'No field for out signals contained in response.', + level: 'error' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_ERROR_NOTIFICATION); + error=true; + }else { + + // add all out signals + + for (let outSig of nodeConfig.out.signals) { + console.log("adding output signal:", outSig); + + if (outSig.enabled) { + let newSignal = { + configID: configID, + direction: 'out', + name: outSig.hasOwnProperty("name") ? outSig.name : "out_" + String(index_out), + unit: outSig.hasOwnProperty("unit") ? outSig.unit : '-', + index: index_out, + scalingFactor: 1.0 + }; + + AppDispatcher.dispatch({ + type: 'signals/start-add', + data: newSignal, + token: token + }); + + index_out++; + } + } + } + + console.log("Configured", index_in-1, "input signals and", index_out-1, "output signals"); + configured=true; + } + + } + + if(!error) { + const SIGNAL_AUTOCONF_INFO_NOTIFICATION = { + title: 'Signal configuration loaded successfully.', + message: '', + level: 'info' + }; + NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_INFO_NOTIFICATION); + } + + } + } export default new SignalsDataManager() From 1f6a4a07ba47cb0ba5a81e9a37dd6c007dbd8f00 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Mon, 6 Jul 2020 12:50:40 +0200 Subject: [PATCH 05/17] Add API host parameter to IC table, make the parameter editable --- src/ic/edit-ic.js | 11 +++++++++++ src/ic/ics.js | 1 + 2 files changed, 12 insertions(+) diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index 404642c..e91c8ef 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -31,6 +31,7 @@ class EditICDialog extends React.Component { this.state = { name: '', host: '', + apihost: '', type: '', category: '', properties: {}, @@ -50,6 +51,10 @@ class EditICDialog extends React.Component { data.host = this.state.host; } + if (this.state.apihost != null && this.state.apihost !== "" && this.state.apihost !== "http://" && this.state.apihost !== this.props.ic.apihost) { + data.apihost = this.state.apihost; + } + if (this.state.type != null && this.state.type !== "" && this.state.type !== this.props.ic.type) { data.type = this.state.type; } @@ -77,6 +82,7 @@ class EditICDialog extends React.Component { this.setState({ name: this.props.ic.name, host: this.props.ic.host, + apihost: this.props.ic.apihost, type: this.props.ic.type, category: this.props.ic.category, properties: _.merge({}, _.get(this.props.ic, 'rawProperties'), _.get(this.props.ic, 'properties')) @@ -97,6 +103,11 @@ class EditICDialog extends React.Component { this.handleChange(e)} /> + + API Host + this.handleChange(e)} /> + + Category (e.g. Simulator, Gateway, ...) this.handleChange(e)} /> diff --git a/src/ic/ics.js b/src/ic/ics.js index e24cd93..5cd7719 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -280,6 +280,7 @@ class InfrastructureComponents extends Component { {/* */} + Date: Sat, 24 Oct 2020 13:37:17 +0200 Subject: [PATCH 06/17] Add column for ManagedExternally parameter #266 --- src/ic/ics.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ic/ics.js b/src/ic/ics.js index 49442d8..635b7a8 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -291,6 +291,16 @@ class InfrastructureComponents extends Component { return dateTime.toLocaleString('de-DE'); } + modifyManagedExternallyColumn(managedExternally){ + + if(managedExternally){ + return + } else { + return + } + + } + render() { const buttonStyle = { marginLeft: '10px' @@ -306,6 +316,7 @@ class InfrastructureComponents extends Component { this.stateLabelStyle(state, component)} /> + this.modifyManagedExternallyColumn(managedexternally)} width='105' /> {/* */} From c2d0378ee51eea263edc54631101e60504613abb Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Sat, 24 Oct 2020 19:01:05 +0200 Subject: [PATCH 07/17] Edit button disabled for externally managed ICs #266 --- src/common/table.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/common/table.js b/src/common/table.js index 87a52be..b1c32f5 100644 --- a/src/common/table.js +++ b/src/common/table.js @@ -103,8 +103,9 @@ class CustomTable extends Component { // add buttons if (child.props.editButton) { - cell.push( Edit } > - ); + let disable = (typeof data.managedexternally !== "undefined" && data.managedexternally); + cell.push({disable? "Externally managed ICs cannot be edited" : "edit"} } > + ); } if (child.props.deleteButton) { From 7a76e5e71bb4d01ec65ebccd2f1456abd7032ee7 Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Wed, 28 Oct 2020 18:30:08 +0100 Subject: [PATCH 08/17] Adapt add, edit and delete dialogs #266 --- src/common/dialogs/delete-dialog.js | 6 +++++- src/ic/edit-ic.js | 22 ++++++++++++++++++++-- src/ic/ics.js | 2 +- src/ic/new-ic.js | 24 ++++++++++++++++++++---- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/common/dialogs/delete-dialog.js b/src/common/dialogs/delete-dialog.js index cbc0cd8..8d114f4 100644 --- a/src/common/dialogs/delete-dialog.js +++ b/src/common/dialogs/delete-dialog.js @@ -16,7 +16,8 @@ ******************************************************************************/ import React from 'react'; -import { Button, Modal } from 'react-bootstrap'; +import { Button, Modal, FormLabel } from 'react-bootstrap'; +import {Collapse} from 'react-collapse'; class DeleteDialog extends React.Component { onModalKeyPress = (event) => { @@ -35,6 +36,9 @@ class DeleteDialog extends React.Component { Are you sure you want to delete the {this.props.title} '{this.props.name}'? + + The IC will be deleted if the respective VILLAScontroller sends "gone" state and no component config is using the IC anymore + diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index e5784e0..9e8fe4a 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -16,9 +16,9 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { FormGroup, FormControl, FormLabel, FormCheck } from 'react-bootstrap'; import _ from 'lodash'; - +import {Collapse} from 'react-collapse'; import Dialog from '../common/dialogs/dialog'; import ParametersEditor from '../common/parameters-editor'; @@ -33,6 +33,7 @@ class EditICDialog extends React.Component { host: '', type: '', category: '', + managedexternally: false, properties: {}, }; } @@ -61,16 +62,25 @@ class EditICDialog extends React.Component { data.properties = this.state.properties } + data.managedexternally = this.state.managedexternally; + this.props.onClose(data); + this.setState({managedexternally: false}); } } else { this.props.onClose(); + this.setState({managedexternally: false}); } } handleChange(e) { + if(e.target.id === "managedexternally"){ + this.setState({ managedexternally : !this.state.managedexternally}); + } + else{ this.setState({ [e.target.id]: e.target.value }); + } } handlePropertiesChange(data) { @@ -83,6 +93,7 @@ class EditICDialog extends React.Component { host: this.props.ic.host, type: this.props.ic.type, category: this.props.ic.category, + managedexternally: false, properties: _.merge({}, _.get(this.props.ic, 'rawProperties'), _.get(this.props.ic, 'properties')) }); } @@ -100,6 +111,13 @@ class EditICDialog extends React.Component { >
UUID: {this.props.ic.uuid} + + this.handleChange(e)}> + + + + Externally managed ICs cannot be edited by users + Name this.handleChange(e)} /> diff --git a/src/ic/ics.js b/src/ic/ics.js index 635b7a8..44173e7 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -370,7 +370,7 @@ class InfrastructureComponents extends Component { this.closeEditModal(data)} ic={this.state.modalIC} /> this.closeImportModal(data)} /> - this.closeDeleteModal(e)} /> + this.closeDeleteModal(e)} /> ); } diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 93f1e83..78c67a8 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -16,8 +16,8 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; - +import { FormGroup, FormControl, FormLabel, FormCheck } from 'react-bootstrap'; +import {Collapse} from 'react-collapse'; import Dialog from '../common/dialogs/dialog'; class NewICDialog extends React.Component { @@ -32,6 +32,7 @@ class NewICDialog extends React.Component { uuid: '', type: '', category: '', + managedexternally: false, }; } @@ -42,7 +43,8 @@ class NewICDialog extends React.Component { name: this.state.name, type: this.state.type, category: this.state.category, - uuid: this.state.uuid + uuid: this.state.uuid, + managedexternally: this.state.managedexternally, }; if (this.state.host != null && this.state.host !== "" && this.state.host !== 'http://') { @@ -50,18 +52,25 @@ class NewICDialog extends React.Component { } this.props.onClose(data); + this.setState({managedexternally: false}); } } else { this.props.onClose(); + this.setState({managedexternally: false}); } } handleChange(e) { + if(e.target.id === "managedexternally"){ + this.setState({ managedexternally : !this.state.managedexternally}); + } + else{ this.setState({ [e.target.id]: e.target.value }); + } } resetState() { - this.setState({ name: '', host: 'http://', uuid: this.uuidv4(), type: '', category: ''}); + this.setState({ name: '', host: 'http://', uuid: this.uuidv4(), type: '', category: '', managedexternally: false}); } validateForm(target) { @@ -110,6 +119,13 @@ class NewICDialog extends React.Component { return ( this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> + + this.handleChange(e)}> + + + + the component will show up in the list only after a VILLAScontroller for the component type has created the component and cannot be edited by users + Name this.handleChange(e)} /> From 0deec453833654da2a5370599e83984239b6eaf8 Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Wed, 28 Oct 2020 20:35:39 +0100 Subject: [PATCH 09/17] Category and type of IC (in edit and add) are now selectable via drop down menu #266 --- src/ic/edit-ic.js | 41 +++++++++++++++++++++++++++++++++++------ src/ic/new-ic.js | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index 9e8fe4a..7386131 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -99,6 +99,26 @@ class EditICDialog extends React.Component { } render() { + let typeOptions = []; + switch(this.state.category){ + case "Simulator": + typeOptions = ["Dummy","Generic","DPsim","RTLAB","RSCAD"]; + break; + case "Controller": + typeOptions = ["Kubernetes","VILLAS-controller"]; + break; + case "Gateway": + typeOptions = ["VILLAS-node","VILLAS-relay"]; + break; + case "Service": + typeOptions = ["EMS","Custom"]; + break; + case "Equipment": + typeOptions = ["Chroma-emulator","Chroma-loads","SMA-sunnyboy","FLEPS","Sonnenbatterie"]; + break; + default: + typeOptions =[]; + } return ( - Category (e.g. Simulator, Gateway, ...) - this.handleChange(e)} /> - + Category + this.handleChange(e)}> + + + + + + - Type (e.g. RTDS, VILLASnode, ...) - this.handleChange(e)} /> - + Type + this.handleChange(e)}> + + {typeOptions.map((name,index) => ( + + ))} + Properties diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 78c67a8..466ead5 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -116,6 +116,26 @@ class NewICDialog extends React.Component { } render() { + let typeOptions = []; + switch(this.state.category){ + case "Simulator": + typeOptions = ["Dummy","Generic","DPsim","RTLAB","RSCAD"]; + break; + case "Controller": + typeOptions = ["Kubernetes","VILLAS-controller"]; + break; + case "Gateway": + typeOptions = ["VILLAS-node","VILLAS-relay"]; + break; + case "Service": + typeOptions = ["EMS","Custom"]; + break; + case "Equipment": + typeOptions = ["Chroma-emulator","Chroma-loads","SMA-sunnyboy","FLEPS","Sonnenbatterie"]; + break; + default: + typeOptions =[]; + } return ( this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> @@ -137,14 +157,24 @@ class NewICDialog extends React.Component { - Category of component (e.g. Simulator, Gateway, ...) - this.handleChange(e)} /> - + Category of component + this.handleChange(e)}> + + + + + + + - Type of component (e.g. RTDS, VILLASnode, ...) - this.handleChange(e)} /> - + Type of component + this.handleChange(e)}> + + {typeOptions.map((name,index) => ( + + ))} + UUID From 8ce2ba11612b34ecf1701435875c0b0cb27fbc8d Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Sun, 1 Nov 2020 15:27:05 +0100 Subject: [PATCH 10/17] Add column for IC uptime, WIP: add IC infos and controls dialog #266 --- src/ic/ic-dialog.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/ic/ics.js | 29 ++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 src/ic/ic-dialog.js diff --git a/src/ic/ic-dialog.js b/src/ic/ic-dialog.js new file mode 100644 index 0000000..b134f95 --- /dev/null +++ b/src/ic/ic-dialog.js @@ -0,0 +1,45 @@ +import React from 'react'; +import {FormLabel} from 'react-bootstrap'; +import Dialog from '../common/dialogs/dialog'; + + +class ICDialog extends React.Component { + valid = true; + + constructor(props) { + super(props); + + this.state = { + ic: props.ic + }; + } + + onClose(canceled) { + this.props.onClose(); + } + + handleChange(e) { + + } + + + render() { + + return ( + this.onClose(c)} + valid={true} + size='lg' + > + + Infos and Controls + + + ); + } +} + +export default ICDialog; diff --git a/src/ic/ics.js b/src/ic/ics.js index 44173e7..e873f2b 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -17,7 +17,7 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import { Button } from 'react-bootstrap'; +import { Button, Badge } from 'react-bootstrap'; import FileSaver from 'file-saver'; import _ from 'lodash'; import moment from 'moment' @@ -31,6 +31,7 @@ import TableColumn from '../common/table-column'; import NewICDialog from './new-ic'; import EditICDialog from './edit-ic'; import ImportICDialog from './import-ic'; +import ICDialog from './ic-dialog'; import ICAction from './ic-action'; import DeleteDialog from '../common/dialogs/delete-dialog'; @@ -78,6 +79,7 @@ class InfrastructureComponents extends Component { ics: ics, modalIC: {}, deleteModal: false, + icModal: false, selectedICs: [], currentUser: JSON.parse(localStorage.getItem("currentUser")) }; @@ -99,7 +101,7 @@ class InfrastructureComponents extends Component { refresh() { - if (this.state.editModal || this.state.deleteModal){ + if (this.state.editModal || this.state.deleteModal || this.state.icModal){ // do nothing since a dialog is open at the moment } else { @@ -139,6 +141,10 @@ class InfrastructureComponents extends Component { } } + closeICModal(data){ + this.setState({ icModal : false }); + } + closeDeleteModal(confirmDelete){ this.setState({ deleteModal: false }); @@ -200,7 +206,7 @@ class InfrastructureComponents extends Component { this.setState({ selectedICs: selectedICs }); } - runAction = action => { + runAction(action) { for (let index of this.state.selectedICs) { AppDispatcher.dispatch({ type: 'ics/start-action', @@ -301,6 +307,16 @@ class InfrastructureComponents extends Component { } + modifyUptimeColumn(uptime){ + if(uptime >= 0){ + return {uptime + "s"} + } + else{ + return Unknown + } + } + + render() { const buttonStyle = { marginLeft: '10px' @@ -312,11 +328,12 @@ class InfrastructureComponents extends Component { this.onICChecked(index, event)} width='30' /> - + this.setState({ icModal: true, modalIC: this.state.ics[index], modalIndex: index })}/> this.stateLabelStyle(state, component)} /> this.modifyManagedExternallyColumn(managedexternally)} width='105' /> + this.modifyUptimeColumn(uptime)}/> {/* */} @@ -343,7 +360,7 @@ class InfrastructureComponents extends Component {
this.runAction(action)} actions={[ { id: '-1', title: 'Select command', data: { action: 'none' } }, { id: '0', title: 'Reset', data: { action: 'reset' } }, @@ -369,6 +386,8 @@ class InfrastructureComponents extends Component { this.closeNewModal(data)} /> this.closeEditModal(data)} ic={this.state.modalIC} /> this.closeImportModal(data)} /> + this.closeICModal(data)} ic={this.state.modalIC} token={this.state.sessionToken} /> + this.closeDeleteModal(e)} />
From 464b09a58ac6e666127fc648de5eaf4f1333cad9 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Thu, 12 Nov 2020 11:51:10 +0100 Subject: [PATCH 11/17] Refactor "host" to "websocketurl" and "apihost" to "apiurl" #266 --- REACT.md | 12 +- doc/Production.md | 2 +- package-lock.json | 1005 +++++++++++++++++++++++++--- package.json | 20 +- src/common/api/websocket-api.js | 24 +- src/ic/edit-ic.js | 28 +- src/ic/ic-data-data-manager.js | 10 +- src/ic/ic-store.js | 14 +- src/ic/ics.js | 6 +- src/ic/import-ic.js | 16 +- src/ic/new-ic.js | 25 +- src/scenario/scenario.js | 12 +- src/signal/signals-data-manager.js | 2 +- 13 files changed, 1019 insertions(+), 157 deletions(-) diff --git a/REACT.md b/REACT.md index e290b93..430d5fa 100644 --- a/REACT.md +++ b/REACT.md @@ -538,7 +538,7 @@ Inside `index.html`, you can use it like this: Only files inside the `public` folder will be accessible by `%PUBLIC_URL%` prefix. If you need to use a file from `src` or `node_modules`, you’ll have to copy it there to explicitly specify your intention to make this file a part of the build. -When you run `npm run build`, Create React App will substitute `%PUBLIC_URL%` with a correct absolute path so your project works even if you use client-side routing or host it at a non-root URL. +When you run `npm run build`, Create React App will substitute `%PUBLIC_URL%` with a correct absolute path so your project works even if you use client-side routing or websocketurl it at a non-root URL. In JavaScript code, you can use `process.env.PUBLIC_URL` for similar purposes: @@ -789,7 +789,7 @@ You can find the companion GitHub repository [here](https://github.com/fullstack >Note: this feature is available with `react-scripts@0.2.3` and higher. -People often serve the front-end React app from the same host and port as their backend implementation.
+People often serve the front-end React app from the same websocketurl and port as their backend implementation.
For example, a production setup might look like this after the app is deployed: ``` @@ -798,7 +798,7 @@ For example, a production setup might look like this after the app is deployed: /api/todos - server handles any /api/* requests using the backend implementation ``` -Such setup is **not** required. However, if you **do** have a setup like this, it is convenient to write requests like `fetch('/api/todos')` without worrying about redirecting them to another host or port during development. +Such setup is **not** required. However, if you **do** have a setup like this, it is convenient to write requests like `fetch('/api/todos')` without worrying about redirecting them to another websocketurl or port during development. To tell the development server to proxy any unknown requests to your API server in development, add a `proxy` field to your `package.json`, for example: @@ -820,7 +820,7 @@ The `proxy` option supports HTTP, HTTPS and WebSocket connections.
If the `proxy` option is **not** flexible enough for you, alternatively you can: * Enable CORS on your server ([here’s how to do it for Express](http://enable-cors.org/server_expressjs.html)). -* Use [environment variables](#adding-custom-environment-variables) to inject the right server host and port into your app. +* Use [environment variables](#adding-custom-environment-variables) to inject the right server websocketurl and port into your app. ## Using HTTPS in Development @@ -1512,10 +1512,10 @@ You can adjust various development and production settings by setting environmen Variable | Development | Production | Usage :--- | :---: | :---: | :--- BROWSER | :white_check_mark: | :x: | By default, Create React App will open the default system browser, favoring Chrome on macOS. Specify a [browser](https://github.com/sindresorhus/opn#app) to override this behavior, or set it to `none` to disable it completely. -HOST | :white_check_mark: | :x: | By default, the development web server binds to `localhost`. You may use this variable to specify a different host. +HOST | :white_check_mark: | :x: | By default, the development web server binds to `localhost`. You may use this variable to specify a different websocketurl. PORT | :white_check_mark: | :x: | By default, the development web server will attempt to listen on port 3000 or prompt you to attempt the next available port. You may use this variable to specify a different port. HTTPS | :white_check_mark: | :x: | When set to `true`, Create React App will run the development server in `https` mode. -PUBLIC_URL | :x: | :white_check_mark: | Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in [`package.json` (`homepage`)](#building-for-relative-paths). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to host your application. +PUBLIC_URL | :x: | :white_check_mark: | Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in [`package.json` (`homepage`)](#building-for-relative-paths). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to websocketurl your application. CI | :large_orange_diamond: | :white_check_mark: | When set to `true`, Create React App treats warnings as failures in the build. It also makes the test runner non-watching. Most CIs set this flag by default. ## Troubleshooting diff --git a/doc/Production.md b/doc/Production.md index e5fd20c..5d55ba0 100644 --- a/doc/Production.md +++ b/doc/Production.md @@ -75,7 +75,7 @@ villas node webdemo.conf ### Visualize real-time data in VILLASweb Dashboards 1. Use the VILLASweb frontend to create a new infrastructure component for the VILLASnode gateway from above (Admin user required). -2. Set the `host` parameter of the component to the target you used as the `web.destinations` parameter in the configuration from above. +2. Set the `websocketurl` parameter of the component to the target you used as the `web.destinations` parameter in the configuration from above. 3. Create a new scenario in VILLASweb and within that scenario create a new component configuration that uses the infrastructure component you created under 2. 4. WIP: Use the signal auto-configure function to retrieve the signal configuration of the VILLASnode automatically. 5. Create a new dashboard with widgets of your choice and link these widgets to the signals received from the infrastructure component. diff --git a/package-lock.json b/package-lock.json index 38291bf..10f2405 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1233,6 +1233,13 @@ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", "requires": { "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "ignore": { @@ -1271,9 +1278,9 @@ } }, "@fortawesome/react-fontawesome": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.11.tgz", - "integrity": "sha512-sClfojasRifQKI0OPqTy8Ln8iIhnxR/Pv/hukBhWnBz9kQRmqi6JSH3nghlhAY7SUeIIM7B5/D2G8WjX0iepVg==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.12.tgz", + "integrity": "sha512-kV6HtqotM3K4YIXlTVvomuIi6QgGCvYm++ImyEx2wwgmSppZ6kbbA29ASwjAUBD63j2OFU0yoxeXpZkjrrX0qQ==", "requires": { "prop-types": "^15.7.2" } @@ -1515,6 +1522,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -1699,6 +1713,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -2275,6 +2296,14 @@ "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==" }, + "@types/http-proxy": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.4.tgz", + "integrity": "sha512-IrSHl2u6AWXduUaDLqYpt45tLVCtYv7o4Z0s1KghBCDgIIS9oW5K1H8mZG/A2CfeLdEa7rTd1ACOiHBc1EMT2Q==", + "requires": { + "@types/node": "*" + } + }, "@types/invariant": { "version": "2.2.34", "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.34.tgz", @@ -2825,6 +2854,11 @@ "color-convert": "^1.9.0" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -2848,6 +2882,11 @@ "readable-stream": "^2.0.6" } }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -3789,6 +3828,14 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "requires": { + "node-gyp-build": "~3.7.0" + } + }, "builtin-modules": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", @@ -3872,6 +3919,15 @@ "unset-value": "^1.0.0" } }, + "cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "requires": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + } + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -3946,6 +4002,16 @@ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001151.tgz", "integrity": "sha512-Zh3sHqskX6mHNrqUerh+fkf0N72cMxrmflzje/JyVImfpknscMnkeJrlFGJcqTmaa0iszdYptGpWMJCRQDkBVw==" }, + "canvas": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.6.1.tgz", + "integrity": "sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA==", + "requires": { + "nan": "^2.14.0", + "node-pre-gyp": "^0.11.0", + "simple-get": "^3.0.3" + } + }, "capture-exit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", @@ -4010,9 +4076,9 @@ "integrity": "sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==" }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -4021,52 +4087,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } + "readdirp": "~3.5.0" } }, "chownr": { @@ -4422,6 +4443,22 @@ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, + "cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "requires": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", @@ -5008,6 +5045,14 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -5035,6 +5080,11 @@ "regexp.prototype.flags": "^1.2.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -5181,6 +5231,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -5215,6 +5270,11 @@ } } }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, "diff-sequences": { "version": "26.5.0", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz", @@ -5774,6 +5834,13 @@ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", "requires": { "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "has-flag": { @@ -6667,6 +6734,14 @@ } } }, + "fibers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-5.0.0.tgz", + "integrity": "sha512-UpGv/YAZp7mhKHxDvC1tColrroGRX90sSvh8RMZV9leo+e5+EkRVgCEZPlmXeo3BUNQTZxUaVdLskq1Q2FyCPg==", + "requires": { + "detect-libc": "^1.0.3" + } + }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -7647,6 +7722,22 @@ } } }, + "http-assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", + "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", + "requires": { + "deep-equal": "~1.0.1", + "http-errors": "~1.7.2" + }, + "dependencies": { + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + } + } + }, "http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", @@ -7853,6 +7944,14 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + } + }, "immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -8248,6 +8347,11 @@ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -8315,6 +8419,11 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz", "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=" }, + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, "is-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", @@ -8915,6 +9024,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -9417,6 +9533,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -9556,6 +9679,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -9712,6 +9842,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -9913,6 +10050,13 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, "resolve": { @@ -10401,6 +10545,14 @@ "set-immediate-shim": "~1.0.1" } }, + "keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "requires": { + "tsscmp": "1.0.6" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -10419,6 +10571,186 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" }, + "koa": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz", + "integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==", + "requires": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "~3.1.0", + "delegates": "^1.0.0", + "depd": "^1.1.2", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^1.2.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + }, + "koa-compress": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/koa-compress/-/koa-compress-4.0.1.tgz", + "integrity": "sha512-It4WYfsBb9HegnFgcBhiRbPeh1LDjXhRM4+xi2jMp8ujwaVAdqhFzHpbDWuTxbLxuBwStn+Bwdwn2zDZxeNChg==", + "requires": { + "bytes": "^3.0.0", + "compressible": "^2.0.0", + "http-errors": "^1.7.3", + "koa-is-json": "^1.0.0", + "statuses": "^2.0.0" + }, + "dependencies": { + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + } + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.0.tgz", + "integrity": "sha512-w9jNUUQdpuVoYqXxnyOakhckBbOxRaoYqJscyIBYCS5ixyCnO7nQn7zBZvP9zf5QOPZcz2DLUpE3KsNPbJBOFA==" + } + } + }, + "koa-connect": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/koa-connect/-/koa-connect-2.1.0.tgz", + "integrity": "sha512-O9pcFafHk0oQsBevlbTBlB9co+2RUQJ4zCzu3qJPmGlGoeEZkne+7gWDkecqDPSbCtED6LmhlQladxs6NjOnMQ==" + }, + "koa-convert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "requires": { + "co": "^4.6.0", + "koa-compose": "^3.0.0" + }, + "dependencies": { + "koa-compose": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", + "requires": { + "any-promise": "^1.1.0" + } + } + } + }, + "koa-is-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=" + }, + "koa-route": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/koa-route/-/koa-route-3.2.0.tgz", + "integrity": "sha1-dimLmaa8+p44yrb+XHmocz51i84=", + "requires": { + "debug": "*", + "methods": "~1.1.0", + "path-to-regexp": "^1.2.0" + } + }, + "koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "dependencies": { + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + } + } + }, + "koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "requires": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "language-subtag-registry": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", @@ -10607,6 +10939,11 @@ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==" }, + "loglevelnext": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-4.0.1.tgz", + "integrity": "sha512-/tlMUn5wqgzg9msy0PiWc+8fpVXEuYPq49c2RGyw2NAh0hSrgq6j/Z3YPnwWsILMoFJ+ZT6ePHnWUonkjDnq2Q==" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10664,6 +11001,11 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -10905,6 +11247,11 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, "mini-create-react-context": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz", @@ -11178,6 +11525,26 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, + "needle": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -11247,6 +11614,11 @@ } } }, + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==" + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -11325,6 +11697,88 @@ } } }, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, "node-releases": { "version": "1.1.64", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.64.tgz", @@ -11461,6 +11915,29 @@ "sort-keys": "^1.0.0" } }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -11734,6 +12211,11 @@ "mimic-fn": "^2.1.0" } }, + "only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" + }, "open": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz", @@ -11812,6 +12294,11 @@ "os-tmpdir": "^1.0.0" } }, + "p-defer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", + "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==" + }, "p-each-series": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", @@ -13428,6 +13915,24 @@ } } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, "rc-align": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.8.tgz", @@ -13481,9 +13986,9 @@ } }, "rc-slider": { - "version": "9.5.4", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.5.4.tgz", - "integrity": "sha512-24goJnWhmWi0ojNZMoPSMni2wh73IPqEK0TJh7rWn10hPLLKgG8x3KRR0g4uUdCS9APHyosqxGXUIJKGydJXVg==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.6.0.tgz", + "integrity": "sha512-XJZjS8JWPnhoS83n9IlZrfblP7zt9urGe881Clq7ZvEpeEQ7z3z/HyuZNFI0JL9rZV7l3pWRtYi1ur6G/7wJcA==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", @@ -13532,9 +14037,9 @@ } }, "rc-trigger": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.0.8.tgz", - "integrity": "sha512-0bgFw39CKWRC4l3eQrqXe0O/e+XgZW68tXVewU/FI3qGs3PWXlPPbInes2ZvTIka/mS5oqOfF7wC1NPwPfo+9w==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.0.9.tgz", + "integrity": "sha512-N+q/ur2dpJSPDWbZQ34ztpGorms1QIphtmFpxKE5z+wMJw2BIASkMDEfwHJ/ssvZQxScjQza0/eQ0CWUI0e+EQ==", "requires": { "@babel/runtime": "^7.11.2", "classnames": "^2.2.6", @@ -13697,12 +14202,13 @@ "integrity": "sha512-cN2tkxBWizhPQ2JHfe0aUSJtmMthKA17NZkTElpiQ2snQAAi1hssXZ2fv88rAPNNvG5ss4t0PbOZT0TIl9Lk3Q==" }, "react-color": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.18.1.tgz", - "integrity": "sha512-X5XpyJS6ncplZs74ak0JJoqPi+33Nzpv5RYWWxn17bslih+X7OlgmfpmGC1fNvdkK7/SGWYf1JJdn7D2n5gSuQ==", + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", "requires": { "@icons/material": "^0.2.4", - "lodash": "^4.17.11", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", "material-colors": "^1.2.1", "prop-types": "^15.5.10", "reactcss": "^1.2.0", @@ -14221,11 +14727,11 @@ } }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "recursive-readdir": { @@ -14586,6 +15092,38 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", + "requires": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + } + } + }, "resolve-pathname": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", @@ -14991,9 +15529,9 @@ "integrity": "sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==" }, "sass": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz", - "integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.28.0.tgz", + "integrity": "sha512-9FWX/0wuE1KxwfiP02chZhHaPzu6adpx9+wGch7WMOuHy5npOo0UapRI3FNSHva2CczaYJu2yNUBN8cCSqHz/A==", "requires": { "chokidar": ">=2.0.0 <4.0.0" } @@ -15391,6 +15929,21 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -16080,6 +16633,11 @@ } } }, + "superstruct": { + "version": "0.10.12", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.10.12.tgz", + "integrity": "sha512-FiNhfegyytDI0QxrrEoeGknFM28SnoHqCBpkWewUm8jRNj74NVxLpiiePvkOo41Ze/aKMSHa/twWjNF81mKaQQ==" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -16382,9 +16940,9 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, "tinycolor2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", - "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" }, "tmp": { "version": "0.0.33", @@ -16482,6 +17040,18 @@ "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" }, + "ts-node": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, "ts-pnp": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", @@ -16513,6 +17083,11 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, "tsutils": { "version": "3.17.1", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", @@ -16558,9 +17133,9 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==" }, "type-is": { "version": "1.6.18", @@ -16585,9 +17160,9 @@ } }, "typescript": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", - "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==" + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==" }, "ua-parser-js": { "version": "0.7.20", @@ -16833,6 +17408,14 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "utf-8-validate": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "requires": { + "node-gyp-build": "~3.7.0" + } + }, "util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", @@ -17830,6 +18413,32 @@ } } }, + "webpack-hot-middleware": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.0.tgz", + "integrity": "sha512-xs5dPOrGPCzuRXNi8F6rwhawWvQQkeli5Ro48PRuQh8pYPCPmNnltP9itiUPT4xI8oW+y0m59lyyeQk54s5VgA==", + "requires": { + "ansi-html": "0.0.7", + "html-entities": "^1.2.0", + "querystring": "^0.2.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "webpack-log": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", @@ -17882,6 +18491,236 @@ } } }, + "webpack-plugin-ramdisk": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/webpack-plugin-ramdisk/-/webpack-plugin-ramdisk-0.1.7.tgz", + "integrity": "sha512-8Zvacs7ic/mRp+6m2s24+5xdGfog+bG3bKr/Ip3ho07z50A+JpEv3dCApqcp4qgNA4/BUSAJG6ncl1kjw5kD/w==", + "requires": { + "chalk": "^4.1.0", + "execa": "^4.0.3", + "superstruct": "^0.10.12" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "webpack-plugin-serve": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-plugin-serve/-/webpack-plugin-serve-1.2.0.tgz", + "integrity": "sha512-wBAQi2ZwDZMUEpbQUQcz//HaBPX6QJp9v6pCyB9efmS1RlhzUwVwRUwQgJ79J/MyElXoos1ToQeLAK5aIStOYQ==", + "requires": { + "chalk": "^4.0.0", + "connect-history-api-fallback": "^1.5.0", + "escalade": "^3.1.0", + "globby": "^11.0.0", + "http-proxy-middleware": "^1.0.3", + "is-path-cwd": "^2.2.0", + "is-promise": "^4.0.0", + "koa": "^2.5.3", + "koa-compress": "^4.0.1", + "koa-connect": "^2.0.1", + "koa-route": "^3.2.0", + "koa-static": "^5.0.0", + "loglevelnext": "^4.0.1", + "nanoid": "^3.1.3", + "onetime": "^5.1.0", + "open": "^7.0.3", + "p-defer": "^3.0.0", + "rimraf": "^3.0.2", + "strip-ansi": "^6.0.0", + "superstruct": "^0.10.12", + "webpack-plugin-ramdisk": "^0.1.2", + "ws": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "http-proxy-middleware": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.0.6.tgz", + "integrity": "sha512-NyL6ZB6cVni7pl+/IT2W0ni5ME00xR0sN27AQZZrpKn1b+qRh+mLbBxIq9Cq1oGfmTc7BUq4HB77mxwCaxAYNg==", + "requires": { + "@types/http-proxy": "^1.17.4", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.20", + "micromatch": "^4.0.2" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", @@ -18394,6 +19233,16 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "ylru": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", + "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/package.json b/package.json index f213215..219d249 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,11 @@ "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.32", "@fortawesome/free-solid-svg-icons": "^5.15.1", - "@fortawesome/react-fontawesome": "^0.1.11", + "@fortawesome/react-fontawesome": "^0.1.12", "babel-runtime": "^6.26.0", "bootstrap": "^4.5.3", + "bufferutil": "^4.0.1", + "canvas": "^2.6.1", "classnames": "^2.2.6", "d3-array": "^2.8.0", "d3-axis": "^2.0.0", @@ -17,6 +19,7 @@ "d3-shape": "^2.0.0", "d3-time-format": "^3.0.0", "es6-promise": "^4.2.8", + "fibers": "^5.0.0", "file-saver": "^2.0.2", "flux": "^3.1.3", "gaugeJS": "^1.3.7", @@ -30,12 +33,12 @@ "node-sass": "^4.14.1", "popper.js": "^1.16.1", "prop-types": "^15.7.2", - "rc-slider": "^9.5.4", + "rc-slider": "^9.6.0", "react": "^16.14.0", "react-bootstrap": "^1.4.0", "react-bootstrap-time-picker": "^2.0.1", "react-collapse": "^5.0.1", - "react-color": "^2.18.1", + "react-color": "^2.19.3", "react-contexify": "^4.1.1", "react-d3": "^0.4.0", "react-dnd": "^10.0.2", @@ -50,10 +53,15 @@ "react-router-dom": "^5.2.0", "react-scripts": "^4.0.0", "react-svg-pan-zoom": "^3.8.1", - "sass": "^1.27.0", + "sass": "^1.28.0", "superagent": "^6.1.0", - "typescript": "^4.0.3", - "validator": "^13.1.17" + "ts-node": "^9.0.0", + "type-fest": "^0.13.1", + "typescript": "^4.0.5", + "utf-8-validate": "^5.0.2", + "validator": "^13.1.17", + "webpack-hot-middleware": "^2.25.0", + "webpack-plugin-serve": "^1.2.0" }, "devDependencies": { "chai": "^4.2.0" diff --git a/src/common/api/websocket-api.js b/src/common/api/websocket-api.js index 71c813d..89a1ee6 100644 --- a/src/common/api/websocket-api.js +++ b/src/common/api/websocket-api.js @@ -16,19 +16,19 @@ ******************************************************************************/ class WebsocketAPI { - constructor(host, callbacks) { - this.host = host; + constructor(websocketurl, callbacks) { + this.websocketurl = websocketurl; this.callbacks = callbacks; this.wasConnected = false; this.isClosing = false; - this.connect(host, callbacks); + this.connect(websocketurl, callbacks); } - connect(host, callbacks) { + connect(websocketurl, callbacks) { // create web socket client - this.socket = new WebSocket(WebsocketAPI.getURL(host), 'live'); + this.socket = new WebSocket(WebsocketAPI.getURL(websocketurl), 'live'); this.socket.binaryType = 'arraybuffer'; this.socket.onclose = this.onClose; this.socket.onopen = this.onOpen; @@ -40,12 +40,12 @@ class WebsocketAPI { } reconnect() { - //console.log("Reconnecting: " + this.host); - this.connect(this.host, this.callbacks); + //console.log("Reconnecting: " + this.websocketurl); + this.connect(this.websocketurl, this.callbacks); } get url() { - return WebsocketAPI.getURL(this.host); + return WebsocketAPI.getURL(this.websocketurl); } send(data) { @@ -58,7 +58,7 @@ class WebsocketAPI { } onError = e => { - console.error('Error on WebSocket connection to: ' + this.host + ':', e); + console.error('Error on WebSocket connection to: ' + this.websocketurl + ':', e); if ('onError' in this.callbacks) this.callbacks.onError(e); @@ -78,16 +78,16 @@ class WebsocketAPI { } else { if (this.wasConnected) { - console.log("Connection to " + this.host + " dropped. Attempt reconnect in 1 sec"); + console.log("Connection to " + this.websocketurl + " dropped. Attempt reconnect in 1 sec"); window.setTimeout(() => { this.reconnect(); }, 1000); } } } - static getURL(host) { + static getURL(websocketurl) { // create an anchor element (note: no need to append this element to the document) var link = document.createElement('a'); - link.href = host; + link.href = websocketurl; if (link.protocol === 'https:') link.protocol = 'wss:'; diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index 1bc6f0d..e9adf0a 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -30,8 +30,8 @@ class EditICDialog extends React.Component { this.state = { name: '', - host: '', - apihost: '', + websocketurl: '', + apiurl: '', type: '', category: '', managedexternally: false, @@ -48,12 +48,12 @@ class EditICDialog extends React.Component { data.name = this.state.name; } - if (this.state.host != null && this.state.host !== "" && this.state.host !== "http://" && this.state.host !== this.props.ic.host) { - data.host = this.state.host; + if (this.state.websocketurl != null && this.state.websocketurl !== "" && this.state.websocketurl !== "http://" && this.state.websocketurl !== this.props.ic.websocketurl) { + data.websocketurl = this.state.websocketurl; } - if (this.state.apihost != null && this.state.apihost !== "" && this.state.apihost !== "http://" && this.state.apihost !== this.props.ic.apihost) { - data.apihost = this.state.apihost; + if (this.state.apiurl != null && this.state.apiurl !== "" && this.state.apiurl !== "http://" && this.state.apiurl !== this.props.ic.apiurl) { + data.apiurl = this.state.apiurl; } if (this.state.type != null && this.state.type !== "" && this.state.type !== this.props.ic.type) { @@ -95,8 +95,8 @@ class EditICDialog extends React.Component { resetState() { this.setState({ name: this.props.ic.name, - host: this.props.ic.host, - apihost: this.props.ic.apihost, + websocketurl: this.props.ic.websocketurl, + apiurl: this.props.ic.apiurl, type: this.props.ic.type, category: this.props.ic.category, managedexternally: false, @@ -149,14 +149,14 @@ class EditICDialog extends React.Component { this.handleChange(e)} /> - - Host - this.handleChange(e)} /> + + Websocket URL + this.handleChange(e)} /> - - API Host - this.handleChange(e)} /> + + API URL + this.handleChange(e)} /> diff --git a/src/ic/ic-data-data-manager.js b/src/ic/ic-data-data-manager.js index 2e09a7c..0dcc853 100644 --- a/src/ic/ic-data-data-manager.js +++ b/src/ic/ic-data-data-manager.js @@ -26,19 +26,19 @@ class IcDataDataManager { this._sockets = {}; } - open(host, identifier) { + open(websocketurl, identifier) { // pass signals to onOpen callback if (this._sockets[identifier] != null) return; // already open? - this._sockets[identifier] = new WebsocketAPI(host, { onOpen: (event) => this.onOpen(event, identifier, true), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) }); + this._sockets[identifier] = new WebsocketAPI(websocketurl, { onOpen: (event) => this.onOpen(event, identifier, true), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) }); } - update(host, identifier) { + update(websocketurl, identifier) { if (this._sockets[identifier] != null) { - if (this._sockets[identifier].host !== host) { + if (this._sockets[identifier].websocketurl !== websocketurl) { this._sockets[identifier].close(); - this._sockets[identifier] = new WebsocketAPI(host, { onOpen: (event) => this.onOpen(event, identifier, false), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier), onError: (error) => this.onError(error, identifier) }); + this._sockets[identifier] = new WebsocketAPI(websocketurl, { onOpen: (event) => this.onOpen(event, identifier, false), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier), onError: (error) => this.onError(error, identifier) }); } } } diff --git a/src/ic/ic-store.js b/src/ic/ic-store.js index d653adf..d73e555 100644 --- a/src/ic/ic-store.js +++ b/src/ic/ic-store.js @@ -35,8 +35,8 @@ class InfrastructureComponentStore extends ArrayStore { // connect to each infrastructure component const ic = action.data; - if (ic.host != null && ic.host !== '') { - ICDataDataManager.update(ic.host, ic.id); + if (ic.websocketurl != null && ic.websocketurl !== '') { + ICDataDataManager.update(ic.websocketurl, ic.id); } return super.reduce(state, action); @@ -44,17 +44,17 @@ class InfrastructureComponentStore extends ArrayStore { // open websocket for each IC contained in array action.data // action.data contains only those IC used by the scenario for (let ic of action.data) { - if (ic.host != null && ic.host !== '') { - ICDataDataManager.open(ic.host, ic.id); + if (ic.websocketurl != null && ic.websocketurl !== '') { + ICDataDataManager.open(ic.websocketurl, ic.id); } else { // TODO add to pool of notifications - const IC_WEBSOCKET_HOST_ERROR = { + const IC_WEBSOCKET_URL_ERROR = { title: 'Websocket connection warning', - message: "Websocket host parameter not available for IC " + ic.name + "(" + ic.uuid + "), connection not possible", + message: "Websocket URL parameter not available for IC " + ic.name + "(" + ic.uuid + "), connection not possible", level: 'warning' }; - NotificationsDataManager.addNotification(IC_WEBSOCKET_HOST_ERROR); + NotificationsDataManager.addNotification(IC_WEBSOCKET_URL_ERROR); } } return super.reduce(state, action); diff --git a/src/ic/ics.js b/src/ic/ics.js index 4696ef6..5e0017a 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -334,10 +334,10 @@ class InfrastructureComponents extends Component { this.modifyManagedExternallyColumn(managedexternally)} width='105' /> this.modifyUptimeColumn(uptime)}/> - + {/* */} - - + + this.stateUpdateModifier(stateUpdateAt)} /> {this.state.currentUser.role === "Admin" ? this.handleChange(e)} /> - - Host - this.handleChange(e)} /> + + Websocket URL + this.handleChange(e)} /> diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 466ead5..8e35a10 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -28,7 +28,7 @@ class NewICDialog extends React.Component { this.state = { name: '', - host: '', + websocketurl: '', uuid: '', type: '', category: '', @@ -47,8 +47,8 @@ class NewICDialog extends React.Component { managedexternally: this.state.managedexternally, }; - if (this.state.host != null && this.state.host !== "" && this.state.host !== 'http://') { - data.host = this.state.host; + if (this.state.websocketurl != null && this.state.websocketurl !== "" && this.state.websocketurl !== 'http://') { + data.websocketurl = this.state.websocketurl; } this.props.onClose(data); @@ -70,14 +70,14 @@ class NewICDialog extends React.Component { } resetState() { - this.setState({ name: '', host: 'http://', uuid: this.uuidv4(), type: '', category: '', managedexternally: false}); + this.setState({ name: '', websocketurl: 'http://', uuid: this.uuidv4(), type: '', category: '', managedexternally: false}); } validateForm(target) { // check all controls let name = true; let uuid = true; - let host = true; + let websocketurl = true; let type = true; let category = true; @@ -97,12 +97,12 @@ class NewICDialog extends React.Component { category = false; } - this.valid = name && uuid && host && type && category; + this.valid = name && uuid && websocketurl && type && category; // return state to control if (target === 'name') return name ? "success" : "error"; if (target === 'uuid') return uuid ? "success" : "error"; - if (target === 'host') return host ? "success" : "error"; + if (target === 'websocketurl') return websocketurl ? "success" : "error"; if (target === 'type') return type ? "success" : "error"; if (target === 'category') return category ? "success" : "error"; } @@ -151,9 +151,14 @@ class NewICDialog extends React.Component { this.handleChange(e)} /> - - Host - this.handleChange(e)} /> + + Websocket URL + this.handleChange(e)} /> + + + + API URL + this.handleChange(e)} /> diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 858a7a6..43e33e0 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -463,7 +463,7 @@ class Scenario extends React.Component { signalsAutoConf(index){ let componentConfig = this.state.configs[index]; - // determine host of infrastructure component + // determine apiurl of infrastructure component let ic = this.state.ics.find(ic => ic.id === componentConfig.icID) if(!ic.type.includes("VILLASnode") && !ic.type.includes("villasnode") && !ic.type.includes("VILLASNODE")){ let message = "Cannot autoconfigure signals for IC type " + ic.type + " of category " + ic.category + ". This is only possible for gateway ICs of type 'VILLASnode'." @@ -478,7 +478,7 @@ class Scenario extends React.Component { return; } - let splitHost = ic.host.split("/") + let splitWebsocketURL = ic.websocketurl.split("/") let request = {}; request["id"] = this.uuidv4(); request["action"] = "nodes" @@ -486,8 +486,8 @@ class Scenario extends React.Component { AppDispatcher.dispatch({ type: 'signals/start-autoconfig', data: request, - url: ic.apihost, - socketname: splitHost[splitHost.length -1], + url: ic.apiurl, + socketname: splitWebsocketURL[splitWebsocketURL.length -1], token: this.state.sessionToken, configID: componentConfig.id }); @@ -542,12 +542,12 @@ class Scenario extends React.Component { console.warn("There is more than one CIM file selected in this component configuration. I will open them all in a separate tab.") } - let base_host = 'aaa.bbb.ccc.ddd/api/v2/files/' + let baseURL = 'aaa.bbb.ccc.ddd/api/v2/files/' for (let file of files) { // endpoint param serves for download and upload of CIM file, token is required for authentication let params = { token: this.state.sessionToken, - endpoint: base_host + String(file.id), + endpoint: baseURL + String(file.id), } // TODO start Pintura for editing CIM/ XML file from here diff --git a/src/signal/signals-data-manager.js b/src/signal/signals-data-manager.js index c8f7127..83d9a9e 100644 --- a/src/signal/signals-data-manager.js +++ b/src/signal/signals-data-manager.js @@ -39,7 +39,7 @@ class SignalsDataManager extends RestDataManager{ startAutoConfig(data, url, socketname, token, configID){ // This function queries the VILLASnode API to obtain the configuration of the VILLASnode located at url - // Endpoint: http[s]://server:port/api/v1 (to be generated based on IC host, port 4000) + // Endpoint: http[s]://server:port/api/v1 (to be generated based on IC API URL, port 4000) // data contains the request data: { action, id, (request)} // See documentation of VILLASnode API: https://villas.fein-aachen.org/doc/node-dev-api-node.html From f110a9c5e7806c29e41b7ac411e26ba35764ad58 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Thu, 12 Nov 2020 12:05:27 +0100 Subject: [PATCH 12/17] Improve edit and add IC dialogs #266 --- src/ic/edit-ic.js | 71 ++++++++++++++++++++++++++++------------------- src/ic/new-ic.js | 22 +++++++-------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index e9adf0a..49ffd79 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -32,10 +32,12 @@ class EditICDialog extends React.Component { name: '', websocketurl: '', apiurl: '', + location: '', + description: '', type: '', category: '', managedexternally: false, - properties: {}, + startParameterScheme: {}, }; } @@ -56,6 +58,14 @@ class EditICDialog extends React.Component { data.apiurl = this.state.apiurl; } + if (this.state.location != null && this.state.location !== this.props.ic.location) { + data.location = this.state.location; + } + + if (this.state.description != null && this.state.description !== this.props.ic.description) { + data.description = this.state.description; + } + if (this.state.type != null && this.state.type !== "" && this.state.type !== this.props.ic.type) { data.type = this.state.type; } @@ -63,8 +73,8 @@ class EditICDialog extends React.Component { if (this.state.category != null && this.state.category !== "" && this.state.category !== this.props.ic.category) { data.category = this.state.category; } - if (this.state.properties !== {}) { - data.properties = this.state.properties + if (this.state.startParameterScheme !== {}) { + data.startParameterScheme = this.state.startParameterScheme } data.managedexternally = this.state.managedexternally; @@ -88,8 +98,8 @@ class EditICDialog extends React.Component { } } - handlePropertiesChange(data) { - this.setState({ properties: data }); + handleStartParameterSchemeChange(data) { + this.setState({ startParameterScheme: data }); } resetState() { @@ -98,9 +108,11 @@ class EditICDialog extends React.Component { websocketurl: this.props.ic.websocketurl, apiurl: this.props.ic.apiurl, type: this.props.ic.type, + location: this.props.ic.location, + description: this.props.ic.description, category: this.props.ic.category, managedexternally: false, - properties: _.merge({}, _.get(this.props.ic, 'rawProperties'), _.get(this.props.ic, 'properties')) + startParameterScheme: this.props.ic.startParameterScheme, }); } @@ -114,7 +126,7 @@ class EditICDialog extends React.Component { typeOptions = ["Kubernetes","VILLAS-controller"]; break; case "Gateway": - typeOptions = ["VILLAS-node","VILLAS-relay"]; + typeOptions = ["VILLASnode","VILLASrelay"]; break; case "Service": typeOptions = ["EMS","Custom"]; @@ -137,28 +149,11 @@ class EditICDialog extends React.Component { >
UUID: {this.props.ic.uuid} - - this.handleChange(e)}> - - - - Externally managed ICs cannot be edited by users - Name this.handleChange(e)} /> - - Websocket URL - this.handleChange(e)} /> - - - - API URL - this.handleChange(e)} /> - - Category this.handleChange(e)}> @@ -178,12 +173,32 @@ class EditICDialog extends React.Component { ))} - - Properties + + Websocket URL + this.handleChange(e)} /> + + + + API URL + this.handleChange(e)} /> + + + + Location + this.handleChange(e)} /> + + + + Description + this.handleChange(e)} /> + + + + Start parameter scheme of IC this.handlePropertiesChange(data)} + onChange={(data) => this.handleStartParameterSchemeChange(data)} /> diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 8e35a10..b5848bd 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -85,7 +85,7 @@ class NewICDialog extends React.Component { name = false; } - if (this.state.uuid === '') { + if (!this.state.managedexternally && this.state.uuid === '') { uuid = false; } @@ -151,16 +151,6 @@ class NewICDialog extends React.Component { this.handleChange(e)} /> - - Websocket URL - this.handleChange(e)} /> - - - - API URL - this.handleChange(e)} /> - - Category of component this.handleChange(e)}> @@ -181,6 +171,16 @@ class NewICDialog extends React.Component { ))} + + Websocket URL + this.handleChange(e)} /> + + + + API URL + this.handleChange(e)} /> + + UUID this.handleChange(e)} /> From a94722677857f45ddec2e543f8616e5968f2098f Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Thu, 12 Nov 2020 15:11:50 +0100 Subject: [PATCH 13/17] Adapt naming of type and category to VILLAScontroller protocol; make signal auto config usable #224 --- src/ic/edit-ic.js | 32 +++++++++++++++--------------- src/ic/new-ic.js | 30 ++++++++++++++-------------- src/scenario/scenario.js | 8 ++------ src/signal/signal-store.js | 3 +-- src/signal/signals-data-manager.js | 25 +++++++++++++---------- 5 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index 49ffd79..f2bd679 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -119,20 +119,20 @@ class EditICDialog extends React.Component { render() { let typeOptions = []; switch(this.state.category){ - case "Simulator": - typeOptions = ["Dummy","Generic","DPsim","RTLAB","RSCAD"]; - break; - case "Controller": - typeOptions = ["Kubernetes","VILLAS-controller"]; + case "simulator": + typeOptions = ["dummy","generic","dpsim","rtlab","rscad"]; break; - case "Gateway": - typeOptions = ["VILLASnode","VILLASrelay"]; + case "controller": + typeOptions = ["kubernetes","villas-controller"]; break; - case "Service": - typeOptions = ["EMS","Custom"]; + case "gateway": + typeOptions = ["villas-node","villas-relay"]; break; - case "Equipment": - typeOptions = ["Chroma-emulator","Chroma-loads","SMA-sunnyboy","FLEPS","Sonnenbatterie"]; + case "service": + typeOptions = ["ems","custom"]; + break; + case "equipment": + typeOptions = ["chroma-emulator","chroma-loads","sma-sunnyboy","fleps","sonnenbatterie"]; break; default: typeOptions =[]; @@ -157,11 +157,11 @@ class EditICDialog extends React.Component { Category this.handleChange(e)}> - - - - - + + + + + diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index b5848bd..45ccc91 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -118,20 +118,20 @@ class NewICDialog extends React.Component { render() { let typeOptions = []; switch(this.state.category){ - case "Simulator": - typeOptions = ["Dummy","Generic","DPsim","RTLAB","RSCAD"]; + case "simulator": + typeOptions = ["dummy","generic","dpsim","rtlab","rscad"]; break; - case "Controller": - typeOptions = ["Kubernetes","VILLAS-controller"]; + case "controller": + typeOptions = ["kubernetes","villas-controller"]; break; - case "Gateway": - typeOptions = ["VILLAS-node","VILLAS-relay"]; + case "gateway": + typeOptions = ["villas-node","villas-relay"]; break; - case "Service": - typeOptions = ["EMS","Custom"]; + case "service": + typeOptions = ["ems","custom"]; break; - case "Equipment": - typeOptions = ["Chroma-emulator","Chroma-loads","SMA-sunnyboy","FLEPS","Sonnenbatterie"]; + case "equipment": + typeOptions = ["chroma-emulator","chroma-loads","sma-sunnyboy","fleps","sonnenbatterie"]; break; default: typeOptions =[]; @@ -155,11 +155,11 @@ class NewICDialog extends React.Component { Category of component this.handleChange(e)}> - - - - - + + + + + diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 43e33e0..33f1edd 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -465,7 +465,7 @@ class Scenario extends React.Component { let componentConfig = this.state.configs[index]; // determine apiurl of infrastructure component let ic = this.state.ics.find(ic => ic.id === componentConfig.icID) - if(!ic.type.includes("VILLASnode") && !ic.type.includes("villasnode") && !ic.type.includes("VILLASNODE")){ + if(!ic.type.includes("villas-node")){ let message = "Cannot autoconfigure signals for IC type " + ic.type + " of category " + ic.category + ". This is only possible for gateway ICs of type 'VILLASnode'." console.warn(message); @@ -479,14 +479,10 @@ class Scenario extends React.Component { } let splitWebsocketURL = ic.websocketurl.split("/") - let request = {}; - request["id"] = this.uuidv4(); - request["action"] = "nodes" AppDispatcher.dispatch({ type: 'signals/start-autoconfig', - data: request, - url: ic.apiurl, + url: ic.apiurl+"/nodes", socketname: splitWebsocketURL[splitWebsocketURL.length -1], token: this.state.sessionToken, configID: componentConfig.id diff --git a/src/signal/signal-store.js b/src/signal/signal-store.js index ff4d228..82ce6bf 100644 --- a/src/signal/signal-store.js +++ b/src/signal/signal-store.js @@ -34,12 +34,11 @@ class SignalStore extends ArrayStore{ return super.reduce(state, action); case 'signals/start-autoconfig': - this.dataManager.startAutoConfig(action.data, action.url, action.socketname, action.token, action.configID) + this.dataManager.startAutoConfig(action.url, action.socketname, action.token, action.configID) return super.reduce(state, action); case 'signals/autoconfig-loaded': console.log("AutoConfig Loaded: ", action.data) - // TODO save signal config contained in action.data this.dataManager.saveSignals(action.data, action.token, action.configID, action.socketname); return super.reduce(state, action); diff --git a/src/signal/signals-data-manager.js b/src/signal/signals-data-manager.js index 83d9a9e..9d61584 100644 --- a/src/signal/signals-data-manager.js +++ b/src/signal/signals-data-manager.js @@ -37,13 +37,13 @@ class SignalsDataManager extends RestDataManager{ } - startAutoConfig(data, url, socketname, token, configID){ + startAutoConfig(url, socketname, token, configID){ // This function queries the VILLASnode API to obtain the configuration of the VILLASnode located at url // Endpoint: http[s]://server:port/api/v1 (to be generated based on IC API URL, port 4000) // data contains the request data: { action, id, (request)} // See documentation of VILLASnode API: https://villas.fein-aachen.org/doc/node-dev-api-node.html - RestAPI.post(url, data).then(response => { + RestAPI.get(url, null).then(response => { AppDispatcher.dispatch({ type: 'signals/autoconfig-loaded', data: response, @@ -59,13 +59,12 @@ class SignalsDataManager extends RestDataManager{ }) } - saveSignals(data, token, configID, socketname){ - // data.response contains the response from the VILLASnode API, an array of node configurations + saveSignals(nodes, token, configID, socketname){ - if(!data.hasOwnProperty("response")){ + if(nodes.length === 0){ const SIGNAL_AUTOCONF_ERROR_NOTIFICATION = { - title: 'Failed to load signal config ', - message: 'VILLASnode returned no response field.', + title: 'Failed to load nodes ', + message: 'VILLASnode returned empty response', level: 'error' }; NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_ERROR_NOTIFICATION); @@ -74,7 +73,8 @@ class SignalsDataManager extends RestDataManager{ let configured = false; let error = false; - for(let nodeConfig of data.response){ + for(let nodeConfig of nodes){ + console.log("parsing node config: ", nodeConfig) if(!nodeConfig.hasOwnProperty("name")){ console.warn("Could not parse the following node config because it lacks a name parameter:", nodeConfig); } else if(nodeConfig.name === socketname){ @@ -88,7 +88,6 @@ class SignalsDataManager extends RestDataManager{ continue; } // signals are not yet configured: - console.log("Adding signals of websocket: ", nodeConfig); let index_in = 1 let index_out = 1 @@ -104,9 +103,10 @@ class SignalsDataManager extends RestDataManager{ // add all in signals for(let inSig of nodeConfig.in.signals) { - console.log("adding input signal:", inSig); if (inSig.enabled) { + console.log("adding input signal:", inSig); + let newSignal = { configID: configID, direction: 'in', @@ -140,9 +140,9 @@ class SignalsDataManager extends RestDataManager{ // add all out signals for (let outSig of nodeConfig.out.signals) { - console.log("adding output signal:", outSig); if (outSig.enabled) { + console.log("adding output signal:", outSig); let newSignal = { configID: configID, direction: 'out', @@ -165,8 +165,11 @@ class SignalsDataManager extends RestDataManager{ console.log("Configured", index_in-1, "input signals and", index_out-1, "output signals"); configured=true; + } else { + console.log("ignoring node with name ",nodeConfig.name, " expecting ", socketname ) } + } if(!error) { From 62b78c5822d019e73a2bab05871a73926baa1d17 Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Fri, 13 Nov 2020 14:18:12 +0100 Subject: [PATCH 14/17] New Ic Dialog: add location and description fields #266 --- src/ic/new-ic.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 45ccc91..5e8a49a 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -181,6 +181,16 @@ class NewICDialog extends React.Component { this.handleChange(e)} /> + + Location + this.handleChange(e)} /> + + + + Description + this.handleChange(e)} /> + + UUID this.handleChange(e)} /> From f096b8d3e0a05d1d6f28fe671d3b73dd26e67fa0 Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Fri, 13 Nov 2020 16:43:02 +0100 Subject: [PATCH 15/17] externally managed ICs don't appear immediately in IC list, add button activates as soon as all required fields are filled #266 --- src/common/array-store.js | 1 + src/ic/new-ic.js | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/common/array-store.js b/src/common/array-store.js index c2cdd27..1ab4b7f 100644 --- a/src/common/array-store.js +++ b/src/common/array-store.js @@ -98,6 +98,7 @@ class ArrayStore extends ReduceStore { return state; case this.type + '/added': + if(typeof action.data.managedexternally !== "undefined" && action.data.managedexternally === true ) return state; return this.updateElements(state, [action.data]); case this.type + '/add-error': diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 5e8a49a..514055a 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -105,6 +105,8 @@ class NewICDialog extends React.Component { if (target === 'websocketurl') return websocketurl ? "success" : "error"; if (target === 'type') return type ? "success" : "error"; if (target === 'category') return category ? "success" : "error"; + + return this.valid; } uuidv4() { @@ -137,7 +139,7 @@ class NewICDialog extends React.Component { typeOptions =[]; } return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> + this.onClose(c)} onReset={() => this.resetState()} valid={this.validateForm()}>
this.handleChange(e)}> @@ -151,7 +153,7 @@ class NewICDialog extends React.Component { this.handleChange(e)} /> - + Category of component this.handleChange(e)}> @@ -162,7 +164,7 @@ class NewICDialog extends React.Component { - + Type of component this.handleChange(e)}> From 9b602348ec7b2cdfb3c995a7d90eefb4d007e86a Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Fri, 13 Nov 2020 18:58:50 +0100 Subject: [PATCH 16/17] Cosmetic changes to new IC dialog / mark required fields #266 --- src/ic/new-ic.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 514055a..134c62b 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -16,8 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, FormCheck } from 'react-bootstrap'; -import {Collapse} from 'react-collapse'; +import { FormGroup, FormControl, FormLabel, FormCheck, OverlayTrigger, Tooltip} from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; class NewICDialog extends React.Component { @@ -142,19 +141,22 @@ class NewICDialog extends React.Component { this.onClose(c)} onReset={() => this.resetState()} valid={this.validateForm()}> - this.handleChange(e)}> - + An externally managed component will show up in the list only after a VILLAScontroller for the component type has created the component and cannot be edited by users} > + this.handleChange(e)}> + + - - the component will show up in the list only after a VILLAScontroller for the component type has created the component and cannot be edited by users - - Name + Required field } > + Name * + this.handleChange(e)} /> - Category of component + Required field } > + Category of component * + this.handleChange(e)}> @@ -165,7 +167,9 @@ class NewICDialog extends React.Component { - Type of component + Required field } > + Type of component * + this.handleChange(e)}> {typeOptions.map((name,index) => ( From 295c4ada163094fcb6c31e4959ffab7e6e81774d Mon Sep 17 00:00:00 2001 From: Laura Fuentes Grau Date: Sun, 15 Nov 2020 15:58:42 +0100 Subject: [PATCH 17/17] Control/Info dialog only available for ICs of type 'villas-node' or 'villas-relay' #265 --- src/ic/ics.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ic/ics.js b/src/ic/ics.js index 5e0017a..5d21299 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -316,6 +316,15 @@ class InfrastructureComponents extends Component { } } + modifyNameColumn(name){ + let ic = this.state.ics.find(ic => ic.name === name); + let index = this.state.ics.indexOf(ic); + if(ic.type === "villas-node" || ic.type === "villas-relay"){ + return } + else{ + return {name} + } + } render() { const buttonStyle = { @@ -328,7 +337,7 @@ class InfrastructureComponents extends Component {
this.onICChecked(index, event)} width='30' /> - this.setState({ icModal: true, modalIC: this.state.ics[index], modalIndex: index })}/> + this.modifyNameColumn(name)}/> this.stateLabelStyle(state, component)} />