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:
parent
6af05ccfe3
commit
6c9cc8946a
10 changed files with 79 additions and 50 deletions
|
@ -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)} />
|
||||
|
|
|
@ -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)} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)} />
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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] })} />
|
||||
|
|
|
@ -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>
|
||||
))}
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,6 @@ class SimulationDataStore extends ReduceStore {
|
|||
state[action.identifier].values.push([]);
|
||||
}
|
||||
|
||||
console.log('Socket opened');
|
||||
|
||||
return state;
|
||||
|
||||
case 'simulatorData/data-changed':
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
border: 1px solid lightgray;
|
||||
|
||||
padding: 3px 6px;
|
||||
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.react-contextmenu {
|
||||
|
|
Loading…
Add table
Reference in a new issue