Commit 7331bf51 authored by Sonja Happ's avatar Sonja Happ
Browse files

cherry picked all changes from the cleanup-widgets branch and merged them to...

cherry picked all changes from the cleanup-widgets branch and merged them to the new file/ folder structure and package versions; most likely, further fixes are required to make things work. Improves #209 and #205
parent 5ecb254e
......@@ -5153,11 +5153,18 @@
}
},
"eslint-utils": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz",
"integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
"requires": {
"eslint-visitor-keys": "^1.0.0"
"eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A=="
}
}
},
"eslint-visitor-keys": {
......@@ -6048,9 +6055,9 @@
"integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ=="
},
"handlebars": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz",
"integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==",
"requires": {
"neo-async": "^2.6.0",
"optimist": "^0.6.1",
......@@ -12841,13 +12848,21 @@
"integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw=="
},
"uglify-js": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
"integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
"version": "3.6.7",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.7.tgz",
"integrity": "sha512-4sXQDzmdnoXiO+xvmTzQsfIiwrjUCSA95rSP4SEd8tDb51W2TiDOlL76Hl+Kw0Ie42PSItCW8/t6pBNCF2R48A==",
"optional": true,
"requires": {
"commander": "~2.20.0",
"commander": "~2.20.3",
"source-map": "~0.6.1"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"optional": true
}
}
},
"uncontrollable": {
......
/**
* File: dashboard-button-group.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 31.05.2018
*
* 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 from 'react';
import PropTypes from 'prop-types';
import { Button } from 'react-bootstrap';
class DashboardButtonGroup extends React.Component {
render() {
const buttonStyle = {
marginLeft: '8px'
};
const buttons = [];
let key = 0;
if (this.props.fullscreen) {
return null;
}
if (this.props.editing) {
buttons.push(
<Button key={key++} bsStyle="info" onClick={this.props.onSave} style={buttonStyle}>
<span class="glyphicon glyphicon-floppy-disk"></span> Save
</Button>,
<Button key={key++} bsStyle="info" onClick={this.props.onCancel} style={buttonStyle}>
<span class="glyphicon glyphicon-remove" ></span> Cancel
</Button>
);
} else {
if (this.props.fullscreen !== true) {
buttons.push(
<Button key={key++} bsStyle="info" onClick={this.props.onFullscreen} style={buttonStyle}>
<span className="glyphicon glyphicon-resize-full"></span> Fullscreen
</Button>
);
}
if (this.props.paused) {
buttons.push(
<Button key={key++} bsStyle="info" onClick={this.props.onUnpause} style={buttonStyle}>
<span className="glyphicon glyphicon-play"></span> Live
</Button>
);
} else {
buttons.push(
<Button key={key++} bsStyle="info" onClick={this.props.onPause} style={buttonStyle}>
<span className="glyphicon glyphicon-pause"></span> Pause
</Button>
);
}
buttons.push(
<Button key={key++} bsStyle="info" onClick={this.props.onEdit} style={buttonStyle}>
<span className="glyphicon glyphicon-pencil"></span> Pause
</Button>
);
}
return <div className='section-buttons-group-right'>
{buttons}
</div>;
}
}
DashboardButtonGroup.propTypes = {
editing: PropTypes.bool,
fullscreen: PropTypes.bool,
paused: PropTypes.bool,
onEdit: PropTypes.func,
onSave: PropTypes.func,
onCancel: PropTypes.func,
onFullscreen: PropTypes.func,
onPause: PropTypes.func,
onUnpause: PropTypes.func
};
export default DashboardButtonGroup;
This diff is collapsed.
/**
* File: widget-area.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 31.05.2018
*
* 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 from 'react';
import PropTypes from 'prop-types';
import Dropzone from './dropzone';
import Grid from './grid';
import WidgetFactory from '../widget/widget-factory';
class WidgetArea extends React.Component {
snapToGrid(value) {
if (this.props.grid === 1) {
return value;
}
return Math.round(value / this.props.grid) * this.props.grid;
}
handleDrop = (item, position) => {
position.x = this.snapToGrid(position.x);
position.y = this.snapToGrid(position.y);
const widget = WidgetFactory.createWidgetOfType(item.name, position, this.props.defaultSimulationModel);
if (this.props.onWidgetAdded != null) {
this.props.onWidgetAdded(widget);
}
}
render() {
const maxHeight = Object.values(this.props.widgets).reduce((currentHeight, widget) => {
const absolutHeight = widget.y + widget.height;
return absolutHeight > currentHeight ? absolutHeight : currentHeight;
}, 0);
return <Dropzone height={maxHeight + 80} onDrop={this.handleDrop} editing={this.props.editing}>
{this.props.children}
<Grid size={this.props.grid} disabled={this.props.grid === 1 || this.props.editing !== true} />
</Dropzone>;
}
}
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.object,
onWidgetAdded: PropTypes.func
};
WidgetArea.defaultProps = {
widgets: {}
};
export default WidgetArea;
/**
* File: widget-context-menu.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 31.05.2018
*
* 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 from 'react';
import PropTypes from 'prop-types';
import { contextMenu, Item, Separator } from 'react-contexify';
class WidgetContextMenu extends React.Component {
editWidget = event => {
if (this.props.onEdit != null) {
this.props.onEdit(this.props.widget, this.props.index);
}
};
deleteWidget = event => {
if (this.props.onDelete != null) {
this.props.onDelete(this.props.widget, this.props.index);
}
};
moveAbove = event => {
this.props.widget.z++;
if (this.props.widget.z > 100) {
this.props.widget.z = 100;
}
if (this.props.onChange != null) {
this.props.onChange(this.props.widget, this.props.index);
}
};
moveToFront = event => {
this.props.widget.z = 100;
if (this.props.onChange != null) {
this.props.onChange(this.props.widget, this.props.index);
}
};
moveUnderneath = event => {
this.props.widget.z--;
if (this.props.widget.z < 0) {
this.props.widget.z = 0;
}
if (this.props.onChange != null) {
this.props.onChange(this.props.widget, this.props.index);
}
};
moveToBack = event => {
this.props.widget.z = 0;
if (this.props.onChange != null) {
this.props.onChange(this.props.widget, this.props.index);
}
};
lockWidget = event => {
this.props.widget.locked = true;
if (this.props.onChange != null) {
this.props.onChange(this.props.widget, this.props.index);
}
};
unlockWidget = event => {
this.props.widget.locked = false;
if (this.props.onChange != null) {
this.props.onChange(this.props.widget, this.props.index);
}
};
render() {
const isLocked = this.props.widget.locked;
return <contextMenu id={'widgetMenu'+ this.props.index}>
<Item disabled={isLocked} onClick={this.editWidget}>Edit</Item>
<Item disabled={isLocked} onClick={this.deleteWidget}>Delete</Item>
<Separator />
<Item disabled={isLocked} onClick={this.moveAbove}>Move above</Item>
<Item disabled={isLocked} onClick={this.moveToFront}>Move to front</Item>
<Item disabled={isLocked} onClick={this.moveUnderneath}>Move underneath</Item>
<Item disabled={isLocked} onClick={this.moveToBack}>Move to back</Item>
<Separator />
<Item disabled={isLocked} onClick={this.lockWidget}>Lock</Item>
<Item disabled={isLocked === false} onClick={this.unlockWidget}>Unlock</Item>
</contextMenu>;
}
}
WidgetContextMenu.propTypes = {
index: PropTypes.number.isRequired,
widget: PropTypes.object.isRequired,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
onChange: PropTypes.func
};
export default WidgetContextMenu
/**
* File: widget-toolbox.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 31.05.2018
*
* 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 from 'react';
import PropTypes from 'prop-types';
import Slider from 'rc-slider';
import ToolboxItem from './toolbox-item';
class WidgetToolbox extends React.Component {
onGridChange = value => {
// value 0 would block all widgets, set 1 as 'grid disabled'
if (value === 0) {
value = 1;
}
if (this.props.onGridChange != null) {
this.props.onGridChange(value);
}
};
render() {
// Only one topology widget at the time is supported
const thereIsTopologyWidget = this.props.widgets != null && Object.values(this.props.widgets).filter(w => w.type === 'Topology').length > 0;
const topologyItemMsg = thereIsTopologyWidget? 'Currently only one is supported' : '';
return <div className='toolbox box-header'>
<ToolboxItem name='Lamp' type='widget' />
<ToolboxItem name='Value' type='widget' />
<ToolboxItem name='Plot' type='widget' />
<ToolboxItem name='Table' type='widget' />
<ToolboxItem name='Label' type='widget' />
<ToolboxItem name='Image' type='widget' />
<ToolboxItem name='PlotTable' type='widget' />
<ToolboxItem name='Button' type='widget' />
<ToolboxItem name='NumberInput' type='widget' />
<ToolboxItem name='Slider' type='widget' />
<ToolboxItem name='Gauge' type='widget' />
<ToolboxItem name='Box' type='widget' />
<ToolboxItem name='HTML' type='html' />
<ToolboxItem name='Topology' type='widget' disabled={thereIsTopologyWidget} title={topologyItemMsg}/>
<div className='section-buttons-group-right'>
<div>
<span>Grid: { this.props.grid > 1 ? this.props.grid : 'Disabled' }</span>
<Slider value={this.props.grid} style={{ width: '80px' }} step={5} onChange={this.onGridChange} />
</div>
</div>
</div>;
};
}
WidgetToolbox.propTypes = {
widgets: PropTypes.array,
grid: PropTypes.number,
onGridChange: PropTypes.func
};
export default WidgetToolbox;
/**
* File: editable-widget-container.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 31.05.2018
*
* 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 from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Rnd } from 'react-rnd';
import { contextMenu } from 'react-contexify';
class EditableWidgetContainer extends React.Component {
constructor(props) {
super(props);
this.rnd = null;
}
snapToGrid(value) {
if (this.props.grid === 1) {
return value;
}
return Math.round(value / this.props.grid) * this.props.grid;
}
borderWasClicked = event => {
if (event.button !== 2) {
return;
}
};
drag = (event, data) => {
const x = this.snapToGrid(data.x);
const y = this.snapToGrid(data.y);
if (x !== data.x || y !== data.y) {
this.rnd.updatePosition({ x, y });
}
};
dragStop = (event, data) => {
const widget = this.props.widget;
widget.x = this.snapToGrid(data.x);
widget.y = this.snapToGrid(data.y);
if (this.props.onWidgetChange != null) {
this.props.onWidgetChange(widget, this.props.index);
}
};
resizeStop = (direction, delta, ref, event) => {
const widget = this.props.widget;
// resize depends on direction
if (direction === 'left' || direction === 'topLeft' || direction === 'bottomLeft') {
widget.x -= delta.width;
}
if (direction === 'top' || direction === 'topLeft' || direction === 'topRight') {
widget.y -= delta.height;
}
widget.width += delta.width;
widget.height += delta.height;
if (this.props.onWidgetChange != null) {
this.props.onWidgetChange(widget, this.props.index);
}
};
render() {
const widget = this.props.widget;
const resizing = {
bottom: !widget.locked,
bottomLeft: !widget.locked,
bottomRight: !widget.locked,
left: !widget.locked,
right: !widget.locked,
top: !widget.locked,
topLeft: !widget.locked,
topRight: !widget.locked
};
const gridArray = [ this.props.grid, this.props.grid ];
const widgetClasses = classNames({
'editing-widget': true,
'locked': widget.locked
});
return <Rnd
ref={c => { this.rnd = c; }}
default={{ x: Number(widget.x), y: Number(widget.y), width: widget.width, height: widget.height }}
minWidth={widget.minWidth}
minHeight={widget.minHeight}
lockAspectRatio={Boolean(widget.lockAspect)}
bounds={'parent'}
className={widgetClasses}
onResizeStart={this.borderWasClicked}
onResizeStop={this.resizeStop}
onDrag={this.drag}
onDragStop={this.dragStop}
dragGrid={gridArray}
resizeGrid={gridArray}
zIndex={widget.z}
enableResizing={resizing}
disableDragging={widget.locked}
>
<contextMenu id={'widgetMenu' + this.props.index}>
{this.props.children}
</contextMenu>
</Rnd>;
}
}
EditableWidgetContainer.propTypes = {
widget: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
grid: PropTypes.number,
onWidgetChange: PropTypes.func
};
export default EditableWidgetContainer