+
+ )
+ }
+}
+
+
+export default App
diff --git a/src/data-managers/visualizations-data-manager.js b/src/common/FluxContainerConverter.js
similarity index 60%
rename from src/data-managers/visualizations-data-manager.js
rename to src/common/FluxContainerConverter.js
index b141880..9d1b371 100644
--- a/src/data-managers/visualizations-data-manager.js
+++ b/src/common/FluxContainerConverter.js
@@ -1,8 +1,4 @@
/**
- * File: visualizations-data-manager.js
- * Author: Markus Grigull
- * Date: 03.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -19,6 +15,20 @@
* along with VILLASweb. If not, see .
******************************************************************************/
-import RestDataManager from './rest-data-manager';
+/// FluxContainerConverter.js
+/// ATTENTION!!! This is an ugly workaround found here https://github.com/facebook/flux/issues/351 to make Flux Containers work with ES6
+
+
+function convert(containerClass) {
+ const tmp = containerClass;
+ containerClass = function(...args) {
+ return new tmp(...args);
+ };
+ containerClass.prototype = tmp.prototype;
+ containerClass.getStores = tmp.getStores;
+ containerClass.calculateState = tmp.calculateState;
+ return containerClass;
+}
+
+export {convert}
-export default new RestDataManager('visualization', '/visualizations');
diff --git a/src/api/rest-api.js b/src/common/api/rest-api.js
similarity index 71%
rename from src/api/rest-api.js
rename to src/common/api/rest-api.js
index 43af793..084456c 100644
--- a/src/api/rest-api.js
+++ b/src/common/api/rest-api.js
@@ -1,8 +1,4 @@
/**
- * File: rest-api.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -23,7 +19,6 @@ import request from 'superagent/lib/client';
import Promise from 'es6-promise';
import NotificationsDataManager from '../data-managers/notifications-data-manager';
-
// TODO: Add this to a central pool of notifications
const SERVER_NOT_REACHABLE_NOTIFICATION = {
title: 'Server not reachable',
@@ -37,32 +32,36 @@ const REQUEST_TIMEOUT_NOTIFICATION = {
level: 'error'
};
-// Check if the error was due to network failure, timeouts, etc.
+// Check if the error was due to network failure, timeouts, etc.
// Can be used for the rest of requests
function isNetworkError(err) {
let result = false;
// If not status nor response fields, it is a network error. TODO: Handle timeouts
- if (err.status == null || err.response == null) {
+ if (err.status == null || err.status === 500 || err.response == null) {
result = true;
-
+
let notification = err.timeout? REQUEST_TIMEOUT_NOTIFICATION : SERVER_NOT_REACHABLE_NOTIFICATION;
NotificationsDataManager.addNotification(notification);
}
return result;
}
+let prevURL = null;
+
class RestAPI {
get(url, token) {
return new Promise(function (resolve, reject) {
var req = request.get(url);
if (token != null) {
- req.set('x-access-token', token);
+ req.set('Authorization', "Bearer " + token);
}
req.end(function (error, res) {
if (res == null || res.status !== 200) {
+ if (req.url !== prevURL) error.handled = isNetworkError(error);
+ prevURL = req.url;
reject(error);
} else {
resolve(JSON.parse(res.text));
@@ -76,9 +75,9 @@ class RestAPI {
var req = request.post(url).send(body).timeout({ response: 5000 }); // Simple response start timeout (3s)
if (token != null) {
- req.set('x-access-token', token);
+ req.set('Authorization', "Bearer " + token);
}
-
+
req.end(function (error, res) {
if (res == null || res.status !== 200) {
@@ -97,11 +96,12 @@ class RestAPI {
var req = request.delete(url);
if (token != null) {
- req.set('x-access-token', token);
+ req.set('Authorization', "Bearer " + token);
}
req.end(function (error, res) {
if (res == null || res.status !== 200) {
+ error.handled = isNetworkError(error);
reject(error);
} else {
resolve(JSON.parse(res.text));
@@ -115,11 +115,12 @@ class RestAPI {
var req = request.put(url).send(body);
if (token != null) {
- req.set('x-access-token', token);
+ req.set('Authorization', "Bearer " + token);
}
req.end(function (error, res) {
if (res == null || res.status !== 200) {
+ error.handled = isNetworkError(error);
reject(error);
} else {
resolve(JSON.parse(res.text));
@@ -128,16 +129,17 @@ class RestAPI {
});
}
- upload(url, data, token, progressCallback) {
+ upload(url, data, token, progressCallback, scenarioID) {
return new Promise(function (resolve, reject) {
- const req = request.post(url).send(data).on('progress', progressCallback);
+ const req = request.post(url + "?scenarioID=" + scenarioID).send(data).on('progress', progressCallback);
if (token != null) {
- req.set('x-access-token', token);
+ req.set('Authorization', "Bearer " + token);
}
req.end(function (error, res) {
if (res == null || res.status !== 200) {
+ error.handled = isNetworkError(error);
reject(error);
} else {
resolve(JSON.parse(res.text));
@@ -145,6 +147,29 @@ class RestAPI {
});
});
}
+
+
+ download(url, token, fileID) {
+ return new Promise(function (resolve, reject) {
+ let req = request.get(url + "/" + fileID).buffer(true).responseType("blob")
+ // use blob response type and buffer
+ if (token != null) {
+ req.set('Authorization', "Bearer " + token);
+ }
+
+ req.end(function (error, res) {
+ if (error !== null || res.status !== 200) {
+ error.handled = isNetworkError(error);
+ reject(error);
+ } else {
+ // file data is contained in res.body (because of blob response type)
+ let parts = url.split("/");
+ resolve({data: res.body, type: res.type, id: parts[parts.length-1]})
+ }
+ });
+ });
+ }
+
}
export default new RestAPI();
diff --git a/src/api/websocket-api.js b/src/common/api/websocket-api.js
similarity index 75%
rename from src/api/websocket-api.js
rename to src/common/api/websocket-api.js
index 94fc953..89a1ee6 100644
--- a/src/api/websocket-api.js
+++ b/src/common/api/websocket-api.js
@@ -1,8 +1,4 @@
/**
- * File: websocket-api.js
- * Author: Markus Grigull
- * Date: 03.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -20,19 +16,19 @@
******************************************************************************/
class WebsocketAPI {
- constructor(endpoint, callbacks) {
- this.endpoint = endpoint;
+ constructor(websocketurl, callbacks) {
+ this.websocketurl = websocketurl;
this.callbacks = callbacks;
this.wasConnected = false;
this.isClosing = false;
- this.connect(endpoint, callbacks);
+ this.connect(websocketurl, callbacks);
}
- connect(endpoint, callbacks) {
+ connect(websocketurl, callbacks) {
// create web socket client
- this.socket = new WebSocket(WebsocketAPI.getURL(endpoint), 'live');
+ this.socket = new WebSocket(WebsocketAPI.getURL(websocketurl), 'live');
this.socket.binaryType = 'arraybuffer';
this.socket.onclose = this.onClose;
this.socket.onopen = this.onOpen;
@@ -44,12 +40,12 @@ class WebsocketAPI {
}
reconnect() {
- //console.log("Reconnecting: " + this.endpoint);
- this.connect(this.endpoint, this.callbacks);
+ //console.log("Reconnecting: " + this.websocketurl);
+ this.connect(this.websocketurl, this.callbacks);
}
get url() {
- return WebsocketAPI.getURL(this.endpoint);
+ return WebsocketAPI.getURL(this.websocketurl);
}
send(data) {
@@ -62,7 +58,7 @@ class WebsocketAPI {
}
onError = e => {
- console.error('Error on WebSocket connection to: ' + this.endpoint + ':', e);
+ console.error('Error on WebSocket connection to: ' + this.websocketurl + ':', e);
if ('onError' in this.callbacks)
this.callbacks.onError(e);
@@ -82,16 +78,16 @@ class WebsocketAPI {
}
else {
if (this.wasConnected) {
- console.log("Connection to " + this.endpoint + " 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(endpoint) {
+ static getURL(websocketurl) {
// create an anchor element (note: no need to append this element to the document)
var link = document.createElement('a');
- link.href = endpoint;
+ link.href = websocketurl;
if (link.protocol === 'https:')
link.protocol = 'wss:';
diff --git a/src/app-dispatcher.js b/src/common/app-dispatcher.js
similarity index 91%
rename from src/app-dispatcher.js
rename to src/common/app-dispatcher.js
index ee54eb5..76866ed 100644
--- a/src/app-dispatcher.js
+++ b/src/common/app-dispatcher.js
@@ -1,8 +1,4 @@
/**
- * File: app-dispatcher.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
diff --git a/src/stores/array-store.js b/src/common/array-store.js
similarity index 59%
rename from src/stores/array-store.js
rename to src/common/array-store.js
index ccd9689..1ab4b7f 100644
--- a/src/stores/array-store.js
+++ b/src/common/array-store.js
@@ -1,8 +1,4 @@
/**
- * File: array-store.js
- * Author: Markus Grigull
- * Date: 03.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -21,7 +17,8 @@
import { ReduceStore } from 'flux/utils';
-import AppDispatcher from '../app-dispatcher';
+import AppDispatcher from './app-dispatcher';
+import NotificationsDataManager from '../common/data-managers/notifications-data-manager';
class ArrayStore extends ReduceStore {
constructor(type, dataManager) {
@@ -39,7 +36,7 @@ class ArrayStore extends ReduceStore {
// search for existing element to update
state.forEach((element, index, array) => {
newElements = newElements.filter((updateElement, newIndex) => {
- if (element._id === updateElement._id) {
+ if (element.id === updateElement.id) {
// update each property
for (var key in updateElement) {
if (updateElement.hasOwnProperty(key)) {
@@ -69,10 +66,10 @@ class ArrayStore extends ReduceStore {
case this.type + '/start-load':
if (Array.isArray(action.data)) {
action.data.forEach((id) => {
- this.dataManager.load(id, action.token);
+ this.dataManager.load(id, action.token,action.param);
});
} else {
- this.dataManager.load(action.data, action.token);
+ this.dataManager.load(action.data, action.token,action.param);
}
return state;
@@ -84,43 +81,73 @@ class ArrayStore extends ReduceStore {
}
case this.type + '/load-error':
- // TODO: Add error message
- return state;
+ if (action.error && !action.error.handled && action.error.response) {
+
+ const USER_LOAD_ERROR_NOTIFICATION = {
+ title: 'Failed to load',
+ message: action.error.response.body.message,
+ level: 'error'
+ };
+ NotificationsDataManager.addNotification(USER_LOAD_ERROR_NOTIFICATION);
+
+ }
+ return super.reduce(state, action);
case this.type + '/start-add':
- this.dataManager.add(action.data, action.token);
+ this.dataManager.add(action.data, action.token,action.param);
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':
- // TODO: Add error message
- return state;
+
+ return state;
+
case this.type + '/start-remove':
- this.dataManager.remove(action.data, action.token);
+ this.dataManager.remove(action.data, action.token,action.param);
return state;
case this.type + '/removed':
- return state.filter((item) => {
- return (item !== action.original);
- });
-
+ if (action.original) {
+ return state.filter((item) => {
+ return (item !== action.original);
+ });
+ } else {
+ return state.filter((item) => {
+ return (item.id !== action.data);
+ });
+ }
+
case this.type + '/remove-error':
- // TODO: Add error message
- return state;
+ if (action.error && !action.error.handled && action.error.response) {
+
+ const USER_REMOVE_ERROR_NOTIFICATION = {
+ title: 'Failed to add remove ',
+ message: action.error.response.body.message,
+ level: 'error'
+ };
+ NotificationsDataManager.addNotification(USER_REMOVE_ERROR_NOTIFICATION);
+
+ }
+ return super.reduce(state, action);
case this.type + '/start-edit':
- this.dataManager.update(action.data, action.token);
+ if(action.id){
+ this.dataManager.update(action.data, action.token,action.param,action.id);
+ }
+ else{
+ this.dataManager.update(action.data, action.token,action.param);
+ }
return state;
case this.type + '/edited':
return this.updateElements(state, [action.data]);
case this.type + '/edit-error':
- // TODO: Add error message
- return state;
+ return state;
default:
return state;
diff --git a/src/data-managers/notifications-data-manager.js b/src/common/data-managers/notifications-data-manager.js
similarity index 89%
rename from src/data-managers/notifications-data-manager.js
rename to src/common/data-managers/notifications-data-manager.js
index f463fcd..3b7601f 100644
--- a/src/data-managers/notifications-data-manager.js
+++ b/src/common/data-managers/notifications-data-manager.js
@@ -1,8 +1,4 @@
/**
- * File: notifications-data-manager.js
- * Author: Markus Grigull
- * Date: 21.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
diff --git a/src/data-managers/simulations-data-manager.js b/src/common/data-managers/notifications-factory.js
similarity index 70%
rename from src/data-managers/simulations-data-manager.js
rename to src/common/data-managers/notifications-factory.js
index 30885aa..a23768f 100644
--- a/src/data-managers/simulations-data-manager.js
+++ b/src/common/data-managers/notifications-factory.js
@@ -1,8 +1,4 @@
/**
- * File: simulation-data-manager.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -19,6 +15,17 @@
* along with VILLASweb. If not, see .
******************************************************************************/
-import RestDataManager from './rest-data-manager';
+class NotificationsFactory {
-export default new RestDataManager('simulation', '/simulations', [ '_id', 'name', 'projects', 'models', 'startParameters' ]);
+ // This is an example
+ static get EXAMPLE_NOTIFICATION() {
+ return {
+ title: 'Example notification',
+ message: 'Write something here that describes what happend.',
+ level: 'warning'
+ };
+ }
+
+}
+
+export default NotificationsFactory;
diff --git a/src/common/data-managers/rest-data-manager.js b/src/common/data-managers/rest-data-manager.js
new file mode 100644
index 0000000..7727a4e
--- /dev/null
+++ b/src/common/data-managers/rest-data-manager.js
@@ -0,0 +1,229 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import RestAPI from '../api/rest-api';
+import AppDispatcher from '../app-dispatcher';
+
+const API_URL = '/api/v2';
+
+class RestDataManager {
+ constructor(type, url, keyFilter) {
+ this.url = url;
+ this.type = type;
+ this.keyFilter = keyFilter;
+ this.onLoad = null;
+ }
+
+ makeURL(part) {
+ return API_URL + part;
+ }
+
+ filterKeys(object) {
+ // don't change anything if no filter is set
+ if (this.keyFilter == null || Array.isArray(this.keyFilter) === false) {
+ return object;
+ }
+
+ // remove all keys not in the filter
+ Object.keys(object).filter(key => {
+ return this.keyFilter.indexOf(key) === -1;
+ }).forEach(key => {
+ delete object[key];
+ });
+
+ return object;
+ }
+
+ requestURL(form, id, param, object = null){
+ switch(form){
+ case 'load/add':
+ if (param === null){
+ if(id != null){
+ return this.makeURL(this.url + '/' + id);
+ }
+ else {
+ return this.makeURL(this.url);
+ }
+ }
+ else{
+ if(id != null){
+ return this.makeURL(this.url + '/' + id + param);
+ }
+ else {
+ return this.makeURL(this.url + param)
+ }
+ }
+ case 'remove/update':
+ if(id !== null){
+ return this.makeURL(this.url + '/' + id);
+
+ }
+ else if(param === null){
+ return this.makeURL(this.url + '/' + object.id);
+ }
+ else{
+ return this.makeURL(this.url + '/' + object.id + param);
+ }
+ default:
+ console.log("something went wrong");
+ break;
+ }
+ }
+
+ load(id, token = null,param = null) {
+ if (id != null) {
+ // load single object
+ RestAPI.get(this.requestURL('load/add',id,param), token).then(response => {
+ let data;
+ if (response.hasOwnProperty(this.type)) {
+ data = this.filterKeys(response[this.type]);
+ }else{
+ // loaded file
+ data = response;
+ }
+
+ AppDispatcher.dispatch({
+ type: this.type + 's/loaded',
+ data: data,
+ token: token
+ });
+
+ if (this.onLoad != null) {
+ this.onLoad(data, token);
+ }
+ }).catch(error => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/load-error',
+ error: error
+ });
+ });
+ } else {
+ // load all objects
+ RestAPI.get(this.requestURL('load/add',id,param), token).then(response => {
+ const data = response[this.type + 's'].map(element => {
+ return this.filterKeys(element);
+ });
+
+ AppDispatcher.dispatch({
+ type: this.type + 's/loaded',
+ data: data,
+ token: token,
+ });
+
+ if (this.onLoad != null) {
+ this.onLoad(data, token);
+ }
+ }).catch(error => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/load-error',
+ error: error
+ });
+ });
+ }
+ }
+
+
+ add(object, token = null, param = null, subObjects = null) {
+ var obj = {};
+ obj[this.type] = this.filterKeys(object);
+ RestAPI.post(this.requestURL('load/add',null,param), obj, token).then(response => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/added',
+ data: response[this.type],
+ token: token
+ });
+
+ // check if POST is done for import of object and issue dispatches of sub-objects
+ if (subObjects !== null){
+ // there are sub-objects to be added for an import
+ for (let objectType of subObjects){
+ let type = Object.keys(objectType) // type can be dashboards, configs, widgets, ...
+ type = type[0];
+ for (let newObj of objectType[type]){
+
+ // set the ID of the object that the sub-object shall be associated with
+ if(type === "configs" || type === "dashboards"){
+ // the main object is a scenario
+ newObj.scenarioID = response[this.type].id
+ } else if (type === "widgets") {
+ // the main object is a dashboard
+ newObj.dashboardID = response[this.type].id
+ } else if (type === "signals") {
+ // the main object is a component configuration
+ newObj.configID = response[this.type].id
+ }
+
+ // iterate over all objects of type 'type' add issue add dispatch
+ AppDispatcher.dispatch({
+ type: type + '/start-add',
+ data: newObj,
+ token: token
+ })
+
+ }
+ }
+
+
+ }
+
+
+ }).catch(error => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/add-error',
+ error: error
+ });
+ });
+ }
+
+ remove(object, token = null, param = null) {
+ RestAPI.delete(this.requestURL('remove/update',null,param,object), token).then(response => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/removed',
+ data: response[this.type],
+ original: object,
+ token: token
+ });
+ }).catch(error => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/remove-error',
+ error: error
+ });
+ });
+ }
+
+ update(object, token = null, param = null, id = null) {
+ var obj = {};
+ obj[this.type] = this.filterKeys(object);
+
+ RestAPI.put(this.requestURL('remove/update',id,param,object), obj, token).then(response => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/edited',
+ data: response[this.type]
+ });
+ }).catch(error => {
+ AppDispatcher.dispatch({
+ type: this.type + 's/edit-error',
+ error: error
+ });
+ });
+ }
+
+
+
+};
+
+export default RestDataManager;
diff --git a/src/components/dialogs/delete-dialog.js b/src/common/dialogs/delete-dialog.js
similarity index 79%
rename from src/components/dialogs/delete-dialog.js
rename to src/common/dialogs/delete-dialog.js
index 13ece5e..8d114f4 100644
--- a/src/components/dialogs/delete-dialog.js
+++ b/src/common/dialogs/delete-dialog.js
@@ -1,8 +1,4 @@
/**
- * File: edit-user.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 02.05.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -20,13 +16,14 @@
******************************************************************************/
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) => {
if (event.key === 'Enter') {
event.preventDefault();
-
+
this.props.onClose(false);
}
}
@@ -39,11 +36,14 @@ 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/components/dialogs/dialog.js b/src/common/dialogs/dialog.js
similarity index 86%
rename from src/components/dialogs/dialog.js
rename to src/common/dialogs/dialog.js
index db4c6a4..4cc15af 100644
--- a/src/components/dialogs/dialog.js
+++ b/src/common/dialogs/dialog.js
@@ -1,8 +1,4 @@
/**
- * File: dialog.js
- * Author: Markus Grigull
- * Date: 03.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -50,7 +46,7 @@ class Dialog extends React.Component {
render() {
return (
-
+ {this.props.title}
@@ -60,7 +56,7 @@ class Dialog extends React.Component {
-
+ {this.props.blendOutCancel? : }
diff --git a/src/components/editable-header.js b/src/common/editable-header.js
similarity index 77%
rename from src/components/editable-header.js
rename to src/common/editable-header.js
index ff15d11..a10b48d 100644
--- a/src/components/editable-header.js
+++ b/src/common/editable-header.js
@@ -1,8 +1,4 @@
/**
- * File: header.js
- * Author: Markus Grigull
- * Date: 25.05.2018
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -18,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see .
******************************************************************************/
-
+// TODO remove this file (not used!)
import React from 'react';
import PropTypes from 'prop-types';
import { FormControl, Button } from 'react-bootstrap';
@@ -36,8 +32,10 @@ class EditableHeader extends React.Component {
};
}
- componentWillReceiveProps(nextProps) {
- this.setState({ title: nextProps.title });
+ static getDerivedStateFromProps(props, state){
+ return {
+ title: props.title
+ };
}
edit = () => {
@@ -66,7 +64,7 @@ class EditableHeader extends React.Component {
};
const iconStyle = {
- float: 'left',
+ float: 'right',
marginLeft: '10px',
marginTop: '25px',
@@ -82,11 +80,11 @@ class EditableHeader extends React.Component {
return
-
-
+
+
;
}
@@ -95,7 +93,7 @@ class EditableHeader extends React.Component {
{this.state.title}
-
+
;
}
}
diff --git a/src/components/footer.js b/src/common/footer.js
similarity index 92%
rename from src/components/footer.js
rename to src/common/footer.js
index e036516..534a18a 100644
--- a/src/components/footer.js
+++ b/src/common/footer.js
@@ -1,8 +1,4 @@
/**
- * File: footer.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
diff --git a/src/components/header-menu.js b/src/common/header-menu.js
similarity index 69%
rename from src/components/header-menu.js
rename to src/common/header-menu.js
index b2daf0e..9c6f7eb 100644
--- a/src/components/header-menu.js
+++ b/src/common/header-menu.js
@@ -1,8 +1,4 @@
/**
- * File: header-menu.js
- * Author: Markus Grigull
- * Date: 17.08.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -26,16 +22,17 @@ import { NavLink } from 'react-router-dom';
export default class HeaderMenu extends React.Component {
render() {
return
-
+
+
Home
-
Projects
-
Simulations
-
Simulators
- { this.props.currentRole === 'admin' ?
+
Scenarios
+
Infrastructure Components
+ { this.props.currentRole === 'Admin' ?
User Management
: ''
}
+
Account
Logout
;
diff --git a/src/components/header.js b/src/common/header.js
similarity index 63%
rename from src/components/header.js
rename to src/common/header.js
index 710ea9b..c5c71b7 100644
--- a/src/components/header.js
+++ b/src/common/header.js
@@ -1,8 +1,4 @@
/**
- * File: header.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -21,20 +17,26 @@
import React from 'react';
import { Col, Button } from 'react-bootstrap';
+import { Hidden } from 'react-grid-system'
import Icon from './icon';
+import config from '../config';
class Header extends React.Component {
render() {
return (
-
-
VILLASweb
-
-
- {this.props.showMenuButton &&
-
- }
+
+
{config.instance} - {config.subtitle}
+
+
+ {this.props.showMenuButton &&
+
+ }
+
+
);
}
diff --git a/src/common/home.js b/src/common/home.js
new file mode 100644
index 0000000..053c293
--- /dev/null
+++ b/src/common/home.js
@@ -0,0 +1,140 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from 'react';
+
+import config from '../config';
+import {Redirect} from "react-router-dom";
+
+class Home extends React.Component {
+ constructor(props) {
+ super(props);
+
+ // create url for API documentation, distinguish between localhost and production deployment
+ let docs_url = "";
+ let docs_location = "/swagger/index.html";
+ let base_url = window.location.origin;
+ if (base_url.search("localhost") === -1){
+ docs_url = base_url + docs_location;
+ } else {
+ // useful for local testing, replace port 3000 with port 4000 (port of backend)
+ docs_url = base_url.replace("3000", "4000") + docs_location;
+ }
+
+ this.state = {
+ docs_url: docs_url
+ };
+
+ }
+
+ getCounts(type) {
+ if (this.state.hasOwnProperty('counts'))
+ return this.state.counts[type];
+ else
+ return '?';
+ }
+
+ render() {
+
+ let currentUser = JSON.parse(localStorage.getItem("currentUser"));
+ if (currentUser == null){
+ console.log("HOME redirecting to logout/ login")
+ return ();
+ }
+
+ return (
+
The development of VILLASframework projects have received funding from
+
+
Urban Energy Lab 4.0 a project funded by OP EFRE NRW (European Regional Development Fund) for the setup of a novel energy research infrastructure.
+
RESERVE a European Union’s Horizon 2020 research and innovation programme under grant agreement No 727481
+
JARA-ENERGY. Jülich-Aachen Research Alliance (JARA) is an initiative of RWTH Aachen University and Forschungszentrum Jülich.
+
+
+
+
+
+
+ {
+ //
+ }
+
+ );
+ }
+}
+
+export default Home;
diff --git a/src/components/icon.js b/src/common/icon.js
similarity index 92%
rename from src/components/icon.js
rename to src/common/icon.js
index 1cff82a..1ad1701 100644
--- a/src/components/icon.js
+++ b/src/common/icon.js
@@ -1,8 +1,4 @@
/**
- * File: icon.js
- * Author: Steffen Vogel
- * Date: 09.06.2018
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
diff --git a/src/components/menu-sidebar.js b/src/common/menu-sidebar.js
similarity index 70%
rename from src/components/menu-sidebar.js
rename to src/common/menu-sidebar.js
index 51d7d83..06d1342 100644
--- a/src/components/menu-sidebar.js
+++ b/src/common/menu-sidebar.js
@@ -1,8 +1,4 @@
/**
- * File: menu-sidebar.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -30,12 +26,12 @@ class SidebarMenu extends React.Component {
Home
-
Projects
-
Simulations
-
Simulators
- { this.props.currentRole === 'admin' ?
-
Users
: ''
+
Scenarios
+
Infrastructure Components
+ { this.props.currentRole === 'Admin' ?
+
User Management
: ''
}
+
Account
Logout
diff --git a/src/components/parameters-editor.js b/src/common/parameters-editor.js
similarity index 95%
rename from src/components/parameters-editor.js
rename to src/common/parameters-editor.js
index 9f17e7e..aca6b05 100644
--- a/src/components/parameters-editor.js
+++ b/src/common/parameters-editor.js
@@ -1,8 +1,4 @@
/**
- * File: header.js
- * Author: Markus Grigull
- * Date: 06.06.2018
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
diff --git a/src/components/table-column.js b/src/common/table-column.js
similarity index 91%
rename from src/components/table-column.js
rename to src/common/table-column.js
index 1aafc2e..df68140 100644
--- a/src/components/table-column.js
+++ b/src/common/table-column.js
@@ -1,8 +1,4 @@
/**
- * File: table-column.js
- * Author: Markus Grigull
- * Date: 06.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -29,14 +25,19 @@ class TableColumn extends Component {
editButton: false,
deleteButton: false,
exportButton: false,
+ duplicateButton: false,
link: '/',
linkKey: '',
dataIndex: false,
inlineEditable: false,
+ inputType: 'text',
clickable: false,
labelKey: null,
checkbox: false,
- checkboxKey: ''
+ checkboxKey: '',
+ labelStyle: null,
+ labelModifier: null
+
};
render() {
diff --git a/src/components/table.js b/src/common/table.js
similarity index 65%
rename from src/components/table.js
rename to src/common/table.js
index 0eaac85..12d0ebf 100644
--- a/src/components/table.js
+++ b/src/common/table.js
@@ -1,8 +1,4 @@
/**
- * File: table.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
@@ -21,7 +17,7 @@
import React, { Component } from 'react';
import _ from 'lodash';
-import { Table, Button, FormControl, Label, Checkbox } from 'react-bootstrap';
+import { Table, Button, FormControl, FormLabel, FormCheck, Tooltip, OverlayTrigger } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import Icon from './icon';
@@ -32,7 +28,7 @@ class CustomTable extends Component {
this.activeInput = null;
this.state = {
- rows: this.getRows(props),
+ rows: CustomTable.getRows(props),
editCell: [ -1, -1 ]
};
}
@@ -45,7 +41,7 @@ class CustomTable extends Component {
this.setState({ editCell: [ column, row ]}); // x, y
}
- addCell(data, index, child) {
+ static addCell(data, index, child) {
// add data to cell
let content = null;
@@ -67,14 +63,14 @@ class CustomTable extends Component {
let cell = [];
if (content != null) {
- content = content.toString();
+ //content = content.toString();
// check if cell should be a link
const linkKey = child.props.linkKey;
if (linkKey && data[linkKey] != null) {
cell.push({content});
} else if (child.props.clickable) {
- cell.push();
+ cell.push();
} else {
cell.push(content);
}
@@ -83,45 +79,63 @@ class CustomTable extends Component {
// add label to content
const labelKey = child.props.labelKey;
if (labelKey && data[labelKey] != null) {
- var labelContent = data[labelKey];
+ let labelContent = data[labelKey];
if (child.props.labelModifier) {
labelContent = child.props.labelModifier(labelContent, data);
}
- cell.push();
+ let labelStyle = child.props.labelStyle(data[labelKey], data)
+
+ cell.push(
+
+
+ {labelContent}
+
+
+ );
}
+
if (child.props.dataIndex) {
cell.push(index);
}
// add buttons
if (child.props.editButton) {
- cell.push();
+ let disable = (typeof data.managedexternally !== "undefined" && data.managedexternally);
+ cell.push({disable? "Externally managed ICs cannot be edited" : "edit"} } >
+ );
}
if (child.props.deleteButton) {
- cell.push();
+ cell.push( Delete } >
+ );
}
if (child.props.checkbox) {
- const checkboxKey = this.props.checkboxKey;
+ const checkboxKey = child.props.checkboxKey;
- cell.push( child.props.onChecked(index, e)} />);
+ cell.push( child.props.onChecked(index, e)} />);
}
if (child.props.exportButton) {
- cell.push();
+ cell.push( Export } >
+ );
+ }
+
+ if (child.props.duplicateButton) {
+ cell.push( Duplicate } >
+ );
}
return cell;
- }
+ } // addCell
- componentWillReceiveProps(nextProps) {
- const rows = this.getRows(nextProps);
+ static getDerivedStateFromProps(props, state){
+ const rows = CustomTable.getRows(props);
- this.setState({ rows });
+ return { rows };
}
componentDidUpdate() {
@@ -141,7 +155,7 @@ class CustomTable extends Component {
this.setState({ editCell: [ -1, -1 ] });
}
- getRows(props) {
+ static getRows(props) {
if (props.data == null) {
return [];
}
@@ -150,13 +164,13 @@ class CustomTable extends Component {
// check if multiple columns
if (Array.isArray(props.children) === false) {
// table only has a single column
- return [ this.addCell(data, index, props.children) ];
+ return [ CustomTable.addCell(data, index, props.children) ];
}
const row = [];
for (let child of props.children) {
- row.push(this.addCell(data, index, child));
+ row.push(CustomTable.addCell(data, index, child));
}
return row;
@@ -200,7 +214,7 @@ class CustomTable extends Component {
return (
{(this.state.editCell[0] === cellIndex && this.state.editCell[1] === rowIndex ) ? (
- children[cellIndex].props.onInlineChange(event, rowIndex, cellIndex)} inputRef={ref => { this.activeInput = ref; }} />
+ children[cellIndex].props.onInlineChange(event, rowIndex, cellIndex)} ref={ref => { this.activeInput = ref; }} />
) : (
{cell.map((element, elementIndex) => (
diff --git a/src/componentconfig/config-store.js b/src/componentconfig/config-store.js
new file mode 100644
index 0000000..65f1d7c
--- /dev/null
+++ b/src/componentconfig/config-store.js
@@ -0,0 +1,69 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import ArrayStore from '../common/array-store';
+import ConfigsDataManager from './configs-data-manager';
+
+class ConfigStore extends ArrayStore {
+
+ constructor() {
+ super('configs', ConfigsDataManager);
+ }
+
+ reduce(state, action) {
+ switch (action.type) {
+
+ case 'configs/loaded':
+ return super.reduce(state, action);
+
+ case 'configs/start-add':
+ // Check if this is a recursive component config import or not
+ if (action.data.hasOwnProperty("outputMapping") || action.data.hasOwnProperty("inputMapping")) {
+ // import
+ let subObjects = []
+ let outputMapping = {}
+ let inputMapping = {}
+
+ if (action.data.hasOwnProperty("outputMapping")){
+ outputMapping["signals"] = action.data.outputMapping
+ subObjects.push(outputMapping)
+ delete action.data.outputMapping; // remove outputMapping signals from config object
+ }
+ if (action.data.hasOwnProperty("inputMapping")){
+ inputMapping["signals"] = action.data.inputMapping
+ subObjects.push(inputMapping)
+ delete action.data.inputMapping; // remove inputMapping signals from config object
+ }
+
+ // action.data should now contain the config and no sub-objects
+ // sub-objects are treated in add method of RestDataManager
+ this.dataManager.add(action.data, action.token,action.param, subObjects);
+ return state
+
+ } else {
+ // no import
+ return super.reduce(state, action);
+ }
+
+ default:
+ return super.reduce(state, action);
+
+ }
+ }
+}
+
+export default new ConfigStore();
diff --git a/src/componentconfig/configs-data-manager.js b/src/componentconfig/configs-data-manager.js
new file mode 100644
index 0000000..3fdca3f
--- /dev/null
+++ b/src/componentconfig/configs-data-manager.js
@@ -0,0 +1,60 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import RestDataManager from '../common/data-managers/rest-data-manager';
+import AppDispatcher from '../common/app-dispatcher';
+
+class ConfigDataManager extends RestDataManager {
+ constructor() {
+ super('config', '/configs');
+
+ this.onLoad = this.onConfigsLoad;
+ }
+
+ onConfigsLoad(data, token) {
+ if (!Array.isArray(data))
+ data = [ data ];
+
+ for (let config of data) {
+
+ // prepare IC data
+ AppDispatcher.dispatch({
+ type: 'icData/prepare',
+ inputLength: parseInt(config.inputLength, 10),
+ outputLength: parseInt(config.outputLength, 10),
+ id: config.icID
+ });
+
+ // request in signals
+ AppDispatcher.dispatch({
+ type: 'signals/start-load',
+ token: token,
+ param: '?direction=in&configID=' + config.id,
+ });
+
+ // request out signals
+ AppDispatcher.dispatch({
+ type: 'signals/start-load',
+ token: token,
+ param: '?direction=out&configID=' + config.id,
+ });
+ }
+
+ }
+}
+
+export default new ConfigDataManager();
diff --git a/src/componentconfig/edit-config.js b/src/componentconfig/edit-config.js
new file mode 100644
index 0000000..2277331
--- /dev/null
+++ b/src/componentconfig/edit-config.js
@@ -0,0 +1,191 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from 'react';
+import {FormGroup, FormControl, FormLabel} from 'react-bootstrap';
+import { Multiselect } from 'multiselect-react-dropdown'
+import Dialog from '../common/dialogs/dialog';
+import ParametersEditor from '../common/parameters-editor';
+
+class EditConfigDialog extends React.Component {
+ valid = false;
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ name: '',
+ icID: '',
+ startParameters: {},
+ selectedFiles: [] // list of selected files {name, id}, this is not the fileIDs list of the config!
+ };
+ }
+
+ onClose(canceled) {
+ if (canceled === false) {
+ if (this.valid) {
+ let data = this.props.config;
+ if (this.state.name !== '' && this.props.config.name !== this.state.name) {
+ data.name = this.state.name;
+ }
+ if (this.state.icID !== '' && this.props.config.icID !== parseInt(this.state.icID)) {
+ data.icID = parseInt(this.state.icID, 10);
+ }
+ if(this.state.startParameters !== {} &&
+ JSON.stringify(this.props.config.startParameters) !== JSON.stringify(this.state.startParameters)){
+ data.startParameters = this.state.startParameters;
+ }
+
+ let IDs = []
+ for(let e of this.state.selectedFiles){
+ IDs.push(e.id)
+ }
+ if(this.props.config.fileIDs !== null && this.props.config.fileIDs !== undefined) {
+ if (JSON.stringify(IDs) !== JSON.stringify(this.props.config.fileIDs)) {
+ data.fileIDs = IDs;
+ }
+ }
+ else{
+ data.fileIDs = IDs
+ }
+
+ //forward modified config to callback function
+ this.props.onClose(data)
+ }
+ } else {
+ this.props.onClose();
+ }
+ }
+
+ handleChange(e) {
+ this.setState({ [e.target.id]: e.target.value });
+ this.valid = this.isValid()
+ }
+
+ handleParameterChange(data) {
+ if (data) {
+ this.setState({startParameters: data});
+ }
+ this.valid = this.isValid()
+ }
+
+ onFileChange(selectedList, changedItem) {
+ this.setState({
+ selectedFiles: selectedList
+ })
+ this.valid = this.isValid()
+ }
+
+
+ isValid() {
+ // input is valid if at least one element has changed from its initial value
+ return this.state.name !== ''
+ || this.state.icID !== ''
+ || this.state.startParameters !== {}
+ }
+
+ resetState() {
+
+ // determine list of selected files incl id and filename
+ let selectedFiles = []
+ if(this.props.config.fileIDs !== null && this.props.config.fileIDs !== undefined) {
+ for (let selectedFileID of this.props.config.fileIDs) {
+ for (let file of this.props.files) {
+ if (file.id === selectedFileID) {
+ selectedFiles.push({name: file.name, id: file.id})
+ }
+ }
+ }
+ }
+
+ this.setState({
+ name: this.props.config.name,
+ icID: this.props.config.icID,
+ startParameters: this.props.config.startParameters,
+ selectedFiles: selectedFiles,
+ });
+ }
+
+
+ render() {
+ const ICOptions = this.props.ics.map(s =>
+
+ );
+
+ let configFileOptions = [];
+ for(let file of this.props.files) {
+ configFileOptions.push(
+ {name: file.name, id: file.id}
+ );
+ }
+
+ return (
+
+ );
+ }
+}
+
+export default EditConfigDialog;
diff --git a/src/componentconfig/import-config.js b/src/componentconfig/import-config.js
new file mode 100644
index 0000000..b11a69e
--- /dev/null
+++ b/src/componentconfig/import-config.js
@@ -0,0 +1,129 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from 'react';
+import { FormGroup, FormControl, FormLabel } from 'react-bootstrap';
+
+import Dialog from '../common/dialogs/dialog';
+
+class ImportConfigDialog extends React.Component {
+ imported = false;
+ valid = false;
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ config: {},
+ name: '',
+ };
+ }
+
+ onClose(canceled){
+ if (canceled) {
+ this.props.onClose();
+
+ return;
+ }
+
+ this.props.onClose(this.state);
+ }
+
+ resetState = () => {
+ this.setState({
+ config: {},
+ name: ''
+ });
+
+ this.imported = false;
+ }
+
+ loadFile = event => {
+ // get file
+ const file = event.target.files[0];
+ if (file.type.match('application/json') === false) {
+ return;
+ }
+
+ // create file reader
+ let reader = new FileReader();
+ let self = this;
+
+ reader.onload = event => {
+ const config = JSON.parse(event.target.result);
+
+ self.imported = true;
+ self.valid = true;
+ this.setState({name: config.name, config: config });
+ };
+
+ reader.readAsText(file);
+ }
+
+ handleChange(e, index) {
+ this.setState({ [e.target.id]: e.target.value });
+ }
+
+ validateForm(target) {
+ // check all controls
+ let name = true;
+
+ if (this.state.name === '') {
+ name = false;
+ }
+ this.valid = name;
+
+ // return state to control
+ if (target === 'name'){
+ return name;
+ }
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default ImportConfigDialog;
diff --git a/src/components/dialogs/edit-project.js b/src/components/dialogs/edit-project.js
deleted file mode 100644
index 2b960b6..0000000
--- a/src/components/dialogs/edit-project.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * File: edit-project.js
- * Author: Markus Grigull
- * Date: 07.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-
-class EditProjectDialog extends React.Component {
- valid: true;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- simulation: '',
- _id: ''
- }
- }
-
- onClose(canceled) {
- if (canceled === false) {
- if (this.valid) {
- this.props.onClose(this.state);
- }
- } else {
- this.props.onClose();
- }
- }
-
- handleChange(e) {
- this.setState({ [e.target.id]: e.target.value });
- }
-
- resetState() {
- this.setState({
- name: this.props.project.name,
- simulation: this.props.project.simulation,
- _id: this.props.project._id
- });
- }
-
- validateForm(target) {
- // check all controls
- var name = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- this.valid = name;
-
- // return state to control
- if (target === 'name') return name ? "success" : "error";
-
- return "success";
- }
-
- render() {
- return (
-
- );
- }
-}
-
-export default EditProjectDialog;
diff --git a/src/components/dialogs/edit-simulation.js b/src/components/dialogs/edit-simulation.js
deleted file mode 100644
index 0b1c87e..0000000
--- a/src/components/dialogs/edit-simulation.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * File: new-simulation.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-import ParametersEditor from '../parameters-editor';
-
-class EditSimulationDialog extends React.Component {
- valid = true;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- _id: '',
- startParameters: {}
- };
- }
-
- onClose = canceled => {
- if (canceled) {
- if (this.props.onClose != null) {
- this.props.onClose();
- }
-
- return;
- }
-
- if (this.valid && this.props.onClose != null) {
- this.props.onClose(this.state);
- }
- }
-
- handleChange = event => {
- this.setState({ [event.target.id]: event.target.value });
- }
-
- resetState = () => {
- this.setState({
- name: this.props.simulation.name,
- _id: this.props.simulation._id,
- startParameters: this.props.simulation.startParameters || {}
- });
- }
-
- handleStartParametersChange = startParameters => {
- this.setState({ startParameters });
- }
-
- validateForm(target) {
- let name = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- this.valid = name;
-
- // return state to control
- if (target === 'name') return name ? 'success' : 'error';
- }
-
- render() {
- return ;
- }
-}
-
-export default EditSimulationDialog;
diff --git a/src/components/dialogs/edit-simulator.js b/src/components/dialogs/edit-simulator.js
deleted file mode 100644
index 346fb2a..0000000
--- a/src/components/dialogs/edit-simulator.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * File: new-simulator.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-import _ from 'lodash';
-
-import Dialog from './dialog';
-import ParametersEditor from '../parameters-editor';
-
-class EditSimulatorDialog extends React.Component {
- valid = true;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- endpoint: ''
- };
- }
-
- onClose(canceled) {
- if (canceled === false) {
- if (this.valid) {
- let data = {};
-
- if (this.state.name != null && this.state.name !== "" && this.state.name !== _.get(this.props.simulator, 'rawProperties.name')) {
- data.name = this.state.name;
- }
-
- if (this.state.endpoint != null && this.state.endpoint !== "" && this.state.endpoint !== "http://" && this.state.endpoint !== _.get(this.props.simulator, 'rawProperties.endpoint')) {
- data.endpoint = this.state.endpoint;
- }
-
- this.props.onClose(data);
- }
- } else {
- this.props.onClose();
- }
- }
-
- handleChange(e) {
- this.setState({ [e.target.id]: e.target.value });
- }
-
- resetState() {
- this.setState({
- name: _.get(this.props.simulator, 'properties.name') || _.get(this.props.simulator, 'rawProperties.name'),
- endpoint: _.get(this.props.simulator, 'properties.endpoint') || _.get(this.props.simulator, 'rawProperties.endpoint')
- });
- }
-
- render() {
- return (
-
- );
- }
-}
-
-export default EditSimulatorDialog;
diff --git a/src/components/dialogs/edit-user.js b/src/components/dialogs/edit-user.js
deleted file mode 100644
index e518b7d..0000000
--- a/src/components/dialogs/edit-user.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * File: edit-user.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 02.05.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-
-class EditUserDialog extends React.Component {
- valid: true;
-
- constructor(props) {
- super(props);
-
- this.state = {
- username: '',
- mail: '',
- role: '',
- _id: ''
- }
- }
-
- onClose(canceled) {
- if (canceled === false) {
- if (this.valid) {
- this.props.onClose(this.state);
- }
- } else {
- this.props.onClose();
- }
- }
-
- handleChange(e) {
- this.setState({ [e.target.id]: e.target.value });
- }
-
- resetState() {
- this.setState({
- username: this.props.user.username,
- mail: this.props.user.mail,
- role: this.props.user.role,
- _id: this.props.user._id
- });
- }
-
- validateForm(target) {
- // check all controls
- var username = true;
-
- if (this.state.username === '') {
- username = false;
- }
-
- this.valid = username;
-
- // return state to control
- if (target === 'username') return username ? "success" : "error";
-
- return "success";
- }
-
- render() {
- return (
-
- );
- }
-}
-
-export default EditUserDialog;
diff --git a/src/components/dialogs/edit-widget-color-control.js b/src/components/dialogs/edit-widget-color-control.js
deleted file mode 100644
index 6a44e3d..0000000
--- a/src/components/dialogs/edit-widget-color-control.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * File: edit-widget-color-control.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 24.04.2017
- * Copyright: 2018, Institute for Automation of Complex Power Systems, EONERC
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { FormGroup, Col, Row, Radio, ControlLabel } from 'react-bootstrap';
-import classNames from 'classnames';
-import { scaleOrdinal, schemeCategory20 } from 'd3-scale';
-
-class EditWidgetColorControl extends Component {
-
- static get ColorPalette() {
- let colorCount = 0;
- const colors = [];
- const colorScale = scaleOrdinal(schemeCategory20);
- while (colorCount < 20) { colors.push(colorScale(colorCount)); colorCount++; }
- colors.unshift('#000', '#FFF'); // include black and white
-
- return colors;
- }
-
- constructor(props) {
- super(props);
-
- this.state = {
- widget: {}
- };
- }
-
- componentWillReceiveProps(nextProps) {
- // Update state's widget with props
- this.setState({ widget: nextProps.widget });
- }
-
- render() {
-
- return (
-
-
-
- { this.props.label }
-
-
- {
- EditWidgetColorControl.ColorPalette.map( (color, idx ) => {
- let colorStyle = {
- background: color,
- borderColor: color
- };
-
- let checkedClass = classNames({
- 'checked': idx === this.state.widget[this.props.controlId]
- });
-
- return ( this.props.handleChange({target: { id: this.props.controlId, value: idx}})} />)
- }
- )
- }
-
-
- )
- }
-}
-
-export default EditWidgetColorControl;
diff --git a/src/components/dialogs/edit-widget-color-zones-control.js b/src/components/dialogs/edit-widget-color-zones-control.js
deleted file mode 100644
index 3367218..0000000
--- a/src/components/dialogs/edit-widget-color-zones-control.js
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * File: edit-widget-color-zones-control.js
- * Author: Markus Grigull
- * Date: 20.08.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, ControlLabel, Button } from 'react-bootstrap';
-
-
-import Icon from '../icon';
-import Table from '../table';
-import TableColumn from '../table-column';
-
-class EditWidgetColorZonesControl extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- widget: {
- zones: []
- },
- selectedZones: []
- };
- }
-
- componentWillReceiveProps(nextProps) {
- this.setState({ widget: nextProps.widget });
- }
-
- addZone = () => {
- // add row
- const widget = this.state.widget;
- widget.zones.push({ strokeStyle: 'ffffff', min: 0, max: 100 });
-
- this.setState({ widget });
-
- this.sendEvent(widget);
- }
-
- removeZones = () => {
- // remove zones
- const widget = this.state.widget;
-
- this.state.selectedZones.forEach(row => {
- widget.zones.splice(row, 1);
- });
-
- this.setState({ selectedZones: [], widget });
-
- this.sendEvent(widget);
- }
-
- changeCell = (event, row, column) => {
- // change row
- const widget = this.state.widget;
-
- if (column === 1) {
- widget.zones[row].strokeStyle = event.target.value;
- } else if (column === 2) {
- widget.zones[row].min = event.target.value;
- } else if (column === 3) {
- widget.zones[row].max = event.target.value;
- }
-
- this.setState({ widget });
-
- this.sendEvent(widget);
- }
-
- sendEvent(widget) {
- // create event
- const event = {
- target: {
- id: 'zones',
- value: widget.zones
- }
- };
-
- this.props.handleChange(event);
- }
-
- checkedCell = (row, event) => {
- // update selected rows
- const selectedZones = this.state.selectedZones;
-
- if (event.target.checked) {
- if (selectedZones.indexOf(row) === -1) {
- selectedZones.push(row);
- }
- } else {
- let index = selectedZones.indexOf(row);
- if (row > -1) {
- selectedZones.splice(index, 1);
- }
- }
-
- this.setState({ selectedZones });
- }
-
- render() {
- return
- Color zones
-
-
-
-
-
-
-
-
-
-
- ;
- }
-}
-
-export default EditWidgetColorZonesControl;
diff --git a/src/components/dialogs/edit-widget-control-creator.js b/src/components/dialogs/edit-widget-control-creator.js
deleted file mode 100644
index fdce7e5..0000000
--- a/src/components/dialogs/edit-widget-control-creator.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * File: edit-widget-control-creator.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 23.05.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- **********************************************************************************/
-
-import React from 'react';
-
-import EditWidgetTextControl from './edit-widget-text-control';
-import EditWidgetNumberControl from './edit-widget-number-control';
-import EditWidgetColorControl from './edit-widget-color-control';
-import EditWidgetTimeControl from './edit-widget-time-control';
-import EditImageWidgetControl from './edit-widget-image-control';
-import EditWidgetSimulationControl from './edit-widget-simulation-control';
-import EditWidgetSignalControl from './edit-widget-signal-control';
-import EditWidgetSignalsControl from './edit-widget-signals-control';
-import EditWidgetOrientation from './edit-widget-orientation';
-import EditWidgetAspectControl from './edit-widget-aspect-control';
-import EditWidgetTextSizeControl from './edit-widget-text-size-control';
-import EditWidgetCheckboxControl from './edit-widget-checkbox-control';
-import EditWidgetColorZonesControl from './edit-widget-color-zones-control';
-import EditWidgetMinMaxControl from './edit-widget-min-max-control';
-import EditWidgetHTMLContent from './edit-widget-html-content';
-import EditWidgetParametersControl from './edit-widget-parameters-control';
-
-export default function createControls(widgetType = null, widget = null, sessionToken = null, files = null, validateForm, simulationModels, handleChange) {
- // Use a list to concatenate the controls according to the widget type
- var dialogControls = [];
-
- switch(widgetType) {
- case 'CustomAction':
- dialogControls.push(
- validateForm(id)} handleChange={e => handleChange(e)} />,
- validateForm(id)} handleChange={e => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />
- )
- break;
- case 'Action':
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />
- )
- break;
- case 'Value':
- let valueBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'signal', value: 0}}]);
- }
- dialogControls.push(
- validateForm(id)} handleChange={e => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => valueBoundOnChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Lamp':
- let lampBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'signal', value: 0}}]);
- }
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => lampBoundOnChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- validateForm(id)} handleChange={e => handleChange(e)} />,
- validateForm(id)} handleChange={(e) => handleChange(e)} />,
- validateForm(id)} handleChange={(e) => handleChange(e)} />,
- );
- break;
- case 'Plot':
- let plotBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'signals', value: []}}]);
- }
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => plotBoundOnChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Table':
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Image':
- // Restrict to only image file types (MIME)
- let imageControlFiles = files == null? [] : files.filter(file => file.type.includes('image'));
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Gauge':
- let gaugeBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'signal', value: ''}}]);
- }
- dialogControls.push(
- validateForm(id)} handleChange={e => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => gaugeBoundOnChange(e) } />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'PlotTable':
- let plotTableBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'preselectedSignals', value: []}}]);
- }
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => plotTableBoundOnChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Slider':
- dialogControls.push(
- handleChange(e)} validate={id => validateForm(id)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Button':
- let buttonBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'signal', value: 0}}]);
- }
- dialogControls.push(
- handleChange(e)} validate={id => validateForm(id)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => buttonBoundOnChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Box':
- dialogControls.push(
- validateForm(id)} handleChange={(e) => handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'Label':
- dialogControls.push(
- handleChange(e)} validate={id => validateForm(id)} />,
- handleChange(e)} />,
- handleChange(e)} />
- );
- break;
- case 'HTML':
- dialogControls.push(
- handleChange(e)} />
- );
- break;
- case 'Topology':
- // Restrict to only xml files (MIME)
- let topologyControlFiles = files == null? [] : files.filter( file => file.type.includes('xml'));
- dialogControls.push(
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />
- );
- break;
-
- case 'Input':
- let inputBoundOnChange = (e) => {
- handleChange([e, {target: {id: 'signal', value: 0}}]);
- }
- dialogControls.push(
- validateForm(id)} handleChange={e => handleChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => inputBoundOnChange(e)} />,
- validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />
- );
- break;
-
- default:
- console.log('Non-valid widget type: ' + widgetType);
- }
-
- return dialogControls;
-}
diff --git a/src/components/dialogs/edit-widget-html-content.js b/src/components/dialogs/edit-widget-html-content.js
deleted file mode 100644
index 3b02bc3..0000000
--- a/src/components/dialogs/edit-widget-html-content.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * File: edit-widget-html-content.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 03.09.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- **********************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-class EditWidgetHTMLContent extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- widget: {}
- };
- }
-
- handleKeyIgnore(event){
- // This function prevents a keystroke from beeing handled by dialog.js
- event.stopPropagation();
- }
-
- componentWillReceiveProps(nextProps) {
- // Update state's widget with props
- this.setState({ widget: nextProps.widget });
- }
-
- render() {
- return
- HTML Content
- this.props.handleChange(e)} />
- ;
- }
-}
-
-export default EditWidgetHTMLContent;
diff --git a/src/components/dialogs/edit-widget-image-control.js b/src/components/dialogs/edit-widget-image-control.js
deleted file mode 100644
index 9db27ac..0000000
--- a/src/components/dialogs/edit-widget-image-control.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * File: edit-widget-image-control.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel, Button, ProgressBar } from 'react-bootstrap';
-
-import AppDispatcher from '../../app-dispatcher';
-
-class EditImageWidgetControl extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- widget: {
- file: ''
- },
- fileList: null,
- progress: 0
- };
- }
-
- componentWillReceiveProps(nextProps) {
- this.setState({ widget: nextProps.widget });
- }
-
- startFileUpload = () => {
- // get selected file
- let formData = new FormData();
-
- for (let key in this.state.fileList) {
- if (this.state.fileList.hasOwnProperty(key) && this.state.fileList[key] instanceof File) {
- formData.append(key, this.state.fileList[key]);
- }
- }
-
- // upload files
- AppDispatcher.dispatch({
- type: 'files/start-upload',
- data: formData,
- token: this.props.sessionToken,
- progressCallback: this.uploadProgress,
- finishedCallback: this.clearProgress
- });
- }
-
- uploadProgress = (e) => {
- this.setState({ progress: Math.round(e.percent) });
- }
-
- clearProgress = () => {
- this.setState({ progress: 0 });
- }
-
- render() {
- return
;
- }
-}
-
-export default EditImageWidgetControl;
diff --git a/src/components/dialogs/edit-widget-min-max-control.js b/src/components/dialogs/edit-widget-min-max-control.js
deleted file mode 100644
index 39218bf..0000000
--- a/src/components/dialogs/edit-widget-min-max-control.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * File: edit-widget-min-max-control.js
- * Author: Markus Grigull
- * Date: 30.08.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel, Checkbox, Table } from 'react-bootstrap';
-
-class EditWidgetMinMaxControl extends React.Component {
- constructor(props) {
- super(props);
-
- const widget = {};
- widget[props.controlID + "UseMinMax"] = false;
- widget[props.controlId + "Min"] = 0;
- widget[props.controlId + "Max"] = 100;
-
- this.state = {
- widget
- };
- }
-
- componentWillReceiveProps(nextProps) {
- this.setState({ widget: nextProps.widget });
- }
-
- render() {
- return
- {this.props.label}
- this.props.handleChange(e)}>Enable min-max
-
-
-
-
-
- Min: this.props.handleChange(e)} />
-
-
- Max: this.props.handleChange(e)} />
-
-
-
-
- ;
- }
-}
-
-export default EditWidgetMinMaxControl;
diff --git a/src/components/dialogs/edit-widget-signals-control.js b/src/components/dialogs/edit-widget-signals-control.js
deleted file mode 100644
index 0b55312..0000000
--- a/src/components/dialogs/edit-widget-signals-control.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * File: edit-widget-signals-control.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 03.04.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- **********************************************************************************/
-
-import React, { Component } from 'react';
-import { FormGroup, Checkbox, ControlLabel, FormControl } from 'react-bootstrap';
-
-class EditWidgetSignalsControl extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- widget: {
- simulator: {}
- }
- };
- }
-
- componentWillReceiveProps(nextProps) {
- // Update state's widget with props
- this.setState({ widget: nextProps.widget });
- }
-
- handleSignalChange(checked, index) {
- var signals = this.state.widget[this.props.controlId];
- var new_signals;
-
- if (checked) {
- // add signal
- new_signals = signals.concat(index);
- } else {
- // remove signal
- new_signals = signals.filter( (idx) => idx !== index );
- }
-
- this.props.handleChange({ target: { id: this.props.controlId, value: new_signals } });
- }
-
- render() {
- const simulationModel = this.props.simulationModels.find(m => m._id === this.state.widget.simulationModel);
-
- let signalsToRender = [];
-
- if (simulationModel != null) {
- // If simulation model update the signals to render
- signalsToRender = simulationModel ? simulationModel.outputMapping : [];
- }
-
- return (
-
- Signals
- {
- signalsToRender.length === 0 || !this.state.widget.hasOwnProperty(this.props.controlId)? (
- No signals available.
- ) : (
- signalsToRender.map((signal, index) => (
- this.handleSignalChange(e.target.checked, index)}>{signal.name}
- ))
- )
- }
-
- );
- }
-}
-
-export default EditWidgetSignalsControl;
diff --git a/src/components/dialogs/edit-widget-simulation-control.js b/src/components/dialogs/edit-widget-simulation-control.js
deleted file mode 100644
index 3ad0642..0000000
--- a/src/components/dialogs/edit-widget-simulation-control.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * File: edit-widget-simulation-control.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 03.04.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- **********************************************************************************/
-
-import React, { Component } from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-class EditWidgetSimulationControl extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- widget: {
- simulationModel: ''
- }
- };
- }
-
- componentWillReceiveProps(nextProps) {
- // Update state's widget with props
- this.setState({ widget: nextProps.widget });
- }
-
- render() {
- return (
-
- Simulation Model
- this.props.handleChange(e)}>
- {
- this.props.simulationModels.length === 0 ? (
-
- ) : (
- this.props.simulationModels.map((model, index) => (
-
- )))
- }
-
-
- );
- }
-}
-
-export default EditWidgetSimulationControl;
diff --git a/src/components/dialogs/edit-widget.js b/src/components/dialogs/edit-widget.js
deleted file mode 100644
index 95e20c7..0000000
--- a/src/components/dialogs/edit-widget.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * File: edit-widget.js
- * Author: Markus Grigull
- * Date: 08.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-//import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-
-import createControls from './edit-widget-control-creator';
-
-class EditWidgetDialog extends React.Component {
- valid = true;
-
- constructor(props) {
- super(props);
-
- this.state = {
- temporal: {
- name: '',
- simulationModel: '',
- signal: 0
- }
- };
- }
-
- onClose(canceled) {
- if (canceled === false) {
- if (this.valid) {
- this.props.onClose(this.state.temporal);
- }
- } else {
- this.props.onClose();
- }
- }
-
- assignAspectRatio(changeObject, fileId) {
- // get aspect ratio of file
- const file = this.props.files.find(element => element._id === fileId);
-
- // scale width to match aspect
- const aspectRatio = file.dimensions.width / file.dimensions.height;
- changeObject.width = this.state.temporal.height * aspectRatio;
-
- return changeObject;
- }
-
- handleChange(e) {
- if (e.constructor === Array) {
- // Every property in the array will be updated
- let changes = e.reduce( (changesObject, event) => {
- changesObject[event.target.id] = event.target.value;
-
- return changesObject;
- }, {});
-
- this.setState({ temporal: Object.assign({}, this.state.temporal, changes ) });
- } else {
- let changeObject = {};
- if (e.target.id === 'lockAspect') {
- changeObject[e.target.id] = e.target.checked;
-
- // correct image aspect if turned on
- if (e.target.checked) {
- changeObject = this.assignAspectRatio(changeObject, this.state.temporal.file);
- }
- } else if (e.target.id === 'file') {
- changeObject[e.target.id] = e.target.value;
-
- // get file and update size (if it's an image)
- if ('lockAspect' in this.state.temporal && this.state.temporal.lockAspect) {
- changeObject = this.assignAspectRatio(changeObject, e.target.value);
- }
- } else if (e.target.type === 'checkbox') {
- changeObject[e.target.id] = e.target.checked;
- } else if (e.target.type === 'number') {
- changeObject[e.target.id] = Number(e.target.value);
- } else {
- changeObject[e.target.id] = e.target.value;
- }
-
- this.setState({ temporal: Object.assign({}, this.state.temporal, changeObject ) });
- }
- }
-
- resetState() {
- var widget_data = Object.assign({}, this.props.widget);
- this.setState({ temporal: widget_data });
- }
-
- validateForm(target) {
- // check all controls
- var name = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- //this.valid = name;
- this.valid = true;
-
- // return state to control
- if (target === 'name') return name ? "success" : "error";
- }
-
- render() {
- let controls = null;
- if (this.props.widget) {
- controls = createControls(
- this.props.widget.type,
- this.state.temporal,
- this.props.sessionToken,
- this.props.files,
- (id) => this.validateForm(id),
- this.props.simulationModels,
- (e) => this.handleChange(e));
- }
-
- return (
-
- );
- }
-}
-
-export default EditWidgetDialog;
diff --git a/src/components/dialogs/import-simulation-model.js b/src/components/dialogs/import-simulation-model.js
deleted file mode 100644
index 137dfe9..0000000
--- a/src/components/dialogs/import-simulation-model.js
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * File: import-simulation-model.js
- * Author: Markus Grigull
- * Date: 03.09.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-import _ from 'lodash';
-
-import Dialog from './dialog';
-
-class ImportSimulationModelDialog extends React.Component {
- imported = false;
-
- constructor(props) {
- super(props);
-
- this.state = {
- model: {}
- };
- }
-
- onClose = canceled => {
- if (canceled) {
- this.props.onClose();
-
- return;
- }
-
- this.props.onClose(this.state.model);
- }
-
- resetState = () => {
- this.setState({
- model: {}
- });
-
- this.imported = false;
- }
-
- loadFile = event => {
- // get file
- const file = event.target.files[0];
- if (file.type.match('application/json') === false) {
- return;
- }
-
- // create file reader
- const reader = new FileReader();
- const self = this;
-
- reader.onload = event => {
- const model = JSON.parse(event.target.result);
-
- model.simulator = this.props.simulators.length > 0 ? this.props.simulators[0]._id : null;
-
- self.imported = true;
-
- this.setState({ model });
- };
-
- reader.readAsText(file);
- }
-
- handleSimulatorChange = event => {
- const model = this.state.model;
-
- model.simulator = event.target.value;
-
- this.setState({ model });
- }
-
- render() {
- return (
-
- );
- }
-}
-
-export default ImportSimulationModelDialog;
diff --git a/src/components/dialogs/import-simulation.js b/src/components/dialogs/import-simulation.js
deleted file mode 100644
index e14eada..0000000
--- a/src/components/dialogs/import-simulation.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * File: import-simulation.js
- * Author: Markus Grigull
- * Date: 03.09.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-import ParametersEditor from '../parameters-editor';
-
-class ImportSimulationDialog extends React.Component {
- valid = false;
- imported = false;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- models: [],
- startParameters: {}
- };
- }
-
- onClose = canceled => {
- if (canceled) {
- if (this.props.onClose != null) {
- this.props.onClose();
- }
-
- return;
- }
-
- if (this.valid && this.props.onClose != null) {
- this.props.onClose(this.state);
- }
- }
-
- handleChange(e, index) {
- if (e.target.id === 'simulator') {
- const models = this.state.models;
- models[index].simulator = JSON.parse(e.target.value);
-
- this.setState({ models });
-
- return;
- }
-
- this.setState({ [e.target.id]: e.target.value });
- }
-
- resetState = () => {
- this.setState({ name: '', models: [], startParameters: {} });
-
- this.imported = false;
- }
-
- loadFile = event => {
- const file = event.target.files[0];
-
- if (!file.type.match('application/json')) {
- return;
- }
-
- // create file reader
- const reader = new FileReader();
- const self = this;
-
- reader.onload = onloadEvent => {
- const simulation = JSON.parse(onloadEvent.target.result);
-
- // simulation.models.forEach(model => {
- // model.simulator = {
- // node: self.props.nodes[0]._id,
- // simulator: 0
- // };
- // });
-
- self.imported = true;
- self.valid = true;
- self.setState({ name: simulation.name, models: simulation.models, startParameters: simulation.startParameters });
- };
-
- reader.readAsText(file);
- }
-
- validateForm(target) {
- // check all controls
- let name = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- this.valid = name;
-
- // return state to control
- if (target === 'name') return name ? "success" : "error";
- }
-
- render() {
- return ;
- }
-}
-
-export default ImportSimulationDialog;
diff --git a/src/components/dialogs/new-project.js b/src/components/dialogs/new-project.js
deleted file mode 100644
index babcf77..0000000
--- a/src/components/dialogs/new-project.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * File: new-project.js
- * Author: Markus Grigull
- * Date: 07.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-
-class NewProjectDialog extends React.Component {
- valid: false;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- simulation: ''
- };
- }
-
- onClose(canceled) {
- if (canceled === false) {
- if (this.valid) {
- this.props.onClose(this.state);
- }
- } else {
- this.props.onClose();
- }
- }
-
- handleChange(e) {
- this.setState({ [e.target.id]: e.target.value });
- }
-
- resetState() {
- this.setState({
- name: '',
- simulation: this.props.simulations[0] != null ? this.props.simulations[0]._id : ''
- });
- }
-
- validateForm(target) {
- // check all controls
- var name = true;
- var simulation = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- if (this.state.simulation === '') {
- simulation = false;
- }
-
- this.valid = name && simulation;
-
- // return state to control
- if (target === 'name') return name ? "success" : "error";
- else if (target === 'simulation') return simulation ? "success" : "error";
- }
-
- render() {
- return (
-
- );
- }
-}
-
-export default NewProjectDialog;
diff --git a/src/components/dialogs/new-simulation.js b/src/components/dialogs/new-simulation.js
deleted file mode 100644
index b09559c..0000000
--- a/src/components/dialogs/new-simulation.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * File: new-simulation.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-import ParametersEditor from '../parameters-editor';
-
-class NewSimulationDialog extends React.Component {
- valid = false;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- startParameters: {}
- };
- }
-
- onClose = canceled => {
- if (canceled) {
- if (this.props.onClose != null) {
- this.props.onClose();
- }
-
- return;
- }
-
- if (this.valid && this.props.onClose != null) {
- this.props.onClose(this.state);
- }
- }
-
- handleChange = event => {
- this.setState({ [event.target.id]: event.target.value });
- }
-
- resetState = () => {
- this.setState({ name: '', startParameters: {} });
- }
-
- handleStartParametersChange = startParameters => {
- this.setState({ startParameters });
- }
-
- validateForm(target) {
- // check all controls
- let name = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- this.valid = name;
-
- // return state to control
- if (target === 'name') return name ? "success" : "error";
- }
-
- render() {
- return ;
- }
-}
-
-export default NewSimulationDialog;
diff --git a/src/components/dialogs/new-simulator.js b/src/components/dialogs/new-simulator.js
deleted file mode 100644
index 1eb5b34..0000000
--- a/src/components/dialogs/new-simulator.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * File: new-simulator.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
-
-import Dialog from './dialog';
-
-class NewSimulatorDialog extends React.Component {
- valid = false;
-
- constructor(props) {
- super(props);
-
- this.state = {
- name: '',
- endpoint: '',
- uuid: ''
- };
- }
-
- onClose(canceled) {
- if (canceled === false) {
- if (this.valid) {
- const data = {
- properties: {
- name: this.state.name
- },
- uuid: this.state.uuid
- };
-
- if (this.state.endpoint != null && this.state.endpoint !== "" && this.state.endpoint !== 'http://') {
- data.properties.endpoint = this.state.endpoint;
- }
-
- this.props.onClose(data);
- }
- } else {
- this.props.onClose();
- }
- }
-
- handleChange(e) {
- this.setState({ [e.target.id]: e.target.value });
- }
-
- resetState() {
- this.setState({ name: '', endpoint: 'http://', uuid: this.uuidv4()});
- }
-
- validateForm(target) {
- // check all controls
- let name = true;
- let uuid = true;
-
- if (this.state.name === '') {
- name = false;
- }
-
- if (this.state.uuid === '') {
- uuid = false;
- }
-
- this.valid = name && uuid;
-
- // return state to control
- if (target === 'name') return name ? "success" : "error";
- if (target === 'uuid') return uuid ? "success" : "error";
- }
-
- 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);
- });
- }
-
- render() {
- return (
-
- );
- }
-}
-
-export default NewSimulatorDialog;
diff --git a/src/components/home.js b/src/components/home.js
deleted file mode 100644
index 86ea56b..0000000
--- a/src/components/home.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * File: home.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-
-import { Link } from 'react-router-dom';
-
-import RestAPI from '../api/rest-api';
-
-import config from '../config';
-
-class Home extends React.Component {
- constructor(props) {
- super(props);
- this.state = {};
- }
-
- getCounts(type) {
- if (this.state.hasOwnProperty('counts'))
- return this.state.counts[type];
- else
- return '?';
- }
-
- componentWillMount() {
- RestAPI.get('/api/v1/counts').then(response => {
- this.setState({ counts: response });
- });
- }
-
- render() {
- return (
-
-
-
Home
-
- Welcome to {config.instance}!
- VILLASweb is a frontend for distributed real-time simulation hosted by {config.admin.name}.
-
-
- This instance is hosting {this.getCounts('projects')} projects consisting of {this.getCounts('simulators')} simulators, {this.getCounts('visualizations')} visualizations and {this.getCounts('simulations')} simulations.
- A total of {this.getCounts('users')} users are registered.
-
The development of VILLASframework projects have received funding from
-
-
RESERVE a European Union’s Horizon 2020 research and innovation programme under grant agreement No 727481
-
JARA-ENERGY. Jülich-Aachen Research Alliance (JARA) is an initiative of RWTH Aachen University and Forschungszentrum Jülich.
-
-
-
-
- {
- //
- }
-
- );
- }
-}
-
-export default Home;
diff --git a/src/components/signal-mapping.js b/src/components/signal-mapping.js
deleted file mode 100644
index 815d90c..0000000
--- a/src/components/signal-mapping.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * File: signalMapping.js
- * Author: Markus Grigull
- * Date: 10.08.2018
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import PropTypes from 'prop-types';
-import { FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap';
-import validator from 'validator';
-
-import Table from './table';
-import TableColumn from './table-column';
-
-class SignalMapping extends React.Component {
- constructor(props) {
- super(props);
-
- var length = props.length;
- if (length === undefined)
- length = 1;
-
- this.state = {
- length: length,
- signals: props.signals
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.length === this.state.length && nextProps.signals === this.state.signals) {
- return;
- }
-
- this.setState({ length: nextProps.length, signals: nextProps.signals });
- }
-
- validateLength(){
- const valid = validator.isInt(this.state.length + '', { min: 1, max: 100 });
-
- return valid ? 'success' : 'error';
- }
-
- handleLengthChange = event => {
- const length = event.target.value;
-
- // update signals to represent length
- const signals = this.state.signals;
-
- if (this.state.length < length) {
- while (signals.length < length) {
- signals.push({ name: 'Signal', type: 'Type' });
- }
- } else {
- signals.splice(length, signals.length - length);
- }
-
- // save updated state
- this.setState({ length, signals });
-
- if (this.props.onChange != null) {
- this.props.onChange(length, signals);
- }
- }
-
- handleMappingChange = (event, row, column) => {
- const signals = this.state.signals;
-
- const length = this.state.length;
-
- if (column === 1) {
- signals[row].name = event.target.value;
- } else if (column === 2) {
- signals[row].type = event.target.value;
- }
-
- this.setState({ length, signals });
-
- if (this.props.onChange != null) {
- this.props.onChange(this.state.length, signals);
- }
- }
-
- render() {
- return
-
- {this.props.name} Length
-
-
-
-
-
- {this.props.name} Mapping
- Click name or type cell to edit
-
-
-
-
-
-
-
;
- }
-}
-
-SignalMapping.propTypes = {
- name: PropTypes.string,
- length: PropTypes.number,
- signals: PropTypes.arrayOf(
- PropTypes.shape({
- name: PropTypes.string.isRequired,
- type: PropTypes.string.isRequired
- })
- ),
- onChange: PropTypes.func
-};
-
-export default SignalMapping;
diff --git a/src/components/simulator-action.js b/src/components/simulator-action.js
deleted file mode 100644
index aef6625..0000000
--- a/src/components/simulator-action.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * File: simulator-actionm.js
- * Author: Markus Grigull
- * Date: 12.04.2018
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Button, DropdownButton, MenuItem } from 'react-bootstrap';
-
-class SimulatorAction extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- selectedAction: null
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (this.state.selectedAction == null) {
- if (nextProps.actions != null && nextProps.actions.length > 0) {
- this.setState({ selectedAction: nextProps.actions[0] });
- }
- }
- }
-
- setAction = id => {
- // search action
- for (let action of this.props.actions) {
- if (action.id === id) {
- this.setState({ selectedAction: action });
- }
- }
- }
-
- render() {
- const actionList = this.props.actions.map(action => (
-
- ));
-
- return
-
- {actionList}
-
-
-
-
;
- }
-}
-
-export default SimulatorAction;
diff --git a/src/components/widget-plot/plot-legend.js b/src/components/widget-plot/plot-legend.js
deleted file mode 100644
index 4bde597..0000000
--- a/src/components/widget-plot/plot-legend.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * File: plot-legend.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 10.04.2017
- * Copyright: 2018, Institute for Automation of Complex Power Systems, EONERC
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { scaleOrdinal, schemeCategory10 } from 'd3-scale';
-
-class PlotLegend extends React.Component {
- render() {
- const colorScale = scaleOrdinal(schemeCategory10);
-
- return
-
- {this.props.signals.map(signal =>
-
- {signal.name}
- {signal.type}
-
- )}
-
-
;
- }
-}
-
-export default PlotLegend;
diff --git a/src/components/widgets/gauge.js b/src/components/widgets/gauge.js
deleted file mode 100644
index d1baa50..0000000
--- a/src/components/widgets/gauge.js
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- * File: gauge.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 31.03.2017
- * Copyright: 2018, Institute for Automation of Complex Power Systems, EONERC
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { Gauge } from 'gaugeJS';
-
-class WidgetGauge extends Component {
- constructor(props) {
- super(props);
-
- this.gaugeCanvas = null;
- this.gauge = null;
-
- this.state = {
- value: 0,
- minValue: null,
- maxValue: null
- };
- }
-
- componentDidMount() {
- this.gauge = new Gauge(this.gaugeCanvas).setOptions(this.computeGaugeOptions(this.props.widget));
- //this.gauge.maxValue = this.state.maxValue;
- //this.gauge.setMinValue(this.state.minValue);
- this.gauge.animationSpeed = 30;
- //this.gauge.set(this.state.value);
-
- //this.updateLabels(this.state.minValue, this.state.maxValue);
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- this.setState({ value: 0 });
- return;
- }
-
- const simulator = nextProps.simulationModel.simulator;
-
- // update value
- if (nextProps.data == null || nextProps.data[simulator] == null
- || nextProps.data[simulator].output == null
- || nextProps.data[simulator].output.values == null
- || nextProps.data[simulator].output.values.length === 0
- || nextProps.data[simulator].output.values[0].length === 0) {
- this.setState({ value: 0 });
- return;
- }
-
- // check if value has changed
- const signal = nextProps.data[simulator].output.values[nextProps.widget.signal];
- // Take just 3 decimal positions
- // Note: Favor this method over Number.toFixed(n) in order to avoid a type conversion, since it returns a String
- if (signal != null) {
- const value = Math.round(signal[signal.length - 1].y * 1e3) / 1e3;
- if (this.state.value !== value && value != null) {
- this.setState({ value });
-
- // update min-max if needed
- let updateLabels = false;
- let minValue = this.state.minValue;
- let maxValue = this.state.maxValue;
-
- if (minValue == null) {
- minValue = value - 0.5;
- updateLabels = true;
-
- this.setState({ minValue });
- this.gauge.setMinValue(minValue);
- }
-
- if (maxValue == null) {
- maxValue = value + 0.5;
- updateLabels = true;
-
- this.setState({ maxValue });
- this.gauge.maxValue = maxValue;
- }
-
- if (nextProps.widget.valueUseMinMax) {
- if (this.state.minValue > nextProps.widget.valueMin) {
- minValue = nextProps.widget.valueMin;
-
- this.setState({ minValue });
- this.gauge.setMinValue(minValue);
-
- updateLabels = true;
- }
-
- if (this.state.maxValue < nextProps.widget.valueMax) {
- maxValue = nextProps.widget.valueMax;
-
- this.setState({ maxValue });
- this.gauge.maxValue = maxValue;
-
- updateLabels = true;
- }
- }
-
- if (updateLabels === false) {
- // check if min/max changed
- if (minValue > this.gauge.minValue) {
- minValue = this.gauge.minValue;
- updateLabels = true;
-
- this.setState({ minValue });
- }
-
- if (maxValue < this.gauge.maxValue) {
- maxValue = this.gauge.maxValue;
- updateLabels = true;
-
- this.setState({ maxValue });
- }
- }
-
- if (updateLabels) {
- this.updateLabels(minValue, maxValue);
- }
-
- // update gauge's value
- this.gauge.set(value);
- }
- }
- }
-
- updateLabels(minValue, maxValue, force) {
- // calculate labels
- const labels = [];
- const labelCount = 5;
- const labelStep = (maxValue - minValue) / (labelCount - 1);
-
- for (let i = 0; i < labelCount; i++) {
- labels.push(minValue + labelStep * i);
- }
-
- // calculate zones
- let zones = this.props.widget.colorZones ? this.props.widget.zones : null;
- if (zones != null) {
- // adapt range 0-100 to actual min-max
- const step = (maxValue - minValue) / 100;
-
- zones = zones.map(zone => {
- return Object.assign({}, zone, { min: (zone.min * step) + +minValue, max: zone.max * step + +minValue, strokeStyle: '#' + zone.strokeStyle });
- });
- }
-
- this.gauge.setOptions({
- staticLabels: {
- font: '10px "Helvetica Neue"',
- labels,
- color: "#000000",
- fractionDigits: 1
- },
- staticZones: zones
- });
- }
-
- computeGaugeOptions(widget) {
- return {
- angle: -0.25,
- lineWidth: 0.2,
- pointer: {
- length: 0.6,
- strokeWidth: 0.035
- },
- radiusScale: 0.8,
- colorStart: '#6EA2B0',
- colorStop: '#6EA2B0',
- strokeColor: '#E0E0E0',
- highDpiSupport: true,
- limitMax: false,
- limitMin: false
- };
- }
-
- render() {
- const componentClass = this.props.editing ? "gauge-widget editing" : "gauge-widget";
- let signalType = null;
-
- if (this.props.simulationModel != null) {
- signalType = (this.props.simulationModel != null && this.props.simulationModel.outputLength > 0 && this.props.widget.signal < this.props.simulationModel.outputLength) ? this.props.simulationModel.outputMapping[this.props.widget.signal].type : '';
- }
-
- return (
-
-
{this.props.widget.name}
-
- );
- }
-}
-
-export default WidgetGauge;
diff --git a/src/components/widgets/image.js b/src/components/widgets/image.js
deleted file mode 100644
index 3438a51..0000000
--- a/src/components/widgets/image.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * File: image.js
- * Author: Markus Grigull
- * Date: 14.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-
-import AppDispatcher from '../../app-dispatcher';
-import config from '../../config';
-
-class WidgetImage extends React.Component {
- componentWillReceiveProps(nextProps) {
- // Query the image referenced by the widget
- let widgetFile = nextProps.widget.file;
- if (widgetFile && !nextProps.files.find(file => file._id === widgetFile)) {
- AppDispatcher.dispatch({
- type: 'files/start-load',
- data: widgetFile,
- token: nextProps.token
- });
- }
- }
-
- render() {
- const file = this.props.files.find(file => file._id === this.props.widget.file);
-
- return (
-
- );
- }
-}
-
-export default WidgetImage;
diff --git a/src/components/widgets/input.js b/src/components/widgets/input.js
deleted file mode 100644
index 63bc655..0000000
--- a/src/components/widgets/input.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * File: input.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 29.03.2017
- * Copyright: 2018, Institute for Automation of Complex Power Systems, EONERC
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { Form, FormGroup, Col, ControlLabel, FormControl, InputGroup } from 'react-bootstrap';
-
-class WidgetInput extends Component {
-
- constructor(props) {
- super(props);
-
- this.state = {
- value: '',
- unit: ''
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- return;
- }
-
- // Update value
- if (nextProps.widget.default_value && this.state.value === undefined) {
- this.setState({
- value: nextProps.widget.default_value
- });
- }
-
- // Update unit
- if (nextProps.widget.simulationModel && nextProps.simulationModel.inputMapping && this.state.unit !== nextProps.simulationModel.inputMapping[nextProps.widget.signal].type) {
- this.setState({
- unit: nextProps.simulationModel.inputMapping[nextProps.widget.signal].type
- });
- }
- }
-
- valueIsChanging(newValue) {
- this.setState({ value: newValue });
- }
-
- valueChanged(newValue) {
- if (this.props.onInputChanged) {
- this.props.onInputChanged(newValue);
- }
- }
-
- handleKeyPress(e) {
- if(e.charCode === 13) {
- this.valueChanged(this.state.value)
- }
- }
-
- render() {
- return (
-
-
-
- );
- }
-}
-
-export default WidgetInput;
diff --git a/src/components/widgets/lamp.js b/src/components/widgets/lamp.js
deleted file mode 100644
index 5b90f56..0000000
--- a/src/components/widgets/lamp.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * File: lamp.js
- * Author: Steffen Vogel
- * Date: 20.09.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-
-import EditWidgetColorControl from '../dialogs/edit-widget-color-control';
-
-class WidgetLamp extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- value: '',
- threshold: 0
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- this.setState({ value: '' });
- return;
- }
-
- const simulator = nextProps.simulationModel.simulator;
-
- // update value
- if (nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].output == null || nextProps.data[simulator].output.values == null) {
- this.setState({ value: '' });
- return;
- }
-
- // check if value has changed
- const signal = nextProps.data[simulator].output.values[nextProps.widget.signal];
- if (signal != null && this.state.value !== signal[signal.length - 1].y) {
- this.setState({ value: signal[signal.length - 1].y });
- }
- }
-
- render() {
- let colors = EditWidgetColorControl.ColorPalette;
- let color;
-
- if (Number(this.state.value) > Number(this.props.widget.threshold))
- color = colors[this.props.widget.on_color];
- else
- color = colors[this.props.widget.off_color];
-
- let style = {
- backgroundColor: color,
- width: this.props.widget.width,
- height: this.props.widget.height
- }
-
- return (
-
- );
- }
-}
-
-export default WidgetLamp;
diff --git a/src/components/widgets/plot-table.js b/src/components/widgets/plot-table.js
deleted file mode 100644
index 368f7c5..0000000
--- a/src/components/widgets/plot-table.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * File: plot-table.js
- * Author: Markus Grigull
- * Date: 15.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import classNames from 'classnames';
-import { FormGroup, Checkbox } from 'react-bootstrap';
-
-import Plot from '../widget-plot/plot';
-import PlotLegend from '../widget-plot/plot-legend';
-
-class WidgetPlotTable extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- preselectedSignals: [],
- signals: []
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- return;
- }
-
- // Update internal selected signals state with props (different array objects)
- if (this.props.widget.signals !== nextProps.widget.signals) {
- this.setState( {signals: nextProps.widget.signals});
- }
-
- // Identify if there was a change in the preselected signals
- if (JSON.stringify(nextProps.widget.preselectedSignals) !== JSON.stringify(this.props.widget.preselectedSignals) || this.state.preselectedSignals.length === 0) {
- // Update the currently selected signals by intersecting with the preselected signals
- // Do the same with the plot values
- var intersection = this.computeIntersection(nextProps.widget.preselectedSignals, nextProps.widget.signals);
- this.setState({ signals: intersection });
-
- this.updatePreselectedSignalsState(nextProps);
- return;
- }
- }
-
- // Perform the intersection of the lists, alternatively could be done with Sets ensuring unique values
- computeIntersection(preselectedSignals, selectedSignals) {
- return preselectedSignals.filter( s => selectedSignals.includes(s));
- }
-
- updatePreselectedSignalsState(nextProps) {
- // Create checkboxes using the signal indices from simulation model
- const preselectedSignals = nextProps.simulationModel.outputMapping.reduce(
- // Loop through simulation model signals
- (accum, model_signal, signal_index) => {
- // Append them if they belong to the current selected type
- if (nextProps.widget.preselectedSignals.indexOf(signal_index) > -1) {
- accum.push(
- {
- index: signal_index,
- name: model_signal.name,
- type: model_signal.type
- }
- )
- }
- return accum;
- }, []);
-
- this.setState({ preselectedSignals });
- }
-
- updateSignalSelection(signal_index, checked) {
- // Update the selected signals and propagate to parent component
- var new_widget = Object.assign({}, this.props.widget, {
- signals: checked? this.state.signals.concat(signal_index) : this.state.signals.filter( (idx) => idx !== signal_index )
- });
- this.props.onWidgetChange(new_widget);
- }
-
- render() {
- let checkBoxes = [];
-
- // Data passed to plot
- if (this.props.simulationModel == null) {
- return ;
- }
-
- const simulator = this.props.simulationModel.simulator;
- let simulatorData = [];
-
- if (this.props.data[simulator] != null && this.props.data[simulator].output != null && this.props.data[simulator].output.values != null) {
- simulatorData = this.props.data[simulator].output.values.filter((values, index) => (
- this.props.widget.signals.findIndex(value => value === index) !== -1
- ));
- }
-
- if (this.state.preselectedSignals && this.state.preselectedSignals.length > 0) {
- // Create checkboxes using the signal indices from simulation model
- checkBoxes = this.state.preselectedSignals.map( (signal) => {
- var checked = this.state.signals.indexOf(signal.index) > -1;
- var chkBxClasses = classNames({
- 'btn': true,
- 'btn-default': true,
- 'active': checked
- });
- return this.updateSignalSelection(signal.index, e.target.checked) } > { signal.name }
- });
- }
-
- // Prepare an array with the signals to show in the legend
- var legendSignals = this.state.preselectedSignals.reduce( (accum, signal, i) => {
- if (this.state.signals.includes(signal.index)) {
- accum.push({
- index: signal.index,
- name: signal.name,
- type: signal.type
- });
- }
- return accum;
- }, []);
-
- return (
-
-
-
-
- { checkBoxes.length > 0 ? (
-
- { checkBoxes }
-
- ) : ( No signal has been pre-selected. )
- }
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-export default WidgetPlotTable;
diff --git a/src/components/widgets/plot.js b/src/components/widgets/plot.js
deleted file mode 100644
index e61ca10..0000000
--- a/src/components/widgets/plot.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * File: plot.js
- * Author: Markus Grigull
- * Date: 08.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-
-import Plot from '../widget-plot/plot';
-import PlotLegend from '../widget-plot/plot-legend';
-
-class WidgetPlot extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- data: [],
- legend: []
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- this.setState({ data: [], legend: [] });
- return;
- }
-
- const simulator = nextProps.simulationModel.simulator;
-
- // Proceed if a simulation with models and a simulator are available
- if (simulator && nextProps.data[simulator] != null && nextProps.data[simulator] != null && nextProps.data[simulator].output != null && nextProps.data[simulator].output.values != null) {
- const chosenSignals = nextProps.widget.signals;
-
- const data = nextProps.data[simulator].output.values.filter((values, index) => (
- nextProps.widget.signals.findIndex(value => value === index) !== -1
- ));
-
- // Query the signals that will be displayed in the legend
- const legend = nextProps.simulationModel.outputMapping.reduce( (accum, model_signal, signal_index) => {
- if (chosenSignals.includes(signal_index)) {
- accum.push({ index: signal_index, name: model_signal.name, type: model_signal.type });
- }
-
- return accum;
- }, []);
-
- this.setState({ data, legend });
- } else {
- this.setState({ data: [], legend: [] });
- }
- }
-
- render() {
- return
-
-
-
-
-
;
- }
-}
-
-export default WidgetPlot;
diff --git a/src/components/widgets/slider.js b/src/components/widgets/slider.js
deleted file mode 100644
index 4212eef..0000000
--- a/src/components/widgets/slider.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * File: slider.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 30.03.2017
- * Copyright: 2018, Institute for Automation of Complex Power Systems, EONERC
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { format } from 'd3';
-import classNames from 'classnames';
-import Slider from 'rc-slider';
-import 'rc-slider/assets/index.css';
-
-class WidgetSlider extends Component {
-
- static get OrientationTypes() {
- return ({
- HORIZONTAL: {value: 0, name: 'Horizontal'},
- VERTICAL: {value: 1, name: 'Vertical'}
- })
- }
-
- constructor(props) {
- super(props);
-
- this.state = {
- unit: ''
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- return;
- }
-
- // Update value
- if (nextProps.widget.default_value && this.state.value === undefined) {
- this.setState({
- value: nextProps.widget.default_value,
- });
- }
-
- // Update unit
- if (nextProps.widget.simulationModel && nextProps.simulationModel.inputMapping && this.state.unit !== nextProps.simulationModel.inputMapping[nextProps.widget.signal].type) {
- this.setState({
- unit: nextProps.simulationModel.inputMapping[nextProps.widget.signal].type
- });
- }
-
- // Check if the orientation changed, update the size if it did
- if (this.props.widget.orientation !== nextProps.widget.orientation) {
- let baseWidget = nextProps.widget;
-
- // Exchange dimensions and constraints
- let newWidget = Object.assign({}, baseWidget, {
- width: baseWidget.height,
- height: baseWidget.width,
- minWidth: baseWidget.minHeight,
- minHeight: baseWidget.minWidth,
- maxWidth: baseWidget.maxHeight,
- maxHeight: baseWidget.maxWidth
- });
-
- nextProps.onWidgetChange(newWidget);
- }
- }
-
- valueIsChanging(newValue) {
- if (this.props.widget.continous_update)
- this.valueChanged(newValue);
-
- this.setState({ value: newValue });
- }
-
- valueChanged(newValue) {
- if (this.props.onInputChanged) {
- this.props.onInputChanged(newValue);
- }
- }
-
- render() {
- let isVertical = this.props.widget.orientation === WidgetSlider.OrientationTypes.VERTICAL.value;
-
- let fields = {
- name: this.props.widget.name,
- control: this.valueIsChanging(v) } onAfterChange={ (v) => this.valueChanged(v) }/>,
- value: { format('.3s')(Number.parseFloat(this.state.value)) },
- unit: { this.state.unit }
- }
-
- var widgetClasses = classNames({
- 'slider-widget': true,
- 'full': true,
- 'vertical': isVertical,
- 'horizontal': !isVertical
- });
-
- return (
- this.props.widget.orientation === WidgetSlider.OrientationTypes.HORIZONTAL.value? (
-
- )
- );
- }
-}
-
-export default WidgetSlider;
diff --git a/src/components/widgets/table.js b/src/components/widgets/table.js
deleted file mode 100644
index 53af120..0000000
--- a/src/components/widgets/table.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * File: table.js
- * Author: Markus Grigull
- * Date: 14.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { format } from 'd3';
-
-import Table from '../table';
-import TableColumn from '../table-column';
-
-class WidgetTable extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- rows: [],
- sequence: null,
- showUnit: false
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- this.setState({ rows: [], sequence: null });
- return;
- }
-
- const simulator = nextProps.simulationModel.simulator;
-
- // check data
- if (nextProps.data == null
- || nextProps.data[simulator] == null
- || nextProps.data[simulator].output == null
- || nextProps.data[simulator].output.values.length === 0
- || nextProps.data[simulator].output.values[0].length === 0) {
-
- // clear values
- this.setState({ rows: [], sequence: null, showUnit: false });
- return;
- }
-
- // check if new data, otherwise skip
- /*if (this.state.sequence >= nextProps.data[simulator.node][simulator.simulator].sequence) {
- return;
- }*/
-
- // get rows
- const rows = [];
-
- nextProps.data[simulator].output.values.forEach((signal, index) => {
- if (index < nextProps.simulationModel.outputMapping.length) {
- rows.push({
- name: nextProps.simulationModel.outputMapping[index].name,
- unit: nextProps.simulationModel.outputMapping[index].type,
- value: signal[signal.length - 1].y
- });
- }
- });
-
- this.setState({ showUnit: nextProps.showUnit, rows: rows, sequence: nextProps.data[simulator].output.sequence });
- }
-
- render() {
- var columns = [
- ,
-
- ];
-
- if (this.props.widget.showUnit)
- columns.push()
-
- return (
-
-
- { columns }
-
-
- );
- }
-}
-
-export default WidgetTable;
diff --git a/src/components/widgets/topology.js b/src/components/widgets/topology.js
deleted file mode 100644
index c47b155..0000000
--- a/src/components/widgets/topology.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/**
- * File: topology.js
- * Author: Ricardo Hernandez-Montoya
- * Date: 08.01.2018
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import {ReactSVGPanZoom} from 'react-svg-pan-zoom';
-import config from '../../config';
-import '../../styles/simple-spinner.css';
-import { cimsvg } from 'libcimsvg';
-
-// Do not show Pintura's grid
-const pinturaGridStyle = {
- display: 'none'
-}
-
-// Avoid another color in the frontend
-const pinturaBackingStyle = {
- fill: 'transparent'
-}
-
-// Center spinner
-const spinnerContainerStyle = {
- width: '100%',
- height: '100%',
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center'
-}
-
-// Topology failed message
-const msgContainerStyle = Object.assign({
- backgroundColor: '#ececec'
-},spinnerContainerStyle)
-
-const msgStyle = {
- fontWeight: 'bold'
-}
-
-// Initialize functions
-function attachComponentEvents() {
- window.onMouseOver = (e) => show(textSibling(e));
- window.onMouseLeave = (e) => hide(textSibling(e));
-}
-
-function textSibling(e) {
- // Find sibling text element and toggle its visibility
- let gParent = e.target.parentElement;
- return gParent.getElementsByTagName('text')[0];
-}
-
-function show(element) {
- element.style.visibility = 'inherit';
-}
-
-function hide(element) {
- element.style.visibility = 'hidden';
-}
-
-// De-initialize functions
-function detachComponentEvents() {
- window.onMouseOver = null;
- window.onMouseLeave = null;
-}
-
-class WidgetTopology extends React.Component {
- constructor(props) {
- super(props);
- this.svgElem = React.createRef();
- this.Viewer = null;
-
- this.state = {
- visualizationState: 'initial'
- };
- }
-
- componentDidMount() {
- if (this.svgElem) {
- window.onMouseLeave = function() {};
- window.onMouseOver = function() {};
- window.onMouseLeave = function() {};
- window.onMouseUp = function() {};
- window.onMouseDown = function() {};
- window.onMouseMove = function() {};
- }
- }
-
- componentWillUnmount() {
- detachComponentEvents();
- }
-
- componentWillReceiveProps(nextProps) {
- const file = nextProps.files.find(file => file._id === nextProps.widget.file);
- // Ensure model is requested only once or a different was selected
- if (this.props.widget.file !== nextProps.widget.file || (this.state.visualizationState === 'initial' && file)) {
- this.setState({'visualizationState': 'loading' });
- if (file) {
- fetch(new Request('/' + config.publicPathBase + file.path))
- .then( response => {
- if (response.status === 200) {
- this.setState({'visualizationState': 'ready' });
- return response.text().then( contents => {
- if (this.svgElem) {
- let cimsvgInstance = new cimsvg(this.svgElem.current);
- cimsvg.setCimsvg(cimsvgInstance);
- cimsvgInstance.setFileCount(1);
- cimsvgInstance.loadFile(contents);
- //cimsvgInstance.fit();
- attachComponentEvents();
- }
- else {
- console.error("The svgElem variable is not initialized before the attempt to create the cimsvg instance.");
- }
- });
- } else {
- throw new Error('Request failed');
- }
- })
- .catch(error => {
- console.error(error);
- this.setState({
- 'visualizationState': 'show_message',
- 'message': 'Topology could not be loaded.'});
- });
- }
- } else {
- // No file has been selected
- if (!nextProps.widget.file) {
- this.setState({
- 'visualizationState': 'show_message',
- 'message': 'Select a topology model first.'});
- }
- }
- }
-
- render() {
- var markup = null;
-
- switch(this.state.visualizationState) {
- case 'loading':
- markup =
);
- }
- return markup;
- }
-}
-
-export default WidgetTopology;
diff --git a/src/components/widgets/value.js b/src/components/widgets/value.js
deleted file mode 100644
index c58f57d..0000000
--- a/src/components/widgets/value.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * File: value.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { format } from 'd3';
-
-class WidgetValue extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- value: '',
- unit: ''
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.simulationModel == null) {
- this.setState({ value: '' });
- return;
- }
-
- const simulator = nextProps.simulationModel.simulator;
-
- // update value
- if (nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].output == null || nextProps.data[simulator].output.values == null) {
- this.setState({ value: '' });
- return;
- }
-
- const unit = nextProps.simulationModel.outputMapping[nextProps.widget.signal].type;
-
- // check if value has changed
- const signal = nextProps.data[simulator].output.values[nextProps.widget.signal];
- if (signal != null && this.state.value !== signal[signal.length - 1].y) {
- this.setState({ value: signal[signal.length - 1].y, unit });
- }
- }
-
- render() {
- var value_to_render = Number(this.state.value);
- return (
-
- );
- }
-}
-
-export default WidgetValue;
diff --git a/src/config.js b/src/config.js
index 4054518..874e58f 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,11 +1,28 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
const config = {
publicPathBase: 'public/',
- instance: 'frontend of the Global RT-SuperLab Demonstration',
+ instance: 'VILLASweb',
+ subtitle: 'ACS',
admin: {
- name: 'Steffen Vogel',
+ name: 'Institute for Automation of Complex Power Systems (ACS), RWTH Aachen University, Germany',
mail: 'stvogel@eonerc.rwth-aachen.de'
}
-}
+};
export default config
diff --git a/src/containers/app.js b/src/containers/app.js
deleted file mode 100644
index 4199935..0000000
--- a/src/containers/app.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * File: app.js
- * Author: Markus Grigull
- * Date: 02.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Container } from 'flux/utils';
-import { DragDropContext } from 'react-dnd';
-import HTML5Backend from 'react-dnd-html5-backend';
-import NotificationSystem from 'react-notification-system';
-import { Redirect, Route } from 'react-router-dom';
-import { Col } from 'react-bootstrap';
-
-import AppDispatcher from '../app-dispatcher';
-import SimulationStore from '../stores/simulation-store';
-import SimulatorStore from '../stores/simulator-store';
-import UserStore from '../stores/user-store';
-import NotificationsDataManager from '../data-managers/notifications-data-manager';
-
-import Home from '../components/home';
-import Header from '../components/header';
-import Footer from '../components/footer';
-import SidebarMenu from '../components/menu-sidebar';
-import HeaderMenu from '../components/header-menu';
-
-import Projects from './projects';
-import Project from './project';
-import Simulators from './simulators';
-import Visualization from './visualization';
-import Simulations from './simulations';
-import Simulation from './simulation';
-import SimulationModel from './simulation-model';
-import Users from './users';
-
-import '../styles/app.css';
-
-class App extends React.Component {
- static getStores() {
- return [ SimulatorStore, UserStore, SimulationStore ];
- }
-
- static calculateState(prevState) {
- let currentUser = UserStore.getState().currentUser;
-
- return {
- simulators: SimulatorStore.getState(),
- simulations: SimulationStore.getState(),
- currentRole: currentUser ? currentUser.role : '',
- token: UserStore.getState().token,
-
- showSidebarMenu: false,
- };
- }
-
- componentWillMount() {
- // if token stored locally, request user
- const token = localStorage.getItem('token');
-
- if (token != null && token !== '') {
- // save token so we dont logout
- this.setState({ token });
-
- AppDispatcher.dispatch({
- type: 'users/logged-in',
- token: token
- });
- }
- }
-
- componentDidMount() {
- // load all simulators and simulations to fetch simulation data
- AppDispatcher.dispatch({
- type: 'simulators/start-load',
- token: this.state.token
- });
-
- AppDispatcher.dispatch({
- type: 'simulations/start-load',
- token: this.state.token
- });
-
- NotificationsDataManager.setSystem(this.refs.notificationSystem);
- }
-
- showSidebarMenu = () => {
- this.setState({ showSidebarMenu: true });
- }
-
- hideSidebarMenu = () => {
- this.setState({ showSidebarMenu: false });
- }
-
- render() {
- if (this.state.token == null) {
- return ();
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-export default DragDropContext(HTML5Backend)(Container.create(App));
diff --git a/src/containers/login.js b/src/containers/login.js
deleted file mode 100644
index 2a812cf..0000000
--- a/src/containers/login.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * File: login.js
- * Author: Markus Grigull
- * Date: 15.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { Container } from 'flux/utils';
-import { PageHeader } from 'react-bootstrap';
-import NotificationSystem from 'react-notification-system';
-import { Redirect } from 'react-router-dom';
-
-import LoginForm from '../components/login-form';
-import Header from '../components/header';
-import Footer from '../components/footer';
-import NotificationsDataManager from '../data-managers/notifications-data-manager';
-
-import AppDispatcher from '../app-dispatcher';
-import UserStore from '../stores/user-store';
-
-class Login extends Component {
- static getStores() {
- return [ UserStore ];
- }
-
- static calculateState() {
- return {
- currentUser: UserStore.getState().currentUser,
- token: UserStore.getState().token,
- loginMessage: UserStore.getState().loginMessage
- };
- }
-
- componentDidMount() {
- NotificationsDataManager.setSystem(this.refs.notificationSystem);
- }
-
- componentWillUpdate(nextProps, nextState) {
- // if token stored locally, request user
- if (nextState.token == null) {
- const token = localStorage.getItem('token');
-
- if (token != null && token !== '' && nextState.currentUser == null) {
- AppDispatcher.dispatch({
- type: 'users/logged-in',
- token: token
- });
- }
- } else {
- // check if logged in
- if (nextState.currentUser != null) {
- // save login in local storage
- localStorage.setItem('token', nextState.token);
- }
- }
- }
-
- render() {
- if (this.state.currentUser != null) {
- return ();
- }
-
- return (
-
-
-
-
-
-
- Login
-
-
-
-
-
-
- );
- }
-}
-
-export default Container.create(Login);
diff --git a/src/containers/project.js b/src/containers/project.js
deleted file mode 100644
index ce5e3b4..0000000
--- a/src/containers/project.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * File: project.js
- * Author: Markus Grigull
- * Date: 03.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { Container } from 'flux/utils';
-import { Button } from 'react-bootstrap';
-import FileSaver from 'file-saver';
-
-import AppDispatcher from '../app-dispatcher';
-import ProjectStore from '../stores/project-store';
-import UserStore from '../stores/user-store';
-import VisualizationStore from '../stores/visualization-store';
-import SimulationStore from '../stores/simulation-store';
-
-import Icon from '../components/icon';
-import CustomTable from '../components/table';
-import TableColumn from '../components/table-column';
-import NewVisualzationDialog from '../components/dialogs/new-visualization';
-import EditVisualizationDialog from '../components/dialogs/edit-visualization';
-import ImportVisualizationDialog from '../components/dialogs/import-visualization';
-
-import DeleteDialog from '../components/dialogs/delete-dialog';
-
-class Visualizations extends Component {
- static getStores() {
- return [ ProjectStore, VisualizationStore, UserStore, SimulationStore ];
- }
-
- static calculateState(prevState, props) {
- prevState = prevState || {};
-
- // load project
- const sessionToken = UserStore.getState().token;
-
- let project = ProjectStore.getState().find(project => project._id === props.match.params.project);
- if (project == null) {
- AppDispatcher.dispatch({
- type: 'projects/start-load',
- data: props.match.params.project,
- token: sessionToken
- });
-
- project = {};
- }
-
- // load simulation
- let simulation = {};
-
- if (project.simulation != null) {
- simulation = SimulationStore.getState().find(simulation => simulation._id === project.simulation);
- }
-
- // load visualizations
- let visualizations = [];
-
- if (project.visualizations != null) {
- visualizations = VisualizationStore.getState().filter(visualization => project.visualizations.includes(visualization._id));
- }
-
- return {
- visualizations,
- project,
- simulation,
- sessionToken,
-
- newModal: prevState.newModal || false,
- deleteModal: prevState.deleteModal || false,
- editModal: prevState.editModal || false,
- importModal: prevState.importModal || false,
- modalData: prevState.modalData || {}
- };
- }
-
- componentDidMount() {
- AppDispatcher.dispatch({
- type: 'visualizations/start-load',
- token: this.state.sessionToken
- });
-
- AppDispatcher.dispatch({
- type: 'simulations/start-load',
- token: this.state.sessionToken
- });
- }
-
- closeNewModal(data) {
- this.setState({ newModal: false });
-
- if (data) {
- // add project to visualization
- data.project = this.state.project._id;
-
- AppDispatcher.dispatch({
- type: 'visualizations/start-add',
- data: data,
- token: this.state.sessionToken
- });
-
- this.setState({ project: {} }, () => {
- AppDispatcher.dispatch({
- type: 'projects/start-load',
- data: this.props.match.params.project,
- token: this.state.sessionToken
- });
- });
- }
- }
-
- closeDeleteModal = confirmDelete => {
- this.setState({ deleteModal: false });
-
- if (confirmDelete === false) {
- return;
- }
-
- AppDispatcher.dispatch({
- type: 'visualizations/start-remove',
- data: this.state.modalData,
- token: this.state.sessionToken
- });
- }
-
- closeEditModal(data) {
- this.setState({ editModal : false });
-
- if (data) {
- AppDispatcher.dispatch({
- type: 'visualizations/start-edit',
- data: data,
- token: this.state.sessionToken
- });
- }
- }
-
- closeImportModal(data) {
- this.setState({ importModal: false });
-
- if (data) {
- data.project = this.state.project._id;
-
- AppDispatcher.dispatch({
- type: 'visualizations/start-add',
- data,
- token: this.state.sessionToken
- });
-
- this.setState({ project: {} }, () => {
- AppDispatcher.dispatch({
- type: 'projects/start-load',
- data: this.props.match.params.project,
- token: this.state.sessionToken
- });
- });
- }
- }
-
- exportVisualization(index) {
- // filter properties
- let visualization = Object.assign({}, this.state.visualizations[index]);
- delete visualization._id;
- delete visualization.project;
- delete visualization.user;
-
- visualization.widgets.forEach(widget => {
- delete widget.simulator;
- });
-
- // show save dialog
- const blob = new Blob([JSON.stringify(visualization, null, 2)], { type: 'application/json' });
- FileSaver.saveAs(blob, 'visualization - ' + visualization.name + '.json');
- }
-
- onModalKeyPress = (event) => {
- if (event.key === 'Enter') {
- event.preventDefault();
-
- this.confirmDeleteModal();
- }
- }
-
- render() {
- const buttonStyle = {
- marginRight: '10px'
- };
-
- return (
-
-
-
-
- {!this.hasValidSimulation() &&
- Simulation with at least one simulation-model required!
- }
-
- this.closeNewModal(data)} simulations={this.state.simulations} />
- this.closeEditModal(data)} project={this.state.modalData} simulations={this.state.simulations} />
-
-
-
- );
- }
-}
-
-export default Container.create(Projects);
diff --git a/src/containers/select-file.js b/src/containers/select-file.js
deleted file mode 100644
index 755356d..0000000
--- a/src/containers/select-file.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * File: selectFile.js
- * Author: Markus Grigull
- * Date: 10.05.2018
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Container } from 'flux/utils';
-import { FormGroup, FormControl, ControlLabel, Button, ProgressBar, Col } from 'react-bootstrap';
-
-import FileStore from '../stores/file-store';
-import UserStore from '../stores/user-store';
-
-import AppDispatcher from '../app-dispatcher';
-
-class SelectFile extends React.Component {
- static getStores() {
- return [ FileStore, UserStore ];
- }
-
- static calculateState() {
- return {
- files: FileStore.getState(),
- sessionToken: UserStore.getState().token,
- selectedFile: '',
- uploadFile: null,
- uploadProgress: 0
- };
- }
-
- componentDidMount() {
- AppDispatcher.dispatch({
- type: 'files/start-load',
- token: this.state.sessionToken
- });
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.value === this.state.selectedSimulator) {
- return;
- }
-
- let selectedSimulator = nextProps.value;
- if (selectedSimulator == null) {
- if (this.state.simulators.length > 0) {
- selectedSimulator = this.state.simulators[0]._id;
- } else {
- selectedSimulator = '';
- }
- }
-
- this.setState({ selectedSimulator });
- }
-
- handleChange = event => {
- this.setState({ selectedFile: event.target.value });
-
- // send file to callback
- if (this.props.onChange != null) {
- const file = this.state.files.find(f => f._id === event.target.value);
-
- this.props.onChange(file);
- }
- }
-
- selectUploadFile = event => {
- this.setState({ uploadFile: event.target.files[0] });
- }
-
- startFileUpload = () => {
- // upload file
- const formData = new FormData();
- formData.append(0, this.state.uploadFile);
-
- AppDispatcher.dispatch({
- type: 'files/start-upload',
- data: formData,
- token: this.state.sessionToken,
- progressCallback: this.updateUploadProgress,
- finishedCallback: this.clearProgress
- });
- }
-
- updateUploadProgress = event => {
- this.setState({ uploadProgress: parseInt(event.percent.toFixed(), 10) });
- }
-
- clearProgress = () => {
- // select uploaded file
- const selectedFile = this.state.files[this.state.files.length - 1]._id;
- this.setState({ selectedFile, uploadProgress: 0 });
- }
-
- render() {
- const fileOptions = this.state.files.map(f =>
-
- );
-
- const progressBarStyle = {
- marginLeft: '100px',
- marginTop: '-25px'
- };
-
- return
-
-
- {this.props.name}
-
-
-
-
- {fileOptions}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
;
- }
-}
-
-export default Container.create(SelectFile);
diff --git a/src/containers/select-simulator.js b/src/containers/select-simulator.js
deleted file mode 100644
index bcf7719..0000000
--- a/src/containers/select-simulator.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * File: selectSimulator.js
- * Author: Markus Grigull
- * Date: 10.05.2018
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Container } from 'flux/utils';
-import { FormGroup, FormControl, ControlLabel, Col } from 'react-bootstrap';
-import _ from 'lodash';
-
-import SimulatorStore from '../stores/simulator-store';
-
-class SelectSimulator extends React.Component {
- static getStores() {
- return [ SimulatorStore ];
- }
-
- static calculateState() {
- return {
- simulators: SimulatorStore.getState(),
- selectedSimulator: ''
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.value === this.state.selectedSimulator) {
- return;
- }
-
- let selectedSimulator = nextProps.value;
- if (selectedSimulator == null) {
- if (this.state.simulators.length > 0) {
- selectedSimulator = this.state.simulators[0]._id;
- } else {
- selectedSimulator = '';
- }
- }
-
- this.setState({ selectedSimulator });
- }
-
- handleChange = event => {
- this.setState({ selectedSimulator: event.target.value });
-
- // send complete simulator to callback
- if (this.props.onChange != null) {
- const simulator = this.state.simulators.find(s => s._id === event.target.value);
-
- this.props.onChange(simulator);
- }
- }
-
- render() {
- const simulatorOptions = this.state.simulators.map(s =>
-
- );
-
- return
-
- Simulator
-
-
-
-
- {simulatorOptions}
-
-
- ;
- }
-}
-
-export default Container.create(SelectSimulator);
diff --git a/src/containers/simulation-model.js b/src/containers/simulation-model.js
deleted file mode 100644
index 975b9e6..0000000
--- a/src/containers/simulation-model.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * File: simulationModel.js
- * Author: Markus Grigull
- * Date: 10.05.2018
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Container } from 'flux/utils';
-import { Button, Col, Form, ControlLabel } from 'react-bootstrap';
-
-import SimulationModelStore from '../stores/simulation-model-store';
-import UserStore from '../stores/user-store';
-import AppDispatcher from '../app-dispatcher';
-
-import SelectSimulator from './select-simulator';
-import SelectFile from './select-file';
-import SignalMapping from '../components/signal-mapping';
-import EditableHeader from '../components/editable-header';
-import ParametersEditor from '../components/parameters-editor';
-
-class SimulationModel extends React.Component {
- static getStores() {
- return [ SimulationModelStore, UserStore ];
- }
-
- static calculateState(prevState, props) {
- const simulationModel = SimulationModelStore.getState().find(m => m._id === props.match.params.simulationModel);
-
- return {
- simulationModel: simulationModel || {},
- sessionToken: UserStore.getState().token
- };
- }
-
- componentWillMount() {
- AppDispatcher.dispatch({
- type: 'simulationModels/start-load',
- data: this.props.match.params.simulationModel,
- token: this.state.sessionToken
- });
- }
-
- submitForm = event => {
- event.preventDefault();
- }
-
- saveChanges = () => {
- AppDispatcher.dispatch({
- type: 'simulationModels/start-edit',
- data: this.state.simulationModel,
- token: this.state.sessionToken
- });
-
- this.props.history.push('/simulations/' + this.state.simulationModel.simulation);
- }
-
- discardChanges = () => {
- this.props.history.push('/simulations/' + this.state.simulationModel.simulation);
- }
-
- handleSimulatorChange = simulator => {
- const simulationModel = this.state.simulationModel;
-
- simulationModel.simulator = simulator;
-
- this.setState({ simulationModel });
- }
-
- handleModelChange = file => {
- console.log(file);
- }
-
- handleConfigurationChange = file => {
- console.log(file);
- }
-
- handleOutputMappingChange = (length, signals) => {
- const simulationModel = this.state.simulationModel;
-
- simulationModel.outputMapping = signals;
- simulationModel.outputLength = length;
-
- this.setState({ simulationModel });
- }
-
- handleInputMappingChange = (length, signals) => {
- const simulationModel = this.state.simulationModel;
-
- simulationModel.inputMapping = signals;
- simulationModel.inputLength = length;
-
- this.setState({ simulationModel });
- }
-
- handleTitleChange = title => {
- const simulationModel = this.state.simulationModel;
-
- simulationModel.name = title;
-
- this.setState({ simulationModel });
- }
-
- handleStartParametersChange = startParameters => {
- const simulationModel = this.state.simulationModel;
-
- simulationModel.startParameters = startParameters;
-
- this.setState({ simulationModel });
- }
-
- render() {
- const buttonStyle = {
- marginRight: '10px'
- };
-
- return
-
-
-
-
;
- }
-}
-
-export default Container.create(SimulationModel, { withProps: true });
diff --git a/src/containers/simulation.js b/src/containers/simulation.js
deleted file mode 100644
index 090a8de..0000000
--- a/src/containers/simulation.js
+++ /dev/null
@@ -1,288 +0,0 @@
-/**
- * File: simulation.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Container } from 'flux/utils';
-import { Button } from 'react-bootstrap';
-import FileSaver from 'file-saver';
-import _ from 'lodash';
-
-import SimulationStore from '../stores/simulation-store';
-import SimulatorStore from '../stores/simulator-store';
-import SimulationModelStore from '../stores/simulation-model-store';
-import UserStore from '../stores/user-store';
-import AppDispatcher from '../app-dispatcher';
-
-import Icon from '../components/icon';
-import Table from '../components/table';
-import TableColumn from '../components/table-column';
-import ImportSimulationModelDialog from '../components/dialogs/import-simulation-model';
-
-import SimulatorAction from '../components/simulator-action';
-import DeleteDialog from '../components/dialogs/delete-dialog';
-
-class Simulation extends React.Component {
- static getStores() {
- return [ SimulationStore, SimulatorStore, SimulationModelStore, UserStore ];
- }
-
- static calculateState(prevState, props) {
- // get selected simulation
- const sessionToken = UserStore.getState().token;
-
- let simulation = SimulationStore.getState().find(s => s._id === props.match.params.simulation);
- if (simulation == null) {
- AppDispatcher.dispatch({
- type: 'simulations/start-load',
- data: props.match.params.simulation,
- token: sessionToken
- });
-
- simulation = {};
- }
-
- // load models
- let simulationModels = [];
- if (simulation.models != null) {
- simulationModels = SimulationModelStore.getState().filter(m => m != null && simulation.models.includes(m._id));
- }
-
- return {
- simulationModels,
- simulation,
-
- simulators: SimulatorStore.getState(),
- sessionToken,
-
- deleteModal: false,
- importModal: false,
- modalData: {},
-
- selectedSimulationModels: []
- }
- }
-
- componentWillMount() {
- AppDispatcher.dispatch({
- type: 'simulations/start-load',
- token: this.state.sessionToken
- });
-
- AppDispatcher.dispatch({
- type: 'simulationModels/start-load',
- token: this.state.sessionToken
- });
-
- AppDispatcher.dispatch({
- type: 'simulators/start-load',
- token: this.state.sessionToken
- });
- }
-
- addSimulationModel = () => {
- const simulationModel = {
- simulation: this.state.simulation._id,
- name: 'New Simulation Model',
- simulator: this.state.simulators.length > 0 ? this.state.simulators[0]._id : null,
- outputLength: 1,
- outputMapping: [{ name: 'Signal', type: 'Type' }],
- inputLength: 1,
- inputMapping: [{ name: 'Signal', type: 'Type' }]
- };
-
- AppDispatcher.dispatch({
- type: 'simulationModels/start-add',
- data: simulationModel,
- token: this.state.sessionToken
- });
-
- this.setState({ simulation: {} }, () => {
- AppDispatcher.dispatch({
- type: 'simulations/start-load',
- data: this.props.match.params.simulation,
- token: this.state.sessionToken
- });
- });
- }
-
- closeDeleteModal = confirmDelete => {
- this.setState({ deleteModal: false });
-
- if (confirmDelete === false) {
- return;
- }
-
- AppDispatcher.dispatch({
- type: 'simulationModels/start-remove',
- data: this.state.modalData,
- token: this.state.sessionToken
- });
- }
-
- importSimulationModel = simulationModel => {
- this.setState({ importModal: false });
-
- if (simulationModel == null) {
- return;
- }
-
- simulationModel.simulation = this.state.simulation._id;
-
- console.log(simulationModel);
-
- AppDispatcher.dispatch({
- type: 'simulationModels/start-add',
- data: simulationModel,
- token: this.state.sessionToken
- });
-
- this.setState({ simulation: {} }, () => {
- AppDispatcher.dispatch({
- type: 'simulations/start-load',
- data: this.props.match.params.simulation,
- token: this.state.sessionToken
- });
- });
- }
-
- getSimulatorName(simulatorId) {
- for (let simulator of this.state.simulators) {
- if (simulator._id === simulatorId) {
- return _.get(simulator, 'properties.name') || _.get(simulator, 'rawProperties.name') || simulator.uuid;
- }
- }
- }
-
- exportModel(index) {
- // filter properties
- const model = Object.assign({}, this.state.simulationModels[index]);
-
- delete model.simulator;
- delete model.simulation;
-
- // show save dialog
- const blob = new Blob([JSON.stringify(model, null, 2)], { type: 'application/json' });
- FileSaver.saveAs(blob, 'simulation model - ' + model.name + '.json');
- }
-
- onSimulationModelChecked(index, event) {
- const selectedSimulationModels = Object.assign([], this.state.selectedSimulationModels);
- for (let key in selectedSimulationModels) {
- if (selectedSimulationModels[key] === index) {
- // update existing entry
- if (event.target.checked) {
- return;
- }
-
- selectedSimulationModels.splice(key, 1);
-
- this.setState({ selectedSimulationModels });
- return;
- }
- }
-
- // add new entry
- if (event.target.checked === false) {
- return;
- }
-
- selectedSimulationModels.push(index);
- this.setState({ selectedSimulationModels });
- }
-
- runAction = action => {
- for (let index of this.state.selectedSimulationModels) {
- // get simulator for model
- let simulator = null;
- for (let sim of this.state.simulators) {
- if (sim._id === this.state.simulationModels[index].simulator) {
- simulator = sim;
- }
- }
-
- if (simulator == null) {
- continue;
- }
-
- if (action.data.action === 'start') {
- action.data.parameters = this.state.simulationModels[index].startParameters;
- }
-
- AppDispatcher.dispatch({
- type: 'simulators/start-action',
- simulator,
- data: action.data,
- token: this.state.sessionToken
- });
- }
- }
-
- render() {
- const buttonStyle = {
- marginLeft: '10px'
- };
-
- return
- );
- }
-}
-
-export default Fullscreenable()(Container.create(Visualization, { withProps: true }));
diff --git a/src/containers/widget.js b/src/containers/widget.js
deleted file mode 100644
index b4df992..0000000
--- a/src/containers/widget.js
+++ /dev/null
@@ -1,297 +0,0 @@
-/**
- * File: widget.js
- * Author: Markus Grigull
- * Date: 04.03.2017
- *
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Container } from 'flux/utils';
-import { ContextMenuProvider } from 'react-contexify';
-import Rnd from 'react-rnd';
-import classNames from 'classnames';
-
-import AppDispatcher from '../app-dispatcher';
-import UserStore from '../stores/user-store';
-import SimulatorDataStore from '../stores/simulator-data-store';
-import SimulationModelStore from '../stores/simulation-model-store';
-import FileStore from '../stores/file-store';
-
-import WidgetCustomAction from '../components/widgets/custom-action';
-import WidgetAction from '../components/widgets/action';
-import WidgetLamp from '../components/widgets/lamp';
-import WidgetValue from '../components/widgets/value';
-import WidgetPlot from '../components/widgets/plot';
-import WidgetTable from '../components/widgets/table';
-import WidgetLabel from '../components/widgets/label';
-import WidgetPlotTable from '../components/widgets/plot-table';
-import WidgetImage from '../components/widgets/image';
-import WidgetButton from '../components/widgets/button';
-import WidgetInput from '../components/widgets/input';
-import WidgetSlider from '../components/widgets/slider';
-import WidgetGauge from '../components/widgets/gauge';
-import WidgetBox from '../components/widgets/box';
-import WidgetHTML from '../components/widgets/html';
-import WidgetTopology from '../components/widgets/topology';
-
-import '../styles/widgets.css';
-
-class Widget extends React.Component {
- static getStores() {
- return [ SimulatorDataStore, SimulationModelStore, FileStore, UserStore ];
- }
-
- static calculateState(prevState, props) {
- const sessionToken = UserStore.getState().token;
-
- let simulatorData = {};
-
- if (props.paused) {
- if (prevState && prevState.simulatorData) {
- simulatorData = JSON.parse(JSON.stringify(prevState.simulatorData));
- }
- } else {
- simulatorData = SimulatorDataStore.getState();
- }
-
- if (prevState) {
- return {
- sessionToken,
- simulatorData,
- files: FileStore.getState(),
- sequence: prevState.sequence + 1,
-
- simulationModels: SimulationModelStore.getState()
- };
- } else {
- return {
- sessionToken,
- simulatorData,
- files: FileStore.getState(),
- sequence: 0,
-
- simulationModels: SimulationModelStore.getState()
- };
- }
- }
-
- constructor(props) {
- super(props);
-
- // Reference to the context menu element
- this.contextMenuTriggerViaDraggable = null;
- }
-
- componentWillMount() {
- // If loading for the first time
- if (this.state.sessionToken) {
- AppDispatcher.dispatch({
- type: 'files/start-load',
- token: this.state.sessionToken
- });
-
- AppDispatcher.dispatch({
- type: 'simulationModels/start-load',
- token: this.state.sessionToken
- });
- }
- }
-
- snapToGrid(value) {
- if (this.props.grid === 1)
- return value;
-
- return Math.round(value / this.props.grid) * this.props.grid;
- }
-
- drag(event, data) {
- const x = this.snapToGrid(data.x);
- const y = this.snapToGrid(data.y);
-
- if (x !== data.x || y !== data.y) {
- this.rnd.updatePosition({ x, y });
- }
- }
-
- dragStop(event, data) {
- // update widget
- let widget = this.props.data;
- widget.x = this.snapToGrid(data.x);
- widget.y = this.snapToGrid(data.y);
-
- this.props.onWidgetChange(widget, this.props.index);
- }
-
- resizeStop(direction, delta, event) {
- // update widget
- let widget = Object.assign({}, this.props.data);
-
- // resize depends on direction
- if (direction === 'left' || direction === 'topLeft' || direction === 'bottomLeft') {
- widget.x -= delta.width;
- }
-
- if (direction === 'top' || direction === 'topLeft' || direction === 'topRight') {
- widget.y -= delta.height;
- }
-
- widget.width += delta.width;
- widget.height += delta.height;
-
- this.props.onWidgetChange(widget, this.props.index);
- }
-
- borderWasClicked(e) {
- // check if it was triggered by the right button
- if (e.button === 2) {
- // launch the context menu using the reference
- if(this.contextMenuTriggerViaDraggable) {
- this.contextMenuTriggerViaDraggable.handleContextClick(e);
- }
- }
- }
-
- inputDataChanged(widget, data) {
- let simulationModel = null;
-
- for (let model of this.state.simulationModels) {
- if (model._id !== widget.simulationModel) {
- continue;
- }
-
- simulationModel = model;
- }
-
- AppDispatcher.dispatch({
- type: 'simulatorData/inputChanged',
- simulator: simulationModel.simulator,
- signal: widget.signal,
- data
- });
- }
-
- render() {
- // configure grid
- const grid = [this.props.grid, this.props.grid];
-
- // get widget element
- const widget = this.props.data;
- let borderedWidget = false;
- let element = null;
- let zIndex = Number(widget.z);
-
- let simulationModel = null;
-
- for (let model of this.state.simulationModels) {
- if (model._id !== widget.simulationModel) {
- continue;
- }
-
- simulationModel = model;
- }
-
- // dummy is passed to widgets to keep updating them while in edit mode
- if (widget.type === 'CustomAction') {
- element =
- } else if (widget.type === 'Action') {
- element =
- } else if (widget.type === 'Lamp') {
- element =
- } else if (widget.type === 'Value') {
- element =
- } else if (widget.type === 'Plot') {
- element =
- } else if (widget.type === 'Table') {
- element =
- } else if (widget.type === 'Label') {
- element =
- } else if (widget.type === 'PlotTable') {
- element = this.props.onWidgetStatusChange(w, this.props.index)} paused={this.props.paused} />
- } else if (widget.type === 'Image') {
- element =
- } else if (widget.type === 'Button') {
- element = this.inputDataChanged(widget, value)} />
- } else if (widget.type === 'Input') {
- element = this.inputDataChanged(widget, value)} />
- } else if (widget.type === 'Slider') {
- element = this.inputDataChanged(widget, value)} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index) } />
- } else if (widget.type === 'Gauge') {
- element =
- } else if (widget.type === 'Box') {
- element =
- } else if (widget.type === 'HTML') {
- element =
- } else if (widget.type === 'Topology') {
- element =
- }
-
- if (widget.type === 'Box')
- zIndex = 0;
-
- const widgetClasses = classNames({
- 'widget': !this.props.editing,
- 'editing-widget': this.props.editing,
- 'border': borderedWidget,
- 'unselectable': false,
- 'locked': widget.locked && this.props.editing
- });
-
- if (this.props.editing) {
- const resizing = { bottom: !widget.locked, bottomLeft: !widget.locked, bottomRight: !widget.locked, left: !widget.locked, right: !widget.locked, top: !widget.locked, topLeft: !widget.locked, topRight: !widget.locked};
-
- return (
- { this.rnd = c; }}
- default={{ x: Number(widget.x), y: Number(widget.y), width: widget.width, height: widget.height }}
- minWidth={widget.minWidth}
- minHeight={widget.minHeight}
- lockAspectRatio={Boolean(widget.lockAspect)}
- bounds={'parent'}
- className={ widgetClasses }
- onResizeStart={(event, direction, ref) => this.borderWasClicked(event)}
- onResizeStop={(event, direction, ref, delta) => this.resizeStop(direction, delta, event)}
- onDrag={(event, data) => this.drag(event, data)}
- onDragStop={(event, data) => this.dragStop(event, data)}
- dragGrid={grid}
- resizeGrid={grid}
- z={zIndex}
- enableResizing={resizing}
- disableDragging={widget.locked}
- >
-
- {element}
-
-
- );
- } else {
- return (
-
- {element}
-
- );
- }
- }
-}
-
-export default Container.create(Widget, { withProps: true });
diff --git a/src/dashboard/dashboard-button-group.js b/src/dashboard/dashboard-button-group.js
new file mode 100644
index 0000000..7f49292
--- /dev/null
+++ b/src/dashboard/dashboard-button-group.js
@@ -0,0 +1,138 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Button,OverlayTrigger, Tooltip } from 'react-bootstrap';
+import Icon from "../common/icon";
+
+class DashboardButtonGroup extends React.Component {
+ render() {
+ const buttonStyle = {
+ marginLeft: '12px',
+ height: '44px',
+ width : '35px'
+ };
+
+ const iconStyle = {
+ color: '#007bff',
+ height: '25px',
+ width : '25px'
+ }
+
+ const buttons = [];
+ let key = 0;
+
+ if (this.props.fullscreen) {
+ return null;
+ }
+
+ if (this.props.editing) {
+ buttons.push(
+ Save changes } >
+
+ ,
+ Discard changes } >
+
+
+ );
+ } else {
+ if (this.props.fullscreen !== true) {
+ buttons.push(
+ Change to fullscreen view } >
+
+
+ );
+ }
+
+ if (this.props.paused) {
+ buttons.push(
+ Continue simulation } >
+
+
+ );
+ } else {
+ buttons.push(
+ Pause simulation } >
+
+
+ );
+ }
+
+ buttons.push(
+ Add, edit or delete files of scenario } >
+
+
+ );
+
+ buttons.push(
+ Add, edit or delete input signals } >
+
+
+ );
+
+ buttons.push(
+ Add, edit or delete output signals } >
+
+
+ );
+
+ buttons.push(
+ Add widgets and edit layout } >
+
+
+ );
+
+ }
+
+ return
+ {buttons}
+
;
+ }
+}
+
+DashboardButtonGroup.propTypes = {
+ editing: PropTypes.bool,
+ fullscreen: PropTypes.bool,
+ paused: PropTypes.bool,
+ onEdit: PropTypes.func,
+ onSave: PropTypes.func,
+ onCancel: PropTypes.func,
+ onFullscreen: PropTypes.func,
+ onPause: PropTypes.func,
+ onUnpause: PropTypes.func
+};
+
+export default DashboardButtonGroup;
diff --git a/src/dashboard/dashboard-store.js b/src/dashboard/dashboard-store.js
new file mode 100644
index 0000000..5219135
--- /dev/null
+++ b/src/dashboard/dashboard-store.js
@@ -0,0 +1,57 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import ArrayStore from '../common/array-store';
+import DashboardsDataManager from './dashboards-data-manager';
+
+class DashboardStore extends ArrayStore {
+ constructor() {
+ super('dashboards', DashboardsDataManager);
+ }
+
+ reduce(state, action) {
+
+ switch (action.type) {
+ case 'dashboards/start-add':
+
+ // Check if this is a recursive dashboard import or not
+ if (action.data.hasOwnProperty("widgets")) {
+ // import
+ let subObjects = []
+ let widgets = {}
+ widgets["widgets"] = action.data.widgets
+ subObjects.push(widgets)
+ delete action.data.widgets; // remove widgets from dashboard object
+
+ // action.data should now contain the dashboard and no sub-objects
+ // sub-objects are treated in add method of RestDataManager
+ this.dataManager.add(action.data, action.token,action.param, subObjects);
+ return state
+
+ } else {
+ // no import
+ return super.reduce(state, action);
+ }
+
+ default:
+ return super.reduce(state, action);
+ }
+ }
+
+}
+
+export default new DashboardStore();
diff --git a/src/dashboard/dashboard.js b/src/dashboard/dashboard.js
new file mode 100644
index 0000000..1bd4002
--- /dev/null
+++ b/src/dashboard/dashboard.js
@@ -0,0 +1,607 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { Component } from 'react';
+import { Container } from 'flux/utils';
+import Fullscreenable from 'react-fullscreenable';
+import classNames from 'classnames';
+
+import EditWidget from '../widget/edit-widget/edit-widget';
+import EditFiles from '../file/edit-files';
+import EditSignalMapping from "../signal/edit-signal-mapping";
+import WidgetContextMenu from '../widget/widget-context-menu';
+import WidgetToolbox from '../widget/widget-toolbox';
+import WidgetArea from '../widget/widget-area';
+import DashboardButtonGroup from './dashboard-button-group';
+
+import DashboardStore from './dashboard-store';
+import SignalStore from '../signal/signal-store'
+import FileStore from '../file/file-store';
+import WidgetStore from '../widget/widget-store';
+import ICStore from '../ic/ic-store'
+import ConfigStore from '../componentconfig/config-store'
+import AppDispatcher from '../common/app-dispatcher';
+
+import 'react-contexify/dist/ReactContexify.min.css';
+import WidgetContainer from '../widget/widget-container';
+import EditableWidgetContainer from '../widget/editable-widget-container';
+
+class Dashboard extends Component {
+
+ static lastWidgetKey = 0;
+ static webSocketsOpened = false;
+ static getStores() {
+ return [DashboardStore, FileStore, WidgetStore, SignalStore, ConfigStore, ICStore];
+ }
+
+ static calculateState(prevState, props) {
+ if (prevState == null) {
+ prevState = {};
+ }
+
+ const sessionToken = localStorage.getItem("token");
+
+ let dashboard = DashboardStore.getState().find(d => d.id === parseInt(props.match.params.dashboard, 10));
+ if (dashboard == null) {
+ AppDispatcher.dispatch({
+ type: 'dashboards/start-load',
+ data: props.match.params.dashboard,
+ token: sessionToken
+ });
+ }
+
+ // obtain all widgets of this dashboard
+ let widgets = WidgetStore.getState().filter(w => w.dashboardID === parseInt(props.match.params.dashboard, 10));
+
+ // compute max y coordinate
+ let maxHeight = null;
+ maxHeight = Object.keys(widgets).reduce((maxHeightSoFar, widgetKey) => {
+ let thisWidget = widgets[widgetKey];
+ let thisWidgetHeight = thisWidget.y + thisWidget.height;
+
+ return thisWidgetHeight > maxHeightSoFar ? thisWidgetHeight : maxHeightSoFar;
+ }, 0);
+
+
+ // filter component configurations to the ones that belong to this scenario
+ let configs = [];
+ let files = [];
+ if (dashboard !== undefined) {
+ configs = ConfigStore.getState().filter(config => config.scenarioID === dashboard.scenarioID);
+ files = FileStore.getState().filter(file => file.scenarioID === dashboard.scenarioID);
+ if (dashboard.height === 0) {
+ dashboard.height = 400;
+ }
+ else if (maxHeight + 80 > dashboard.height) {
+ dashboard.height = maxHeight + 80;
+ }
+ }
+
+ // filter signals to the ones belonging to the scenario at hand
+ let signals = []
+ let allSignals = SignalStore.getState();
+ let sig, con;
+ for (sig of allSignals) {
+ for (con of configs) {
+ if (sig.configID === con.id) {
+ signals.push(sig);
+ }
+ }
+ }
+
+ // filter ICs to the ones used by this scenario
+ let ics = []
+ if (configs.length > 0) {
+ ics = ICStore.getState().filter(ic => {
+ let ICused = false;
+ for (let config of configs) {
+ if (ic.id === config.icID) {
+ ICused = true;
+ break;
+ }
+ }
+ return ICused;
+ });
+ }
+
+ let editOutputSignalsModal = prevState.editOutputSignalsModal;
+ let editInputSignalsModal = prevState.editInputSignalsModal;
+
+ return {
+ dashboard,
+ widgets,
+ signals,
+ sessionToken,
+ files,
+ configs,
+ ics,
+
+ editing: prevState.editing || false,
+ paused: prevState.paused || false,
+
+ editModal: prevState.editModal || false,
+ editOutputSignalsModal: editOutputSignalsModal,
+ editInputSignalsModal: editInputSignalsModal,
+ filesEditModal: prevState.filesEditModal || false,
+ filesEditSaveState: prevState.filesEditSaveState || [],
+ modalData: null,
+ modalIndex: null,
+ widgetChangeData: [],
+ widgetOrigIDs: prevState.widgetOrigIDs || [],
+
+ maxWidgetHeight: maxHeight || null,
+ };
+
+ }
+
+ static getNewWidgetKey() {
+ const widgetKey = this.lastWidgetKey;
+ this.lastWidgetKey++;
+
+ return widgetKey;
+ }
+
+ componentDidMount() {
+
+ Dashboard.webSocketsOpened = false;
+
+ // load widgets of dashboard
+ AppDispatcher.dispatch({
+ type: 'widgets/start-load',
+ token: this.state.sessionToken,
+ param: '?dashboardID=' + parseInt(this.props.match.params.dashboard, 10),
+ });
+
+ // load ICs to enable that component configs and dashboards work with them
+ AppDispatcher.dispatch({
+ type: 'ics/start-load',
+ token: this.state.sessionToken
+ });
+
+ }
+
+ componentDidUpdate(prevProps: Readonly