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 widgets at cursor drop position, widget zIndex

Add context menu for zIndex ordering

Bug: zIndex is only applied after saving visualization
This commit is contained in:
Markus Grigull 2017-03-15 13:13:39 +01:00
parent 6af05ccfe3
commit 6c9cc8946a
10 changed files with 79 additions and 50 deletions

View file

@ -26,7 +26,6 @@ class EditSimulatorDialog extends Component {
this.state = {
name: '',
simulatorid: '1',
endpoint: '',
_id: ''
};
@ -47,7 +46,6 @@ class EditSimulatorDialog extends Component {
resetState() {
this.setState({
name: this.props.simulator.name,
simulatorid: this.props.simulator.simulatorid,
endpoint: this.props.simulator.endpoint,
_id: this.props.simulator._id
});
@ -55,7 +53,6 @@ class EditSimulatorDialog extends Component {
validateForm(target) {
// check all controls
var simulatorid = true;
var endpoint = true;
var name = true;
@ -63,20 +60,14 @@ class EditSimulatorDialog extends Component {
name = false;
}
// test if simulatorid is a number (in a string, not type of number)
if (!/^\d+$/.test(this.state.simulatorid)) {
simulatorid = false;
}
if (this.state.endpoint === '') {
endpoint = false;
}
this.valid = simulatorid && endpoint && name;
this.valid = endpoint && name;
// return state to control
if (target === 'name') return name ? "success" : "error";
else if (target === 'simulatorid') return simulatorid ? "success" : "error";
else return endpoint ? "success" : "error";
}
@ -89,11 +80,6 @@ class EditSimulatorDialog extends Component {
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
<FormGroup controlId="simulatorid" validationState={this.validateForm('simulatorid')}>
<ControlLabel>Simulator ID</ControlLabel>
<FormControl type="number" placeholder="Enter simulator ID" value={this.state.simulatorid} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
<FormGroup controlId="endpoint" validationState={this.validateForm('endpoint')}>
<ControlLabel>Endpoint</ControlLabel>
<FormControl type="text" placeholder="Enter endpoint" value={this.state.endpoint} onChange={(e) => this.handleChange(e)} />

View file

@ -15,6 +15,7 @@ import Dialog from './dialog';
import EditValueWidget from './edit-widget-value';
import EditPlotWidget from './edit-widget-plot';
import EditTableWidget from './edit-widget-table';
import EditImageWidget from './edit-widget-image';
class EditWidgetDialog extends Component {
static propTypes = {
@ -81,6 +82,8 @@ class EditWidgetDialog extends Component {
widgetDialog = <EditPlotWidget widget={this.state.widget} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />;
} else if (this.props.widget.type === 'Table') {
widgetDialog = <EditTableWidget widget={this.state.widget} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />;
} else if (this.props.widget.type === 'Image') {
widgetDialog = <EditImageWidget widget={this.state.widget} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />;
}
}

View file

@ -25,7 +25,6 @@ class NewSimulatorDialog extends Component {
this.state = {
name: '',
simulatorid: '1',
endpoint: ''
};
}
@ -43,12 +42,11 @@ class NewSimulatorDialog extends Component {
}
resetState() {
this.setState({ name: '', simulatorid: '1', endpoint: '' });
this.setState({ name: '', endpoint: '' });
}
validateForm(target) {
// check all controls
var simulatorid = true;
var endpoint = true;
var name = true;
@ -56,20 +54,14 @@ class NewSimulatorDialog extends Component {
name = false;
}
// test if simulatorid is a number (in a string, not type of number)
if (!/^\d+$/.test(this.state.simulatorid)) {
simulatorid = false;
}
if (this.state.endpoint === '') {
endpoint = false;
}
this.valid = simulatorid && endpoint && name;
this.valid = endpoint && name;
// return state to control
if (target === 'name') return name ? "success" : "error";
else if (target === 'simulatorid') return simulatorid ? "success" : "error";
else return endpoint ? "success" : "error";
}
@ -82,11 +74,6 @@ class NewSimulatorDialog extends Component {
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
<FormGroup controlId="simulatorid" validationState={this.validateForm('simulatorid')}>
<ControlLabel>Simulator ID</ControlLabel>
<FormControl type="number" placeholder="Enter simulator ID" value={this.state.simulatorid} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
<FormGroup controlId="endpoint" validationState={this.validateForm('endpoint')}>
<ControlLabel>Endpoint</ControlLabel>
<FormControl type="text" placeholder="Enter endpoint" value={this.state.endpoint} onChange={(e) => this.handleChange(e)} />

View file

@ -12,8 +12,14 @@ import { DropTarget } from 'react-dnd';
import classNames from 'classnames';
const dropzoneTarget = {
drop(props, monitor) {
props.onDrop(monitor.getItem());
drop(props, monitor, component) {
// get drop position
var position = monitor.getSourceClientOffset();
var dropzoneRect = component.wrapper.getBoundingClientRect();
position.x -= dropzoneRect.left;
position.y -= dropzoneRect.top;
props.onDrop(monitor.getItem(), position);
}
};
@ -41,7 +47,7 @@ class Dropzone extends Component {
});
return this.props.connectDropTarget(
<div className={toolboxClass}>
<div className={toolboxClass} ref={wrapper => this.wrapper = wrapper}>
{this.props.children}
</div>
);

View file

@ -79,7 +79,6 @@ class Simulators extends Component {
<Table data={this.state.simulators}>
<TableColumn title='Name' dataKey='name' />
<TableColumn title='ID' dataKey='simulatorid' width='80' />
<TableColumn title='Running' dataKey='running' width='80' />
<TableColumn title='Endpoint' dataKey='endpoint' width='120' />
<TableColumn title='' width='70' editButton deleteButton onEdit={(index) => this.setState({ editModal: true, modalSimulator: this.state.simulators[index] })} onDelete={(index) => this.setState({ deleteModal: true, modalSimulator: this.state.simulators[index] })} />

View file

@ -99,15 +99,15 @@ class Visualization extends Component {
});
}
handleDrop(item) {
handleDrop(item, position) {
// add new widget
var widget = {
name: 'Name',
type: item.name,
width: 100,
height: 100,
x: 0,
y: 0,
x: position.x,
y: position.y,
z: 0
};
@ -185,6 +185,54 @@ class Visualization extends Component {
this.forceUpdate();
}
moveWidgetAbove(e, data) {
// increase z-Order
var visualization = this.state.visualization;
var widget = visualization.widgets[data.index]
widget.z++;
visualization.widgets[data.index] = widget;
this.setState({ visualization: visualization });
this.forceUpdate();
}
moveWidgetToFront(e, data) {
// increase z-Order
var visualization = this.state.visualization;
var widget = visualization.widgets[data.index]
widget.z = 100;
visualization.widgets[data.index] = widget;
this.setState({ visualization: visualization });
this.forceUpdate();
}
moveWidgetUnderneath(e, data) {
// decrease z-Order
var visualization = this.state.visualization;
var widget = visualization.widgets[data.index]
widget.z--;
if (widget.z < 0) {
widget.z = 0;
}
visualization.widgets[data.index] = widget;
this.setState({ visualization: visualization });
this.forceUpdate();
}
moveWidgetToBack(e, data) {
// increase z-Order
var visualization = this.state.visualization;
var widget = visualization.widgets[data.index]
widget.z = 0;
visualization.widgets[data.index] = widget;
this.setState({ visualization: visualization });
this.forceUpdate();
}
render() {
return (
<div>
@ -216,7 +264,7 @@ class Visualization extends Component {
</div>
}
<Dropzone onDrop={item => this.handleDrop(item)} editing={this.state.editing}>
<Dropzone onDrop={(item, position) => this.handleDrop(item, position)} editing={this.state.editing}>
{this.state.visualization.widgets != null &&
this.state.visualization.widgets.map((widget, index) => (
<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} />
@ -228,6 +276,11 @@ class Visualization extends Component {
<ContextMenu id={'widgetMenu' + index} key={index}>
<MenuItem data={{index: index}} onClick={(e, data) => this.editWidget(e, data)}>Edit</MenuItem>
<MenuItem data={{index: index}} onClick={(e, data) => this.deleteWidget(e, data)}>Delete</MenuItem>
<MenuItem divider />
<MenuItem data={{index: index}} onClick={(e, data) => this.moveWidgetAbove(e, data)}>Move above</MenuItem>
<MenuItem data={{index: index}} onClick={(e, data) => this.moveWidgetToFront(e, data)}>Move to front</MenuItem>
<MenuItem data={{index: index}} onClick={(e, data) => this.moveWidgetUnderneath(e, data)}>Move underneath</MenuItem>
<MenuItem data={{index: index}} onClick={(e, data) => this.moveWidgetToBack(e, data)}>Move to back</MenuItem>
</ContextMenu>
))}

View file

@ -61,6 +61,8 @@ class Widget extends Component {
}
render() {
console.log('render widget ' + this.props.data.z + this.props.data.type);
// configure grid
var grid = this.props.grid;
if (!grid) {
@ -92,6 +94,7 @@ class Widget extends Component {
onDragStop={(event, ui) => this.dragStop(event, ui)}
moveGrid={grid}
resizeGrid={grid}
zIndex={widget.z}
>
<ContextMenuTrigger id={'widgetMenu' + this.props.index} attributes={{ style: { width: '100%', height: '100%' } }}>
{element}
@ -100,7 +103,7 @@ class Widget extends Component {
);
} else {
return (
<div className="widget" style={{ width: Number(widget.width), height: Number(widget.height), left: Number(widget.x), top: Number(widget.y), position: 'absolute' }}>
<div className="widget" style={{ width: Number(widget.width), height: Number(widget.height), left: Number(widget.x), top: Number(widget.y), 'zIndex': Number(widget.z), position: 'absolute' }}>
{element}
</div>
);

View file

@ -23,13 +23,9 @@ class SimulatorDataDataManager {
this._sockets.close();
this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) });
console.log('Modified socket');
}
} else {
this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) });
console.log('New socket');
}
}
@ -51,8 +47,6 @@ class SimulatorDataDataManager {
onMessage(event, identifier) {
var message = this.bufferToMessage(event.data);
//console.log(message);
AppDispatcher.dispatch({
type: 'simulatorData/data-changed',
data: message,
@ -69,7 +63,6 @@ class SimulatorDataDataManager {
let OFFSET_VERSION = 4;
var bits = data.getUint8(0);
var simulator = data.getUint8(0x01);
var endian = (bits >> OFFSET_ENDIAN) & 0x1 ? 0 : 1;
var length = data.getUint16(0x02, endian);
@ -82,8 +75,7 @@ class SimulatorDataDataManager {
length: length,
sequence: data.getUint32(0x04, endian),
timestamp: data.getUint32(0x08, endian) * 1e3 + data.getUint32(0x0C, endian) * 1e-6,
values: values,
simulator: simulator
values: values
};
}
}

View file

@ -39,8 +39,6 @@ class SimulationDataStore extends ReduceStore {
state[action.identifier].values.push([]);
}
console.log('Socket opened');
return state;
case 'simulatorData/data-changed':

View file

@ -14,6 +14,8 @@
border: 1px solid lightgray;
padding: 3px 6px;
background-color: #fff;
}
.react-contextmenu {