mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Add node dialogs and backend
This commit is contained in:
parent
6b1a8ca776
commit
232e972657
4 changed files with 256 additions and 52 deletions
98
src/components/dialog/edit-node.js
Normal file
98
src/components/dialog/edit-node.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* File: edit-node.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 06.07.2017
|
||||
*
|
||||
* 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 { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
|
||||
|
||||
import Dialog from './dialog';
|
||||
|
||||
class NewNodeDialog extends React.Component {
|
||||
valid: false;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
name: '',
|
||||
endpoint: '',
|
||||
config: {},
|
||||
simulators: [],
|
||||
_id: ''
|
||||
};
|
||||
}
|
||||
|
||||
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: this.props.node.name, endpoint: this.props.node.endpoint, config: this.props.node.config, simulators: this.props.node.simulators, _id: this.props.node._id });
|
||||
}
|
||||
|
||||
validateForm(target) {
|
||||
// check all controls
|
||||
var endpoint = true;
|
||||
var name = true;
|
||||
|
||||
if (this.state.name === '') {
|
||||
name = false;
|
||||
}
|
||||
|
||||
if (this.state.endpoint === '') {
|
||||
endpoint = false;
|
||||
}
|
||||
|
||||
this.valid = endpoint && name;
|
||||
|
||||
// return state to control
|
||||
if (target === 'name') return name ? "success" : "error";
|
||||
else return endpoint ? "success" : "error";
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Dialog show={this.props.show} title="Edit Node" 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.name} 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)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NewNodeDialog;
|
97
src/components/dialog/new-node.js
Normal file
97
src/components/dialog/new-node.js
Normal file
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* File: new-node.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 06.07.2017
|
||||
*
|
||||
* 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 { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
|
||||
|
||||
import Dialog from './dialog';
|
||||
|
||||
class NewNodeDialog extends React.Component {
|
||||
valid: false;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
name: '',
|
||||
endpoint: '',
|
||||
config: {},
|
||||
simulators: []
|
||||
};
|
||||
}
|
||||
|
||||
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: '', endpoint: '', config: {}, simulators: [] });
|
||||
}
|
||||
|
||||
validateForm(target) {
|
||||
// check all controls
|
||||
var endpoint = true;
|
||||
var name = true;
|
||||
|
||||
if (this.state.name === '') {
|
||||
name = false;
|
||||
}
|
||||
|
||||
if (this.state.endpoint === '') {
|
||||
endpoint = false;
|
||||
}
|
||||
|
||||
this.valid = endpoint && name;
|
||||
|
||||
// return state to control
|
||||
if (target === 'name') return name ? "success" : "error";
|
||||
else return endpoint ? "success" : "error";
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Dialog show={this.props.show} title="New Node" 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="endpoint" validationState={this.validateForm('endpoint')}>
|
||||
<ControlLabel>Endpoint</ControlLabel>
|
||||
<FormControl type="text" placeholder="Enter endpoint" value={this.state.endpoint} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NewNodeDialog;
|
|
@ -28,10 +28,7 @@ class NodeTree extends React.Component {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
treeData: [
|
||||
{ title: 'Chicken', subtitle: 'localhost:5000', children: [ { title: 'Egg' } ], expanded: true },
|
||||
{ title: 'Cow', subtitle: 'localhost:5001', children: [ { title: 'Milk' }, { title: 'Cheese' }], expanded: true },
|
||||
]
|
||||
treeData: []
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,20 +47,35 @@ class NodeTree extends React.Component {
|
|||
buttons.push(<Button bsSize="small"><Glyphicon glyph="plus" /></Button>)
|
||||
}
|
||||
|
||||
buttons.push(<Button bsSize="small"><Glyphicon glyph="pencil" /></Button>);
|
||||
buttons.push(<Button bsSize="small" onClick={() => this.props.onEdit(rowInfo.node)}><Glyphicon glyph="pencil" /></Button>);
|
||||
buttons.push(<Button bsSize="small" onClick={() => this.props.onDelete(rowInfo.node)}><Glyphicon glyph="trash" /></Button>);
|
||||
|
||||
return {
|
||||
buttons: buttons
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// compare if data changed
|
||||
if (this.props.data == null || this.props.data !== nextProps.data) {
|
||||
// generate new state
|
||||
var treeData = [];
|
||||
|
||||
nextProps.data.forEach((node) => {
|
||||
treeData.push({ title: node.name, subtitle: node.endpoint, id: node._id });
|
||||
});
|
||||
|
||||
this.setState({ treeData });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SortableTree
|
||||
treeData={ this.state.treeData }
|
||||
onChange={ (treeData) => this.setState({ treeData }) }
|
||||
style={{ height: 400 }}
|
||||
maxDepth='2'
|
||||
maxDepth={ 2 }
|
||||
canDrag={ (node, path) => this.canNodeDrag(node, path) }
|
||||
canDrop={ (node, prevPath) => this.canNodeDrop(node, prevPath) }
|
||||
generateNodeProps={(rowInfo) => this.generateNodeProps(rowInfo) }
|
||||
|
|
|
@ -27,10 +27,8 @@ import AppDispatcher from '../app-dispatcher';
|
|||
//import SimulatorStore from '../stores/simulator-store';
|
||||
import NodeStore from '../stores/node-store';
|
||||
|
||||
import Table from '../components/table';
|
||||
import TableColumn from '../components/table-column';
|
||||
import NewSimulatorDialog from '../components/dialog/new-simulator';
|
||||
import EditSimulatorDialog from '../components/dialog/edit-simulator';
|
||||
import NewNodeDialog from '../components/dialog/new-node';
|
||||
import EditNodeDialog from '../components/dialog/edit-node';
|
||||
import NodeTree from '../components/node-tree';
|
||||
|
||||
class Simulators extends Component {
|
||||
|
@ -45,7 +43,7 @@ class Simulators extends Component {
|
|||
newModal: false,
|
||||
deleteModal: false,
|
||||
editModal: false,
|
||||
modalSimulator: {}
|
||||
modalData: {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -56,81 +54,80 @@ class Simulators extends Component {
|
|||
}
|
||||
|
||||
closeNewModal(data) {
|
||||
this.setState({ newModal : false });
|
||||
this.setState({ newModal: false });
|
||||
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-add',
|
||||
type: 'nodes/start-add',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
showEditModal(data) {
|
||||
// find node with id
|
||||
var node = this.state.nodes.find((element) => {
|
||||
return element._id === data.id;
|
||||
});
|
||||
|
||||
this.setState({ editModal: true, modalData: node });
|
||||
}
|
||||
|
||||
closeEditModal(data) {
|
||||
this.setState({ editModal: false });
|
||||
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'nodes/start-edit',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
showDeleteModal(data) {
|
||||
// find node with id
|
||||
var node = this.state.nodes.find((element) => {
|
||||
return element._id === data.id;
|
||||
});
|
||||
|
||||
this.setState({ deleteModal: true, modalData: node });
|
||||
}
|
||||
|
||||
confirmDeleteModal() {
|
||||
this.setState({ deleteModal: false });
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-remove',
|
||||
data: this.state.modalSimulator
|
||||
type: 'nodes/start-remove',
|
||||
data: this.state.modalData
|
||||
});
|
||||
}
|
||||
|
||||
closeEditModal(data) {
|
||||
this.setState({ editModal : false });
|
||||
|
||||
if (data) {
|
||||
AppDispatcher.dispatch({
|
||||
type: 'simulators/start-edit',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
labelStyle(value) {
|
||||
if (value === true) return 'success';
|
||||
else return 'warning';
|
||||
}
|
||||
|
||||
labelModifier(value) {
|
||||
if (value === true) return 'Running';
|
||||
else return 'Not running';
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className='section'>
|
||||
<h1>Simulators</h1>
|
||||
|
||||
<Button><Glyphicon glyph="plus" /> Add Node</Button>
|
||||
<Button onClick={() => this.setState({ newModal: true })}><Glyphicon glyph="plus" /> Add Node</Button>
|
||||
|
||||
<NodeTree />
|
||||
<NodeTree data={this.state.nodes} onDelete={(node) => this.showDeleteModal(node)} onEdit={(node) => this.showEditModal(node)} />
|
||||
|
||||
{/* <Table data={this.state.simulators}>
|
||||
<TableColumn title='Name' dataKey='name' labelKey='running' labelStyle={(value) => this.labelStyle(value)} labelModifier={(value) => this.labelModifier(value)} />
|
||||
<TableColumn title='Endpoint' dataKey='endpoint' width='180' />
|
||||
<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] })} />
|
||||
</Table>
|
||||
|
||||
<Button onClick={() => this.setState({ newModal: true })}><Glyphicon glyph="plus" /> Simulator</Button>
|
||||
|
||||
<NewSimulatorDialog show={this.state.newModal} onClose={(data) => this.closeNewModal(data)} />
|
||||
|
||||
<EditSimulatorDialog show={this.state.editModal} onClose={(data) => this.closeEditModal(data)} simulator={this.state.modalSimulator} />
|
||||
<NewNodeDialog show={this.state.newModal} onClose={(data) => this.closeNewModal(data)} />
|
||||
<EditNodeDialog node={this.state.modalData} show={this.state.editModal} onClose={(data) => this.closeEditModal(data)} />
|
||||
|
||||
<Modal show={this.state.deleteModal}>
|
||||
<Modal.Header>
|
||||
<Modal.Title>Delete Simulator</Modal.Title>
|
||||
<Modal.Title>Delete Node</Modal.Title>
|
||||
</Modal.Header>
|
||||
|
||||
<Modal.Body>
|
||||
Are you sure you want to delete the simulator <strong>'{this.state.modalSimulator.name}'</strong>?
|
||||
Are you sure you want to delete the node <strong>'{this.state.modalData.name}'</strong>?
|
||||
</Modal.Body>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button onClick={() => this.setState({ deleteModal: false })}>Cancel</Button>
|
||||
<Button bsStyle="danger" onClick={() => this.confirmDeleteModal()}>Delete</Button>
|
||||
</Modal.Footer>
|
||||
</Modal> */}
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue