From e64e8902fb7e4cb7820c2ae066463af3a59c214c Mon Sep 17 00:00:00 2001 From: Sandro Weber <webers@in.tum.de> Date: Mon, 24 May 2021 22:39:09 +0200 Subject: [PATCH] simulation view can start/pause simulation --- src/App.js | 4 +- .../experiment-list/simulation-details.js | 12 +++-- .../simulation-view/simulation-view.css | 8 +-- .../simulation-view/simulation-view.js | 51 ++++++++++++------- .../execution/experiment-execution-service.js | 2 +- .../execution/running-simulation-service.js | 19 ++++++- 6 files changed, 67 insertions(+), 29 deletions(-) diff --git a/src/App.js b/src/App.js index 2fb35e2..63e3253 100644 --- a/src/App.js +++ b/src/App.js @@ -14,8 +14,8 @@ class App extends React.Component { <ErrorDialog /> <HashRouter> <Switch> - <Route path='/experiments-overview' component={ExperimentOverview} /> - <Route path='/simulation-view/:simID' component={SimulationView} /> + <Route path='/experiments-overview' component={ExperimentOverview} /> + <Route path='/simulation-view/:serverIP/:simulationID' component={SimulationView} /> <Route path='/' component={EntryPage} /> </Switch> </HashRouter> diff --git a/src/components/experiment-list/simulation-details.js b/src/components/experiment-list/simulation-details.js index 26107c7..6b2950f 100644 --- a/src/components/experiment-list/simulation-details.js +++ b/src/components/experiment-list/simulation-details.js @@ -55,6 +55,13 @@ class SimulationDetails extends React.Component { }); } + joinSimulation(simulationInfo) { + console.info(simulationInfo); + this.props.history.push({ + pathname: '/simulation-view/' + simulationInfo.server + '/' + simulationInfo.runningSimulation.simulationID + }); + } + render() { return ( <div className='simulations-details-wrapper'> @@ -81,10 +88,7 @@ class SimulationDetails extends React.Component { type="button" className='nrp-btn btn-default' disabled={this.isJoinDisabled(simulation)} onClick={() => { - console.info(simulation); - this.props.history.push({ - pathname: '/simulation-view/' + simulation.runningSimulation.simulationID - }); + this.joinSimulation(simulation); }}> <ImEnter className='icon' />Join </button> diff --git a/src/components/simulation-view/simulation-view.css b/src/components/simulation-view/simulation-view.css index 0477b6a..3371c7a 100644 --- a/src/components/simulation-view/simulation-view.css +++ b/src/components/simulation-view/simulation-view.css @@ -1,7 +1,7 @@ .simulation-view-wrapper { display: grid; - grid-template-rows: 63px auto; - grid-template-columns: 100px auto; + grid-template-rows: auto auto; + grid-template-columns: 66px auto; grid-template-areas: "simulation-view-header simulation-view-header" "simulation-view-sidebar simulation-view-mainview"; @@ -28,7 +28,7 @@ background-color: red; } -.simulation-view-flexlayout { +.flexlayout__layout { position: relative; height: calc(100vh - 63px); } @@ -69,7 +69,9 @@ margin: 2px; padding: 2px; font-size: 0.7em; + color: black; font-weight: bold; + background-color: lightgray; } iframe { diff --git a/src/components/simulation-view/simulation-view.js b/src/components/simulation-view/simulation-view.js index 8c903ae..568d8f4 100644 --- a/src/components/simulation-view/simulation-view.js +++ b/src/components/simulation-view/simulation-view.js @@ -1,12 +1,14 @@ import React from 'react'; import FlexLayout from 'flexlayout-react'; import { OverlayTrigger, Tooltip, Button } from 'react-bootstrap'; -import { RiPlayFill, RiLayout6Line } from 'react-icons/ri'; +import { RiPlayFill, RiPauseFill, RiLayout6Line } from 'react-icons/ri'; import { GiExitDoor } from 'react-icons/gi'; import { TiMediaRecord } from 'react-icons/ti'; import { VscDebugRestart } from 'react-icons/vsc'; import SimulationToolsService from './simulation-tools-service'; +import RunningSimulationService from '../../services/experiments/execution/running-simulation-service'; +import { EXPERIMENT_STATE } from '../../services/experiments/experiment-constants'; import '../../../node_modules/flexlayout-react/style/light.css'; import './simulation-view.css'; @@ -34,29 +36,34 @@ const jsonBaseLayout = { } }; -const classNameMapper = (className) => { - if (className === 'flexlayout__layout') { - return 'simulation-view-flexlayout'; - } - else { - return className; - } -}; - export default class SimulationView extends React.Component { constructor(props) { super(props); - console.info(this.state); - console.info(this.props); + + const {serverIP, simulationID} = props.match.params; + //console.info('SimulationView ' + serverIP + ' ' + simulationID); + this.serverIP = serverIP; + this.simulationID = simulationID; + this.serverURL = 'http://' + this.serverIP + ':8080'; this.state = {model: FlexLayout.Model.fromJson(jsonBaseLayout)}; - console.info(this.state); + this.updateSimulationInfo(); this.refLayout = React.createRef(); } - factory = (node) => { - return SimulationToolsService.instance.flexlayoutNodeFactory(node); + async updateSimulationInfo() { + let simInfo = await RunningSimulationService.instance.getInfo(this.serverURL, this.simulationID); + this.setState({simulationInfo: simInfo}); + } + + async onButtonStartPause() { + let newState = this.state.simulationInfo.state === EXPERIMENT_STATE.PAUSED + ? EXPERIMENT_STATE.STARTED + : EXPERIMENT_STATE.PAUSED; + await RunningSimulationService.instance.updateState(this.serverURL, this.simulationID, newState); + + this.updateSimulationInfo(); } render() { @@ -67,7 +74,13 @@ export default class SimulationView extends React.Component { <div className='simulation-view-control-buttons'> <button className='nrp-btn btn-default'><GiExitDoor className='icon' /></button> <button className='nrp-btn btn-default'><VscDebugRestart className='icon' /></button> - <button className='nrp-btn btn-default'><RiPlayFill className='icon' /></button> + <button className='nrp-btn btn-default' onClick={() => { + this.onButtonStartPause(); + }}> + {this.state.simulationInfo && this.state.simulationInfo.state === EXPERIMENT_STATE.PAUSED + ? <RiPlayFill className='icon' /> + : <RiPauseFill className='icon' />} + </button> <button className='nrp-btn btn-default'><TiMediaRecord className='icon' /></button> </div> @@ -108,8 +121,10 @@ export default class SimulationView extends React.Component { })} </div> <div className='simulation-view-mainview'> - <FlexLayout.Layout ref={this.refLayout} model={this.state.model} factory={this.factory} - classNameMapper={classNameMapper}/> + <FlexLayout.Layout ref={this.refLayout} model={this.state.model} + factory={(node) => { + return SimulationToolsService.instance.flexlayoutNodeFactory(node); + }} /> </div> </div> ); diff --git a/src/services/experiments/execution/experiment-execution-service.js b/src/services/experiments/execution/experiment-execution-service.js index 0076fbf..eb01587 100644 --- a/src/services/experiments/execution/experiment-execution-service.js +++ b/src/services/experiments/execution/experiment-execution-service.js @@ -200,7 +200,7 @@ class ExperimentExecutionService extends HttpService { return SimulationService.instance.updateState( serverURL, simulationID, - { state: state } + state ); } diff --git a/src/services/experiments/execution/running-simulation-service.js b/src/services/experiments/execution/running-simulation-service.js index 754ccc8..b5f148a 100644 --- a/src/services/experiments/execution/running-simulation-service.js +++ b/src/services/experiments/execution/running-simulation-service.js @@ -164,13 +164,30 @@ class SimulationService extends HttpService { async updateState(serverURL, simulationID, state) { let url = serverURL + '/simulation/' + simulationID + '/state'; try { - let response = await this.httpRequestPUT(url, JSON.stringify(state)); + let response = await this.httpRequestPUT(url, JSON.stringify({ state: state })); return response; } catch (error) { ErrorHandlerService.instance.updateSimulationError(error); } } + + /** + * Get simulation information. + * @param {string} serverURL The full URL of the server the simulation is running on + * @param {string} simulationID The simulation ID + * @returns The simulation information + */ + async getInfo(serverURL, simulationID) { + let url = serverURL + '/simulation/' + simulationID; + try { + let response = await (await this.httpRequestGET(url)).json(); + return response; + } + catch (error) { + ErrorHandlerService.instance.networkError(error); + } + } } export default SimulationService; -- GitLab