mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-16 00:00:03 +01:00
Merge branch 'renaming-simulator-simmodel' into 'develop'
Renaming simulator and simmodel See merge request acs/public/villas/web!55
This commit is contained in:
commit
1de37c4bf1
38 changed files with 422 additions and 631 deletions
|
@ -6,7 +6,6 @@ import EditWidgetTextControl from '../../widget/edit-widget/edit-widget-text-con
|
|||
import EditWidgetColorControl from '../../widget/edit-widget/edit-widget-color-control';
|
||||
import EditWidgetTimeControl from '../../widget/edit-widget/edit-widget-time-control';
|
||||
import EditImageWidgetControl from '../../widget/edit-widget/edit-widget-image-control';
|
||||
import EditWidgetSimulationControl from '../../widget/edit-widget/edit-widget-simulation-control';
|
||||
import EditWidgetSignalControl from '../../widget/edit-widget/edit-widget-signal-control';
|
||||
import EditWidgetSignalsControl from '../../widget/edit-widget/edit-widget-signals-control';
|
||||
import EditWidgetOrientation from '../../widget/edit-widget/edit-widget-orientation';
|
||||
|
@ -25,23 +24,23 @@ describe('edit widget control creator', () => {
|
|||
});
|
||||
|
||||
var runs = [
|
||||
{ args: { widgetType: 'Lamp' }, result: { controlNumber: 5, controlTypes: [EditWidgetSimulationControl, EditWidgetSignalControl, EditWidgetTextControl, EditWidgetColorControl, EditWidgetColorControl] } },
|
||||
{ args: { widgetType: 'Value' }, result: { controlNumber: 5, controlTypes: [EditWidgetTextControl, EditWidgetSimulationControl, EditWidgetSignalControl, EditWidgetTextSizeControl, EditWidgetCheckboxControl] } },
|
||||
{ args: { widgetType: 'Plot' }, result: { controlNumber: 5, controlTypes: [EditWidgetTimeControl, EditWidgetSimulationControl, EditWidgetSignalsControl, EditWidgetTextControl, EditWidgetMinMaxControl] } },
|
||||
{ args: { widgetType: 'Table' }, result: { controlNumber: 2, controlTypes: [EditWidgetSimulationControl, EditWidgetCheckboxControl] } },
|
||||
{ args: { widgetType: 'Lamp' }, result: { controlNumber: 5, controlTypes: [EditWidgetSignalControl, EditWidgetTextControl, EditWidgetColorControl, EditWidgetColorControl] } },
|
||||
{ args: { widgetType: 'Value' }, result: { controlNumber: 5, controlTypes: [EditWidgetTextControl, EditWidgetSignalControl, EditWidgetTextSizeControl, EditWidgetCheckboxControl] } },
|
||||
{ args: { widgetType: 'Plot' }, result: { controlNumber: 5, controlTypes: [EditWidgetTimeControl, EditWidgetSignalsControl, EditWidgetTextControl, EditWidgetMinMaxControl] } },
|
||||
{ args: { widgetType: 'Table' }, result: { controlNumber: 2, controlTypes: [EditWidgetCheckboxControl] } },
|
||||
{ args: { widgetType: 'Image' }, result: { controlNumber: 2, controlTypes: [EditImageWidgetControl, EditWidgetAspectControl] } },
|
||||
{ args: { widgetType: 'Gauge' }, result: { controlNumber: 6, controlTypes: [EditWidgetTextControl, EditWidgetSimulationControl, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetColorZonesControl, EditWidgetMinMaxControl] } },
|
||||
{ args: { widgetType: 'PlotTable' }, result: { controlNumber: 5, controlTypes: [EditWidgetSimulationControl, EditWidgetSignalsControl, EditWidgetTextControl, EditWidgetTimeControl, EditWidgetMinMaxControl] } },
|
||||
{ args: { widgetType: 'Slider' }, result: { controlNumber: 9, controlTypes: [EditWidgetTextControl, EditWidgetOrientation, EditWidgetSimulationControl, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetCheckboxControl, EditWidgetMinMaxControl, EditWidgetNumberControl, EditWidgetNumberControl] } },
|
||||
{ args: { widgetType: 'Button' }, result: { controlNumber: 6, controlTypes: [EditWidgetTextControl, EditWidgetSimulationControl, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetNumberControl, EditWidgetNumberControl] } },
|
||||
{ args: { widgetType: 'Gauge' }, result: { controlNumber: 6, controlTypes: [EditWidgetTextControl, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetColorZonesControl, EditWidgetMinMaxControl] } },
|
||||
{ args: { widgetType: 'PlotTable' }, result: { controlNumber: 5, controlTypes: [EditWidgetSignalsControl, EditWidgetTextControl, EditWidgetTimeControl, EditWidgetMinMaxControl] } },
|
||||
{ args: { widgetType: 'Slider' }, result: { controlNumber: 9, controlTypes: [EditWidgetTextControl, EditWidgetOrientation, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetCheckboxControl, EditWidgetMinMaxControl, EditWidgetNumberControl, EditWidgetNumberControl] } },
|
||||
{ args: { widgetType: 'Button' }, result: { controlNumber: 6, controlTypes: [EditWidgetTextControl, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetNumberControl, EditWidgetNumberControl] } },
|
||||
{ args: { widgetType: 'Box' }, result: { controlNumber: 2, controlTypes: [EditWidgetColorControl, EditWidgetColorControl] } },
|
||||
{ args: { widgetType: 'Label' }, result: { controlNumber: 3, controlTypes: [EditWidgetTextControl, EditWidgetTextSizeControl, EditWidgetColorControl] } },
|
||||
{ args: { widgetType: 'HTML' }, result: { controlNumber: 1, controlTypes: [EditWidgetHTMLContent] } },
|
||||
{ args: { widgetType: 'Input'}, result: { controlNumber: 3, controlTypes: [EditWidgetTextControl, EditWidgetSimulationControl, EditWidgetSignalControl] } }
|
||||
{ args: { widgetType: 'Input'}, result: { controlNumber: 3, controlTypes: [EditWidgetTextControl, EditWidgetSignalControl] } }
|
||||
];
|
||||
|
||||
runs.forEach( (run) => {
|
||||
let itMsg = run.args.widgetType + ' widget edit model should have correct controls';
|
||||
let itMsg = run.args.widgetType + ' widget edit should have correct controls';
|
||||
it(itMsg, () => {
|
||||
let controls = createControls(run.args.widgetType, null, null, null, null, null, null);
|
||||
|
||||
|
|
33
src/app.js
33
src/app.js
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: app.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 02.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -30,7 +26,7 @@ import { Hidden } from 'react-grid-system'
|
|||
|
||||
import AppDispatcher from './common/app-dispatcher';
|
||||
import ScenarioStore from './scenario/scenario-store';
|
||||
import SimulatorStore from './simulator/simulator-store';
|
||||
import ICStore from './ic/ic-store';
|
||||
import LoginStore from './user/login-store';
|
||||
import NotificationsDataManager from './common/data-managers/notifications-data-manager';
|
||||
|
||||
|
@ -40,7 +36,7 @@ import Footer from './common/footer';
|
|||
import SidebarMenu from './common/menu-sidebar';
|
||||
import HeaderMenu from './common/header-menu';
|
||||
|
||||
import Simulators from './simulator/simulators';
|
||||
import InfrastructureComponents from './ic/ics';
|
||||
import Dashboard from './dashboard/dashboard';
|
||||
import Scenarios from './scenario/scenarios';
|
||||
import Scenario from './scenario/scenario';
|
||||
|
@ -52,13 +48,13 @@ import './styles/app.css';
|
|||
class App extends React.Component {
|
||||
|
||||
static getStores() {
|
||||
return [ SimulatorStore, LoginStore, ScenarioStore];
|
||||
return [ ICStore, LoginStore, ScenarioStore];
|
||||
}
|
||||
|
||||
static calculateState(prevState) {
|
||||
|
||||
return {
|
||||
simulators: SimulatorStore.getState(),
|
||||
ics: ICStore.getState(),
|
||||
scenarios: ScenarioStore.getState(),
|
||||
currentUser: LoginStore.getState().currentUser,
|
||||
token: LoginStore.getState().token,
|
||||
|
@ -80,19 +76,6 @@ class App extends React.Component {
|
|||
currentUser: currentUser
|
||||
});
|
||||
}
|
||||
|
||||
// load all simulators and scenarios to fetch data
|
||||
// AppDispatcher.dispatch({
|
||||
// type: 'simulators/start-load',
|
||||
// token: this.state.token
|
||||
// });
|
||||
//
|
||||
// AppDispatcher.dispatch({
|
||||
// type: 'scenarios/start-load',
|
||||
// token: this.state.token
|
||||
// });
|
||||
|
||||
|
||||
}
|
||||
|
||||
showSidebarMenu = () => {
|
||||
|
@ -136,7 +119,7 @@ class App extends React.Component {
|
|||
<Route path="/dashboards/:dashboard" component={Dashboard} />
|
||||
<Route exact path="/scenarios" component={Scenarios} />
|
||||
<Route path="/scenarios/:scenario" component={Scenario} />
|
||||
<Route path="/simulators" component={Simulators} />
|
||||
<Route path="/infrastructure" component={InfrastructureComponents} />
|
||||
<Route path="/user" component={User} />
|
||||
<Route path="/users" component={Users} />
|
||||
</div>
|
||||
|
@ -150,12 +133,6 @@ class App extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
// Removed routes
|
||||
//<Route exact path="/projects" component={Projects} />
|
||||
//<Route path="/projects/:project" component={Project} />
|
||||
//<Route exact path="/simulations" component={Simulations} />
|
||||
//<Route path="/simulations/:simulation" component={Simulation} />
|
||||
|
||||
let fluxContainerConverter = require('./common/FluxContainerConverter');
|
||||
export default Container.create(fluxContainerConverter.convert(App));
|
||||
//DragDropContext(HTML5Backend)(Container.create(App));
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
/**
|
||||
* File: notifications-factory.js
|
||||
* Description: An unique source of pre-defined notifications that are displayed
|
||||
* throughout the application.
|
||||
* Author: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
|
||||
* Date: 13.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
|
||||
|
@ -24,10 +17,11 @@
|
|||
|
||||
class NotificationsFactory {
|
||||
|
||||
static get NO_SIM_MODEL_AVAILABLE() {
|
||||
// This is an example
|
||||
static get EXAMPLE_NOTIFICATION() {
|
||||
return {
|
||||
title: 'No simulation model available',
|
||||
message: 'Consider defining a simulation model in the simulators section.',
|
||||
title: 'Example notification',
|
||||
message: 'Write something here that describes what happend.',
|
||||
level: 'warning'
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: header-menu.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 17.08.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -31,9 +27,8 @@ export default class HeaderMenu extends React.Component {
|
|||
|
||||
<ul>
|
||||
<li><NavLink to="/home" activeClassName="active" title="Home" onClick={this.props.onClose}>Home</NavLink></li>
|
||||
<li><NavLink to="/projects" activeClassName="active" title="Projects" onClick={this.props.onClose}>Projects</NavLink></li>
|
||||
<li><NavLink to="/simulations" activeClassName="active" title="Simulations" onClick={this.props.onClose}>Simulations</NavLink></li>
|
||||
<li><NavLink to="/simulators" activeClassName="active" title="Simulators" onClick={this.props.onClose}>Simulators</NavLink></li>
|
||||
<li><NavLink to="/scenario" activeClassName="active" title="Scenarios" onClick={this.props.onClose}>Scenarios</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure Components" onClick={this.props.onClose}>Infrastructure Components</NavLink></li>
|
||||
{ this.props.currentRole === 'Admin' ?
|
||||
<li><NavLink to="/users" activeClassName="active" title="User Management" onClick={this.props.onClose}>User Management</NavLink></li> : ''
|
||||
}
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
//<li><NavLink to="/simulations" activeClassName="active" title="Simulations">Simulations</NavLink></li>
|
||||
//<li><NavLink to="/projects" activeClassName="active" title="Projects">Projects</NavLink></li>
|
||||
|
||||
class SidebarMenu extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
|
@ -34,7 +31,7 @@ class SidebarMenu extends React.Component {
|
|||
<ul>
|
||||
<li><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
|
||||
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
|
||||
<li><NavLink to="/simulators" activeClassName="active" title="Infrastructure Components">Infrastructure Components</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure Components">Infrastructure Components</NavLink></li>
|
||||
{ this.props.currentRole === 'Admin' ?
|
||||
<li><NavLink to="/users" activeClassName="active" title="User Management">User Management</NavLink></li> : ''
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulation-model-store.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 20.04.2018
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -20,21 +16,21 @@
|
|||
******************************************************************************/
|
||||
|
||||
import ArrayStore from '../common/array-store';
|
||||
import SimulationModelsDataManager from './simulation-models-data-manager';
|
||||
import ConfigsDataManager from './configs-data-manager';
|
||||
|
||||
class SimulationModelStore extends ArrayStore {
|
||||
class ConfigStore extends ArrayStore {
|
||||
|
||||
constructor() {
|
||||
super('simulationModels', SimulationModelsDataManager);
|
||||
super('configs', ConfigsDataManager);
|
||||
}
|
||||
|
||||
reduce(state, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case 'simulationModels/loaded':
|
||||
case 'configs/loaded':
|
||||
|
||||
SimulationModelsDataManager.loadSignals(action.token, action.data);
|
||||
SimulationModelsDataManager.loadFiles(action.token, action.data);
|
||||
ConfigsDataManager.loadSignals(action.token, action.data);
|
||||
ConfigsDataManager.loadFiles(action.token, action.data);
|
||||
return super.reduce(state, action);
|
||||
|
||||
default:
|
||||
|
@ -44,4 +40,4 @@ class SimulationModelStore extends ArrayStore {
|
|||
}
|
||||
}
|
||||
|
||||
export default new SimulationModelStore();
|
||||
export default new ConfigStore();
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulation-models-data-manager.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 20.04.2018
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -23,35 +19,35 @@ import RestDataManager from '../common/data-managers/rest-data-manager';
|
|||
import AppDispatcher from '../common/app-dispatcher';
|
||||
import RestAPI from "../common/api/rest-api";
|
||||
|
||||
class SimulationModelDataManager extends RestDataManager {
|
||||
class ConfigDataManager extends RestDataManager {
|
||||
constructor() {
|
||||
super('simulationModel', '/models');
|
||||
super('config', '/configs');
|
||||
|
||||
this.onLoad = this.onModelsLoad;
|
||||
this.onLoad = this.onConfigsLoad;
|
||||
}
|
||||
|
||||
onModelsLoad(data) {
|
||||
onConfigsLoad(data) {
|
||||
if (!Array.isArray(data))
|
||||
data = [ data ];
|
||||
|
||||
for (let model of data)
|
||||
this.loadModelData(model);
|
||||
for (let config of data)
|
||||
this.loadICData(config);
|
||||
}
|
||||
|
||||
loadModelData(model) {
|
||||
loadICData(config) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulatorData/prepare',
|
||||
inputLength: parseInt(model.inputLength, 10),
|
||||
outputLength: parseInt(model.outputLength, 10),
|
||||
id: model.simulator
|
||||
type: 'icData/prepare',
|
||||
inputLength: parseInt(config.inputLength, 10),
|
||||
outputLength: parseInt(config.outputLength, 10),
|
||||
id: config.icID
|
||||
});
|
||||
}
|
||||
|
||||
loadSignals(token, models){
|
||||
loadSignals(token, configs){
|
||||
|
||||
for (let model of models) {
|
||||
for (let config of configs) {
|
||||
// request in signals
|
||||
RestAPI.get(this.makeURL('/signals?direction=in&modelID=' + model.id), token).then(response => {
|
||||
RestAPI.get(this.makeURL('/signals?direction=in&configID=' + config.id), token).then(response => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'signals/loaded',
|
||||
data: response.signals
|
||||
|
@ -59,7 +55,7 @@ class SimulationModelDataManager extends RestDataManager {
|
|||
});
|
||||
|
||||
// request out signals
|
||||
RestAPI.get(this.makeURL('/signals?direction=out&modelID=' + model.id), token).then(response => {
|
||||
RestAPI.get(this.makeURL('/signals?direction=out&configID=' + config.id), token).then(response => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'signals/loaded',
|
||||
data: response.signals
|
||||
|
@ -69,10 +65,10 @@ class SimulationModelDataManager extends RestDataManager {
|
|||
}
|
||||
}
|
||||
|
||||
loadFiles(token, models){
|
||||
for (let model of models) {
|
||||
// request files of simulation model
|
||||
RestAPI.get(this.makeURL('/files?objectType=model&objectID=' + model.id), token).then(response => {
|
||||
loadFiles(token, configs){
|
||||
for (let config of configs) {
|
||||
// request files of config
|
||||
RestAPI.get(this.makeURL('/files?objectType=config&objectID=' + config.id), token).then(response => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'files/loaded',
|
||||
data: response.files
|
||||
|
@ -82,4 +78,4 @@ class SimulationModelDataManager extends RestDataManager {
|
|||
}
|
||||
}
|
||||
|
||||
export default new SimulationModelDataManager();
|
||||
export default new ConfigDataManager();
|
|
@ -23,7 +23,7 @@ import Dialog from '../common/dialogs/dialog';
|
|||
import ParametersEditor from '../common/parameters-editor';
|
||||
import SelectFile from "../file/select-file";
|
||||
|
||||
class EditSimulationModelDialog extends React.Component {
|
||||
class EditConfigDialog extends React.Component {
|
||||
valid = false;
|
||||
|
||||
constructor(props) {
|
||||
|
@ -32,10 +32,10 @@ class EditSimulationModelDialog extends React.Component {
|
|||
this.state = {
|
||||
selectedFile: null,
|
||||
name: '',
|
||||
simulatorID: '',
|
||||
icID: '',
|
||||
configuration: null,
|
||||
startParameters: {},
|
||||
selectedModelFileID:0
|
||||
selectedFileID:0
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -44,22 +44,22 @@ class EditSimulationModelDialog extends React.Component {
|
|||
onClose(canceled) {
|
||||
if (canceled === false) {
|
||||
if (this.valid) {
|
||||
let data = this.props.simulationModel;
|
||||
if (this.state.name !== '' && this.props.simulationModel.name !== this.state.name) {
|
||||
let data = this.props.config;
|
||||
if (this.state.name !== '' && this.props.config.name !== this.state.name) {
|
||||
data.name = this.state.name;
|
||||
}
|
||||
if (this.state.simulatorID !== '' && this.props.simulationModel.simulatorID !== parseInt(this.state.simulatorID)) {
|
||||
data.simulatorID = parseInt(this.state.simulatorID, 10);
|
||||
if (this.state.icID !== '' && this.props.config.icID !== parseInt(this.state.icID)) {
|
||||
data.icID = parseInt(this.state.icID, 10);
|
||||
}
|
||||
if(this.state.startParameters !== {} && this.props.simulationModel.startParameters !== this.state.startParameters){
|
||||
if(this.state.startParameters !== {} && this.props.config.startParameters !== this.state.startParameters){
|
||||
data.startParameters = this.state.startParameters;
|
||||
}
|
||||
if (parseInt(this.state.selectedModelFileID, 10) !== 0 &&
|
||||
this.props.simulationModel.selectedModelFileID !== parseInt(this.state.selectedModelFileID)) {
|
||||
data.selectedModelFileID = parseInt(this.state.selectedModelFileID, 10);
|
||||
if (parseInt(this.state.selectedFileID, 10) !== 0 &&
|
||||
this.props.config.selectedFileID !== parseInt(this.state.selectedFileID)) {
|
||||
data.selectedFileID = parseInt(this.state.selectedFileID, 10);
|
||||
}
|
||||
|
||||
//forward modified simulation model to callback function
|
||||
//forward modified config to callback function
|
||||
this.props.onClose(data)
|
||||
}
|
||||
} else {
|
||||
|
@ -81,9 +81,9 @@ class EditSimulationModelDialog extends React.Component {
|
|||
this.valid = this.isValid()
|
||||
}
|
||||
|
||||
handleSelectedModelFileChange(newFileID){
|
||||
handleSelectedFileChange(newFileID){
|
||||
console.log("Config file change to: ", newFileID);
|
||||
this.setState({selectedModelFileID: newFileID})
|
||||
this.setState({selectedFileID: newFileID})
|
||||
|
||||
this.valid = this.isValid()
|
||||
}
|
||||
|
@ -91,11 +91,11 @@ class EditSimulationModelDialog extends React.Component {
|
|||
isValid() {
|
||||
// input is valid if at least one element has changed from its initial value
|
||||
return this.state.name !== ''
|
||||
|| this.state.simulatorID !== ''
|
||||
|| this.state.icID !== ''
|
||||
|| this.state.startParameters !== {}
|
||||
|| this.state.selectedFile != null
|
||||
|| this.state.configuration != null
|
||||
|| this.state.selectedModelFileID !== 0;
|
||||
|| this.state.selectedFileID !== 0;
|
||||
}
|
||||
|
||||
resetState() {
|
||||
|
@ -103,7 +103,7 @@ class EditSimulationModelDialog extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const simulatorOptions = this.props.simulators.map(s =>
|
||||
const ICOptions = this.props.ics.map(s =>
|
||||
<option key={s.id} value={s.id}>{_.get(s, 'properties.name') || _.get(s, 'rawProperties.name') || s.uuid}</option>
|
||||
);
|
||||
|
||||
|
@ -112,30 +112,22 @@ class EditSimulationModelDialog extends React.Component {
|
|||
<form>
|
||||
<FormGroup controlId="name">
|
||||
<FormLabel column={false}>Name</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.simulationModel.name} value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl type="text" placeholder={this.props.config.name} value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup controlId="simulatorID">
|
||||
<FormLabel column={false}> Simulator </FormLabel>
|
||||
<FormControl as="select" placeholder='Select infrastructure component' value={this.state.simulatorID} onChange={(e) => this.handleChange(e)}>
|
||||
{simulatorOptions}
|
||||
<FormGroup controlId="icID">
|
||||
<FormLabel column={false}> Infrastructure Component </FormLabel>
|
||||
<FormControl as="select" placeholder='Select infrastructure component' value={this.state.icID} onChange={(e) => this.handleChange(e)}>
|
||||
{ICOptions}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
|
||||
|
||||
<SelectFile type='model' name='Configuration File' onChange={(e) => this.handleSelectedModelFileChange(e)} value={this.state.selectedModelFileID} objectID={this.props.simulationModel.id}/>
|
||||
|
||||
|
||||
{/*<SelectFile type='configuration' name='Configuration' onChange={(e) => this.handleChange(e)} value={this.state.configuration} />*/}
|
||||
|
||||
|
||||
|
||||
|
||||
<SelectFile type='config' name='Configuration File' onChange={(e) => this.handleSelectedFileChange(e)} value={this.state.selectedFileID} objectID={this.props.config.id}/>
|
||||
|
||||
<FormGroup controlId='startParameters'>
|
||||
<FormLabel> Start Parameters </FormLabel>
|
||||
<ParametersEditor content={this.props.simulationModel.startParameters} onChange={(data) => this.handleParameterChange(data)} />
|
||||
<ParametersEditor content={this.props.config.startParameters} onChange={(data) => this.handleParameterChange(data)} />
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Dialog>
|
||||
|
@ -143,4 +135,4 @@ class EditSimulationModelDialog extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default EditSimulationModelDialog;
|
||||
export default EditConfigDialog;
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: import-simulation-model.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 03.09.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -25,14 +21,14 @@ import _ from 'lodash';
|
|||
|
||||
import Dialog from '../common/dialogs/dialog';
|
||||
|
||||
class ImportSimulationModelDialog extends React.Component {
|
||||
class ImportConfigDialog extends React.Component {
|
||||
imported = false;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
model: {}
|
||||
config: {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -43,12 +39,12 @@ class ImportSimulationModelDialog extends React.Component {
|
|||
return;
|
||||
}
|
||||
|
||||
this.props.onClose(this.state.model);
|
||||
this.props.onClose(this.state.config);
|
||||
}
|
||||
|
||||
resetState = () => {
|
||||
this.setState({
|
||||
model: {}
|
||||
config: {}
|
||||
});
|
||||
|
||||
this.imported = false;
|
||||
|
@ -66,24 +62,24 @@ class ImportSimulationModelDialog extends React.Component {
|
|||
const self = this;
|
||||
|
||||
reader.onload = event => {
|
||||
const model = JSON.parse(event.target.result);
|
||||
const config = JSON.parse(event.target.result);
|
||||
|
||||
model.simulator = this.props.simulators.length > 0 ? this.props.simulators[0]._id : null;
|
||||
config.icID = this.props.ics.length > 0 ? this.props.ics[0]._id : null;
|
||||
|
||||
self.imported = true;
|
||||
|
||||
this.setState({ model });
|
||||
this.setState({ config: config });
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
handleSimulatorChange = event => {
|
||||
const model = this.state.model;
|
||||
handleICChange = event => {
|
||||
const config = this.state.config;
|
||||
|
||||
model.simulator = event.target.value;
|
||||
config.icID = event.target.value;
|
||||
|
||||
this.setState({ model });
|
||||
this.setState({ config: config });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -95,11 +91,11 @@ class ImportSimulationModelDialog extends React.Component {
|
|||
<FormControl type='file' onChange={this.loadFile} />
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup controlId='simulator'>
|
||||
<FormGroup controlId='IC'>
|
||||
<FormLabel>Infrastructure Component</FormLabel>
|
||||
<FormControl disabled={this.imported === false} as='select' placeholder='Select infrastructure component' value={this.state.model.simulator} onChange={this.handleSimulatorChange}>
|
||||
{this.props.simulators.map(simulator => (
|
||||
<option key={simulator.id} value={simulator.id}>{_.get(simulator, 'properties.name') || _.get(simulator, 'rawProperties.name')}</option>
|
||||
<FormControl disabled={this.imported === false} as='select' placeholder='Select infrastructure component' value={this.state.config.icID} onChange={this.handleICChange}>
|
||||
{this.props.ics.map(ic => (
|
||||
<option key={ic.id} value={ic.id}>{_.get(ic, 'properties.name') || _.get(ic, 'rawProperties.name')}</option>
|
||||
))}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
|
@ -109,4 +105,4 @@ class ImportSimulationModelDialog extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ImportSimulationModelDialog;
|
||||
export default ImportConfigDialog;
|
|
@ -33,7 +33,6 @@ import DashboardButtonGroup from './dashboard-button-group';
|
|||
|
||||
import LoginStore from '../user/login-store';
|
||||
import DashboardStore from './dashboard-store';
|
||||
//import SimulationModelStore from '../simulationmodel/simulation-model-store';
|
||||
import SignalStore from '../signal/signal-store'
|
||||
import FileStore from '../file/file-store';
|
||||
import WidgetStore from '../widget/widget-store';
|
||||
|
@ -76,11 +75,6 @@ class Dashboard extends Component {
|
|||
return thisWidgetHeight > maxHeightSoFar? thisWidgetHeight : maxHeightSoFar;
|
||||
}, 0);
|
||||
|
||||
//let simulationModels = [];
|
||||
//if (prevState.simulation != null) {
|
||||
// simulationModels = SimulationModelStore.getState().filter(m => prevState.simulation.models.includes(m._id));
|
||||
//}
|
||||
|
||||
// TODO filter signals to the ones belonging to the scenario at hand!
|
||||
let signals = SignalStore.getState();
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: import-simulator.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 04.04.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -68,12 +64,12 @@ class ImportDashboardDialog extends React.Component {
|
|||
var self = this;
|
||||
|
||||
reader.onload = function(event) {
|
||||
// read simulator
|
||||
// read IC
|
||||
const dashboard = JSON.parse(event.target.result);
|
||||
|
||||
let defaultSimulator = "";
|
||||
if (self.props.simulation.models != null) {
|
||||
defaultSimulator = self.props.simulation.models[0].simulator;
|
||||
/*let defaultIC = "";
|
||||
if (self.props.configs != null) {
|
||||
defaultIC = self.props.configs[0].icID;
|
||||
}
|
||||
|
||||
dashboard.widgets.forEach(widget => {
|
||||
|
@ -83,7 +79,6 @@ class ImportDashboardDialog extends React.Component {
|
|||
case 'Table':
|
||||
case 'PlotTable':
|
||||
case 'Gauge':
|
||||
widget.simulator = defaultSimulator;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -91,6 +86,8 @@ class ImportDashboardDialog extends React.Component {
|
|||
}
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
self.imported = true;
|
||||
self.valid = true;
|
||||
self.setState({ name: dashboard.name, widgets: dashboard.widgets, grid: dashboard.grid });
|
||||
|
|
|
@ -38,7 +38,7 @@ class SelectFile extends React.Component {
|
|||
static calculateState(prevState, props) {
|
||||
|
||||
let files = FileStore.getState().filter((file) => {
|
||||
return (file.simulationModelID === props.objectID)
|
||||
return (file.configID === props.objectID)
|
||||
});
|
||||
|
||||
console.log("props.objectID=", props.objectID)
|
||||
|
@ -111,7 +111,7 @@ class SelectFile extends React.Component {
|
|||
<option key={f.id} value={f.id}>{f.name}</option>
|
||||
);
|
||||
} else {
|
||||
fileOptions = <option >No files for this simulation model</option>
|
||||
fileOptions = <option >No files for this component config</option>
|
||||
}
|
||||
|
||||
/*const progressBarStyle = {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/**
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -23,7 +22,7 @@ import _ from 'lodash';
|
|||
import Dialog from '../common/dialogs/dialog';
|
||||
import ParametersEditor from '../common/parameters-editor';
|
||||
|
||||
class EditSimulatorDialog extends React.Component {
|
||||
class EditICDialog extends React.Component {
|
||||
valid = true;
|
||||
|
||||
constructor(props) {
|
||||
|
@ -38,13 +37,13 @@ class EditSimulatorDialog extends React.Component {
|
|||
onClose(canceled) {
|
||||
if (canceled === false) {
|
||||
if (this.valid) {
|
||||
let data = this.props.simulator.properties;
|
||||
let data = this.props.ic.properties;
|
||||
|
||||
if (this.state.name != null && this.state.name !== "" && this.state.name !== _.get(this.props.simulator, 'rawProperties.name')) {
|
||||
if (this.state.name != null && this.state.name !== "" && this.state.name !== _.get(this.props.ic, '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')) {
|
||||
if (this.state.endpoint != null && this.state.endpoint !== "" && this.state.endpoint !== "http://" && this.state.endpoint !== _.get(this.props.ic, 'rawProperties.endpoint')) {
|
||||
data.endpoint = this.state.endpoint;
|
||||
}
|
||||
|
||||
|
@ -61,8 +60,8 @@ class EditSimulatorDialog extends React.Component {
|
|||
|
||||
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')
|
||||
name: _.get(this.props.ic, 'properties.name') || _.get(this.props.ic, 'rawProperties.name'),
|
||||
endpoint: _.get(this.props.ic, 'properties.endpoint') || _.get(this.props.ic, 'rawProperties.endpoint')
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -72,17 +71,17 @@ class EditSimulatorDialog extends React.Component {
|
|||
<form>
|
||||
<FormGroup controlId="name">
|
||||
<FormLabel column={false}>Name</FormLabel>
|
||||
<FormControl type="text" placeholder={_.get(this.props.simulator, 'properties.name')} value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl type="text" placeholder={_.get(this.props.ic, 'properties.name')} value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="endpoint">
|
||||
<FormLabel column={false}>Endpoint</FormLabel>
|
||||
<FormControl type="text" placeholder={_.get(this.props.simulator, 'properties.endpoint')} value={this.state.endpoint || 'http://' } onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl type="text" placeholder={_.get(this.props.ic, 'properties.endpoint')} value={this.state.endpoint || 'http://' } onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId='properties'>
|
||||
<FormLabel column={false}>Properties</FormLabel>
|
||||
<ParametersEditor content={_.merge({}, _.get(this.props.simulator, 'rawProperties'), _.get(this.props.simulator, 'properties'))} disabled={true} />
|
||||
<ParametersEditor content={_.merge({}, _.get(this.props.ic, 'rawProperties'), _.get(this.props.ic, 'properties'))} disabled={true} />
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Dialog>
|
||||
|
@ -90,4 +89,4 @@ class EditSimulatorDialog extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default EditSimulatorDialog;
|
||||
export default EditICDialog;
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulator-actionm.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 12.04.2018
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -22,7 +18,7 @@
|
|||
import React from 'react';
|
||||
import { Button, ButtonToolbar, DropdownButton, DropdownItem } from 'react-bootstrap';
|
||||
|
||||
class SimulatorAction extends React.Component {
|
||||
class ICAction extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -70,4 +66,4 @@ class SimulatorAction extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SimulatorAction;
|
||||
export default ICAction;
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulator-data-data-manager.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 03.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -25,7 +21,7 @@ import AppDispatcher from '../common/app-dispatcher';
|
|||
const OFFSET_TYPE = 2;
|
||||
const OFFSET_VERSION = 4;
|
||||
|
||||
class SimulatorDataDataManager {
|
||||
class IcDataDataManager {
|
||||
constructor() {
|
||||
this._sockets = {};
|
||||
}
|
||||
|
@ -71,7 +67,7 @@ class SimulatorDataDataManager {
|
|||
|
||||
onOpen(event, identifier, firstOpen) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulatorData/opened',
|
||||
type: 'icData/opened',
|
||||
id: identifier,
|
||||
firstOpen: firstOpen
|
||||
});
|
||||
|
@ -79,7 +75,7 @@ class SimulatorDataDataManager {
|
|||
|
||||
onClose(event, identifier) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulatorData/closed',
|
||||
type: 'icData/closed',
|
||||
id: identifier,
|
||||
notification: (event.code !== 4000)
|
||||
});
|
||||
|
@ -93,7 +89,7 @@ class SimulatorDataDataManager {
|
|||
|
||||
if (msgs.length > 0) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulatorData/data-changed',
|
||||
type: 'icData/data-changed',
|
||||
data: msgs,
|
||||
id: identifier
|
||||
});
|
||||
|
@ -165,4 +161,4 @@ class SimulatorDataDataManager {
|
|||
}
|
||||
}
|
||||
|
||||
export default new SimulatorDataDataManager();
|
||||
export default new IcDataDataManager();
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulator-data-store.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 03.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -22,11 +18,11 @@
|
|||
import { ReduceStore } from 'flux/utils';
|
||||
|
||||
import AppDispatcher from '../common/app-dispatcher';
|
||||
import SimulatorDataDataManager from './simulator-data-data-manager';
|
||||
import ICDataDataManager from './ic-data-data-manager';
|
||||
|
||||
const MAX_VALUES = 10000;
|
||||
|
||||
class SimulationDataStore extends ReduceStore {
|
||||
class ICDataStore extends ReduceStore {
|
||||
constructor() {
|
||||
super(AppDispatcher);
|
||||
}
|
||||
|
@ -37,14 +33,14 @@ class SimulationDataStore extends ReduceStore {
|
|||
|
||||
reduce(state, action) {
|
||||
switch (action.type) {
|
||||
case 'simulatorData/opened':
|
||||
// create entry for simulator
|
||||
case 'icData/opened':
|
||||
// create entry for infrastructure component
|
||||
if (state[action.id] === undefined)
|
||||
state[action.id] = {};
|
||||
|
||||
return state;
|
||||
|
||||
case 'simulatorData/prepare':
|
||||
case 'icData/prepare':
|
||||
state[action.id] = {
|
||||
output: {
|
||||
sequence: -1,
|
||||
|
@ -64,8 +60,8 @@ class SimulationDataStore extends ReduceStore {
|
|||
this.__emitChange();
|
||||
return state;
|
||||
|
||||
case 'simulatorData/data-changed':
|
||||
// get index for simulator id
|
||||
case 'icData/data-changed':
|
||||
// get index for IC id
|
||||
if (state[action.id] == null) {
|
||||
return state;
|
||||
}
|
||||
|
@ -80,7 +76,7 @@ class SimulationDataStore extends ReduceStore {
|
|||
for (let j = 0; j < action.data.length; j++) {
|
||||
let smp = action.data[j];
|
||||
|
||||
// add data to simulator
|
||||
// add data to infrastructure component
|
||||
for (let i = 0; i < smp.length; i++) {
|
||||
while (state[action.id].output.values.length < i + 1) {
|
||||
state[action.id].output.values.push([]);
|
||||
|
@ -105,17 +101,17 @@ class SimulationDataStore extends ReduceStore {
|
|||
|
||||
return state;
|
||||
|
||||
case 'simulatorData/inputChanged':
|
||||
if (state[action.simulator] == null || state[action.simulator].input == null) {
|
||||
case 'icData/inputChanged':
|
||||
if (state[action.ic] == null || state[action.ic].input == null) {
|
||||
return state;
|
||||
}
|
||||
|
||||
// update message properties
|
||||
state[action.simulator].input.timestamp = Date.now();
|
||||
state[action.simulator].input.sequence++;
|
||||
state[action.simulator].input.values[action.signal] = action.data;
|
||||
state[action.ic].input.timestamp = Date.now();
|
||||
state[action.ic].input.sequence++;
|
||||
state[action.ic].input.values[action.signal] = action.data;
|
||||
|
||||
SimulatorDataDataManager.send(state[action.simulator].input, action.simulator);
|
||||
ICDataDataManager.send(state[action.ic].input, action.ic);
|
||||
|
||||
return state;
|
||||
|
||||
|
@ -125,4 +121,4 @@ class SimulationDataStore extends ReduceStore {
|
|||
}
|
||||
}
|
||||
|
||||
export default new SimulationDataStore();
|
||||
export default new ICDataStore();
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulator-store.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 03.03.2018
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -22,57 +18,55 @@
|
|||
import _ from 'lodash';
|
||||
|
||||
import ArrayStore from '../common/array-store';
|
||||
import SimulatorsDataManager from './simulators-data-manager';
|
||||
import SimulatorDataDataManager from './simulator-data-data-manager';
|
||||
import ICsDataManager from './ics-data-manager';
|
||||
import ICDataDataManager from './ic-data-data-manager';
|
||||
|
||||
class SimulatorStore extends ArrayStore {
|
||||
class InfrastructureComponentStore extends ArrayStore {
|
||||
constructor() {
|
||||
super('simulators', SimulatorsDataManager);
|
||||
super('ics', ICsDataManager);
|
||||
}
|
||||
|
||||
reduce(state, action) {
|
||||
switch(action.type) {
|
||||
case 'simulators/loaded':
|
||||
// connect to each simulator
|
||||
for (let simulator of action.data) {
|
||||
const endpoint = _.get(simulator, 'properties.endpoint') || _.get(simulator, 'rawProperties.endpoint');
|
||||
|
||||
case 'ics/loaded':
|
||||
// connect to each infrastructure component
|
||||
for (let ic of action.data) {
|
||||
const endpoint = _.get(ic, 'properties.endpoint') || _.get(ic, 'rawProperties.endpoint');
|
||||
if (endpoint != null && endpoint !== '') {
|
||||
SimulatorDataDataManager.open(endpoint, simulator.id);
|
||||
ICDataDataManager.open(endpoint, ic.id);
|
||||
} else {
|
||||
// console.warn('Endpoint not found for simulator at ' + endpoint);
|
||||
// console.log(simulator);
|
||||
// console.warn('Endpoint not found for IC at ' + endpoint);
|
||||
// console.log(ic);
|
||||
}
|
||||
}
|
||||
|
||||
return super.reduce(state, action);
|
||||
|
||||
case 'simulators/edited':
|
||||
// connect to each simulator
|
||||
const simulator = action.data;
|
||||
const endpoint = _.get(simulator, 'properties.endpoint') || _.get(simulator, 'rawProperties.endpoint');
|
||||
case 'ics/edited':
|
||||
// connect to each infrastructure component
|
||||
const ic = action.data;
|
||||
const endpoint = _.get(ic, 'properties.endpoint') || _.get(ic, 'rawProperties.endpoint');
|
||||
|
||||
if (endpoint != null && endpoint !== '') {
|
||||
console.log("Updating simulatorid " + simulator.id);
|
||||
SimulatorDataDataManager.update(endpoint, simulator.id);
|
||||
ICDataDataManager.update(endpoint, ic.id);
|
||||
}
|
||||
|
||||
return super.reduce(state, action);
|
||||
|
||||
case 'simulators/fetched':
|
||||
case 'ics/fetched':
|
||||
return this.updateElements(state, [action.data]);
|
||||
|
||||
case 'simulators/fetch-error':
|
||||
case 'ics/fetch-error':
|
||||
return state;
|
||||
|
||||
case 'simulators/start-action':
|
||||
case 'ics/start-action':
|
||||
if (!Array.isArray(action.data))
|
||||
action.data = [ action.data ]
|
||||
|
||||
SimulatorsDataManager.doActions(action.simulator, action.data, action.token);
|
||||
ICsDataManager.doActions(action.ic, action.data, action.token);
|
||||
return state;
|
||||
|
||||
case 'simulators/action-error':
|
||||
case 'ics/action-error':
|
||||
console.log(action.error);
|
||||
return state;
|
||||
|
||||
|
@ -82,4 +76,4 @@ class SimulatorStore extends ArrayStore {
|
|||
}
|
||||
}
|
||||
|
||||
export default new SimulatorStore();
|
||||
export default new InfrastructureComponentStore();
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulator-data-manager.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 03.03.2018
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -23,25 +19,25 @@ import RestDataManager from '../common/data-managers/rest-data-manager';
|
|||
import RestAPI from '../common/api/rest-api';
|
||||
import AppDispatcher from '../common/app-dispatcher';
|
||||
|
||||
class SimulatorsDataManager extends RestDataManager {
|
||||
class IcsDataManager extends RestDataManager {
|
||||
constructor() {
|
||||
super('simulator', '/simulators');
|
||||
super('ic', '/ic');
|
||||
}
|
||||
|
||||
doActions(simulator, action, token = null) {
|
||||
// TODO: Make only simulator id dependent
|
||||
RestAPI.post(this.makeURL(this.url + '/' + simulator.id), action, token).then(response => {
|
||||
doActions(ic, action, token = null) {
|
||||
// TODO: Make only infrastructure component id dependent
|
||||
RestAPI.post(this.makeURL(this.url + '/' + ic.id), action, token).then(response => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/action-started',
|
||||
type: 'ics/action-started',
|
||||
data: response
|
||||
});
|
||||
}).catch(error => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/action-error',
|
||||
type: 'ics/action-error',
|
||||
error
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new SimulatorsDataManager();
|
||||
export default new IcsDataManager();
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: simulators.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 02.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -26,22 +22,22 @@ import FileSaver from 'file-saver';
|
|||
import _ from 'lodash';
|
||||
|
||||
import AppDispatcher from '../common/app-dispatcher';
|
||||
import SimulatorStore from './simulator-store';
|
||||
import InfrastructureComponentStore from './ic-store';
|
||||
import LoginStore from '../user/login-store';
|
||||
|
||||
import Icon from '../common/icon';
|
||||
import Table from '../common/table';
|
||||
import TableColumn from '../common/table-column';
|
||||
import NewSimulatorDialog from './new-simulator';
|
||||
import EditSimulatorDialog from './edit-simulator';
|
||||
import ImportSimulatorDialog from './import-simulator';
|
||||
import NewICDialog from './new-ic';
|
||||
import EditICDialog from './edit-ic';
|
||||
import ImportICDialog from './import-ic';
|
||||
|
||||
import SimulatorAction from './simulator-action';
|
||||
import ICAction from './ic-action';
|
||||
import DeleteDialog from '../common/dialogs/delete-dialog';
|
||||
|
||||
class Simulators extends Component {
|
||||
class InfrastructureComponents extends Component {
|
||||
static getStores() {
|
||||
return [ LoginStore, SimulatorStore ];
|
||||
return [ LoginStore, InfrastructureComponentStore ];
|
||||
}
|
||||
|
||||
static statePrio(state) {
|
||||
|
@ -65,9 +61,9 @@ class Simulators extends Component {
|
|||
}
|
||||
|
||||
static calculateState() {
|
||||
const simulators = SimulatorStore.getState().sort((a, b) => {
|
||||
const ics = InfrastructureComponentStore.getState().sort((a, b) => {
|
||||
if (a.state !== b.state) {
|
||||
return Simulators.statePrio(a.state) > Simulators.statePrio(b.state);
|
||||
return InfrastructureComponents.statePrio(a.state) > InfrastructureComponents.statePrio(b.state);
|
||||
}
|
||||
else if (a.name !== b.name) {
|
||||
return a.name < b.name;
|
||||
|
@ -79,17 +75,17 @@ class Simulators extends Component {
|
|||
|
||||
return {
|
||||
sessionToken: LoginStore.getState().token,
|
||||
simulators,
|
||||
modalSimulator: {},
|
||||
ics: ics,
|
||||
modalIC: {},
|
||||
deleteModal: false,
|
||||
|
||||
selectedSimulators: []
|
||||
selectedICs: []
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-load',
|
||||
type: 'ics/start-load',
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
|
||||
|
@ -108,7 +104,7 @@ class Simulators extends Component {
|
|||
}
|
||||
else {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-load',
|
||||
type: 'ics/start-load',
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
}
|
||||
|
@ -120,7 +116,7 @@ class Simulators extends Component {
|
|||
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-add',
|
||||
type: 'ics/start-add',
|
||||
data,
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
|
@ -131,13 +127,13 @@ class Simulators extends Component {
|
|||
this.setState({ editModal : false });
|
||||
|
||||
if (data) {
|
||||
let simulator = this.state.simulators[this.state.modalIndex];
|
||||
simulator.properties = data;
|
||||
this.setState({ simulator });
|
||||
let ic = this.state.ics[this.state.modalIndex];
|
||||
ic.properties = data;
|
||||
this.setState({ ic: ic });
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-edit',
|
||||
data: simulator,
|
||||
type: 'ics/start-edit',
|
||||
data: ic,
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
}
|
||||
|
@ -151,20 +147,20 @@ class Simulators extends Component {
|
|||
}
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-remove',
|
||||
data: this.state.modalSimulator,
|
||||
type: 'ics/start-remove',
|
||||
data: this.state.modalIC,
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
}
|
||||
|
||||
exportSimulator(index) {
|
||||
exportIC(index) {
|
||||
// filter properties
|
||||
let simulator = Object.assign({}, this.state.simulators[index]);
|
||||
delete simulator.id;
|
||||
let ic = Object.assign({}, this.state.ics[index]);
|
||||
delete ic.id;
|
||||
|
||||
// show save dialog
|
||||
const blob = new Blob([JSON.stringify(simulator, null, 2)], { type: 'application/json' });
|
||||
FileSaver.saveAs(blob, 'simulator - ' + (_.get(simulator, 'properties.name') || _.get(simulator, 'rawProperties.name') || 'undefined') + '.json');
|
||||
const blob = new Blob([JSON.stringify(ic, null, 2)], { type: 'application/json' });
|
||||
FileSaver.saveAs(blob, 'ic - ' + (_.get(ic, 'properties.name') || _.get(ic, 'rawProperties.name') || 'undefined') + '.json');
|
||||
}
|
||||
|
||||
closeImportModal(data) {
|
||||
|
@ -172,25 +168,25 @@ class Simulators extends Component {
|
|||
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-add',
|
||||
type: 'ics/start-add',
|
||||
data,
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onSimulatorChecked(index, event) {
|
||||
const selectedSimulators = Object.assign([], this.state.selectedSimulators);
|
||||
for (let key in selectedSimulators) {
|
||||
if (selectedSimulators[key] === index) {
|
||||
onICChecked(index, event) {
|
||||
const selectedICs = Object.assign([], this.state.selectedICs);
|
||||
for (let key in selectedICs) {
|
||||
if (selectedICs[key] === index) {
|
||||
// update existing entry
|
||||
if (event.target.checked) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedSimulators.splice(key, 1);
|
||||
selectedICs.splice(key, 1);
|
||||
|
||||
this.setState({ selectedSimulators });
|
||||
this.setState({ selectedICs: selectedICs });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -200,34 +196,34 @@ class Simulators extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
selectedSimulators.push(index);
|
||||
this.setState({ selectedSimulators });
|
||||
selectedICs.push(index);
|
||||
this.setState({ selectedICs: selectedICs });
|
||||
}
|
||||
|
||||
runAction = action => {
|
||||
for (let index of this.state.selectedSimulators) {
|
||||
for (let index of this.state.selectedICs) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-action',
|
||||
simulator: this.state.simulators[index],
|
||||
type: 'ics/start-action',
|
||||
ic: this.state.ics[index],
|
||||
data: action.data,
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static isSimulatorOutdated(simulator) {
|
||||
if (!simulator.stateUpdatedAt)
|
||||
static isICOutdated(component) {
|
||||
if (!component.stateUpdatedAt)
|
||||
return true;
|
||||
|
||||
const fiveMinutes = 5 * 60 * 1000;
|
||||
|
||||
return Date.now() - new Date(simulator.stateUpdatedAt) > fiveMinutes;
|
||||
return Date.now() - new Date(component.stateUpdatedAt) > fiveMinutes;
|
||||
}
|
||||
|
||||
static stateLabelStyle(state, simulator){
|
||||
static stateLabelStyle(state, component){
|
||||
var style = [ 'label' ];
|
||||
|
||||
if (Simulators.isSimulatorOutdated(simulator) && state !== 'shutdown') {
|
||||
if (InfrastructureComponents.isICOutdated(component) && state !== 'shutdown') {
|
||||
style.push('label-outdated');
|
||||
}
|
||||
|
||||
|
@ -274,30 +270,30 @@ class Simulators extends Component {
|
|||
<div className='section'>
|
||||
<h1>Infrastructure Components</h1>
|
||||
|
||||
<Table data={this.state.simulators}>
|
||||
<TableColumn checkbox onChecked={(index, event) => this.onSimulatorChecked(index, event)} width='30' />
|
||||
<Table data={this.state.ics}>
|
||||
<TableColumn checkbox onChecked={(index, event) => this.onICChecked(index, event)} width='30' />
|
||||
<TableColumn title='Name' dataKeys={['properties.name', 'rawProperties.name']} />
|
||||
<TableColumn title='State' labelKey='state' tooltipKey='error' labelModifier={Simulators.stateLabelModifier} labelStyle={Simulators.stateLabelStyle} />
|
||||
<TableColumn title='State' labelKey='state' tooltipKey='error' labelModifier={InfrastructureComponents.stateLabelModifier} labelStyle={InfrastructureComponents.stateLabelStyle} />
|
||||
<TableColumn title='Category' dataKeys={['properties.category', 'rawProperties.category']} />
|
||||
<TableColumn title='Type' dataKeys={['properties.type', 'rawProperties.type']} />
|
||||
<TableColumn title='Location' dataKeys={['properties.location', 'rawProperties.location']} />
|
||||
{/* <TableColumn title='Realm' dataKeys={['properties.realm', 'rawProperties.realm']} /> */}
|
||||
<TableColumn title='Host' dataKey='host' />
|
||||
<TableColumn title='Last Update' dataKey='stateUpdatedAt' modifier={Simulators.stateUpdateModifier} />
|
||||
<TableColumn title='Last Update' dataKey='stateUpdatedAt' modifier={InfrastructureComponents.stateUpdateModifier} />
|
||||
<TableColumn
|
||||
width='200'
|
||||
editButton
|
||||
exportButton
|
||||
deleteButton
|
||||
onEdit={index => this.setState({ editModal: true, modalSimulator: this.state.simulators[index], modalIndex: index })}
|
||||
onExport={index => this.exportSimulator(index)}
|
||||
onDelete={index => this.setState({ deleteModal: true, modalSimulator: this.state.simulators[index], modalIndex: index })}
|
||||
onEdit={index => this.setState({ editModal: true, modalIC: this.state.ics[index], modalIndex: index })}
|
||||
onExport={index => this.exportIC(index)}
|
||||
onDelete={index => this.setState({ deleteModal: true, modalIC: this.state.ics[index], modalIndex: index })}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<div style={{ float: 'left' }}>
|
||||
<SimulatorAction
|
||||
runDisabled={this.state.selectedSimulators.length === 0}
|
||||
<ICAction
|
||||
runDisabled={this.state.selectedICs.length === 0}
|
||||
runAction={this.runAction}
|
||||
actions={[ { id: '0', title: 'Reset', data: { action: 'reset' } }, { id: '1', title: 'Shutdown', data: { action: 'shutdown' } } ]}/>
|
||||
</div>
|
||||
|
@ -309,15 +305,15 @@ class Simulators extends Component {
|
|||
|
||||
<div style={{ clear: 'both' }} />
|
||||
|
||||
<NewSimulatorDialog show={this.state.newModal} onClose={data => this.closeNewModal(data)} />
|
||||
<EditSimulatorDialog show={this.state.editModal} onClose={data => this.closeEditModal(data)} simulator={this.state.modalSimulator} />
|
||||
<ImportSimulatorDialog show={this.state.importModal} onClose={data => this.closeImportModal(data)} />
|
||||
<NewICDialog show={this.state.newModal} onClose={data => this.closeNewModal(data)} />
|
||||
<EditICDialog show={this.state.editModal} onClose={data => this.closeEditModal(data)} ic={this.state.modalIC} />
|
||||
<ImportICDialog show={this.state.importModal} onClose={data => this.closeImportModal(data)} />
|
||||
|
||||
<DeleteDialog title="simulator" name={_.get(this.state.modalSimulator, 'properties.name') || _.get(this.state.modalSimulator, 'rawProperties.name') || 'Unknown'} show={this.state.deleteModal} onClose={(e) => this.closeDeleteModal(e)} />
|
||||
<DeleteDialog title="infrastructure-component" name={_.get(this.state.modalIC, 'properties.name') || _.get(this.state.modalIC, 'rawProperties.name') || 'Unknown'} show={this.state.deleteModal} onClose={(e) => this.closeDeleteModal(e)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let fluxContainerConverter = require('../common/FluxContainerConverter');
|
||||
export default Container.create(fluxContainerConverter.convert(Simulators));
|
||||
export default Container.create(fluxContainerConverter.convert(InfrastructureComponents));
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: new-simulator.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 27.03.2018
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -25,7 +21,7 @@ import _ from 'lodash';
|
|||
|
||||
import Dialog from '../common/dialogs/dialog';
|
||||
|
||||
class ImportSimulatorDialog extends React.Component {
|
||||
class ImportICDialog extends React.Component {
|
||||
valid = false;
|
||||
imported = false;
|
||||
|
||||
|
@ -80,13 +76,13 @@ class ImportSimulatorDialog extends React.Component {
|
|||
const self = this;
|
||||
|
||||
reader.onload = function(event) {
|
||||
// read simulator
|
||||
const simulator = JSON.parse(event.target.result);
|
||||
// read component
|
||||
const ic = JSON.parse(event.target.result);
|
||||
self.imported = true;
|
||||
self.setState({
|
||||
name: _.get(simulator, 'properties.name') || _.get(simulator, 'rawProperties.name'),
|
||||
endpoint: _.get(simulator, 'properties.endpoint') || _.get(simulator, 'rawProperties.endpoint'),
|
||||
uuid: simulator.uuid
|
||||
name: _.get(ic, 'properties.name') || _.get(ic, 'rawProperties.name'),
|
||||
endpoint: _.get(ic, 'properties.endpoint') || _.get(ic, 'rawProperties.endpoint'),
|
||||
uuid: ic.uuid
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -143,4 +139,4 @@ class ImportSimulatorDialog extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ImportSimulatorDialog;
|
||||
export default ImportICDialog;
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: new-simulator.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 02.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -24,7 +20,7 @@ import { FormGroup, FormControl, FormLabel } from 'react-bootstrap';
|
|||
|
||||
import Dialog from '../common/dialogs/dialog';
|
||||
|
||||
class NewSimulatorDialog extends React.Component {
|
||||
class NewICDialog extends React.Component {
|
||||
valid = false;
|
||||
|
||||
constructor(props) {
|
||||
|
@ -119,4 +115,4 @@ class NewSimulatorDialog extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default NewSimulatorDialog;
|
||||
export default NewICDialog;
|
|
@ -35,7 +35,7 @@ class ImportScenarioDialog extends React.Component {
|
|||
this.state = {
|
||||
name: '',
|
||||
running: '',
|
||||
simulationModels: [],
|
||||
configs: [],
|
||||
startParameters: {}
|
||||
};
|
||||
}
|
||||
|
@ -55,14 +55,14 @@ class ImportScenarioDialog extends React.Component {
|
|||
}
|
||||
|
||||
handleChange(e, index) {
|
||||
if (e.target.id === 'simulator') {
|
||||
const models = this.state.models;
|
||||
models[index].simulator = JSON.parse(e.target.value);
|
||||
/*if (e.target.id === 'icID') {
|
||||
const configs = this.state.configs;
|
||||
configs[index].icID = JSON.parse(e.target.value);
|
||||
|
||||
this.setState({ models });
|
||||
this.setState({ configs: configs });
|
||||
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
this.setState({ [e.target.id]: e.target.value });
|
||||
|
||||
|
@ -77,7 +77,7 @@ class ImportScenarioDialog extends React.Component {
|
|||
}
|
||||
|
||||
resetState = () => {
|
||||
this.setState({ name: '', models: [], startParameters: {} });
|
||||
this.setState({ name: '', configs: [], startParameters: {} });
|
||||
|
||||
this.imported = false;
|
||||
}
|
||||
|
@ -96,16 +96,9 @@ class ImportScenarioDialog extends React.Component {
|
|||
reader.onload = onloadEvent => {
|
||||
const scenario = JSON.parse(onloadEvent.target.result);
|
||||
|
||||
// scenario.simulationModels.forEach(model => {
|
||||
// model.simulator = {
|
||||
// node: self.props.nodes[0]._id,
|
||||
// simulator: 0
|
||||
// };
|
||||
// });
|
||||
|
||||
self.imported = true;
|
||||
self.valid = true;
|
||||
self.setState({ name: scenario.name, models: scenario.simulationModels, startParameters: scenario.startParameters, running: scenario.running });
|
||||
self.setState({ name: scenario.name, configs: scenario.configs, startParameters: scenario.startParameters, running: scenario.running });
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
|
@ -131,18 +124,6 @@ class ImportScenarioDialog extends React.Component {
|
|||
<ParametersEditor content={this.state.startParameters} onChange={this.handleStartParametersChange} disabled={this.imported === false} />
|
||||
</FormGroup>
|
||||
|
||||
{/* {this.state.models.map((model, index) => (
|
||||
<FormGroup controlId="simulator" key={index}>
|
||||
<FormLabel>{model.name} - Simulator</FormLabel>
|
||||
<FormControl componentClass="select" placeholder="Select simulator" value={JSON.stringify({ node: model.simulator.node, simulator: model.simulator.simulator})} onChange={(e) => this.handleChange(e, index)}>
|
||||
{this.props.nodes.map(node => (
|
||||
node.simulators.map((simulator, index) => (
|
||||
<option key={node._id + index} value={JSON.stringify({ node: node._id, simulator: index })}>{node.name}/{simulator.name}</option>
|
||||
))
|
||||
))}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
))} */}
|
||||
</form>
|
||||
</Dialog>;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: scenario.js
|
||||
* Author: Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* Date: 20.08.2019
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -26,9 +22,9 @@ import FileSaver from 'file-saver';
|
|||
import _ from 'lodash';
|
||||
|
||||
import ScenarioStore from './scenario-store';
|
||||
import SimulatorStore from '../simulator/simulator-store';
|
||||
import ICStore from '../ic/ic-store';
|
||||
import DashboardStore from '../dashboard/dashboard-store';
|
||||
import SimulationModelStore from '../simulationmodel/simulation-model-store';
|
||||
import ConfigStore from '../componentconfig/config-store';
|
||||
import LoginStore from '../user/login-store';
|
||||
import SignalStore from '../signal/signal-store'
|
||||
import AppDispatcher from '../common/app-dispatcher';
|
||||
|
@ -36,19 +32,19 @@ import AppDispatcher from '../common/app-dispatcher';
|
|||
import Icon from '../common/icon';
|
||||
import Table from '../common/table';
|
||||
import TableColumn from '../common/table-column';
|
||||
import ImportSimulationModelDialog from '../simulationmodel/import-simulation-model';
|
||||
import ImportConfigDialog from '../componentconfig/import-config';
|
||||
import ImportDashboardDialog from "../dashboard/import-dashboard";
|
||||
import NewDashboardDialog from "../dashboard/new-dashboard";
|
||||
|
||||
import SimulatorAction from '../simulator/simulator-action';
|
||||
import ICAction from '../ic/ic-action';
|
||||
import DeleteDialog from '../common/dialogs/delete-dialog';
|
||||
import EditSimulationModelDialog from "../simulationmodel/edit-simulation-model";
|
||||
import EditConfigDialog from "../componentconfig/edit-config";
|
||||
import EditSignalMapping from "../signal/edit-signal-mapping";
|
||||
import FileStore from "../file/file-store"
|
||||
|
||||
class Scenario extends React.Component {
|
||||
static getStores() {
|
||||
return [ ScenarioStore, SimulationModelStore, DashboardStore, SimulatorStore, LoginStore, SignalStore, FileStore];
|
||||
return [ ScenarioStore, ConfigStore, DashboardStore, ICStore, LoginStore, SignalStore, FileStore];
|
||||
}
|
||||
|
||||
static calculateState(prevState, props) {
|
||||
|
@ -67,8 +63,8 @@ class Scenario extends React.Component {
|
|||
// obtain all dashboards of a scenario
|
||||
let dashboards = DashboardStore.getState().filter(dashb => dashb.scenarioID === parseInt(props.match.params.scenario, 10));
|
||||
|
||||
// obtain all simulation models of a scenario
|
||||
let simulationModels = SimulationModelStore.getState().filter(simmodel => simmodel.scenarioID === parseInt(props.match.params.scenario, 10));
|
||||
// obtain all component configurations of a scenario
|
||||
let configs = ConfigStore.getState().filter(config => config.scenarioID === parseInt(props.match.params.scenario, 10));
|
||||
|
||||
let signals = SignalStore.getState();
|
||||
let files = FileStore.getState();
|
||||
|
@ -77,18 +73,18 @@ class Scenario extends React.Component {
|
|||
return {
|
||||
scenario,
|
||||
sessionToken,
|
||||
simulationModels,
|
||||
configs: configs,
|
||||
dashboards,
|
||||
signals,
|
||||
files,
|
||||
simulators: SimulatorStore.getState(),
|
||||
ics: ICStore.getState(),
|
||||
|
||||
deleteSimulationModelModal: false,
|
||||
importSimulationModelModal: false,
|
||||
editSimulationModelModal: false,
|
||||
modalSimulationModelData: {},
|
||||
selectedSimulationModels: [],
|
||||
modalSimulationModelIndex: 0,
|
||||
deleteConfigModal: false,
|
||||
importConfigModal: false,
|
||||
editConfigModal: false,
|
||||
modalConfigData: {},
|
||||
selectedConfigs: [],
|
||||
modalConfigIndex: 0,
|
||||
|
||||
editOutputSignalsModal: false,
|
||||
editInputSignalsModal: false,
|
||||
|
@ -109,9 +105,9 @@ class Scenario extends React.Component {
|
|||
token: this.state.sessionToken
|
||||
});
|
||||
|
||||
// load simulation models for selected scenario
|
||||
// load component configurations for selected scenario
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/start-load',
|
||||
type: 'configs/start-load',
|
||||
token: this.state.sessionToken,
|
||||
param: '?scenarioID='+this.state.scenario.id,
|
||||
});
|
||||
|
@ -123,9 +119,9 @@ class Scenario extends React.Component {
|
|||
param: '?scenarioID='+this.state.scenario.id,
|
||||
});
|
||||
|
||||
// load simulators to enable that simulation models work with them
|
||||
// load ICs to enable that component configs work with them
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-load',
|
||||
type: 'ics/start-load',
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
|
||||
|
@ -133,20 +129,20 @@ class Scenario extends React.Component {
|
|||
}
|
||||
|
||||
/* ##############################################
|
||||
* Simulation Model modification methods
|
||||
* Component Configuration modification methods
|
||||
############################################## */
|
||||
|
||||
addSimulationModel(){
|
||||
const simulationModel = {
|
||||
addConfig(){
|
||||
const config = {
|
||||
scenarioID: this.state.scenario.id,
|
||||
name: 'New Simulation Model',
|
||||
simulatorID: this.state.simulators.length > 0 ? this.state.simulators[0].id : null,
|
||||
name: 'New Component Configuration',
|
||||
icID: this.state.ics.length > 0 ? this.state.ics[0].id : null,
|
||||
startParameters: {},
|
||||
};
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/start-add',
|
||||
data: simulationModel,
|
||||
type: 'configs/start-add',
|
||||
data: config,
|
||||
token: this.state.sessionToken
|
||||
});
|
||||
|
||||
|
@ -159,44 +155,44 @@ class Scenario extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
closeEditSimulationModelModal(data){
|
||||
this.setState({ editSimulationModelModal : false });
|
||||
closeEditConfigModal(data){
|
||||
this.setState({ editConfigModal : false });
|
||||
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/start-edit',
|
||||
type: 'configs/start-edit',
|
||||
data: data,
|
||||
token: this.state.sessionToken,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
closeDeleteSimulationModelModal(confirmDelete) {
|
||||
this.setState({ deleteSimulationModelModal: false });
|
||||
closeDeleteConfigModal(confirmDelete) {
|
||||
this.setState({ deleteConfigModal: false });
|
||||
|
||||
if (confirmDelete === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/start-remove',
|
||||
data: this.state.modalSimulationModelData,
|
||||
type: 'configs/start-remove',
|
||||
data: this.state.modalConfigData,
|
||||
token: this.state.sessionToken
|
||||
});
|
||||
}
|
||||
|
||||
importSimulationModel(simulationModel){
|
||||
this.setState({ importSimulationModelModal: false });
|
||||
importConfig(config){
|
||||
this.setState({ importConfigModal: false });
|
||||
|
||||
if (simulationModel == null) {
|
||||
if (config == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
simulationModel.scenario = this.state.scenario.id;
|
||||
config.scenario = this.state.scenario.id;
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/start-add',
|
||||
data: simulationModel,
|
||||
type: 'configs/start-add',
|
||||
data: config,
|
||||
token: this.state.sessionToken
|
||||
});
|
||||
|
||||
|
@ -209,27 +205,27 @@ class Scenario extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
exportModel(index) {
|
||||
exportConfig(index) {
|
||||
// filter properties
|
||||
const model = Object.assign({}, this.state.simulationModels[index]);
|
||||
const config = Object.assign({}, this.state.configs[index]);
|
||||
|
||||
// show save dialog
|
||||
const blob = new Blob([JSON.stringify(model, null, 2)], { type: 'application/json' });
|
||||
FileSaver.saveAs(blob, 'simulation model - ' + model.name + '.json');
|
||||
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
|
||||
FileSaver.saveAs(blob, 'config-' + config.name + '.json');
|
||||
}
|
||||
|
||||
onSimulationModelChecked(index, event) {
|
||||
const selectedSimulationModels = Object.assign([], this.state.selectedSimulationModels);
|
||||
for (let key in selectedSimulationModels) {
|
||||
if (selectedSimulationModels[key] === index) {
|
||||
onConfigChecked(index, event) {
|
||||
const selectedConfigs = Object.assign([], this.state.selectedConfigs);
|
||||
for (let key in selectedConfigs) {
|
||||
if (selectedConfigs[key] === index) {
|
||||
// update existing entry
|
||||
if (event.target.checked) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedSimulationModels.splice(key, 1);
|
||||
selectedConfigs.splice(key, 1);
|
||||
|
||||
this.setState({ selectedSimulationModels });
|
||||
this.setState({ selectedConfigs: selectedConfigs });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -239,41 +235,41 @@ class Scenario extends React.Component {
|
|||
return;
|
||||
}
|
||||
|
||||
selectedSimulationModels.push(index);
|
||||
this.setState({ selectedSimulationModels });
|
||||
selectedConfigs.push(index);
|
||||
this.setState({ selectedConfigs: selectedConfigs });
|
||||
}
|
||||
|
||||
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;
|
||||
for (let index of this.state.selectedConfigs) {
|
||||
// get IC for component config
|
||||
let ic = null;
|
||||
for (let component of this.state.ics) {
|
||||
if (component._id === this.state.configs[index].icID) {
|
||||
ic = component;
|
||||
}
|
||||
}
|
||||
|
||||
if (simulator == null) {
|
||||
if (ic == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (action.data.action === 'start') {
|
||||
action.data.parameters = this.state.simulationModels[index].startParameters;
|
||||
action.data.parameters = this.state.configs[index].startParameters;
|
||||
}
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-action',
|
||||
simulator,
|
||||
type: 'ics/start-action',
|
||||
ic: ic,
|
||||
data: action.data,
|
||||
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;
|
||||
getICName(icID) {
|
||||
for (let ic of this.state.ics) {
|
||||
if (ic.id === icID) {
|
||||
return _.get(ic, 'properties.name') || _.get(ic, 'rawProperties.name') || ic.uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +345,7 @@ class Scenario extends React.Component {
|
|||
}
|
||||
|
||||
closeNewSignalModal(data){
|
||||
//data contains the new signal incl. simulationModelID and direction
|
||||
//data contains the new signal incl. configID and direction
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'signals/start-add',
|
||||
|
@ -410,38 +406,38 @@ class Scenario extends React.Component {
|
|||
|
||||
{/*Component Configurations table*/}
|
||||
<h2>Component Configurations</h2>
|
||||
<Table data={this.state.simulationModels}>
|
||||
<TableColumn checkbox onChecked={(index, event) => this.onSimulationModelChecked(index, event)} width='30' />
|
||||
<Table data={this.state.configs}>
|
||||
<TableColumn checkbox onChecked={(index, event) => this.onConfigChecked(index, event)} width='30' />
|
||||
<TableColumn title='Name' dataKey='name' />
|
||||
<TableColumn title='Selected configuration file' dataKey='selectedModelFileID' modifier={(selectedModelFileID) => this.getFileName(selectedModelFileID)}/>
|
||||
<TableColumn title='Selected configuration file' dataKey='selectedFileID' modifier={(selectedFileID) => this.getFileName(selectedFileID)}/>
|
||||
<TableColumn
|
||||
title='# Output Signals'
|
||||
dataKey='outputLength'
|
||||
editButton
|
||||
onEdit={index => this.setState({ editOutputSignalsModal: true, modalSimulationModelData: this.state.simulationModels[index], modalSimulationModelIndex: index })}
|
||||
onEdit={index => this.setState({ editOutputSignalsModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })}
|
||||
/>
|
||||
<TableColumn
|
||||
title='# Input Signals'
|
||||
dataKey='inputLength'
|
||||
editButton
|
||||
onEdit={index => this.setState({ editInputSignalsModal: true, modalSimulationModelData: this.state.simulationModels[index], modalSimulationModelIndex: index })}
|
||||
onEdit={index => this.setState({ editInputSignalsModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })}
|
||||
/>
|
||||
<TableColumn title='Infrastructure Component' dataKey='simulatorID' modifier={(simulatorID) => this.getSimulatorName(simulatorID)} />
|
||||
<TableColumn title='Infrastructure Component' dataKey='icID' modifier={(icID) => this.getICName(icID)} />
|
||||
<TableColumn
|
||||
title='Edit/ Delete/ Export'
|
||||
width='200'
|
||||
editButton
|
||||
deleteButton
|
||||
exportButton
|
||||
onEdit={index => this.setState({ editSimulationModelModal: true, modalSimulationModelData: this.state.simulationModels[index], modalSimulationModelIndex: index })}
|
||||
onDelete={(index) => this.setState({ deleteSimulationModelModal: true, modalSimulationModelData: this.state.simulationModels[index], modalSimulationModelIndex: index })}
|
||||
onExport={index => this.exportModel(index)}
|
||||
onEdit={index => this.setState({ editConfigModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })}
|
||||
onDelete={(index) => this.setState({ deleteConfigModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })}
|
||||
onExport={index => this.exportConfig(index)}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<div style={{ float: 'left' }}>
|
||||
<SimulatorAction
|
||||
runDisabled={this.state.selectedSimulationModels.length === 0}
|
||||
<ICAction
|
||||
runDisabled={this.state.selectedConfigs.length === 0}
|
||||
runAction={this.runAction}
|
||||
actions={[
|
||||
{ id: '0', title: 'Start', data: { action: 'start' } },
|
||||
|
@ -452,15 +448,15 @@ class Scenario extends React.Component {
|
|||
</div>
|
||||
|
||||
<div style={{ float: 'right' }}>
|
||||
<Button onClick={() => this.addSimulationModel()} style={buttonStyle}><Icon icon="plus" /> Simulation Model</Button>
|
||||
<Button onClick={() => this.setState({ importSimulationModelModal: true })} style={buttonStyle}><Icon icon="upload" /> Import</Button>
|
||||
<Button onClick={() => this.addConfig()} style={buttonStyle}><Icon icon="plus" /> Component Configuration</Button>
|
||||
<Button onClick={() => this.setState({ importConfigModal: true })} style={buttonStyle}><Icon icon="upload" /> Import</Button>
|
||||
</div>
|
||||
|
||||
<div style={{ clear: 'both' }} />
|
||||
|
||||
<EditSimulationModelDialog show={this.state.editSimulationModelModal} onClose={data => this.closeEditSimulationModelModal(data)} simulationModel={this.state.modalSimulationModelData} simulators={this.state.simulators} />
|
||||
<ImportSimulationModelDialog show={this.state.importSimulationModelModal} onClose={data => this.importSimulationModel(data)} simulators={this.state.simulators} />
|
||||
<DeleteDialog title="component configuration" name={this.state.modalSimulationModelData.name} show={this.state.deleteSimulationModelModal} onClose={(c) => this.closeDeleteSimulationModelModal(c)} />
|
||||
<EditConfigDialog show={this.state.editConfigModal} onClose={data => this.closeEditConfigModal(data)} config={this.state.modalConfigData} ics={this.state.ics} />
|
||||
<ImportConfigDialog show={this.state.importConfigModal} onClose={data => this.importConfig(data)} ics={this.state.ics} />
|
||||
<DeleteDialog title="component configuration" name={this.state.modalConfigData.name} show={this.state.deleteConfigModal} onClose={(c) => this.closeDeleteConfigModal(c)} />
|
||||
|
||||
<EditSignalMapping
|
||||
show={this.state.editOutputSignalsModal}
|
||||
|
@ -469,7 +465,7 @@ class Scenario extends React.Component {
|
|||
onDelete={(data) => this.closeDeleteSignalModal(data)}
|
||||
direction="Output"
|
||||
signals={this.state.signals}
|
||||
simulationModelID={this.state.modalSimulationModelData.id} />
|
||||
configID={this.state.modalConfigData.id} />
|
||||
<EditSignalMapping
|
||||
show={this.state.editInputSignalsModal}
|
||||
onCloseEdit={(data, direction) => this.closeEditSignalsModal(data, direction)}
|
||||
|
@ -477,7 +473,7 @@ class Scenario extends React.Component {
|
|||
onDelete={(data) => this.closeDeleteSignalModal(data)}
|
||||
direction="Input"
|
||||
signals={this.state.signals}
|
||||
simulationModelID={this.state.modalSimulationModelData.id}/>
|
||||
configID={this.state.modalConfigData.id}/>
|
||||
|
||||
{/*Dashboard table*/}
|
||||
<h2>Dashboards</h2>
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: scenarios-data-manager.js
|
||||
* Author: Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* Date: 20.08.2019
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -25,18 +21,18 @@ import AppDispatcher from "../common/app-dispatcher";
|
|||
|
||||
class ScenariosDataManager extends RestDataManager {
|
||||
constructor() {
|
||||
super('scenario', '/scenarios', ['id', 'name', 'running', 'simulationModelIDs', 'userIDs', 'dashboardIDs', 'startParameters' ]);
|
||||
super('scenario', '/scenarios');
|
||||
}
|
||||
|
||||
getSimulationModels(token, id) {
|
||||
RestAPI.get(this.makeURL('/scenarios/' + id + '/models'), token).then(response => {
|
||||
getComponentConfigs(token, id) {
|
||||
RestAPI.get(this.makeURL('/scenarios/' + id + '/configs'), token).then(response => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'scenarios/simulationmodels',
|
||||
simulationmodels: response.models
|
||||
type: 'scenarios/configs',
|
||||
configs: response.configs
|
||||
});
|
||||
}).catch(error => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'scenarios/simulationmodels-error',
|
||||
type: 'scenarios/configs-error',
|
||||
error: error
|
||||
});
|
||||
});
|
||||
|
|
|
@ -158,7 +158,7 @@ class Scenarios extends Component {
|
|||
let scenario = Object.assign({}, this.state.scenarios[index]);
|
||||
delete scenario.id;
|
||||
|
||||
// TODO request missing scenario parameters (Dashboards and Simulation Modles) recursively for export
|
||||
// TODO request missing scenario parameters (Dashboards and component configs) recursively for export
|
||||
|
||||
// show save dialog
|
||||
const blob = new Blob([JSON.stringify(scenario, null, 2)], { type: 'application/json' });
|
||||
|
|
|
@ -52,9 +52,9 @@ class EditSignalMapping extends React.Component {
|
|||
|
||||
static getDerivedStateFromProps(props, state){
|
||||
|
||||
// filter all signals by Simulation Model ID and direction
|
||||
// filter all signals by configID and direction
|
||||
let signals = props.signals.filter((sig) => {
|
||||
return (sig.simulationModelID === props.simulationModelID) && (sig.direction === state.dir);
|
||||
return (sig.configID === props.configID) && (sig.direction === state.dir);
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -115,7 +115,7 @@ class EditSignalMapping extends React.Component {
|
|||
console.log("add signal");
|
||||
|
||||
let newSignal = {
|
||||
simulationModelID: this.props.simulationModelID,
|
||||
configID: this.props.configID,
|
||||
direction: this.state.dir,
|
||||
name: "PlaceholderName",
|
||||
unit: "PlaceholderUnit",
|
||||
|
@ -130,7 +130,7 @@ class EditSignalMapping extends React.Component {
|
|||
this.valid=false;
|
||||
|
||||
let signals = this.props.signals.filter((sig) => {
|
||||
return (sig.simulationModelID === this.props.simulationModelID) && (sig.direction === this.state.dir);
|
||||
return (sig.configID === this.props.configID) && (sig.direction === this.state.dir);
|
||||
});
|
||||
|
||||
this.setState({signals: signals})
|
||||
|
@ -173,7 +173,7 @@ EditSignalMapping.propTypes = {
|
|||
name: PropTypes.string.isRequired,
|
||||
unit: PropTypes.string.isRequired,
|
||||
direction: PropTypes.string.isRequired,
|
||||
simulationModelID: PropTypes.number.isRequired,
|
||||
configID: PropTypes.number.isRequired,
|
||||
index: PropTypes.number.isRequired
|
||||
|
||||
})
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/**
|
||||
* File: signal-store.js
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -28,10 +26,10 @@ class SignalStore extends ArrayStore{
|
|||
reduce(state, action) {
|
||||
switch (action.type) {
|
||||
case 'signals/added':
|
||||
SignalsDataManager.reloadSimulationModel(action.token, action.data);
|
||||
SignalsDataManager.reloadConfig(action.token, action.data);
|
||||
return super.reduce(state, action);
|
||||
case 'signals/removed':
|
||||
SignalsDataManager.reloadSimulationModel(action.token, action.data);
|
||||
SignalsDataManager.reloadConfig(action.token, action.data);
|
||||
return super.reduce(state, action);
|
||||
|
||||
default:
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/**
|
||||
* File: signals-data-manager.js
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -27,13 +25,13 @@ class SignalsDataManager extends RestDataManager{
|
|||
super('signal', '/signals');
|
||||
}
|
||||
|
||||
reloadSimulationModel(token, data){
|
||||
reloadConfig(token, data){
|
||||
// request in signals
|
||||
console.log("Reloading simulation model due to signal add/remove")
|
||||
RestAPI.get(this.makeURL('/models/' + data.simulationModelID), token).then(response => {
|
||||
console.log("Reloading component config due to signal add/remove")
|
||||
RestAPI.get(this.makeURL('/configs/' + data.configID), token).then(response => {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/edited',
|
||||
data: response.simulationModel
|
||||
type: 'configs/edited',
|
||||
data: response.config
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: user-store.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 15.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -23,7 +19,7 @@ import { ReduceStore } from 'flux/utils';
|
|||
|
||||
import AppDispatcher from '../common/app-dispatcher';
|
||||
import UsersDataManager from './users-data-manager';
|
||||
import SimulatorDataDataManager from '../simulator/simulator-data-data-manager';
|
||||
import ICDataDataManager from '../ic/ic-data-data-manager';
|
||||
|
||||
class LoginStore extends ReduceStore {
|
||||
constructor() {
|
||||
|
@ -45,8 +41,8 @@ class LoginStore extends ReduceStore {
|
|||
return Object.assign({}, state, { loginMessage: null });
|
||||
|
||||
case 'users/logout':
|
||||
// disconnect from all simulators
|
||||
SimulatorDataDataManager.closeAll();
|
||||
// disconnect from all infrastructure components
|
||||
ICDataDataManager.closeAll();
|
||||
//remove token and current user from local storage
|
||||
localStorage.clear();
|
||||
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/**
|
||||
* File: edit-widget-simulation-control.js
|
||||
* Author: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
**********************************************************************************/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { FormGroup, FormControl, FormLabel } from 'react-bootstrap';
|
||||
|
||||
class EditWidgetSimulationControl extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
widget: {
|
||||
customProperties: {
|
||||
simulationModel: ''
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state){
|
||||
return{
|
||||
widget: props.widget
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<FormGroup controlId="simulationModel">
|
||||
<FormLabel>Simulation Model</FormLabel>
|
||||
<FormControl as="select" placeholder="Select simulation model" value={this.state.widget.simulationModel || '' } onChange={(e) => this.props.handleChange(e)}>
|
||||
{
|
||||
this.props.simulationModels.length === 0 ? (
|
||||
<option disabled value style={{ display: 'none' }}> No simulation models available. </option>
|
||||
) : (
|
||||
this.props.simulationModels.map((model, index) => (
|
||||
<option key={index} value={model._id}>{model.name}</option>
|
||||
)))
|
||||
}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EditWidgetSimulationControl;
|
|
@ -24,8 +24,8 @@ import { Container } from 'flux/utils';
|
|||
|
||||
import AppDispatcher from '../common/app-dispatcher';
|
||||
import LoginStore from '../user/login-store';
|
||||
import SimulatorDataStore from '../simulator/simulator-data-store';
|
||||
import SimulationModelStore from '../simulationmodel/simulation-model-store';
|
||||
import ICDataStore from '../ic/ic-data-store';
|
||||
import ConfigsStore from '../componentconfig/config-store';
|
||||
import FileStore from '../file/file-store';
|
||||
import SignalStore from '../signal/signal-store'
|
||||
|
||||
|
@ -53,39 +53,39 @@ import '../styles/widgets.css';
|
|||
|
||||
class Widget extends React.Component {
|
||||
static getStores() {
|
||||
return [ SimulatorDataStore, SimulationModelStore, FileStore, LoginStore, SignalStore];
|
||||
return [ ICDataStore, ConfigsStore, FileStore, LoginStore, SignalStore];
|
||||
}
|
||||
|
||||
static calculateState(prevState, props) {
|
||||
|
||||
let simulatorData = {};
|
||||
let icData = {};
|
||||
|
||||
if (props.paused) {
|
||||
if (prevState && prevState.simulatorData) {
|
||||
simulatorData = JSON.parse(JSON.stringify(prevState.simulatorData));
|
||||
if (prevState && prevState.icData) {
|
||||
icData = JSON.parse(JSON.stringify(prevState.icData));
|
||||
}
|
||||
} else {
|
||||
simulatorData = SimulatorDataStore.getState();
|
||||
icData = ICDataStore.getState();
|
||||
}
|
||||
|
||||
// Get the simulator IDs and signal indexes for all signals of the widget
|
||||
let simulationModels = SimulationModelStore.getState();
|
||||
// Get the IC IDs and signal indexes for all signals of the widget
|
||||
let configs = ConfigsStore.getState();
|
||||
// TODO make sure that the signals are only the signals that belong to the scenario at hand
|
||||
let signals = SignalStore.getState();
|
||||
let simulatorIDs = [];
|
||||
let icIDs = [];
|
||||
if ( props.data.signalIDs.length > 0){
|
||||
for (let i in props.data.signalIDs.length){
|
||||
let signal = signals.find(s => s.id === props.data.signalIDs[i]);
|
||||
let model = simulationModels.find(m => m.id === signal.simulationModelID);
|
||||
simulatorIDs[i] = model.simulatorID;
|
||||
let config = configs.find(m => m.id === signal.configID);
|
||||
icIDs[i] = config.icID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
simulatorData,
|
||||
icData: icData,
|
||||
signals: signals,
|
||||
simulatorIDs: simulatorIDs,
|
||||
icIDs: icIDs,
|
||||
files: FileStore.getState(),
|
||||
|
||||
sequence: prevState != null ? prevState.sequence + 1 : 0,
|
||||
|
@ -105,10 +105,10 @@ class Widget extends React.Component {
|
|||
param: '?objectID=1&objectType=widget'
|
||||
});*/
|
||||
|
||||
// TODO no not load simulation models here, since they are loaded via the scenario, pass them as props
|
||||
// TODO no not load component congfigs here, since they are loaded via the scenario, pass them as props
|
||||
/*
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulationModels/start-load',
|
||||
type: 'configs/start-load',
|
||||
token: this.state.sessionToken,
|
||||
param: '?scenarioID=1' // TODO do not hardcode scenarioID!
|
||||
});
|
||||
|
@ -118,8 +118,8 @@ class Widget extends React.Component {
|
|||
inputDataChanged(widget, data) {
|
||||
// The following assumes that a widget modifies/ uses exactly one signal
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulatorData/inputChanged',
|
||||
simulator: this.state.simulatorIDs[0],
|
||||
type: 'icData/inputChanged',
|
||||
ic: this.state.icIDs[0],
|
||||
signal: this.state.signals[0].index,
|
||||
data
|
||||
});
|
||||
|
@ -128,21 +128,21 @@ class Widget extends React.Component {
|
|||
createWidget(widget) {
|
||||
|
||||
if (widget.type === 'CustomAction') {
|
||||
return <WidgetCustomAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
|
||||
return <WidgetCustomAction widget={widget} data={this.state.icData} dummy={this.state.sequence} signals={this.state.signals} icIDs={this.state.icIDs} />
|
||||
} else if (widget.type === 'Action') {
|
||||
return <WidgetAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} />
|
||||
return <WidgetAction widget={widget} data={this.state.icData} dummy={this.state.sequence} />
|
||||
} else if (widget.type === 'Lamp') {
|
||||
return <WidgetLamp widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
|
||||
return <WidgetLamp widget={widget} data={this.state.icData} dummy={this.state.sequence} signals={this.state.signals} icIDs={this.state.icIDs} />
|
||||
} else if (widget.type === 'Value') {
|
||||
return <WidgetValue widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
|
||||
return <WidgetValue widget={widget} data={this.state.icData} dummy={this.state.sequence} signals={this.state.signals} icIDs={this.state.icIDs} />
|
||||
} else if (widget.type === 'Plot') {
|
||||
return <WidgetPlot widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} paused={this.props.paused} />
|
||||
return <WidgetPlot widget={widget} data={this.state.icData} dummy={this.state.sequence} paused={this.props.paused} />
|
||||
} else if (widget.type === 'Table') {
|
||||
return <WidgetTable widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
|
||||
return <WidgetTable widget={widget} data={this.state.icData} dummy={this.state.sequence} signals={this.state.signals} icIDs={this.state.icIDs} />
|
||||
} else if (widget.type === 'Label') {
|
||||
return <WidgetLabel widget={widget} />
|
||||
} else if (widget.type === 'PlotTable') {
|
||||
return <WidgetPlotTable widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} editing={this.props.editing} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index)} paused={this.props.paused} />
|
||||
return <WidgetPlotTable widget={widget} data={this.state.icData} dummy={this.state.sequence} editing={this.props.editing} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index)} paused={this.props.paused} />
|
||||
} else if (widget.type === 'Image') {
|
||||
return <WidgetImage widget={widget} files={this.state.files} token={this.state.sessionToken} />
|
||||
} else if (widget.type === 'Button') {
|
||||
|
@ -152,7 +152,7 @@ class Widget extends React.Component {
|
|||
} else if (widget.type === 'Slider') {
|
||||
return <WidgetSlider widget={widget} editing={this.props.editing} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index) } onInputChanged={value => this.inputDataChanged(widget, value)} signals={this.state.signals}/>
|
||||
} else if (widget.type === 'Gauge') {
|
||||
return <WidgetGauge widget={widget} data={this.state.simulatorData} editing={this.props.editing} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
|
||||
return <WidgetGauge widget={widget} data={this.state.icData} editing={this.props.editing} signals={this.state.signals} icIDs={this.state.icIDs} />
|
||||
} else if (widget.type === 'Box') {
|
||||
return <WidgetBox widget={widget} editing={this.props.editing} />
|
||||
} else if (widget.type === 'HTML') {
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
/**
|
||||
* File: action.js
|
||||
* Author: Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* Date: 21.11.2018
|
||||
* 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
|
||||
|
@ -24,7 +19,7 @@ import React, { Component } from 'react';
|
|||
import { Button } from 'react-bootstrap';
|
||||
import Icon from '../../common/icon';
|
||||
import LoginStore from '../../user/login-store';
|
||||
import SimulatorStore from '../../simulator/simulator-store';
|
||||
import ICStore from '../../ic/ic-store';
|
||||
import AppDispatcher from '../../common/app-dispatcher';
|
||||
|
||||
class WidgetCustomAction extends Component {
|
||||
|
@ -32,12 +27,12 @@ class WidgetCustomAction extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
simulator: null
|
||||
ic: null
|
||||
};
|
||||
}
|
||||
|
||||
static getStores() {
|
||||
return [ SimulatorStore, LoginStore ];
|
||||
return [ ICStore, LoginStore ];
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state){
|
||||
|
@ -46,15 +41,15 @@ class WidgetCustomAction extends Component {
|
|||
}
|
||||
|
||||
return{
|
||||
simulator: SimulatorStore.getState().find(s => s.id === props.simulatorIDs[0]),
|
||||
ic: ICStore.getState().find(s => s.id === props.icIDs[0]),
|
||||
sessionToken: LoginStore.getState().token
|
||||
};
|
||||
}
|
||||
|
||||
onClick() {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-action',
|
||||
simulator: this.state.simulator,
|
||||
type: 'ics/start-action',
|
||||
ic: this.state.ic,
|
||||
data: this.props.widget.customProperties.actions,
|
||||
token: this.state.sessionToken
|
||||
});
|
||||
|
@ -62,7 +57,7 @@ class WidgetCustomAction extends Component {
|
|||
|
||||
render() {
|
||||
return <div className="widget-custom-action full">
|
||||
<Button className="full" disabled={this.state.simulator === null} onClick={(e) => this.onClick()}>
|
||||
<Button className="full" disabled={this.state.ic === null} onClick={(e) => this.onClick()}>
|
||||
<Icon icon={this.props.widget.customProperties.icon} /> <span dangerouslySetInnerHTML={{ __html: this.props.widget.name }} />
|
||||
</Button>
|
||||
</div>;
|
||||
|
|
|
@ -84,15 +84,15 @@ class WidgetGauge extends Component {
|
|||
returnState["unit"] = widgetSignal.unit;
|
||||
}
|
||||
|
||||
const simulator = props.simulatorIDs[0];
|
||||
const ICid = props.icIDs[0];
|
||||
|
||||
// update value
|
||||
if (props.data == null
|
||||
|| props.data[simulator] == null
|
||||
|| props.data[simulator].output == null
|
||||
|| props.data[simulator].output.values == null
|
||||
|| props.data[simulator].output.values.length === 0
|
||||
|| props.data[simulator].output.values[0].length === 0) {
|
||||
|| props.data[ICid] == null
|
||||
|| props.data[ICid].output == null
|
||||
|| props.data[ICid].output.values == null
|
||||
|| props.data[ICid].output.values.length === 0
|
||||
|| props.data[ICid].output.values[0].length === 0) {
|
||||
returnState["value"] = 0;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ class WidgetGauge extends Component {
|
|||
let updateMaxValue = false;
|
||||
|
||||
// check if value has changed
|
||||
const signalData = props.data[simulator].output.values[widgetSignal.index];
|
||||
const signalData = props.data[ICid].output.values[widgetSignal.index];
|
||||
// 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 (signalData != null) {
|
||||
|
|
|
@ -38,20 +38,20 @@ class WidgetLamp extends Component {
|
|||
return{ value: ''};
|
||||
}
|
||||
|
||||
const simulator = props.simulatorIDs[0];
|
||||
const ic = props.icIDs[0];
|
||||
let signalID = props.widget.signalIDs[0];
|
||||
let widgetSignal = props.signals.find(sig => sig.id === signalID);
|
||||
|
||||
// update value
|
||||
if (props.data == null
|
||||
|| props.data[simulator] == null
|
||||
|| props.data[simulator].output == null
|
||||
|| props.data[simulator].output.values == null) {
|
||||
|| props.data[ic] == null
|
||||
|| props.data[ic].output == null
|
||||
|| props.data[ic].output.values == null) {
|
||||
return{value:''};
|
||||
}
|
||||
|
||||
// check if value has changed
|
||||
const signalData = props.data[simulator].output.values[widgetSignal.index];
|
||||
const signalData = props.data[ic].output.values[widgetSignal.index];
|
||||
if (signalData != null && state.value !== signalData[signalData.length - 1].y) {
|
||||
return { value: signalData[signalData.length - 1].y };
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class WidgetPlotTable extends Component {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
|
||||
if (this.props.simulationModel == null) {
|
||||
if (this.props.config == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -64,18 +64,18 @@ class WidgetPlotTable extends Component {
|
|||
}
|
||||
|
||||
updatePreselectedSignalsState(props) {
|
||||
// Create checkboxes using the signal indices from simulation model
|
||||
if(props.simulationModel.outputMapping){
|
||||
const preselectedSignals = props.simulationModel.outputMapping.reduce(
|
||||
// Loop through simulation model signals
|
||||
(accum, model_signal, signal_index) => {
|
||||
// Create checkboxes using the signal indices from component config
|
||||
if(props.config.outputMapping){
|
||||
const preselectedSignals = props.config.outputMapping.reduce(
|
||||
// Loop through component config signals
|
||||
(accum, signal, signal_index) => {
|
||||
// Append them if they belong to the current selected type
|
||||
if (props.widget.customProperties.preselectedSignals.indexOf(signal_index) > -1) {
|
||||
accum.push(
|
||||
{
|
||||
index: signal_index,
|
||||
name: model_signal.name,
|
||||
type: model_signal.type
|
||||
name: signal.name,
|
||||
type: signal.type
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -98,21 +98,21 @@ class WidgetPlotTable extends Component {
|
|||
let checkBoxes = [];
|
||||
|
||||
// Data passed to plot
|
||||
if (this.props.simulationModel == null) {
|
||||
if (this.props.config == null) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
const simulator = this.props.simulationModel.simulator;
|
||||
let simulatorData = [];
|
||||
const ic = this.props.config.icID;
|
||||
let icData = [];
|
||||
|
||||
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) => (
|
||||
if (this.props.data[ic] != null && this.props.data[ic].output != null && this.props.data[ic].output.values != null) {
|
||||
icData = this.props.data[ic].output.values.filter((values, index) => (
|
||||
this.props.widget.customProperties.signals.findIndex(value => value === index) !== -1
|
||||
));
|
||||
}
|
||||
|
||||
if (this.state.preselectedSignals && this.state.preselectedSignals.length > 0) {
|
||||
// Create checkboxes using the signal indices from simulation model
|
||||
// Create checkboxes using the signal indices from component config
|
||||
checkBoxes = this.state.preselectedSignals.map( (signal) => {
|
||||
var checked = this.state.signals.indexOf(signal.index) > -1;
|
||||
var chkBxClasses = classNames({
|
||||
|
@ -151,7 +151,7 @@ class WidgetPlotTable extends Component {
|
|||
|
||||
<div className="widget-plot">
|
||||
<Plot
|
||||
data={simulatorData}
|
||||
data={icData}
|
||||
time={this.props.widget.customProperties.time}
|
||||
width={this.props.widget.width - 100}
|
||||
height={this.props.widget.height - 55}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
/**
|
||||
* File: plot.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 08.03.2017
|
||||
*
|
||||
* This file is part of VILLASweb.
|
||||
*
|
||||
* VILLASweb is free software: you can redistribute it and/or modify
|
||||
|
@ -37,27 +33,27 @@ class WidgetPlot extends React.Component {
|
|||
|
||||
static getDerivedStateFromProps(props, state){
|
||||
|
||||
if (props.simulationModel == null) {
|
||||
if (props.config == null) {
|
||||
return{
|
||||
data: [],
|
||||
legend: [],
|
||||
};
|
||||
}
|
||||
|
||||
const simulator = props.simulationModel.simulator;
|
||||
const ic = props.config.icID;
|
||||
|
||||
// Proceed if a simulation with models and a simulator are available
|
||||
if (simulator && props.data[simulator] != null && props.data[simulator] != null && props.data[simulator].output != null && props.data[simulator].output.values != null) {
|
||||
// Proceed if a config and a IC are available
|
||||
if (ic && props.data[ic] != null && props.data[ic] != null && props.data[ic].output != null && props.data[ic].output.values != null) {
|
||||
const chosenSignals = props.widget.customProperties.signals;
|
||||
|
||||
const data = props.data[simulator].output.values.filter((values, index) => (
|
||||
const data = props.data[ic].output.values.filter((values, index) => (
|
||||
props.widget.customProperties.signals.findIndex(value => value === index) !== -1
|
||||
));
|
||||
|
||||
// Query the signals that will be displayed in the legend
|
||||
const legend = props.simulationModel.outputMapping.reduce( (accum, model_signal, signal_index) => {
|
||||
const legend = props.config.outputMapping.reduce( (accum, signal, signal_index) => {
|
||||
if (chosenSignals.includes(signal_index)) {
|
||||
accum.push({ index: signal_index, name: model_signal.name, type: model_signal.type });
|
||||
accum.push({ index: signal_index, name: signal.name, type: signal.type });
|
||||
}
|
||||
|
||||
return accum;
|
||||
|
|
|
@ -47,7 +47,7 @@ class WidgetTable extends Component {
|
|||
}
|
||||
|
||||
|
||||
const simulator = props.simulatorIDs[0];
|
||||
const ICid = props.icIDs[0];
|
||||
let widgetSignals = props.signals.find(sig => {
|
||||
for (let id of props.widget.signalIDs){
|
||||
if (id === sig.id){
|
||||
|
@ -59,10 +59,10 @@ class WidgetTable extends Component {
|
|||
|
||||
// check data
|
||||
if (props.data == null
|
||||
|| props.data[simulator] == null
|
||||
|| props.data[simulator].output == null
|
||||
|| props.data[simulator].output.values.length === 0
|
||||
|| props.data[simulator].output.values[0].length === 0) {
|
||||
|| props.data[ICid] == null
|
||||
|| props.data[ICid].output == null
|
||||
|| props.data[ICid].output.values.length === 0
|
||||
|| props.data[ICid].output.values[0].length === 0) {
|
||||
|
||||
// clear values
|
||||
return{
|
||||
|
@ -75,7 +75,7 @@ class WidgetTable extends Component {
|
|||
// get rows
|
||||
const rows = [];
|
||||
|
||||
props.data[simulator].output.values.forEach((signal, index) => {
|
||||
props.data[ICid].output.values.forEach((signal, index) => {
|
||||
let s = widgetSignals.find( sig => sig.index === index);
|
||||
// if the signal is used by the widget
|
||||
if (s !== undefined) {
|
||||
|
@ -91,7 +91,7 @@ class WidgetTable extends Component {
|
|||
return {
|
||||
showUnit: props.showUnit,
|
||||
rows: rows,
|
||||
sequence: props.data[simulator].output.sequence
|
||||
sequence: props.data[ICid].output.sequence
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,14 @@ class WidgetValue extends Component {
|
|||
return null;
|
||||
}
|
||||
|
||||
const simulator = props.simulatorIDs[0];
|
||||
// TODO does the following line make sense?
|
||||
const ICid = props.icIDs[0];
|
||||
|
||||
// update value
|
||||
if (props.data == null
|
||||
|| props.data[simulator] == null
|
||||
|| props.data[simulator].output == null
|
||||
|| props.data[simulator].output.values == null) {
|
||||
|| props.data[ICid] == null
|
||||
|| props.data[ICid].output == null
|
||||
|| props.data[ICid].output.values == null) {
|
||||
return{ value: '' };
|
||||
}
|
||||
|
||||
|
@ -56,7 +57,7 @@ class WidgetValue extends Component {
|
|||
}
|
||||
|
||||
// check if value has changed
|
||||
const signalData = props.data[simulator].output.values[signal.index];
|
||||
const signalData = props.data[ICid].output.values[signal.index];
|
||||
if (signalData != null && state.value !== signalData[signalData.length - 1].y) {
|
||||
return {
|
||||
value: signalData[signalData.length - 1].y,
|
||||
|
|
Loading…
Add table
Reference in a new issue