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

Add edit dialog to widgets and value-widget

Data and simulation is passed properly to widgets
This commit is contained in:
Markus Grigull 2017-03-08 20:30:23 +01:00
parent 7161ea7adc
commit 24d009e214
5 changed files with 205 additions and 91 deletions

View file

@ -7,86 +7,58 @@
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
import React, { Component, PropTypes } from 'react';
import React, { Component } from 'react';
import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
import Dialog from './dialog';
class EditWidgetValueDialog extends Component {
static propTypes = {
show: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired
};
valid: false;
class EditValueWidget extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
simulator: '',
signal: 0
}
widget: {
simulator: '',
signal: 0
}
};
}
onClose(canceled) {
if (canceled === false) {
this.props.onClose(this.state);
} else {
this.props.onClose();
}
}
handleChange(e) {
this.setState({ [e.target.id]: e.target.value });
}
resetState() {
this.setState({ name: '' });
}
validateForm(target) {
// check all controls
var name = true;
if (this.state.name === '') {
name = false;
}
this.valid = name;
// return state to control
if (target === 'name') return name ? "success" : "error";
return "success";
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
}
render() {
// get selected simulation model
var simulationModel = {};
if (this.props.simulation) {
this.props.simulation.models.forEach((model) => {
if (model.simulation === this.state.widget.simulation) {
simulationModel = model;
}
});
}
return (
<Dialog show={this.props.show} title="New Visualization" buttonTitle="add" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
<form>
<FormGroup controlId="name" validationState={this.validateForm('name')}>
<ControlLabel>Name</ControlLabel>
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
<FormGroup controlId="simulator">
<ControlLabel>Simulator</ControlLabel>
<FormControl componentClass="select" placeholder="Select simulator">
<option value="RTDS">RTDS</option>
<option value="Opal">Opal</option>
</FormControl>
</FormGroup>
<FormGroup controlId="signal" validationState={this.validateForm('signal')}>
<ControlLabel>Signal</ControlLabel>
<FormControl type="text" placeholder="Enter signal" value={this.state.endpoint} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
</form>
</Dialog>
<div>
<FormGroup controlId="simulator">
<ControlLabel>Simulator</ControlLabel>
<FormControl componentClass="select" placeholder="Select simulator" value={this.state.widget.simulator} onChange={(e) => this.props.handleChange(e)}>
{this.props.simulation.models.map((model, index) => (
<option key={index} value={model.simulator}>{model.name}</option>
))}
</FormControl>
</FormGroup>
<FormGroup controlId="signal">
<ControlLabel>Signal</ControlLabel>
<FormControl componentClass="select" placeholder="Select signal" value={this.state.widget.signal} onChange={(e) => this.props.handleChange(e)}>
{simulationModel.mapping.map((signal, index) => (
<option key={index} value={index}>{simulationModel.mapping[index].name}</option>
))}
</FormControl>
</FormGroup>
</div>
);
}
}
export default EditWidgetValueDialog;
export default EditValueWidget;

View file

