1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/web/ synced 2025-03-09 00:00:01 +01:00

WIP resolving dependencies of widgets on simulation models (use signals instead)

This commit is contained in:
Sonja Happ 2020-02-19 15:04:37 +01:00
parent 937bda8f1c
commit 87be9069f1
15 changed files with 244 additions and 253 deletions

View file

@ -33,7 +33,8 @@ 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 SimulationModelStore from '../simulationmodel/simulation-model-store';
import SignalStore from '../signal/signal-store'
import FileStore from '../file/file-store';
import WidgetStore from '../widget/widget-store';
import AppDispatcher from '../common/app-dispatcher';
@ -44,7 +45,7 @@ class Dashboard extends Component {
static lastWidgetKey = 0;
static getStores() {
return [ DashboardStore, SimulationModelStore, FileStore, LoginStore, WidgetStore ];
return [ DashboardStore, FileStore, LoginStore, WidgetStore, SignalStore ];
}
static calculateState(prevState, props) {
@ -75,15 +76,18 @@ class Dashboard extends Component {
return thisWidgetHeight > maxHeightSoFar? thisWidgetHeight : maxHeightSoFar;
}, 0);
let simulationModels = [];
//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();
return {
dashboard,
widgets,
simulationModels,
signals,
sessionToken: sessionToken,
files: null,
@ -398,7 +402,14 @@ class Dashboard extends Component {
)}
<EditWidget sessionToken={this.state.sessionToken} show={this.state.editModal} onClose={this.closeEdit.bind(this)} widget={this.state.modalData} simulationModels={this.state.simulationModels} files={this.state.files} />
<EditWidget
sessionToken={this.state.sessionToken}
show={this.state.editModal}
onClose={this.closeEdit.bind(this)}
widget={this.state.modalData}
signals={this.state.signals}
files={this.state.files}
/>
</div>

View file

@ -38,7 +38,7 @@ import EditWidgetMinMaxControl from './edit-widget-min-max-control';
import EditWidgetHTMLContent from './edit-widget-html-content';
import EditWidgetParametersControl from './edit-widget-parameters-control';
export default function CreateControls(widgetType = null, widget = null, sessionToken = null, files = null, validateForm, simulationModels, handleChange) {
export default function CreateControls(widgetType = null, widget = null, sessionToken = null, files = null, validateForm, signals, handleChange) {
// Use a list to concatenate the controls according to the widget type
var DialogControls = [];
@ -47,54 +47,47 @@ export default function CreateControls(widgetType = null, widget = null, session
DialogControls.push(
<EditWidgetTextControl key={0} widget={widget} controlId={'name'} label={'Text'} placeholder={'Enter text'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetTextControl key={1} widget={widget} controlId={'icon'} label={'Icon'} placeholder={'Enter an awesome font icon name'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetSimulationControl key={2} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetParametersControl key={3} widget={widget} controlId={'actions'} label={'Actions'} handleChange={(e) => handleChange(e)} />
)
<EditWidgetParametersControl key={2} widget={widget} controlId={'actions'} label={'Actions'} handleChange={(e) => handleChange(e)} />
);
break;
case 'Action':
DialogControls.push(
<EditWidgetSimulationControl key={0} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />
)
<EditWidgetSignalControl key={0} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
);
break;
case 'Value':
let valueBoundOnChange = (e) => {
handleChange([e, {target: {id: 'signal', value: 0}}]);
}
};
DialogControls.push(
<EditWidgetTextControl key={0} widget={widget} controlId={'name'} label={'Text'} placeholder={'Enter text'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetSimulationControl key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => valueBoundOnChange(e)} />,
<EditWidgetSignalControl key={2} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextSizeControl key={3} widget={widget} handleChange={e => handleChange(e)} />,
<EditWidgetCheckboxControl key={4} widget={widget} controlId={'showUnit'} text="Show unit" handleChange={e => handleChange(e)} />
<EditWidgetSignalControl key={1} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextSizeControl key={2} widget={widget} handleChange={e => handleChange(e)} />,
<EditWidgetCheckboxControl key={3} widget={widget} controlId={'showUnit'} text="Show unit" handleChange={e => handleChange(e)} />
);
break;
case 'Lamp':
let lampBoundOnChange = (e) => {
handleChange([e, {target: {id: 'signal', value: 0}}]);
}
};
DialogControls.push(
<EditWidgetSimulationControl key={0} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => lampBoundOnChange(e)} />,
<EditWidgetSignalControl key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={2} widget={widget} controlId={'threshold'} label={'Threshold'} placeholder={'0.5'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetColorControl key={3} widget={widget} controlId={'on_color'} label={'Color On'} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetColorControl key={4} widget={widget} controlId={'off_color'} label={'Color Off'} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetSignalControl key={0} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={1} widget={widget} controlId={'threshold'} label={'Threshold'} placeholder={'0.5'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetColorControl key={2} widget={widget} controlId={'on_color'} label={'Color On'} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetColorControl key={3} widget={widget} controlId={'off_color'} label={'Color Off'} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
);
break;
case 'Plot':
let plotBoundOnChange = (e) => {
handleChange([e, {target: {id: 'signals', value: []}}]);
}
DialogControls.push(
<EditWidgetTimeControl key={0} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetSimulationControl key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => plotBoundOnChange(e)} />,
<EditWidgetSignalsControl key={2} controlId={'signals'} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={3} controlId={'ylabel'} label={'Y-Axis name'} placeholder={'Enter a name for the y-axis'} widget={widget} handleChange={(e) => handleChange(e)} />,
<EditWidgetMinMaxControl key={4} widget={widget} controlId="y" handleChange={e => handleChange(e)} />
<EditWidgetTimeControl key={0} widget={widget} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetSignalsControl key={1} controlId={'signalIDs'} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={2} controlId={'ylabel'} label={'Y-Axis name'} placeholder={'Enter a name for the y-axis'} widget={widget} handleChange={(e) => handleChange(e)} />,
<EditWidgetMinMaxControl key={3} widget={widget} controlId="y" handleChange={e => handleChange(e)} />
);
break;
case 'Table':
DialogControls.push(
<EditWidgetSimulationControl key={0} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetSignalsControl key={0} controlId={'signalIDs'} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={1} widget={widget} controlId={'showUnit'} text="Show unit" handleChange={e => handleChange(e)} />
);
break;
@ -102,59 +95,55 @@ export default function CreateControls(widgetType = null, widget = null, session
// Restrict to only image file types (MIME)
let imageControlFiles = files == null? [] : files.filter(file => file.type.includes('image'));
DialogControls.push(
<EditImageWidgetControl key={0} sessionToken={sessionToken} widget={widget} files={imageControlFiles} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditImageWidgetControl key={0} sessionToken={sessionToken} widget={widget} files={imageControlFiles} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetAspectControl key={1} widget={widget} handleChange={e => handleChange(e)} />
);
break;
case 'Gauge':
let gaugeBoundOnChange = (e) => {
handleChange([e, {target: {id: 'signal', value: ''}}]);
}
};
DialogControls.push(
<EditWidgetTextControl key={0} widget={widget} controlId={'name'} label={'Text'} placeholder={'Enter text'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetSimulationControl key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => gaugeBoundOnChange(e) } />,
<EditWidgetSignalControl key={2} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={3} widget={widget} controlId="colorZones" text="Show color zones" handleChange={e => handleChange(e)} />,
<EditWidgetColorZonesControl key={4} widget={widget} handleChange={e => handleChange(e)} />,
<EditWidgetMinMaxControl key={5} widget={widget} controlId="value" handleChange={e => handleChange(e)} />
<EditWidgetSignalControl key={1} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={2} widget={widget} controlId="colorZones" text="Show color zones" handleChange={e => handleChange(e)} />,
<EditWidgetColorZonesControl key={3} widget={widget} handleChange={e => handleChange(e)} />,
<EditWidgetMinMaxControl key={4} widget={widget} controlId="value" handleChange={e => handleChange(e)} />
);
break;
case 'PlotTable':
let plotTableBoundOnChange = (e) => {
handleChange([e, {target: {id: 'preselectedSignals', value: []}}]);
}
handleChange([e, {target: {id: 'signalIDs', value: []}}]);
};
DialogControls.push(
<EditWidgetSimulationControl key={0} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => plotTableBoundOnChange(e)} />,
<EditWidgetSignalsControl key={1} controlId={'preselectedSignals'} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={2} controlId={'ylabel'} label={'Y-Axis'} placeholder={'Enter a name for the Y-axis'} widget={widget} handleChange={(e) => handleChange(e)} />,
<EditWidgetTimeControl key={3} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetMinMaxControl key={4} widget={widget} controlId="y" handleChange={e => handleChange(e)} />
<EditWidgetSignalsControl key={0} controlId={'signalIDs'} widget={widget} validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={1} controlId={'ylabel'} label={'Y-Axis'} placeholder={'Enter a name for the Y-axis'} widget={widget} handleChange={(e) => handleChange(e)} />,
<EditWidgetTimeControl key={2} widget={widget} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetMinMaxControl key={3} widget={widget} controlId="y" handleChange={e => handleChange(e)} />
);
break;
case 'Slider':
DialogControls.push(
<EditWidgetTextControl key={0} widget={widget} controlId={'name'} label={'Text'} placeholder={'Enter text'} handleChange={e => handleChange(e)} validate={id => validateForm(id)} />,
<EditWidgetOrientation key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetSimulationControl key={2} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetSignalControl key={3} widget={widget} input validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={4} text={'Continous Update'} controlId={'continous_update'} widget={widget} input simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={5} widget={widget} controlId={'showUnit'} text="Show unit" handleChange={e => handleChange(e)} />,
<EditWidgetMinMaxControl key={6} widget={widget} controlId={'range'} handleChange={e => handleChange(e)} />,
<EditWidgetNumberControl key={7} widget={widget} controlId={'step'} label={'Step Size'} defaultValue={0.1} handleChange={(e) => handleChange(e)} />,
<EditWidgetNumberControl key={8} widget={widget} controlId={'default_value'} label={'Default Value'} defaultValue={50} handleChange={(e) => handleChange(e)} />
<EditWidgetOrientation key={1} widget={widget} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />,
<EditWidgetSignalControl key={2} widget={widget} input validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={3} text={'Continous Update'} controlId={'continous_update'} widget={widget} input handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={4} widget={widget} controlId={'showUnit'} text="Show unit" handleChange={e => handleChange(e)} />,
<EditWidgetMinMaxControl key={5} widget={widget} controlId={'range'} handleChange={e => handleChange(e)} />,
<EditWidgetNumberControl key={6} widget={widget} controlId={'step'} label={'Step Size'} defaultValue={0.1} handleChange={(e) => handleChange(e)} />,
<EditWidgetNumberControl key={7} widget={widget} controlId={'default_value'} label={'Default Value'} defaultValue={50} handleChange={(e) => handleChange(e)} />
);
break;
case 'Button':
let buttonBoundOnChange = (e) => {
handleChange([e, {target: {id: 'signal', value: 0}}]);
}
};
DialogControls.push(
<EditWidgetTextControl key={0} widget={widget} controlId={'name'} label={'Text'} placeholder={'Enter text'} handleChange={e => handleChange(e)} validate={id => validateForm(id)} />,
<EditWidgetSimulationControl key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => buttonBoundOnChange(e)} />,
<EditWidgetSignalControl key={2} widget={widget} controlId={'signal'} input validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={3} widget={widget} controlId={'toggle'} text="Toggle" handleChange={e => handleChange(e)} />,
<EditWidgetNumberControl key={4} widget={widget} controlId={'on_value'} label={'On Value'} defaultValue={1} handleChange={(e) => handleChange(e)} />,
<EditWidgetNumberControl key={5} widget={widget} controlId={'off_value'} label={'Off Value'} defaultValue={0} handleChange={(e) => handleChange(e)} />
<EditWidgetSignalControl key={1} widget={widget} input validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetCheckboxControl key={2} widget={widget} controlId={'toggle'} text="Toggle" handleChange={e => handleChange(e)} />,
<EditWidgetNumberControl key={3} widget={widget} controlId={'on_value'} label={'On Value'} defaultValue={1} handleChange={(e) => handleChange(e)} />,
<EditWidgetNumberControl key={4} widget={widget} controlId={'off_value'} label={'Off Value'} defaultValue={0} handleChange={(e) => handleChange(e)} />
);
break;
case 'Box':
@ -179,18 +168,17 @@ export default function CreateControls(widgetType = null, widget = null, session
// Restrict to only xml files (MIME)
let topologyControlFiles = files == null? [] : files.filter( file => file.type.includes('xml'));
DialogControls.push(
<EditImageWidgetControl key={0} sessionToken={sessionToken} widget={widget} files={topologyControlFiles} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />
<EditImageWidgetControl key={0} sessionToken={sessionToken} widget={widget} files={topologyControlFiles} validate={(id) => validateForm(id)} handleChange={(e) => handleChange(e)} />
);
break;
case 'Input':
let inputBoundOnChange = (e) => {
handleChange([e, {target: {id: 'signal', value: 0}}]);
}
};
DialogControls.push(
<EditWidgetTextControl key={0} widget={widget} controlId={'name'} label={'Text'} placeholder={'Enter text'} validate={id => validateForm(id)} handleChange={e => handleChange(e)} />,
<EditWidgetSimulationControl key={1} widget={widget} validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => inputBoundOnChange(e)} />,
<EditWidgetSignalControl key={2} widget={widget} controlId={'signal'} input validate={(id) => validateForm(id)} simulationModels={simulationModels} handleChange={(e) => handleChange(e)} />
<EditWidgetSignalControl key={2} widget={widget} input validate={(id) => validateForm(id)} signals={signals} handleChange={(e) => handleChange(e)} />
);
break;

View file

@ -27,9 +27,7 @@ class EditWidgetSignalControl extends Component {
super(props);
this.state = {
widget: {
simulationModel: ''
}
widget: {}
};
}
@ -40,28 +38,17 @@ class EditWidgetSignalControl extends Component {
}
render() {
const simulationModel = this.props.simulationModels.find(m => m._id === this.state.widget.simulationModel);
let signalsToRender = [];
if (simulationModel != null) {
if (this.props.input) {
signalsToRender = simulationModel ? simulationModel.inputMapping : [];
} else {
signalsToRender = simulationModel ? simulationModel.outputMapping : [];
}
}
return (
<FormGroup controlId="signal">
<FormLabel>Signal</FormLabel>
<FormControl as="select" placeholder="Select signal" value={this.state.widget.signal} onChange={(e) => this.props.handleChange(e)}>
<FormControl as="select" placeholder="Select signal" value={this.props.widget.signalIDs[0]} onChange={(e) => this.props.handleChange(e)}>
{
signalsToRender.length === 0 ? (
this.props.signals.length === 0 ? (
<option disabled value style={{ display: 'none' }}>No signals available.</option>
) : (
signalsToRender.map((signal, index) => (
<option key={index} value={index}>{signal.name}</option>
this.props.signals.map((signal, index) => (
<option key={index} value={signal.id}>{signal.name}</option>
))
)
}

View file

@ -27,9 +27,7 @@ class EditWidgetSignalsControl extends Component {
super(props);
this.state = {
widget: {
simulator: {}
}
widget: { }
};
}
@ -39,40 +37,31 @@ class EditWidgetSignalsControl extends Component {
};
}
handleSignalChange(checked, index) {
var signals = this.state.widget[this.props.controlId];
handleSignalChange(checked, signalID) {
var signals = this.state.widget.signalIDs;
var new_signals;
if (checked) {
// add signal
new_signals = signals.concat(index);
new_signals = signals.concat(signalID);
} else {
// remove signal
new_signals = signals.filter( (idx) => idx !== index );
new_signals = signals.filter( (id) => id !== signalID );
}
this.props.handleChange({ target: { id: this.props.controlId, value: new_signals } });
}
render() {
const simulationModel = this.props.simulationModels.find(m => m._id === this.state.widget.simulationModel);
let signalsToRender = [];
if (simulationModel != null) {
// If simulation model update the signals to render
signalsToRender = simulationModel ? simulationModel.outputMapping : [];
}
return (
<FormGroup>
<FormLabel>Signals</FormLabel>
{
signalsToRender.length === 0 || !this.state.widget.hasOwnProperty(this.props.controlId)? (
this.props.signals === 0 || !this.state.widget.hasOwnProperty(this.props.controlId)? (
<FormLabel>No signals available</FormLabel>
) : (
signalsToRender.map((signal, index) => (
<FormCheck key={index} checked={this.state.widget[this.props.controlId].indexOf(index) !== -1} onChange={(e) => this.handleSignalChange(e.target.checked, index)}>{signal.name}</FormCheck>
this.props.signals.map((signal, index) => (
<FormCheck key={signal.id} checked={this.state.widget.signalIDs.indexOf(signal.id) !== -1} onChange={(e) => this.handleSignalChange(e.target.checked, signal.id)}>{signal.name}</FormCheck>
))
)
}

View file

@ -69,7 +69,7 @@ class EditWidgetDialog extends React.Component {
handleChange(e) {
// TODO: check what we really need in this function. Can we reduce its complexity?
if (e.constructor === Array) {
if (e.constructor === Array) {
// Every property in the array will be updated
let changes = e.reduce( (changesObject, event) => {
changesObject[event.target.id] = event.target.value;
@ -80,46 +80,42 @@ class EditWidgetDialog extends React.Component {
this.setState({ temporal: Object.assign({}, this.state.temporal, changes ) });
}
if(e.target.type !== 'text'){
let changeObject = {};
if (e.target.id === 'lockAspect') {
changeObject[e.target.id] = e.target.checked;
if(e.target.type !== 'text'){
let changeObject = {};
if (e.target.id === 'lockAspect') {
changeObject[e.target.id] = e.target.checked;
// correct image aspect if turned on
if (e.target.checked) {
changeObject = this.assignAspectRatio(changeObject, this.state.temporal.file);
}
} else if (e.target.id === 'file') {
changeObject[e.target.id] = e.target.value;
// get file and update size (if it's an image)
if ('lockAspect' in this.state.temporal && this.state.temporal.lockAspect) {
changeObject = this.assignAspectRatio(changeObject, e.target.value);
}
} else if (e.target.type === 'checkbox') {
changeObject[e.target.id] = e.target.checked;
} else if (e.target.type === 'number') {
changeObject[e.target.id] = Number(e.target.value);
// correct image aspect if turned on
if (e.target.checked) {
changeObject = this.assignAspectRatio(changeObject, this.state.temporal.file);
}
} else if (e.target.id === 'file') {
changeObject[e.target.id] = e.target.value;
else {
changeObject[e.target.id] = e.target.value;
// get file and update size (if it's an image)
if ('lockAspect' in this.state.temporal && this.state.temporal.lockAspect) {
changeObject = this.assignAspectRatio(changeObject, e.target.value);
}
} else if (e.target.type === 'checkbox') {
changeObject[e.target.id] = e.target.checked;
} else if (e.target.type === 'number') {
changeObject[e.target.id] = Number(e.target.value);
} else {
changeObject[e.target.id] = e.target.value;
}
let finalChange = this.state.temporal;
finalChange.customProperties[e.target.id] = changeObject[e.target.id];
this.setState({ temporal: finalChange});
} else {
if(this.state.temporal[e.target.id]){
let finalChange = this.state.temporal;
finalChange.customProperties[e.target.id] = changeObject[e.target.id];
finalChange[e.target.id] = e.target.value;
this.setState({ temporal: finalChange});
}
else{
if(this.state.temporal[e.target.id]){
let finalChange = this.state.temporal;
finalChange[e.target.id] = e.target.value;
this.setState({ temporal: finalChange});
}
}
}
}
resetState() {
@ -151,7 +147,7 @@ class EditWidgetDialog extends React.Component {
this.props.sessionToken,
this.props.files,
(id) => this.validateForm(id),
this.props.simulationModels,
this.props.signals,
(e) => this.handleChange(e));
}

View file

@ -40,7 +40,7 @@ class WidgetArea extends React.Component {
position.x = this.snapToGrid(position.x);
position.y = this.snapToGrid(position.y);
const widget = WidgetFactory.createWidgetOfType(item.name, position, this.props.defaultSimulationModel);
const widget = WidgetFactory.createWidgetOfType(item.name, position);
if (this.props.onWidgetAdded != null) {
this.props.onWidgetAdded(widget);
@ -66,7 +66,6 @@ WidgetArea.propTypes = {
children: PropTypes.node, //TODO is .node correct here? Was .children before leading to compile error
editing: PropTypes.bool,
grid: PropTypes.number,
defaultSimulationModel: PropTypes.string,
//widgets: PropTypes.array,
onWidgetAdded: PropTypes.func
};

View file

@ -25,7 +25,7 @@ import WidgetSlider from './widgets/slider';
class WidgetFactory {
static createWidgetOfType(type, position, defaultSimulationModel = null) {
static createWidgetOfType(type, position) {
let widget = {
name: 'Name',
@ -36,7 +36,8 @@ class WidgetFactory {
y: position.y,
z: position.z,
locked: false,
customProperties: {}
customProperties: {},
signalIDs: [],
};
// set type specific properties
@ -60,14 +61,10 @@ class WidgetFactory {
widget.customProperties.icon = 'star';
widget.width = 100;
widget.height = 50;
widget.customProperties.simulationModel = defaultSimulationModel;
break;
case 'Action':
widget.customProperties.simulationModel = defaultSimulationModel;
break;
case 'Lamp':
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signal = 0;
widget.minWidth = 5;
widget.minHeight = 5;
widget.width = 20;
@ -77,8 +74,6 @@ class WidgetFactory {
widget.customProperties.threshold = 0.5;
break;
case 'Value':
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signal = 0;
widget.minWidth = 70;
widget.minHeight = 20;
widget.width = 120;
@ -88,8 +83,6 @@ class WidgetFactory {
widget.customProperties.showUnit = false;
break;
case 'Plot':
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signals = [ 0 ];
widget.customProperties.ylabel = '';
widget.customProperties.time = 60;
widget.minWidth = 400;
@ -101,7 +94,6 @@ class WidgetFactory {
widget.customProperties.yUseMinMax = false;
break;
case 'Table':
widget.customProperties.simulationModel = defaultSimulationModel;
widget.minWidth = 200;
widget.width = 300;
widget.height = 200;
@ -116,9 +108,6 @@ class WidgetFactory {
widget.customProperties.fontColor = 0;
break;
case 'PlotTable':
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.preselectedSignals = [];
widget.customProperties.signals = []; // initialize selected signals
widget.customProperties.ylabel = '';
widget.minWidth = 200;
widget.minHeight = 100;
@ -143,16 +132,12 @@ class WidgetFactory {
widget.height = 100;
widget.customProperties.background_color = 1;
widget.customProperties.font_color = 0;
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signal = 0;
break;
case 'Input':
widget.minWidth = 200;
widget.minHeight = 50;
widget.width = 200;
widget.height = 50;
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signal = 0;
break;
case 'Slider':
widget.minWidth = 380;
@ -160,17 +145,13 @@ class WidgetFactory {
widget.width = 400;
widget.height = 50;
widget.customProperties.orientation = WidgetSlider.OrientationTypes.HORIZONTAL.value; // Assign default orientation
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signal = 0;
widget.customProperties.rangeMin = 0;
widget.customProperties.rangeMax = 200;
widget.customProperties.rangeUseMinMax = true;
widget.customProperties.showUnit = true
widget.customProperties.showUnit = true;
break;
case 'Gauge':
widget.customProperties.simulationModel = defaultSimulationModel;
widget.customProperties.signal = 0;
widget.minWidth = 100;
widget.minHeight = 150;
widget.width = 150;

View file

@ -27,6 +27,7 @@ import LoginStore from '../user/login-store';
import SimulatorDataStore from '../simulator/simulator-data-store';
import SimulationModelStore from '../simulationmodel/simulation-model-store';
import FileStore from '../file/file-store';
import SignalStore from '../signal/signal-store'
import EditableWidgetContainer from './editable-widget-container';
import WidgetContainer from './widget-container';
@ -52,7 +53,7 @@ import '../styles/widgets.css';
class Widget extends React.Component {
static getStores() {
return [ SimulatorDataStore, SimulationModelStore, FileStore, LoginStore ];
return [ SimulatorDataStore, SimulationModelStore, FileStore, LoginStore, SignalStore];
}
static calculateState(prevState, props) {
@ -67,10 +68,25 @@ class Widget extends React.Component {
simulatorData = SimulatorDataStore.getState();
}
// Get the simulator IDs and signal indexes for all signals of the widget
let simulationModels = SimulationModelStore.getState();
// TODO make sure that the signals are only the signals that belong to the scenario at hand
let signals = SignalStore.getState();
let simulatorIDs = [];
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;
}
}
return {
simulatorData,
signals: signals,
simulatorIDs: simulatorIDs,
files: FileStore.getState(),
simulationModels: SimulationModelStore.getState(),
sequence: prevState != null ? prevState.sequence + 1 : 0,
@ -90,71 +106,53 @@ class Widget extends React.Component {
});*/
// TODO no not load simulation models here, since they are loaded via the scenario, pass them as props
/*
AppDispatcher.dispatch({
type: 'simulationModels/start-load',
token: this.state.sessionToken,
param: '?scenarioID=1' // TODO do not hardcode scenarioID!
});
*/
}
inputDataChanged(widget, data) {
let simulationModel = null;
for (let model of this.state.simulationModels) {
if (model.id !== widget.simulationModel) {
continue;
}
simulationModel = model;
}
// The following assumes that a widget modifies/ uses exactly one signal
AppDispatcher.dispatch({
type: 'simulatorData/inputChanged',
simulator: simulationModel.simulator,
signal: widget.signal,
simulator: this.state.simulatorIDs[0],
signal: this.state.signals[0].index,
data
});
}
createWidget(widget) {
let simulationModel = null;
for (let model of this.state.simulationModels) {
if (model.id !== widget.simulationModel) {
continue;
}
simulationModel = model;
}
if (widget.type === 'CustomAction') {
return <WidgetCustomAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulationModel={simulationModel} />
return <WidgetCustomAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
} else if (widget.type === 'Action') {
return <WidgetAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulationModel={simulationModel}/>
return <WidgetAction widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} />
} else if (widget.type === 'Lamp') {
return <WidgetLamp widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulationModel={simulationModel} />
return <WidgetLamp widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
} else if (widget.type === 'Value') {
return <WidgetValue widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulationModel={simulationModel} />
return <WidgetValue widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
} else if (widget.type === 'Plot') {
return <WidgetPlot widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulationModel={simulationModel} paused={this.props.paused} />
return <WidgetPlot widget={widget} data={this.state.simulatorData} 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} simulationModel={simulationModel} />
return <WidgetTable widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
} 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} simulationModel={simulationModel} editing={this.props.editing} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index)} paused={this.props.paused} />
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} />
} else if (widget.type === 'Image') {
return <WidgetImage widget={widget} files={this.state.files} token={this.state.sessionToken} />
} else if (widget.type === 'Button') {
return <WidgetButton widget={widget} editing={this.props.editing} simulationModel={simulationModel} onInputChanged={(value) => this.inputDataChanged(widget, value)} />
return <WidgetButton widget={widget} editing={this.props.editing} onInputChanged={(value) => this.inputDataChanged(widget, value)} signals={this.state.signals} />
} else if (widget.type === 'NumberInput') {
return <WidgetInput widget={widget} editing={this.props.editing} simulationModel={simulationModel} onInputChanged={(value) => this.inputDataChanged(widget, value)} />
return <WidgetInput widget={widget} editing={this.props.editing} onInputChanged={(value) => this.inputDataChanged(widget, value)} />
} else if (widget.type === 'Slider') {
return <WidgetSlider widget={widget} editing={this.props.editing} simulationModel={simulationModel} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index) } onInputChanged={value => this.inputDataChanged(widget, value)} />
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} simulationModel={simulationModel} />
return <WidgetGauge widget={widget} data={this.state.simulatorData} editing={this.props.editing} signals={this.state.signals} simulatorIDs={this.state.simulatorIDs} />
} else if (widget.type === 'Box') {
return <WidgetBox widget={widget} editing={this.props.editing} />
} else if (widget.type === 'HTML') {

View file

@ -41,11 +41,12 @@ class WidgetCustomAction extends Component {
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel === null)
return null; //no change
if(props.widget.signalIDs.length === 0){
return null;
}
return{
simulator: SimulatorStore.getState().find(s => s._id === props.simulationModel.simulator),
simulator: SimulatorStore.getState().find(s => s.id === props.simulatorIDs[0]),
sessionToken: LoginStore.getState().token
};
}

View file

@ -33,6 +33,7 @@ class WidgetGauge extends Component {
this.state = {
value: 0,
unit: '',
minValue: null,
maxValue: null,
};
@ -69,11 +70,21 @@ class WidgetGauge extends Component {
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{value:0};
if(props.widget.signalIDs.length === 0){
return null;
}
const simulator = props.simulationModel.simulator;
let returnState = {}
// Update unit (assuming there is exactly one signal for this widget)
let signalID = props.widget.signalIDs[0];
let widgetSignal = props.signals.find(sig => sig.id === signalID);
if(widgetSignal !== undefined){
returnState["unit"] = widgetSignal.unit;
}
const simulator = props.simulatorIDs[0];
// update value
if (props.data == null
@ -82,7 +93,7 @@ class WidgetGauge extends Component {
|| props.data[simulator].output.values == null
|| props.data[simulator].output.values.length === 0
|| props.data[simulator].output.values[0].length === 0) {
return{value:0};
returnState["value"] = 0;
}
// memorize if min or max value is updated
@ -91,11 +102,11 @@ class WidgetGauge extends Component {
let updateMaxValue = false;
// check if value has changed
const signal = props.data[simulator].output.values[props.widget.customProperties.signal];
const signalData = props.data[simulator].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 (signal != null) {
const value = Math.round(signal[signal.length - 1].y * 1e3) / 1e3;
if (signalData != null) {
const value = Math.round(signalData[signalData.length - 1].y * 1e3) / 1e3;
let minValue = null;
let maxValue = null;
if (state.value !== value && value != null) {
@ -149,7 +160,6 @@ class WidgetGauge extends Component {
}
// prepare returned state
let returnState = null;
if(updateValue === true){
returnState["value"] = value;
}
@ -160,8 +170,13 @@ class WidgetGauge extends Component {
returnState["maxValue"] = maxValue;
}
return returnState
} // if there is a signal
if (returnState !== {}){
return returnState;
}
else{
return null;
}
} // if there is signal data
}
@ -218,17 +233,12 @@ class WidgetGauge extends Component {
render() {
const componentClass = this.props.editing ? "gauge-widget editing" : "gauge-widget";
let signalType = null;
if (this.props.simulationModel != null) {
signalType = (this.props.simulationModel != null && this.props.simulationModel.outputLength > 0 && this.props.widget.customProperties.signal < this.props.simulationModel.outputLength) ? this.props.simulationModel.outputMapping[this.props.widget.customProperties.signal].type : '';
}
return (
<div className={componentClass}>
<div className="gauge-name">{this.props.widget.name}</div>
<canvas ref={node => this.gaugeCanvas = node} />
<div className="gauge-unit">{signalType}</div>
<div className="gauge-unit">{this.state.unit}</div>
<div className="gauge-value">{this.state.value}</div>
</div>
);

View file

@ -35,24 +35,31 @@ class WidgetInput extends Component {
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
if(props.widget.signalIDs.length === 0){
return null;
}
let returnState = null;
let returnState = {};
// Update value
if (props.widget.customProperties.default_value && this.state.value === undefined) {
returnState["value"] = props.widget.customProperties.default_value;
}
// Update unit
if (props.widget.customProperties.simulationModel
&& props.simulationModel.inputMapping
&& state.unit !== props.simulationModel.inputMapping[props.widget.customProperties.signal].type) {
returnState["unit"] = props.simulationModel.inputMapping[props.widget.customProperties.signal].type;
// Update unit (assuming there is exactly one signal for this widget)
let signalID = props.widget.signalIDs[0];
let signal = props.signals.find(sig => sig.id === signalID);
if(signal !== undefined){
returnState["unit"] = signal.unit;
}
return returnState;
if (returnState !== {}){
return returnState;
}
else{
return null;
}
}
valueIsChanging(newValue) {

View file

@ -34,11 +34,13 @@ class WidgetLamp extends Component {
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
if(props.widget.signalIDs.length === 0){
return{ value: ''};
}
const simulator = props.simulationModel.simulator;
const simulator = props.simulatorIDs[0];
let signalID = props.widget.signalIDs[0];
let widgetSignal = props.signals.find(sig => sig.id === signalID);
// update value
if (props.data == null
@ -49,9 +51,9 @@ class WidgetLamp extends Component {
}
// check if value has changed
const signal = props.data[simulator].output.values[props.widget.customProperties.signal];
if (signal != null && state.value !== signal[signal.length - 1].y) {
return { value: signal[signal.length - 1].y };
const signalData = props.data[simulator].output.values[widgetSignal.index];
if (signalData != null && state.value !== signalData[signalData.length - 1].y) {
return { value: signalData[signalData.length - 1].y };
}
return null;

View file

@ -39,14 +39,21 @@ class WidgetSlider extends Component {
super(props);
this.state = {
unit: 'bla',
unit: '',
};
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return null;
if(props.widget.signalIDs.length === 0){
// set value to default
if (props.widget.customProperties.default_value && state.value === undefined) {
returnState["value"] = props.widget.customProperties.default_value;
} else { // if no default available
return null;
}
}
let returnState = {};
@ -56,11 +63,11 @@ class WidgetSlider extends Component {
returnState["value"] = props.widget.customProperties.default_value;
}
// Update unit
if (props.widget.customProperties.simulationModel
&& props.simulationModel.inputMapping &&
state.unit !== props.simulationModel.inputMapping[props.widget.customProperties.signal].type) {
returnState["unit"] = props.simulationModel.inputMapping[props.widget.customProperties.signal].type;
// Update unit (assuming there is exactly one signal for this widget)
let signalID = props.widget.signalIDs[0];
let signal = props.signals.find(sig => sig.id === signalID);
if(signal !== undefined){
returnState["unit"] = signal.unit;
}
if (returnState !== {}){

View file

@ -38,14 +38,24 @@ class WidgetTable extends Component {
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
if(props.widget.signalIDs.length === 0){
return{
rows: [],
sequence: null,
};
}
const simulator = props.simulationModel.simulator;
const simulator = props.simulatorIDs[0];
let widgetSignals = props.signals.find(sig => {
for (let id of props.widget.signalIDs){
if (id === sig.id){
return true;
}
}
return false;
});
// check data
if (props.data == null
@ -62,19 +72,17 @@ class WidgetTable extends Component {
};
}
// check if new data, otherwise skip
/*if (state.sequence >= props.data[simulator.node][simulator.simulator].sequence) {
return;
}*/
// get rows
const rows = [];
props.data[simulator].output.values.forEach((signal, index) => {
if (index < props.simulationModel.outputMapping.length) {
let s = widgetSignals.find( sig => sig.index === index);
// if the signal is used by the widget
if (s !== undefined) {
// push data of the signal
rows.push({
name: props.simulationModel.outputMapping[index].name,
unit: props.simulationModel.outputMapping[index].type,
name: s.name,
unit: s.unit,
value: signal[signal.length - 1].y
});
}

View file

@ -33,26 +33,33 @@ class WidgetValue extends Component {
}
static getDerivedStateFromProps(props, state){
if (props.simulationModel == null) {
return{ value: '' };
if(props.widget.signalIDs.length === 0){
return null;
}
const simulator = props.simulationModel.simulator;
const simulator = props.simulatorIDs[0];
// update value
if (props.data == null || props.data[simulator] == null || props.data[simulator].output == null || props.data[simulator].output.values == null) {
if (props.data == null
|| props.data[simulator] == null
|| props.data[simulator].output == null
|| props.data[simulator].output.values == null) {
return{ value: '' };
}
// TODO fixme (unit)
//const unit = props.simulationModel.outputMapping[props.widget.customProperties.signal].type;
const unit = 42;
// Update unit (assuming there is exactly one signal for this widget)
let unit = '';
let signalID = props.widget.signalIDs[0];
let signal = props.signals.find(sig => sig.id === signalID);
if(signal !== undefined){
unit = signal.unit;
}
// check if value has changed
const signal = props.data[simulator].output.values[props.widget.customProperties.signal];
if (signal != null && state.value !== signal[signal.length - 1].y) {
const signalData = props.data[simulator].output.values[signal.index];
if (signalData != null && state.value !== signalData[signalData.length - 1].y) {
return {
value: signal[signal.length - 1].y,
value: signalData[signalData.length - 1].y,
unit: unit,
};
}