From a4ef517670a136e3d1bcd0c14c40aa889cb5c326 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Mon, 18 Sep 2017 14:32:17 +0200 Subject: [PATCH] Improve imports and exports --- src/components/dialog/export-simulator.js | 88 ------------------- src/components/dialog/import-node.js | 64 +++++++++++--- src/components/dialog/import-simulation.js | 26 +----- src/components/dialog/new-node.js | 2 +- src/components/dialog/new-simulation-model.js | 2 +- src/components/node-tree.js | 1 + src/containers/simulation.js | 42 ++++++++- src/containers/simulations.js | 82 +++++++++-------- 8 files changed, 138 insertions(+), 169 deletions(-) delete mode 100644 src/components/dialog/export-simulator.js diff --git a/src/components/dialog/export-simulator.js b/src/components/dialog/export-simulator.js deleted file mode 100644 index 31ec523..0000000 --- a/src/components/dialog/export-simulator.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * File: export-simulator.js - * Author: Markus Grigull - * Date: 04.04.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'; - -class ExportSimulatorDialog extends Component { - static propTypes = { - show: PropTypes.bool.isRequired, - onClose: PropTypes.func.isRequired - }; - - valid: false; - - constructor(props) { - super(props); - - this.state = { - name: '', - endpoint: '' - }; - } - - 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: '' }); - } - - 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 ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Name - this.handleChange(e)} /> - - - - Endpoint - this.handleChange(e)} /> - - -
-
- ); - } -} - -export default ExportSimulatorDialog; diff --git a/src/components/dialog/import-node.js b/src/components/dialog/import-node.js index ed10849..e1128df 100644 --- a/src/components/dialog/import-node.js +++ b/src/components/dialog/import-node.js @@ -1,11 +1,23 @@ /** - * File: import-simulator.js + * File: import-node.js * Author: Markus Grigull - * Date: 04.04.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. - **********************************************************************************/ + * Date: 03.09.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 . + ******************************************************************************/ import React from 'react'; import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; @@ -14,13 +26,15 @@ import Dialog from './dialog'; class ImportNodeDialog extends React.Component { valid = false; + imported = false; constructor(props) { super(props); this.state = { name: '', - endpoint: '' + endpoint: '', + simulators: [] }; } @@ -38,6 +52,8 @@ class ImportNodeDialog extends React.Component { resetState() { this.setState({ name: '', endpoint: '' }); + + this.imported = false; } loadFile(fileList) { @@ -53,14 +69,34 @@ class ImportNodeDialog extends React.Component { reader.onload = function(event) { // read simulator - const simulator = JSON.parse(event.target.result); - self.valid = true; - self.setState({ name: simulator.name, endpoint: simulator.endpoint }); + const node = JSON.parse(event.target.result); + self.imported = true; + self.setState({ name: node.name, endpoint: node.endpoint, simulators: node.simulators }); }; reader.readAsText(file); } + validateForm(target) { + // check all controls + let endpoint = true; + let name = true; + + if (this.state.name === '' || this.props.nodes.find(node => node.name === this.state.name) !== undefined) { + name = false; + } + + if (this.state.endpoint === '' || this.props.nodes.find(node => node.endpoint === this.state.endpoint) !== undefined) { + endpoint = false; + } + + this.valid = endpoint && name; + + // return state to control + if (target === 'name') return name ? "success" : "error"; + else return endpoint ? "success" : "error"; + } + render() { return ( this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> @@ -70,14 +106,14 @@ class ImportNodeDialog extends React.Component { this.loadFile(e.target.files)} /> - + Name - this.handleChange(e)} /> + this.handleChange(e)} /> - + Endpoint - this.handleChange(e)} /> + this.handleChange(e)} /> diff --git a/src/components/dialog/import-simulation.js b/src/components/dialog/import-simulation.js index a7e18ac..624b11e 100644 --- a/src/components/dialog/import-simulation.js +++ b/src/components/dialog/import-simulation.js @@ -33,21 +33,13 @@ class ImportSimulationDialog extends React.Component { this.state = { name: '', - selectedModels: [] + models: [], }; } onClose(canceled) { if (canceled === false) { - // create simulation - const simulation = { - name: this.state.name, - models: this.props.simulation.models.filter((element, index) => { - return this.state.selectedModels[index]; - }) - }; - - this.props.onClose(simulation); + this.props.onClose(this.state); } else { this.props.onClose(); } @@ -112,20 +104,6 @@ class ImportSimulationDialog extends React.Component { if (target === 'name') return name ? "success" : "error"; } - selectModels(event) { - // update selection - const selectedModels = this.state.selectedModels.map((element, index) => { - // eslint-disable-next-line - if (event.target.id == index) { - return !element; - } else { - return element; - } - }); - - this.setState({ selectedModels: selectedModels }); - } - render() { return ( this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> diff --git a/src/components/dialog/new-node.js b/src/components/dialog/new-node.js index 54be1c9..e7ec1c9 100644 --- a/src/components/dialog/new-node.js +++ b/src/components/dialog/new-node.js @@ -25,7 +25,7 @@ import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; import Dialog from './dialog'; class NewNodeDialog extends React.Component { - valid: false; + valid = false; constructor(props) { super(props); diff --git a/src/components/dialog/new-simulation-model.js b/src/components/dialog/new-simulation-model.js index a4e3bbb..9538b30 100644 --- a/src/components/dialog/new-simulation-model.js +++ b/src/components/dialog/new-simulation-model.js @@ -27,7 +27,7 @@ import TableColumn from '../table-column'; import Dialog from './dialog'; class NewSimulationModelDialog extends React.Component { - valid: false; + valid = false; constructor(props) { super(props); diff --git a/src/components/node-tree.js b/src/components/node-tree.js index 24c1be3..7513710 100644 --- a/src/components/node-tree.js +++ b/src/components/node-tree.js @@ -47,6 +47,7 @@ class NodeTree extends React.Component { buttons.push(); buttons.push(); buttons.push(); + buttons.push(); } else { // get child index var index = rowInfo.path[1] - rowInfo.path[0] - 1; diff --git a/src/containers/simulation.js b/src/containers/simulation.js index a2b2d99..e28a8e9 100644 --- a/src/containers/simulation.js +++ b/src/containers/simulation.js @@ -21,7 +21,7 @@ import React from 'react'; import { Container } from 'flux/utils'; -import { Button, Modal, Glyphicon, FormControl, FormGroup, Form } from 'react-bootstrap'; +import { Button, Modal, Glyphicon } from 'react-bootstrap'; import FileSaver from 'file-saver'; import SimulationStore from '../stores/simulation-store'; @@ -129,6 +129,20 @@ class Simulation extends React.Component { } } + closeImportModal(data) { + this.setState({ importModal: false }); + + if (data) { + this.state.simulation.models.push(data); + + AppDispatcher.dispatch({ + type: 'simulations/start-edit', + data: this.state.simulation, + token: this.state.sessionToken + }); + } + } + getSimulatorName(simulator) { var name = "undefined"; @@ -141,6 +155,16 @@ class Simulation extends React.Component { return name; } + exportModel(index) { + // filter properties + let simulationModel = Object.assign({}, this.state.simulation.models[index]); + delete simulationModel.simulator; + + // show save dialog + const blob = new Blob([JSON.stringify(simulationModel, null, 2)], { type: 'application/json' }); + FileSaver.saveAs(blob, 'simulation model - ' + simulationModel.name + '.json'); + } + onModalKeyPress = (event) => { if (event.key === 'Enter') { event.preventDefault(); @@ -194,14 +218,24 @@ class Simulation extends React.Component { this.getSimulatorName(simulator)} /> - this.setState({ editModal: true, modalData: this.state.simulation.models[index], modalIndex: index })} onDelete={(index) => this.setState({ deleteModal: true, modalData: this.state.simulation.models[index], modalIndex: index })} onExport={(index) => this.exportSimulationModel(this.state.simulation.models[index])} /> + this.setState({ editModal: true, modalData: this.state.simulation.models[index], modalIndex: index })} + onDelete={(index) => this.setState({ deleteModal: true, modalData: this.state.simulation.models[index], modalIndex: index })} + onExport={index => this.exportModel(index)} + /> - + + this.closeNewModal(data)} nodes={this.state.nodes} /> - this.closeEditModal(data)} data={this.state.modalData} nodes={this.state.nodes} /> + this.closeImportModal(data)} nodes={this.state.nodes} /> this.setState({ deleteModal: false })} onKeyPress={this.onModalKeyPress}> diff --git a/src/containers/simulations.js b/src/containers/simulations.js index f5acf69..3acc22a 100644 --- a/src/containers/simulations.js +++ b/src/containers/simulations.js @@ -21,12 +21,13 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import { Button, Modal, Glyphicon, FormGroup, FormControl, Form } from 'react-bootstrap'; +import { Button, Modal, Glyphicon } from 'react-bootstrap'; import FileSaver from 'file-saver'; import AppDispatcher from '../app-dispatcher'; import SimulationStore from '../stores/simulation-store'; import UserStore from '../stores/user-store'; +import NodeStore from '../stores/node-store'; import Table from '../components/table'; import TableColumn from '../components/table-column'; @@ -36,12 +37,13 @@ import ImportSimulationDialog from '../components/dialog/import-simulation'; class Simulations extends Component { static getStores() { - return [ SimulationStore, UserStore ]; + return [ SimulationStore, UserStore, NodeStore ]; } static calculateState() { return { simulations: SimulationStore.getState(), + nodes: NodeStore.getState(), sessionToken: UserStore.getState().token, newModal: false, @@ -119,6 +121,18 @@ class Simulations extends Component { } } + closeImportModal(data) { + this.setState({ importModal: false }); + + if (data) { + AppDispatcher.dispatch({ + type: 'simulations/start-add', + data, + token: this.state.sessionToken + }); + } + } + onModalKeyPress = (event) => { if (event.key === 'Enter') { event.preventDefault(); @@ -126,29 +140,6 @@ class Simulations extends Component { this.confirmDeleteModal(); } } - - closeImportModal(data) { - this.setState({ importModal : false }); - - if (data) { - AppDispatcher.dispatch({ - type: 'simulations/start-add', - data: data - }); - } - } - - exportSimulation(data) { - // filter properties - var simulation = Object.assign({}, data); - delete simulation._id; - delete simulation.projects; - delete simulation.running; - - // show save dialog - const blob = new Blob([JSON.stringify(simulation, null, 2)], { type: 'application/json' }); - FileSaver.saveAs(blob, simulation.name + '.json'); - } loadFile(fileList) { // get file @@ -170,6 +161,23 @@ class Simulations extends Component { reader.readAsText(file); } + exportSimulation(index) { + // filter properties + let simulation = Object.assign({}, this.state.simulations[index]); + delete simulation._id; + delete simulation.projects; + delete simulation.running; + delete simulation.user; + + simulation.models.forEach(model => { + delete model.simulator; + }); + + // show save dialog + const blob = new Blob([JSON.stringify(simulation, null, 2)], { type: 'application/json' }); + FileSaver.saveAs(blob, 'simulation - ' + simulation.name + '.json'); + } + render() { return (
@@ -177,23 +185,23 @@ class Simulations extends Component { - this.setState({ editModal: true, modalSimulation: this.state.simulations[index] })} onDelete={index => this.setState({ deleteModal: true, modalSimulation: this.state.simulations[index] })} onExport={(index) => this.exportSimulation(this.state.simulations[index])} /> + this.setState({ editModal: true, modalSimulation: this.state.simulations[index] })} + onDelete={index => this.setState({ deleteModal: true, modalSimulation: this.state.simulations[index] })} + onExport={index => this.exportSimulation(index)} + />
-
- - - - - - { this.fileInput = ref; }} type="file" style={{ display: 'none' }} onChange={(e) => this.loadFile(e.target.files)} /> - - -
+ + this.closeNewModal(data)} /> this.closeEditModal(data)} simulation={this.state.modalSimulation} /> - this.closeImportModal(data)} simulation={this.state.modalSimulation} /> + this.closeImportModal(data)} nodes={this.state.nodes} /> this.setState({ deleteModal: false })} onKeyPress={this.onModalKeyPress}>