@ -0,0 +1,95 @@
/**
* File: edit-widget.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 08.03.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
import React, { Component, PropTypes } from 'react';
import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
import Dialog from './dialog';
import EditValueWidget from './edit-widget-value';
class EditWidgetDialog extends Component {
static propTypes = {
show: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired
};
valid: true;
constructor(props) {
super(props);
this.state = {
widget: {
name: '',
simulator: '',
signal: 0
}
};
}
onClose(canceled) {
if (canceled === false) {
this.props.onClose(this.state.widget);
} else {
this.props.onClose();
}
}
handleChange(e) {
var widget = this.state.widget;
widget[e.target.id] = e.target.value;
this.setState({ widget: widget });
console.log(this.state.widget);
}
resetState() {
this.setState({ widget: this.props.widget });
}
validateForm(target) {
// check all controls
var name = true;
if (this.state.name === '') {
name = false;
}
this.valid = name;
// return state to control
if (target === 'name') return name ? "success" : "error";
}
render() {
// get widget part
var widgetDialog = null;
if (this.props.widget && this.props.widget.type === 'Value') {
widgetDialog = <EditValueWidget widget={this.state.widget} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />;
}
return (
<Dialog show={this.props.show} title="Edit Widget" buttonTitle="save" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
<form>
<FormGroup controlId="name" validationState={this.validateForm('name')}>
<ControlLabel>Name</ControlLabel>
<FormControl type="text" placeholder="Enter name" value={this.state.widget.name} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
{widgetDialog}
</form>
</Dialog>
);
}
}
export default EditWidgetDialog;

View file

@ -9,23 +9,20 @@
import React, { Component } from 'react';
//import EditWidgetValueDialog from './dialog-edit-widget-value';
class WidgetValue extends Component {
render() {
// calculate value
var value = null;
const identifier = '58bfd9facd76830327c8b6d4';
const signal = 2;
const widget = this.props.widget;
if (this.props.data && this.props.data[identifier] && this.props.data[identifier].values) {
const signalArray = this.props.data[identifier].values[signal];
if (this.props.data && this.props.data[widget.simulator] && this.props.data[widget.simulator].values) {
const signalArray = this.props.data[widget.simulator].values[widget.signal];
value = signalArray[signalArray.length - 1].y;
}
return (
<div>
{this.props.widget.name}: {value}
{widget.name}: {value}
</div>
);
}

View file

@ -15,6 +15,7 @@ import { ContextMenu, MenuItem } from 'react-contextmenu';
import ToolboxItem from '../components/toolbox-item';
import Dropzone from '../components/dropzone';
import Widget from './widget';
import EditWidget from '../components/dialog/edit-widget';
import VisualizationStore from '../stores/visualization-store';
import ProjectStore from '../stores/project-store';
@ -27,24 +28,25 @@ class Visualization extends Component {
}
static calculateState(prevState) {
if (prevState) {
return {
visualizations: VisualizationStore.getState(),
visualization: prevState.visualization,
editing: prevState.editing,
grid: prevState.grid
};
if (prevState == null) {
prevState = {};
}
return {
visualizations: VisualizationStore.getState(),
projects: ProjectStore.getState(),
simulations: SimulationStore.getState(),
visualization: {},
simulation: null,
editing: false,
grid: false
}
visualization: prevState.visualization || {},
project: prevState.project || null,
simulation: prevState.simulation || null,
editing: prevState.editing || false,
grid: prevState.grid || false,
editModal: prevState.editModal || false,
modalData: prevState.modalData || null,
modalIndex: prevState.modalIndex || null
};
}
componentWillMount() {
@ -57,6 +59,29 @@ class Visualization extends Component {
if (this.state.visualization._id !== this.props.params.visualization) {
this.reloadVisualization();
}
// load depending project
if (this.state.project == null && this.state.projects) {
this.state.projects.forEach((project) => {
if (project._id === this.state.visualization.project) {
this.setState({ project: project, simulation: null });
AppDispatcher.dispatch({
type: 'simulations/start-load',
data: project.simulation
});
}
});
}
// load depending simulation
if (this.state.simulation == null && this.state.simulations && this.state.project) {
this.state.simulations.forEach((simulation) => {
if (simulation._id === this.state.project.simulation) {
this.setState({ simulation: simulation });
}
});
}
}
reloadVisualization() {
@ -64,7 +89,12 @@ class Visualization extends Component {
this.state.visualizations.forEach((visualization) => {
if (visualization._id === this.props.params.visualization) {
// JSON.parse(JSON.stringify(obj)) = deep clone to make also copy of widget objects inside
this.setState({ visualization: JSON.parse(JSON.stringify(visualization)) });
this.setState({ visualization: JSON.parse(JSON.stringify(visualization)), project: null });
AppDispatcher.dispatch({
type: 'projects/start-load',
data: visualization.project
});
}
});
}
@ -81,6 +111,12 @@ class Visualization extends Component {
z: 0
};
// set type specific properties
if (item.name === 'Value') {
widget.simulator = this.state.simulation.models[0].simulator;
widget.signal = 0;
}
var visualization = this.state.visualization;
visualization.widgets.push(widget);
@ -97,7 +133,19 @@ class Visualization extends Component {
}
editWidget(e, data) {
this.setState({ editModal: true, modalData: this.state.visualization.widgets[data.index], modalIndex: data.index });
}
closeEdit(data) {
if (data) {
// save changes temporarily
var visualization = this.state.visualization;
visualization.widgets[this.state.modalIndex] = data;
this.setState({ editModal: false, visualization: visualization });
} else {
this.setState({ editModal: false });
}
}
deleteWidget(e, data) {
@ -155,7 +203,7 @@ class Visualization extends Component {
<Dropzone onDrop={item => this.handleDrop(item)} editing={this.state.editing}>
{this.state.visualization.widgets != null &&
this.state.visualization.widgets.map((widget, index) => (
<Widget key={index} data={widget} onWidgetChange={(w, i) => this.widgetChange(w, i)} editing={this.state.editing} index={index} grid={this.state.grid} />
<Widget key={index} data={widget} simulation={this.state.simulation} onWidgetChange={(w, i) => this.widgetChange(w, i)} editing={this.state.editing} index={index} grid={this.state.grid} />
))}
</Dropzone>
@ -166,6 +214,8 @@ class Visualization extends Component {
<MenuItem data={{index: index}} onClick={(e, data) => this.deleteWidget(e, data)}>Delete</MenuItem>
</ContextMenu>
))}
<EditWidget show={this.state.editModal} onClose={(data) => this.closeEdit(data)} widget={this.state.modalData} simulation={this.state.simulation} />
</div>
</div>
);

View file

@ -77,14 +77,14 @@ class Widget extends Component {
resizeGrid={grid}
>
<ContextMenuTrigger id={'widgetMenu' + this.props.index} attributes={{ style: { width: '100%', height: '100%' } }}>
<WidgetValue widget={widget} data={this.state.simulatorData} sequence={this.state.sequence} />
<WidgetValue widget={widget} data={this.state.simulatorData} sequence={this.state.sequence} simulation={this.props.simulation} />
</ContextMenuTrigger>
</Rnd>
);
} else {
return (
<div className="widget" style={{ width: Number(widget.width), height: Number(widget.height), left: Number(widget.x), top: Number(widget.y), position: 'absolute' }}>
<WidgetValue widget={widget} data={this.state.simulatorData} sequence={this.state.sequence} />
<WidgetValue widget={widget} data={this.state.simulatorData} sequence={this.state.sequence} simulation={this.props.simulation} />
</div>
);
}