From 5f0aed670be7fbead5ecc762c51941d0dac2a578 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Thu, 10 May 2018 11:09:59 +0200 Subject: [PATCH 01/14] Start with simulation model view, add selectSimulator component --- src/containers/app.js | 2 + src/containers/selectSimulator.js | 86 +++++++++++++++++++++++++++++++ src/containers/simulation.js | 2 +- src/containers/simulationModel.js | 79 ++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/containers/selectSimulator.js create mode 100644 src/containers/simulationModel.js diff --git a/src/containers/app.js b/src/containers/app.js index bb70935..420442f 100644 --- a/src/containers/app.js +++ b/src/containers/app.js @@ -45,6 +45,7 @@ import Simulators from './simulators'; import Visualization from './visualization'; import Simulations from './simulations'; import Simulation from './simulation'; +import SimulationModel from './simulationModel'; import Users from './users'; import '../styles/app.css'; @@ -134,6 +135,7 @@ class App extends React.Component { + diff --git a/src/containers/selectSimulator.js b/src/containers/selectSimulator.js new file mode 100644 index 0000000..2a74fcb --- /dev/null +++ b/src/containers/selectSimulator.js @@ -0,0 +1,86 @@ +/** + * File: selectSimulator.js + * Author: Markus Grigull + * Date: 10.08.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 . + ******************************************************************************/ + +import React from 'react'; +import { Container } from 'flux/utils'; +import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; +import _ from 'lodash'; + +import SimulatorStore from '../stores/simulator-store'; +import UserStore from '../stores/user-store'; + +class SelectSimulator extends React.Component { + static getStores() { + return [ SimulatorStore, UserStore ]; + } + + static calculateState() { + return { + simulators: SimulatorStore.getState(), + sessionToken: UserStore.getState().token, + selectedSimulator: '' + }; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.value === this.state.selectedSimulator) { + return; + } + + let selectedSimulator = nextProps.value; + if (selectedSimulator == null) { + if (this.state.simulators.length > 0) { + selectedSimulator = this.state.simulators[0]._id; + } else { + selectedSimulator = ''; + } + } + + this.setState({ selectedSimulator }); + } + + handleChange = event => { + // update selection + this.setState({ selectedSimulator: event.target.value }); + + // send complete simulator to callback + const simulator = this.state.simulators.find(s => s._id === event.target.value); + + if (this.props.onChange != null) { + this.props.onChange(simulator); + } + } + + render() { + const simulatorOptions = this.state.simulators.map(s => + + ); + + return + Simulator + + {simulatorOptions} + + ; + } +} + +export default Container.create(SelectSimulator); diff --git a/src/containers/simulation.js b/src/containers/simulation.js index d772a61..74e5702 100644 --- a/src/containers/simulation.js +++ b/src/containers/simulation.js @@ -245,7 +245,7 @@ class Simulation extends React.Component { this.onSimulationModelChecked(index, event)} width='30' /> - + this.getSimulatorName(simulator)} /> diff --git a/src/containers/simulationModel.js b/src/containers/simulationModel.js new file mode 100644 index 0000000..77a0193 --- /dev/null +++ b/src/containers/simulationModel.js @@ -0,0 +1,79 @@ +/** + * File: simulationModel.js + * Author: Markus Grigull + * Date: 10.08.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 . + ******************************************************************************/ + +import React from 'react'; +import { Container } from 'flux/utils'; +import { Button } from 'react-bootstrap'; + +import SimulationModelStore from '../stores/simulation-model-store'; +import UserStore from '../stores/user-store'; +import AppDispatcher from '../app-dispatcher'; + +import SelectSimulator from './selectSimulator'; + +class SimulationModel extends React.Component { + static getStores() { + return [ SimulationModelStore, UserStore ]; + } + + static calculateState(prevState, props) { + const simulationModel = SimulationModelStore.getState().find(m => m._id === props.match.params.simulationModel); + + return { + simulationModel: simulationModel || {}, + sessionToken: UserStore.getState().token + }; + } + + componentWillMount() { + AppDispatcher.dispatch({ + type: 'simulationModels/start-load', + data: this.props.match.params.simulationModel, + token: this.state.sessionToken + }); + } + + submitForm = event => { + event.preventDefault(); + } + + saveChanges = () => { + + } + + handleSimulatorChange = simulator => { + console.log(simulator); + } + + render() { + return
+

{this.state.simulationModel.name}

+ +
+ + + + +
; + } +} + +export default Container.create(SimulationModel, { withProps: true }); From 78c7fbfa0bcf89068b676158951c073bb5c6172d Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Thu, 10 May 2018 12:34:05 +0200 Subject: [PATCH 02/14] Add select file component --- src/containers/selectFile.js | 133 ++++++++++++++++++++++++ src/containers/selectSimulator.js | 9 +- src/containers/simulationModel.js | 13 +++ src/data-managers/files-data-manager.js | 4 +- 4 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 src/containers/selectFile.js diff --git a/src/containers/selectFile.js b/src/containers/selectFile.js new file mode 100644 index 0000000..1461989 --- /dev/null +++ b/src/containers/selectFile.js @@ -0,0 +1,133 @@ +/** + * File: selectFile.js + * Author: Markus Grigull + * Date: 10.08.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 . + ******************************************************************************/ + +import React from 'react'; +import { Container } from 'flux/utils'; +import { FormGroup, FormControl, ControlLabel, Button, ProgressBar } from 'react-bootstrap'; + +import FileStore from '../stores/file-store'; +import UserStore from '../stores/user-store'; + +import AppDispatcher from '../app-dispatcher'; + +class SelectFile extends React.Component { + static getStores() { + return [ FileStore, UserStore ]; + } + + static calculateState() { + return { + files: FileStore.getState(), + sessionToken: UserStore.getState().token, + selectedFile: '', + uploadFile: null, + uploadProgress: 0 + }; + } + + componentDidMount() { + AppDispatcher.dispatch({ + type: 'files/start-load', + token: this.state.sessionToken + }); + } + + componentWillReceiveProps(nextProps) { + if (nextProps.value === this.state.selectedSimulator) { + return; + } + + let selectedSimulator = nextProps.value; + if (selectedSimulator == null) { + if (this.state.simulators.length > 0) { + selectedSimulator = this.state.simulators[0]._id; + } else { + selectedSimulator = ''; + } + } + + this.setState({ selectedSimulator }); + } + + handleChange = event => { + this.setState({ selectedFile: event.target.value }); + + // send file to callback + if (this.props.onChange != null) { + const file = this.state.files.find(f => f._id === event.target.value); + + this.props.onChange(file); + } + } + + selectUploadFile = event => { + this.setState({ uploadFile: event.target.files[0] }); + } + + startFileUpload = () => { + // upload file + const formData = new FormData(); + formData.append(0, this.state.uploadFile); + + AppDispatcher.dispatch({ + type: 'files/start-upload', + data: formData, + token: this.state.sessionToken, + progressCallback: this.updateUploadProgress, + finishedCallback: this.clearProgress + }); + } + + updateUploadProgress = event => { + this.setState({ uploadProgress: parseInt(event.percent.toFixed(), 10) }); + } + + clearProgress = () => { + // select uploaded file + const selectedFile = this.state.files[this.state.files.length - 1]._id; + this.setState({ selectedFile, uploadProgress: 0 }); + } + + render() { + const fileOptions = this.state.files.map(f => + + ); + + return
+ + {this.props.name} + + {fileOptions} + + + + + Upload {this.props.name} + + + + + +
; + } +} + +export default Container.create(SelectFile); diff --git a/src/containers/selectSimulator.js b/src/containers/selectSimulator.js index 2a74fcb..3df40ad 100644 --- a/src/containers/selectSimulator.js +++ b/src/containers/selectSimulator.js @@ -25,17 +25,15 @@ import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; import _ from 'lodash'; import SimulatorStore from '../stores/simulator-store'; -import UserStore from '../stores/user-store'; class SelectSimulator extends React.Component { static getStores() { - return [ SimulatorStore, UserStore ]; + return [ SimulatorStore ]; } static calculateState() { return { simulators: SimulatorStore.getState(), - sessionToken: UserStore.getState().token, selectedSimulator: '' }; } @@ -58,13 +56,12 @@ class SelectSimulator extends React.Component { } handleChange = event => { - // update selection this.setState({ selectedSimulator: event.target.value }); // send complete simulator to callback - const simulator = this.state.simulators.find(s => s._id === event.target.value); - if (this.props.onChange != null) { + const simulator = this.state.simulators.find(s => s._id === event.target.value); + this.props.onChange(simulator); } } diff --git a/src/containers/simulationModel.js b/src/containers/simulationModel.js index 77a0193..db68ae3 100644 --- a/src/containers/simulationModel.js +++ b/src/containers/simulationModel.js @@ -28,6 +28,7 @@ import UserStore from '../stores/user-store'; import AppDispatcher from '../app-dispatcher'; import SelectSimulator from './selectSimulator'; +import SelectFile from './selectFile'; class SimulationModel extends React.Component { static getStores() { @@ -63,6 +64,14 @@ class SimulationModel extends React.Component { console.log(simulator); } + handleModelChange = file => { + console.log(file); + } + + handleConfigurationChange = file => { + console.log(file); + } + render() { return

{this.state.simulationModel.name}

@@ -70,6 +79,10 @@ class SimulationModel extends React.Component {
+ + + +
; diff --git a/src/data-managers/files-data-manager.js b/src/data-managers/files-data-manager.js index c63f895..60cbdad 100644 --- a/src/data-managers/files-data-manager.js +++ b/src/data-managers/files-data-manager.js @@ -30,8 +30,10 @@ class FilesDataManager extends RestDataManager { upload(file, token = null, progressCallback = null, finishedCallback = null) { RestAPI.upload(this.makeURL('/upload'), file, token, progressCallback).then(response => { + console.log(response); + AppDispatcher.dispatch({ - type: 'files/uploaded' + type: 'files/uploaded', }); // Trigger a files reload From b52655a1c71a821d2fc1e4511cf48f96a7d06f0c Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 16 May 2018 15:27:34 +0200 Subject: [PATCH 03/14] Add signal mapping component Rename files to match naming conventions --- package-lock.json | 31 ++++- package.json | 4 +- src/components/signal-mapping.js | 125 ++++++++++++++++++ src/containers/app.js | 2 +- .../{selectFile.js => select-file.js} | 0 ...selectSimulator.js => select-simulator.js} | 0 ...simulationModel.js => simulation-model.js} | 22 ++- 7 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 src/components/signal-mapping.js rename src/containers/{selectFile.js => select-file.js} (100%) rename src/containers/{selectSimulator.js => select-simulator.js} (100%) rename src/containers/{simulationModel.js => simulation-model.js} (71%) diff --git a/package-lock.json b/package-lock.json index 5ce72e9..b8e396b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8322,11 +8322,29 @@ } }, "prop-types": { - "version": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha512-vCFzoUFaZkVNeFkhK1KbSq4cn97GDrpfBt9K2qLkGnPAEFhEv3M61Lk5t+B7c0QfMLWo0fPkowk/4SuXerh26Q==", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "requires": { - "fbjs": "^0.8.9", - "loose-envify": "^1.3.1" + "fbjs": "^0.8.16", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + }, + "dependencies": { + "fbjs": { + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.9" + } + } } }, "proxy-addr": { @@ -12309,6 +12327,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "validator": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.2.0.tgz", + "integrity": "sha512-gz/uknWtNfZTj1BLUzYHDxOoiQ7A4wZ6xPuuE6RpxswR4cNyT4I5kN9jmU0AQr7IBEap9vfYChI2TpssTN6Itg==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index f09ae20..f54e1a9 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "gaugeJS": "^1.3.2", "immutable": "^3.8.1", "lodash": "^4.17.5", + "prop-types": "^15.6.1", "rc-slider": "^8.3.0", "react": "^15.4.2", "react-bootstrap": "^0.31.1", @@ -34,7 +35,8 @@ "react-scripts": "1.0.10", "react-sortable-tree": "^0.1.19", "react-svg-pan-zoom": "^2.14.1", - "superagent": "^3.5.0" + "superagent": "^3.5.0", + "validator": "^10.2.0" }, "devDependencies": { "chai": "^4.1.0" diff --git a/src/components/signal-mapping.js b/src/components/signal-mapping.js new file mode 100644 index 0000000..3c975b8 --- /dev/null +++ b/src/components/signal-mapping.js @@ -0,0 +1,125 @@ +/** + * File: signalMapping.js + * Author: Markus Grigull + * Date: 10.08.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 . + ******************************************************************************/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap'; +import validator from 'validator'; + +import Table from './table'; +import TableColumn from './table-column'; + +class SignalMapping extends React.Component { + constructor(props) { + super(props); + + this.state = { + length: props.length, + signals: props.signals + }; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.length === this.state.length && nextProps.signals === this.state.signals) { + return; + } + + this.setState({ length: nextProps.length, signals: nextProps.signals }); + } + + validateLength(){ + const valid = validator.isInt(this.state.length + '', { min: 1, max: 100 }); + + return valid ? 'success' : 'error'; + } + + handleLengthChange = event => { + const length = event.target.value; + + // update signals to represent length + const signals = this.state.signals; + + if (this.state.length < length) { + while (signals.length < length) { + signals.push({ name: 'Signal', type: 'Type' }); + } + } else { + signals.splice(length, signals.length - length); + } + + // save updated state + this.setState({ length, signals }); + + if (this.props.onChange != null) { + this.props.onChange(length, signals); + } + } + + handleMappingChange = (event, row, column) => { + const signals = this.state.signals; + + if (column === 1) { + signals[row].name = event.target.value; + } else if (column === 2) { + signals[row].type = event.target.value; + } + + this.setState({ signals }); + + if (this.props.onChange != null) { + this.props.onChange(this.state.length, signals); + } + } + + render() { + return
+ + {this.props.name} Length + + + + + + {this.props.name} Mapping + Click name or type cell to edit +
+ + + +
+ + ; + } +} + +SignalMapping.propTypes = { + name: PropTypes.string, + length: PropTypes.number, + signals: PropTypes.arrayOf( + PropTypes.shape({ + name: PropTypes.string.isRequired, + type: PropTypes.string.isRequired + }) + ), + onChange: PropTypes.func +}; + +export default SignalMapping; diff --git a/src/containers/app.js b/src/containers/app.js index 420442f..4199935 100644 --- a/src/containers/app.js +++ b/src/containers/app.js @@ -45,7 +45,7 @@ import Simulators from './simulators'; import Visualization from './visualization'; import Simulations from './simulations'; import Simulation from './simulation'; -import SimulationModel from './simulationModel'; +import SimulationModel from './simulation-model'; import Users from './users'; import '../styles/app.css'; diff --git a/src/containers/selectFile.js b/src/containers/select-file.js similarity index 100% rename from src/containers/selectFile.js rename to src/containers/select-file.js diff --git a/src/containers/selectSimulator.js b/src/containers/select-simulator.js similarity index 100% rename from src/containers/selectSimulator.js rename to src/containers/select-simulator.js diff --git a/src/containers/simulationModel.js b/src/containers/simulation-model.js similarity index 71% rename from src/containers/simulationModel.js rename to src/containers/simulation-model.js index db68ae3..f2558db 100644 --- a/src/containers/simulationModel.js +++ b/src/containers/simulation-model.js @@ -27,8 +27,9 @@ import SimulationModelStore from '../stores/simulation-model-store'; import UserStore from '../stores/user-store'; import AppDispatcher from '../app-dispatcher'; -import SelectSimulator from './selectSimulator'; -import SelectFile from './selectFile'; +import SelectSimulator from './select-simulator'; +import SelectFile from './select-file'; +import SignalMapping from '../components/signal-mapping'; class SimulationModel extends React.Component { static getStores() { @@ -72,16 +73,27 @@ class SimulationModel extends React.Component { console.log(file); } + handleOutputMappingChange = (length, signals) => { + console.log(length); + console.log(signals); + } + render() { return

{this.state.simulationModel.name}

- +
+ - + - + +
+ +
+ +
From b5d6749ebd69e358f88883ddba0396dca60d8613 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Fri, 25 May 2018 10:03:15 +0200 Subject: [PATCH 04/14] Update simulation model view --- src/containers/select-file.js | 42 ++++++++++++++++++++++-------- src/containers/select-simulator.js | 15 +++++++---- src/containers/simulation-model.js | 29 ++++++++++++++++----- src/styles/app.css | 5 ++++ 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/containers/select-file.js b/src/containers/select-file.js index 1461989..47613d9 100644 --- a/src/containers/select-file.js +++ b/src/containers/select-file.js @@ -21,7 +21,7 @@ import React from 'react'; import { Container } from 'flux/utils'; -import { FormGroup, FormControl, ControlLabel, Button, ProgressBar } from 'react-bootstrap'; +import { FormGroup, FormControl, ControlLabel, Button, ProgressBar, Col } from 'react-bootstrap'; import FileStore from '../stores/file-store'; import UserStore from '../stores/user-store'; @@ -39,7 +39,7 @@ class SelectFile extends React.Component { sessionToken: UserStore.getState().token, selectedFile: '', uploadFile: null, - uploadProgress: 0 + uploadProgress: 100 }; } @@ -111,21 +111,41 @@ class SelectFile extends React.Component { ); - return
+ const divStyle = { + + }; + + return
- {this.props.name} - - {fileOptions} - + + {this.props.name} + + + + + {fileOptions} + + - Upload {this.props.name} - + + + - - + + + + + + + + + +
; } } diff --git a/src/containers/select-simulator.js b/src/containers/select-simulator.js index 3df40ad..ad42000 100644 --- a/src/containers/select-simulator.js +++ b/src/containers/select-simulator.js @@ -21,7 +21,7 @@ import React from 'react'; import { Container } from 'flux/utils'; -import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; +import { FormGroup, FormControl, ControlLabel, Col } from 'react-bootstrap'; import _ from 'lodash'; import SimulatorStore from '../stores/simulator-store'; @@ -72,10 +72,15 @@ class SelectSimulator extends React.Component { ); return - Simulator - - {simulatorOptions} - + + Simulator + + + + + {simulatorOptions} + + ; } } diff --git a/src/containers/simulation-model.js b/src/containers/simulation-model.js index f2558db..a1929d2 100644 --- a/src/containers/simulation-model.js +++ b/src/containers/simulation-model.js @@ -21,7 +21,7 @@ import React from 'react'; import { Container } from 'flux/utils'; -import { Button } from 'react-bootstrap'; +import { Button, Col, Form } from 'react-bootstrap'; import SimulationModelStore from '../stores/simulation-model-store'; import UserStore from '../stores/user-store'; @@ -78,25 +78,40 @@ class SimulationModel extends React.Component { console.log(signals); } + handleInputMappingChange = (length, signals) => { + console.log(length); + console.log(signals); + } + render() { + const sectionStyle = { + + }; + return

{this.state.simulationModel.name}

-
-
+ + -
+ -
+ -
+ + + + + + +
- +
; } } diff --git a/src/styles/app.css b/src/styles/app.css index 16f8a65..52cb3bd 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -386,3 +386,8 @@ body { .section-buttons-group-right .rc-slider { margin-left: 12px; } + +.form-horizontal .form-group { + margin-left: 0 !important; + margin-right: 0 !important; +} From 7acad6a6d10fb6f365b11b04b5f758cbe7eaf973 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Fri, 25 May 2018 10:20:34 +0200 Subject: [PATCH 05/14] Place progress bar at correct position --- src/containers/select-file.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/containers/select-file.js b/src/containers/select-file.js index 47613d9..1940736 100644 --- a/src/containers/select-file.js +++ b/src/containers/select-file.js @@ -111,11 +111,12 @@ class SelectFile extends React.Component { ); - const divStyle = { - + const progressBarStyle = { + marginLeft: '100px', + marginTop: '-25px' }; - return
+ return
{this.props.name} @@ -140,12 +141,9 @@ class SelectFile extends React.Component { Upload file - + - - -
; } } From b94f73377b9285b5947594baeccdead4f6ab44b1 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 11:12:56 +0200 Subject: [PATCH 06/14] Add editable header component --- src/components/editable-header.js | 81 ++++++++++++++++++++++++++++++ src/containers/select-file.js | 4 +- src/containers/select-simulator.js | 2 +- src/containers/simulation-model.js | 5 +- 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 src/components/editable-header.js diff --git a/src/components/editable-header.js b/src/components/editable-header.js new file mode 100644 index 0000000..3995a25 --- /dev/null +++ b/src/components/editable-header.js @@ -0,0 +1,81 @@ +/** + * File: header.js + * Author: Markus Grigull + * Date: 25.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 . + ******************************************************************************/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { Glyphicon, FormControl } from 'react-bootstrap'; + +class EditableHeader extends React.Component { + constructor(props) { + super(props); + + this.state = { + editing: false, + title: props.title + }; + } + + componentWillReceiveProps(nextProps) { + this.setState({ title: nextProps.title }); + } + + startEditing = () => { + this.setState({ editing: true }); + } + + stopEditing = () => { + this.setState({ editing: false }); + } + + onChange = event => { + + } + + render() { + if (this.state.editing) { + const editStyle = { + maxWidth: '500px' + }; + + return
+
+ + + + +
; + } + + return
+

+ {this.state.title} +

+ + +
; + } +} + +EditableHeader.PropTypes = { + title: PropTypes.string +}; + +export default EditableHeader; diff --git a/src/containers/select-file.js b/src/containers/select-file.js index 1940736..aeca543 100644 --- a/src/containers/select-file.js +++ b/src/containers/select-file.js @@ -1,7 +1,7 @@ /** * File: selectFile.js * Author: Markus Grigull - * Date: 10.08.2018 + * Date: 10.05.2018 * * This file is part of VILLASweb. * @@ -39,7 +39,7 @@ class SelectFile extends React.Component { sessionToken: UserStore.getState().token, selectedFile: '', uploadFile: null, - uploadProgress: 100 + uploadProgress: 0 }; } diff --git a/src/containers/select-simulator.js b/src/containers/select-simulator.js index ad42000..bcf7719 100644 --- a/src/containers/select-simulator.js +++ b/src/containers/select-simulator.js @@ -1,7 +1,7 @@ /** * File: selectSimulator.js * Author: Markus Grigull - * Date: 10.08.2018 + * Date: 10.05.2018 * * This file is part of VILLASweb. * diff --git a/src/containers/simulation-model.js b/src/containers/simulation-model.js index a1929d2..1e1379a 100644 --- a/src/containers/simulation-model.js +++ b/src/containers/simulation-model.js @@ -1,7 +1,7 @@ /** * File: simulationModel.js * Author: Markus Grigull - * Date: 10.08.2018 + * Date: 10.05.2018 * * This file is part of VILLASweb. * @@ -30,6 +30,7 @@ import AppDispatcher from '../app-dispatcher'; import SelectSimulator from './select-simulator'; import SelectFile from './select-file'; import SignalMapping from '../components/signal-mapping'; +import EditableHeader from '../components/editable-header'; class SimulationModel extends React.Component { static getStores() { @@ -89,7 +90,7 @@ class SimulationModel extends React.Component { }; return
-

{this.state.simulationModel.name}

+
From 25b0f011514d56fb25fd1770073252425df8a06a Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 11:43:31 +0200 Subject: [PATCH 07/14] Finish editable header component --- src/components/editable-header.js | 42 ++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/components/editable-header.js b/src/components/editable-header.js index 3995a25..1b83755 100644 --- a/src/components/editable-header.js +++ b/src/components/editable-header.js @@ -37,45 +37,69 @@ class EditableHeader extends React.Component { this.setState({ title: nextProps.title }); } - startEditing = () => { + edit = () => { this.setState({ editing: true }); } - stopEditing = () => { + save = () => { this.setState({ editing: false }); + + if (this.props.onChange != null) { + this.props.onChange(this.state.title); + } + } + + cancel = () => { + this.setState({ editing: false, title: this.props.title }); } onChange = event => { - + this.setState({ title: event.target.value }); } render() { + const wrapperStyle= { + float: 'left' + }; + + const glyphStyle = { + float: 'left', + + marginLeft: '10px', + marginTop: '25px', + marginBottom: '20px' + }; + if (this.state.editing) { const editStyle = { - maxWidth: '500px' + maxWidth: '500px', + + marginTop: '10px' }; return
- + - + +
; } return
-

+

{this.state.title}

- +
; } } EditableHeader.PropTypes = { - title: PropTypes.string + title: PropTypes.string.isRequired, + onChange: PropTypes.func }; export default EditableHeader; From 4964a5f79fc567a95c7efcf6085746fcc92794e9 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 11:57:12 +0200 Subject: [PATCH 08/14] Add save and cancel button functionallity --- src/containers/simulation-model.js | 55 +++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/containers/simulation-model.js b/src/containers/simulation-model.js index 1e1379a..b3652bd 100644 --- a/src/containers/simulation-model.js +++ b/src/containers/simulation-model.js @@ -59,11 +59,25 @@ class SimulationModel extends React.Component { } saveChanges = () => { + AppDispatcher.dispatch({ + type: 'simulationModels/start-edit', + data: this.state.simulationModel, + token: this.state.sessionToken + }); + this.props.history.push('/simulations/' + this.state.simulationModel.simulation); + } + + discardChanges = () => { + this.props.history.push('/simulations/' + this.state.simulationModel.simulation); } handleSimulatorChange = simulator => { - console.log(simulator); + const simulationModel = this.state.simulationModel; + + simulationModel.simulator = simulator; + + this.setState({ simulationModel }); } handleModelChange = file => { @@ -75,25 +89,41 @@ class SimulationModel extends React.Component { } handleOutputMappingChange = (length, signals) => { - console.log(length); - console.log(signals); + const simulationModel = this.state.simulationModel; + + simulationModel.outputMapping = signals; + simulationModel.outputLength = length; + + this.setState({ simulationModel }); } handleInputMappingChange = (length, signals) => { - console.log(length); - console.log(signals); + const simulationModel = this.state.simulationModel; + + simulationModel.inputMapping = signals; + simulationModel.inputLength = length; + + this.setState({ simulationModel }); + } + + handleTitleChange = title => { + const simulationModel = this.state.simulationModel; + + simulationModel.name = title; + + this.setState({ simulationModel }); } render() { - const sectionStyle = { - + const buttonStyle = { + marginRight: '10px' }; return
- +
- + @@ -101,17 +131,18 @@ class SimulationModel extends React.Component { - + - +
- + +
; } From ce1972dd45d8885cd3c8ce60db29779c65c27c6b Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 12:04:19 +0200 Subject: [PATCH 09/14] Fix props loading in table component --- src/components/table.js | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/components/table.js b/src/components/table.js index df2b7fe..9d593fe 100644 --- a/src/components/table.js +++ b/src/components/table.js @@ -24,15 +24,14 @@ import _ from 'lodash'; import { Table, Button, Glyphicon, FormControl, Label, Checkbox } from 'react-bootstrap'; import { Link } from 'react-router-dom'; -//import TableColumn from './table-column'; - class CustomTable extends Component { constructor(props) { super(props); this.activeInput = null; + this.state = { - rows: [], + rows: this.getRows(props), editCell: [ -1, -1 ] }; } @@ -119,30 +118,9 @@ class CustomTable extends Component { } componentWillReceiveProps(nextProps) { - // check if data exists - if (nextProps.data == null) { - this.setState({ rows: [] }); - return; - } + const rows = this.getRows(nextProps); - // create row data - var rows = nextProps.data.map((data, index) => { - // check if multiple columns - if (Array.isArray(nextProps.children)) { - var row = []; - - nextProps.children.forEach(child => { - row.push(this.addCell(data, index, child)); - }); - - return row; - } else { - // table only has a single column - return [ this.addCell(data, index, nextProps.children) ]; - } - }); - - this.setState({ rows: rows }); + this.setState({ rows }); } componentDidUpdate() { @@ -162,6 +140,28 @@ class CustomTable extends Component { this.setState({ editCell: [ -1, -1 ] }); } + getRows(props) { + if (props.data == null) { + return []; + } + + return props.data.map((data, index) => { + // check if multiple columns + if (Array.isArray(props.children) === false) { + // table only has a single column + return [ this.addCell(data, index, props.children) ]; + } + + const row = []; + + for (let child of props.children) { + row.push(this.addCell(data, index, child)); + } + + return row; + }); + } + render() { // get children let children = this.props.children; From c5a9ccdf75cc379cd28b524eeb3fa107c7039ebc Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 12:56:52 +0200 Subject: [PATCH 10/14] Remove old simulation model dialogs --- .../dialog/edit-simulation-model.js | 186 ------------------ src/components/dialog/new-simulation-model.js | 182 ----------------- src/containers/simulation.js | 135 ++++++------- 3 files changed, 61 insertions(+), 442 deletions(-) delete mode 100644 src/components/dialog/edit-simulation-model.js delete mode 100644 src/components/dialog/new-simulation-model.js diff --git a/src/components/dialog/edit-simulation-model.js b/src/components/dialog/edit-simulation-model.js deleted file mode 100644 index a194ea6..0000000 --- a/src/components/dialog/edit-simulation-model.js +++ /dev/null @@ -1,186 +0,0 @@ -/** - * File: edit-simulation-model.js - * Author: Markus Grigull - * Date: 04.03.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, HelpBlock } from 'react-bootstrap'; -import _ from 'lodash'; - -import Table from '../table'; -import TableColumn from '../table-column'; -import Dialog from './dialog'; - -class EditSimulationModelDialog extends React.Component { - valid = false; - - constructor(props) { - super(props); - - this.state = { - _id: '', - name: '', - simulator: '', - simulation: '', - outputLength: 1, - inputLength: 1, - outputMapping: [{ name: 'Signal', type: 'Type' }], - inputMapping: [{ name: 'Signal', type: 'Type' }] - } - } - - onClose(canceled) { - if (canceled === false) { - if (this.valid) { - this.props.onClose(this.state); - } - } else { - this.props.onClose(); - } - } - - handleChange(e) { - let mapping = null; - - if (e.target.id === 'outputLength') { - mapping = this.state.outputMapping; - } else if (e.target.id === 'inputLength') { - mapping = this.state.inputMapping; - } - - if (mapping != null) { - // change mapping size - if (e.target.value > mapping.length) { - // add missing signals - while (mapping.length < e.target.value) { - mapping.push({ name: 'Signal', type: 'Type' }); - } - } else { - // remove signals - mapping.splice(e.target.value, mapping.length - e.target.value); - } - } - - this.setState({ [e.target.id]: e.target.value }); - } - - handleMappingChange(key, event, row, column) { - const mapping = this.state[key]; - - if (column === 1) { - mapping[row].name = event.target.value; - } else if (column === 2) { - mapping[row].type = event.target.value; - } - - this.setState({ [key]: mapping }); - } - - resetState() { - this.setState({ - _id: this.props.data._id, - simulation: this.props.data.simulation, - name: this.props.data.name, - simulator: this.props.data.simulator, - outputLength: this.props.data.outputLength, - inputLength: this.props.data.inputLength, - outputMapping: this.props.data.outputMapping, - inputMapping: this.props.data.inputMapping - }); - } - - validateForm(target) { - // check all controls - var name = true; - let inputLength = true; - let outputLength = true; - - if (this.state.name === '') { - name = false; - } - - // test if simulatorid is a number (in a string, not type of number) - if (!/^\d+$/.test(this.state.outputLength)) { - outputLength = false; - } - - if (!/^\d+$/.test(this.state.inputLength)) { - inputLength = false; - } - - this.valid = name && inputLength && outputLength; - - // return state to control - if (target === 'name') return name ? "success" : "error"; - else if (target === 'outputLength') return outputLength ? "success" : "error"; - else if (target === 'inputLength') return inputLength ? "success" : "error"; - } - - render() { - return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Name - this.handleChange(e)} /> - - - - Simulator - this.handleChange(e)}> - {this.props.simulators.map(simulator => ( - - ))} - - - - Output Length - this.handleChange(e)} /> - - - - Output Mapping - Click Name or Type cell to edit - - - this.handleMappingChange('outputMapping', event, row, column)} /> - this.handleMappingChange('outputMapping', event, row, column)} /> -
-
- - Input Length - this.handleChange(e)} /> - - - - Input Mapping - Click Name or Type cell to edit - - - this.handleMappingChange('inputMapping', event, row, column)} /> - this.handleMappingChange('inputMapping', event, row, column)} /> -
-
-
-
- ); - } -} - -export default EditSimulationModelDialog; diff --git a/src/components/dialog/new-simulation-model.js b/src/components/dialog/new-simulation-model.js deleted file mode 100644 index 40daf9c..0000000 --- a/src/components/dialog/new-simulation-model.js +++ /dev/null @@ -1,182 +0,0 @@ -/** - * File: new-simulation-model.js - * Author: Markus Grigull - * Date: 04.03.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, HelpBlock } from 'react-bootstrap'; -import _ from 'lodash'; - -import Table from '../table'; -import TableColumn from '../table-column'; -import Dialog from './dialog'; - -class NewSimulationModelDialog extends React.Component { - valid = false; - - constructor(props) { - super(props); - - this.state = { - name: '', - simulator: '', - outputLength: '1', - inputLength: '1', - outputMapping: [ { name: 'Signal', type: 'Type' } ], - inputMapping: [ { name: 'Signal', type: 'Type' } ] - }; - } - - onClose(canceled) { - if (canceled === false) { - if (this.valid) { - this.props.onClose(this.state); - } - } else { - this.props.onClose(); - } - } - - handleChange(e) { - let mapping = null; - - if (e.target.id === 'outputLength') { - mapping = this.state.outputMapping; - } else if (e.target.id === 'inputLength') { - mapping = this.state.inputMapping; - } - - if (mapping != null) { - // change mapping size - if (e.target.value > mapping.length) { - // add missing signals - while (mapping.length < e.target.value) { - mapping.push({ name: 'Signal', type: 'Type' }); - } - } else { - // remove signals - mapping.splice(e.target.value, mapping.length - e.target.value); - } - } - - this.setState({ [e.target.id]: e.target.value }); - } - - handleMappingChange(key, event, row, column) { - const mapping = this.state[key]; - - if (column === 1) { - mapping[row].name = event.target.value; - } else if (column === 2) { - mapping[row].type = event.target.value; - } - - this.setState({ [key]: mapping }); - } - - resetState() { - this.setState({ - name: '', - simulator: this.props.simulators[0]._id || '', - outputLength: '1', - inputLength: '1', - outputMapping: [{ name: 'Signal', type: 'Type' }], - inputMapping: [{ name: 'Signal', type: 'Type' }] - }); - } - - validateForm(target) { - // check all controls - let name = true; - let inputLength = true; - let outputLength = true; - - if (this.state.name === '') { - name = false; - } - - // test if simulatorid is a number (in a string, not type of number) - if (!/^\d+$/.test(this.state.outputLength)) { - outputLength = false; - } - - if (!/^\d+$/.test(this.state.inputLength)) { - inputLength = false; - } - - this.valid = name && inputLength && outputLength; - - // return state to control - if (target === 'name') return name ? "success" : "error"; - else if (target === 'outputLength') return outputLength ? "success" : "error"; - else if (target === 'inputLength') return inputLength ? "success" : "error"; - } - - render() { - return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Name - this.handleChange(e)} /> - - - - Simulator - this.handleChange(e)}> - {this.props.simulators.map(simulator => ( - - ))} - - - - Output Length - this.handleChange(e)} /> - - - - Output Mapping - Click Name or Type cell to edit - - - this.handleMappingChange('outputMapping', event, row, column)} /> - this.handleMappingChange('outputMapping', event, row, column)} /> -
-
- - Input Length - this.handleChange(e)} /> - - - - Input Mapping - Click Name or Type cell to edit - - - this.handleMappingChange('inputMapping', event, row, column)} /> - this.handleMappingChange('inputMapping', event, row, column)} /> -
-
-
-
- ); - } -} - -export default NewSimulationModelDialog; diff --git a/src/containers/simulation.js b/src/containers/simulation.js index 74e5702..181b7a5 100644 --- a/src/containers/simulation.js +++ b/src/containers/simulation.js @@ -33,8 +33,6 @@ import AppDispatcher from '../app-dispatcher'; import Table from '../components/table'; import TableColumn from '../components/table-column'; -import NewSimulationModelDialog from '../components/dialog/new-simulation-model'; -import EditSimulationModelDialog from '../components/dialog/edit-simulation-model'; import ImportSimulationModelDialog from '../components/dialog/import-simulation-model'; import SimulatorAction from '../components/simulator-action'; @@ -73,12 +71,9 @@ class Simulation extends React.Component { simulators: SimulatorStore.getState(), sessionToken, - newModal: false, deleteModal: false, - editModal: false, importModal: false, modalData: {}, - modalIndex: null, selectedSimulationModels: [] } @@ -101,26 +96,30 @@ class Simulation extends React.Component { }); } - closeNewModal(data) { - this.setState({ newModal : false }); + addSimulationModel = () => { + const simulationModel = { + simulation: this.state.simulation._id, + name: 'New Simulation Model', + simulator: this.state.simulators.length > 0 ? this.state.simulators[0]._id : null, + outputLength: 1, + outputMapping: [{ name: 'Signal', type: 'Type' }], + inputLength: 1, + inputMapping: [{ name: 'Signal', type: 'Type' }] + }; - if (data) { - data.simulation = this.state.simulation._id; + AppDispatcher.dispatch({ + type: 'simulationModels/start-add', + data: simulationModel, + token: this.state.sessionToken + }); + this.setState({ simulation: {} }, () => { AppDispatcher.dispatch({ - type: 'simulationModels/start-add', - data, + type: 'simulations/start-load', + data: this.props.match.params.simulation, token: this.state.sessionToken }); - - this.setState({ simulation: {} }, () => { - AppDispatcher.dispatch({ - type: 'simulations/start-load', - data: this.props.match.params.simulation, - token: this.state.sessionToken - }); - }); - } + }); } closeDeleteModal = confirmDelete => { @@ -137,18 +136,6 @@ class Simulation extends React.Component { }); } - closeEditModal(data) { - this.setState({ editModal : false }); - - if (data) { - AppDispatcher.dispatch({ - type: 'simulationModels/start-edit', - data, - token: this.state.sessionToken - }); - } - } - closeImportModal(data) { this.setState({ importModal: false }); @@ -239,52 +226,52 @@ class Simulation extends React.Component { } render() { - return ( -
-

{this.state.simulation.name}

+ const buttonStyle = { + marginLeft: '10px' + }; - - this.onSimulationModelChecked(index, event)} width='30' /> - - this.getSimulatorName(simulator)} /> - - - this.setState({ editModal: true, modalData: this.state.simulationModels[index], modalIndex: index })} - onDelete={(index) => this.setState({ deleteModal: true, modalData: this.state.simulationModels[index], modalIndex: index })} - onExport={index => this.exportModel(index)} - /> -
+ return
+

{this.state.simulation.name}

-
- -
+ + this.onSimulationModelChecked(index, event)} width='30' /> + + this.getSimulatorName(simulator)} /> + + + this.setState({ deleteModal: true, modalData: this.state.simulationModels[index], modalIndex: index })} + onExport={index => this.exportModel(index)} + /> +
-
- - -
- - this.closeNewModal(data)} simulators={this.state.simulators} /> - this.closeEditModal(data)} data={this.state.modalData} simulators={this.state.simulators} /> - this.closeImportModal(data)} simulators={this.state.simulators} /> - - +
+
- ); + +
+ + +
+ +
+ + this.closeImportModal(data)} simulators={this.state.simulators} /> + + +
; } } From ca20df0b3bd61edd098a2efcf9702fd6fb4b4995 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 13:04:23 +0200 Subject: [PATCH 11/14] Add autofocus to editable header --- src/components/editable-header.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/editable-header.js b/src/components/editable-header.js index 1b83755..77a4293 100644 --- a/src/components/editable-header.js +++ b/src/components/editable-header.js @@ -24,6 +24,8 @@ import PropTypes from 'prop-types'; import { Glyphicon, FormControl } from 'react-bootstrap'; class EditableHeader extends React.Component { + titleInput = null; + constructor(props) { super(props); @@ -79,7 +81,7 @@ class EditableHeader extends React.Component { return
- + From b6207cf80b496f5f38e3df4f8d807ef2f7b056cf Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 13:31:43 +0200 Subject: [PATCH 12/14] Update simulation model import dialog --- .../dialog/import-simulation-model.js | 165 ++++-------------- src/containers/simulation.js | 35 ++-- 2 files changed, 50 insertions(+), 150 deletions(-) diff --git a/src/components/dialog/import-simulation-model.js b/src/components/dialog/import-simulation-model.js index 1f9a2ff..137dfe9 100644 --- a/src/components/dialog/import-simulation-model.js +++ b/src/components/dialog/import-simulation-model.js @@ -20,194 +20,89 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap'; +import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; import _ from 'lodash'; -import Table from '../table'; -import TableColumn from '../table-column'; import Dialog from './dialog'; class ImportSimulationModelDialog extends React.Component { - valid = false; imported = false; constructor(props) { super(props); this.state = { - name: '', - simulator: '', - outputLength: '1', - inputLength: '1', - outputMapping: [ { name: 'Signal', type: 'Type' } ], - inputMapping: [{ name: 'Signal', type: 'Type' }] + model: {} }; } - onClose(canceled) { - if (canceled === false) { - this.props.onClose(this.state); - } else { + onClose = canceled => { + if (canceled) { this.props.onClose(); + + return; } + + this.props.onClose(this.state.model); } - resetState() { + resetState = () => { this.setState({ - name: '', - simulator: '', - outputLength: '1', - inputLength: '1', - outputMapping: [{ name: 'Signal', type: 'Type' }], - inputMapping: [{ name: 'Signal', type: 'Type' }] + model: {} }); this.imported = false; } - handleChange(e) { - let mapping = null; - - if (e.target.id === 'outputLength') { - mapping = this.state.outputMapping; - } else if (e.target.id === 'inputLength') { - mapping = this.state.inputMapping; - } - - if (mapping != null) { - // change mapping size - if (e.target.value > mapping.length) { - // add missing signals - while (mapping.length < e.target.value) { - mapping.push({ name: 'Signal', type: 'Type' }); - } - } else { - // remove signals - mapping.splice(e.target.value, mapping.length - e.target.value); - } - } - - this.setState({ [e.target.id]: e.target.value }); - } - - handleMappingChange(key, event, row, column) { - const mapping = this.state[key]; - - if (column === 1) { - mapping[row].name = event.target.value; - } else if (column === 2) { - mapping[row].type = event.target.value; - } - - this.setState({ [key]: mapping }); - } - - loadFile(fileList) { + loadFile = event => { // get file - const file = fileList[0]; - if (!file.type.match('application/json')) { + const file = event.target.files[0]; + if (file.type.match('application/json') === false) { return; } // create file reader - var reader = new FileReader(); - var self = this; + const reader = new FileReader(); + const self = this; - reader.onload = function(event) { - // read simulator + reader.onload = event => { const model = JSON.parse(event.target.result); + model.simulator = this.props.simulators.length > 0 ? this.props.simulators[0]._id : null; + self.imported = true; - self.valid = true; - self.setState({ name: model.name, mapping: model.mapping, length: model.length, simulator: { node: self.props.nodes[0]._id, simulator: 0 } }); + + this.setState({ model }); }; reader.readAsText(file); } - validateForm(target) { - // check all controls - var name = true; - let inputLength = true; - let outputLength = true; - var simulator = true; + handleSimulatorChange = event => { + const model = this.state.model; - if (this.state.name === '') { - name = false; - } + model.simulator = event.target.value; - if (this.state.simulator === '') { - simulator = false; - } - - // test if simulatorid is a number (in a string, not type of number) - if (!/^\d+$/.test(this.state.outputLength)) { - outputLength = false; - } - - if (!/^\d+$/.test(this.state.inputLength)) { - inputLength = false; - } - - this.valid = name && inputLength && outputLength && simulator; - - // return state to control - if (target === 'name') return name ? "success" : "error"; - else if (target === 'outputLength') return outputLength ? "success" : "error"; - else if (target === 'inputLength') return inputLength ? "success" : "error"; - else if (target === 'simulator') return simulator ? "success" : "error"; + this.setState({ model }); } render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> +
- + Simulation Model File - this.loadFile(e.target.files)} /> + - - Name - this.handleChange(e)} /> - - - + Simulator - this.handleChange(e)}> + {this.props.simulators.map(simulator => ( - + ))} - - Output Length - this.handleChange(e)} /> - - - - Output Mapping - Click Name or Type cell to edit - - - this.handleMappingChange('outputMapping', event, row, column)} /> - this.handleMappingChange('outputMapping', event, row, column)} /> -
-
- - Input Length - this.handleChange(e)} /> - - - - Input Mapping - Click Name or Type cell to edit - - - this.handleMappingChange('inputMapping', event, row, column)} /> - this.handleMappingChange('inputMapping', event, row, column)} /> -
-
); diff --git a/src/containers/simulation.js b/src/containers/simulation.js index 181b7a5..77d6d1d 100644 --- a/src/containers/simulation.js +++ b/src/containers/simulation.js @@ -136,26 +136,30 @@ class Simulation extends React.Component { }); } - closeImportModal(data) { + importSimulationModel = simulationModel => { this.setState({ importModal: false }); - if (data) { - data.simulation = this.state.simulation._id; + if (simulationModel == null) { + return; + } + simulationModel.simulation = this.state.simulation._id; + + console.log(simulationModel); + + AppDispatcher.dispatch({ + type: 'simulationModels/start-add', + data: simulationModel, + token: this.state.sessionToken + }); + + this.setState({ simulation: {} }, () => { AppDispatcher.dispatch({ - type: 'simulationModels/start-add', - data, + type: 'simulations/start-load', + data: this.props.match.params.simulation, token: this.state.sessionToken }); - - this.setState({ simulation: {} }, () => { - AppDispatcher.dispatch({ - type: 'simulations/start-load', - data: this.props.match.params.simulation, - token: this.state.sessionToken - }); - }); - } + }); } getSimulatorName(simulatorId) { @@ -169,6 +173,7 @@ class Simulation extends React.Component { exportModel(index) { // filter properties const model = Object.assign({}, this.state.simulationModels[index]); + delete model.simulator; delete model.simulation; @@ -268,7 +273,7 @@ class Simulation extends React.Component {
- this.closeImportModal(data)} simulators={this.state.simulators} /> +
; From 472af5c1266df49f75b93b9eb3c8ad339833d3fc Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 13:33:54 +0200 Subject: [PATCH 13/14] Disable model and configuration controls while not usable --- src/containers/select-file.js | 6 +++--- src/containers/simulation-model.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/containers/select-file.js b/src/containers/select-file.js index aeca543..755356d 100644 --- a/src/containers/select-file.js +++ b/src/containers/select-file.js @@ -123,7 +123,7 @@ class SelectFile extends React.Component { - + {fileOptions} @@ -131,13 +131,13 @@ class SelectFile extends React.Component { - + - diff --git a/src/containers/simulation-model.js b/src/containers/simulation-model.js index b3652bd..172ef72 100644 --- a/src/containers/simulation-model.js +++ b/src/containers/simulation-model.js @@ -126,9 +126,9 @@ class SimulationModel extends React.Component { - + - + From 444efaf6e07f3dff5d75afc83bc8d5af81a892a9 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Wed, 30 May 2018 19:06:26 +0200 Subject: [PATCH 14/14] Fix ui test for slider widget --- src/__tests__/components/dialog/edit-widget-control-creator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/components/dialog/edit-widget-control-creator.js b/src/__tests__/components/dialog/edit-widget-control-creator.js index ef02578..d9915bb 100644 --- a/src/__tests__/components/dialog/edit-widget-control-creator.js +++ b/src/__tests__/components/dialog/edit-widget-control-creator.js @@ -31,7 +31,7 @@ describe('edit widget control creator', () => { { args: { widgetType: 'Image' }, result: { controlNumber: 2, controlTypes: [EditImageWidgetControl, EditWidgetAspectControl] } }, { args: { widgetType: 'Gauge' }, result: { controlNumber: 6, controlTypes: [EditWidgetTextControl, EditWidgetSimulatorControl, EditWidgetSignalControl, EditWidgetCheckboxControl, EditWidgetColorZonesControl, EditWidgetMinMaxControl] } }, { args: { widgetType: 'PlotTable' }, result: { controlNumber: 5, controlTypes: [EditWidgetSimulatorControl, EditWidgetSignalsControl, EditWidgetTextControl, EditWidgetTimeControl, EditWidgetMinMaxControl] } }, - { args: { widgetType: 'Slider' }, result: { controlNumber: 3, controlTypes: [EditWidgetOrientation, EditWidgetSimulatorControl, EditWidgetSignalControl] } }, + { args: { widgetType: 'Slider' }, result: { controlNumber: 4, controlTypes: [EditWidgetTextControl, EditWidgetOrientation, EditWidgetSimulatorControl, EditWidgetSignalControl] } }, { args: { widgetType: 'Button' }, result: { controlNumber: 4, controlTypes: [EditWidgetColorControl, EditWidgetSimulatorControl, EditWidgetSignalControl] } }, { args: { widgetType: 'Box' }, result: { controlNumber: 1, controlTypes: [EditWidgetColorControl] } }, { args: { widgetType: 'Label' }, result: { controlNumber: 3, controlTypes: [EditWidgetTextControl, EditWidgetTextSizeControl, EditWidgetColorControl] } },