1
0
Fork 0
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:
Sonja Happ 2020-03-12 12:47:26 +01:00
commit 1de37c4bf1
38 changed files with 422 additions and 631 deletions

View file

@ -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);

View file

@ -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));

View file

@ -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'
};
}

View file

@ -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> : ''
}

View file

@ -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> : ''
}

View file

@ -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();

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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 });

View file

@ -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 = {

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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));

View file

@ -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;

View file

@ -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;

View file

@ -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>;
}

View file

@ -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>

View file

@ -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
});
});

View file

@ -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' });

View file

@ -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
})

View file

@ -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:

View file

@ -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
});
});

View file

@ -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();

View file

@ -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;

View file

@ -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') {

View file

@ -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>;

View file

@ -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) {

View file

@ -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 };
}

View file

@ -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}

View file

@ -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;

View file

@ -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
};
}

View file

@ -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,