diff --git a/src/components/experiment-list/experiment-list-element.js b/src/components/experiment-list/experiment-list-element.js index 7e1170fb9e5af245d14c9ac2f3354fa11983489d..1734b1caae2ca8b03c2cd751d30a2bdf5624f4af 100644 --- a/src/components/experiment-list/experiment-list-element.js +++ b/src/components/experiment-list/experiment-list-element.js @@ -17,7 +17,9 @@ const SHORT_DESCRIPTION_LENGTH = 200; export default class ExperimentListElement extends React.Component { constructor(props) { super(props); - this.state = {}; + this.state = { + showSimDetails: true + }; //TODO: put in service? this.canLaunchExperiment = (this.props.experiment.private && this.props.experiment.owned) || @@ -164,8 +166,8 @@ export default class ExperimentListElement extends React.Component { }}> <div className='btn-group' role='group' > {this.canLaunchExperiment && - exp.configuration.experimentFile && exp.configuration.bibiConfSrc - ? <button onClick={() => { + exp.configuration.experimentFile && exp.configuration.bibiConfSrc ? + <button onClick={() => { ExperimentExecutionService.instance.startNewExperiment(exp, false); }} disabled={this.isLaunchDisabled()} @@ -177,74 +179,76 @@ export default class ExperimentListElement extends React.Component { {this.canLaunchExperiment && config.brainProcesses > 1 && this.props.availableServers.length > 0 && - exp.configuration.experimentFile && exp.configuration.bibiConfSrc - - ? <button className='btn btn-default'> + exp.configuration.experimentFile && exp.configuration.bibiConfSrc ? + <button className='btn btn-default'> <i className='fa fa-plus'></i> Launch in Single Process Mode </button> : null} {this.canLaunchExperiment && this.props.availableServers.length > 1 && - exp.configuration.experimentFile && exp.configuration.bibiConfSrc - - ? <button className='btn btn-default' > + exp.configuration.experimentFile && exp.configuration.bibiConfSrc ? + <button className='btn btn-default' > <i className='fa fa-layer-group'></i> Launch Multiple </button> : null} {/* isPrivateExperiment */} - {this.canLaunchExperiment - ? <button className='btn btn-default'> + {this.canLaunchExperiment ? + <button className='btn btn-default'> <i className='fa fa-times'></i> Delete </button> : null} {/* Records button */} - {this.canLaunchExperiment - ? <button className='btn btn-default'> + {this.canLaunchExperiment ? + <button className='btn btn-default'> <i className='fa fa-sign-in'></i> Recordings » </button> : null} {/* Export button */} - {this.canLaunchExperiment - ? <button className='btn btn-default'> + {this.canLaunchExperiment ? + <button className='btn btn-default'> <i className='fa fa-file-export'></i> Export </button> : null} {/* Simulations button */} - {this.canLaunchExperiment && exp.joinableServers.length > 0 - ? <button className='btn btn-default' > + {this.canLaunchExperiment && exp.joinableServers.length > 0 ? + <button className='btn btn-default' + onClick={() => { + this.setState({ showSimDetails: !this.state.showSimDetails }); + }}> <i className='fa fa-sign-in'></i> Simulations » </button> : null} {/* Clone button */} {config.canCloneExperiments && (!exp.configuration.privateStorage || - (exp.configuration.experimentFile && exp.configuration.bibiConfSrc)) - ? <button className='btn btn-default'> + (exp.configuration.experimentFile && exp.configuration.bibiConfSrc)) ? + <button className='btn btn-default'> <i className='fa fa-pencil-alt'></i> Clone </button> : null} {/* Files button */} - {this.canLaunchExperiment - ? <button className='btn btn-default' > + {this.canLaunchExperiment ? + <button className='btn btn-default' > <i className='fa fa-list-alt'></i> Files </button> : null} {/* Shared button */} - {this.canLaunchExperiment - ? <button className='btn btn-default'> + {this.canLaunchExperiment ? + <button className='btn btn-default'> <i className='fas fa-share-alt'></i> Share </button> : null} </div> </div> } - {this.state.selected /*&& exp.joinableServers.length > 0*/ ? + + {this.state.selected && exp.joinableServers.length > 0 && this.state.showSimDetails ? <SimulationDetails simulations={exp.joinableServers} /> : null } diff --git a/src/components/experiment-list/experiment-list.css b/src/components/experiment-list/experiment-list.css index 4921e81fae032a0bc82734757ad58f17aaf364bd..be1ab3c776ebb0ba1949c127d78177b43a552477 100644 --- a/src/components/experiment-list/experiment-list.css +++ b/src/components/experiment-list/experiment-list.css @@ -16,4 +16,10 @@ li.nostyle { grid-area: experiments; color: black; background-color: white; +} + +.no-items-notification { + margin: 10px; + font-size: 1.5em; + font-weight: bold; } \ No newline at end of file diff --git a/src/components/experiment-list/experiment-list.js b/src/components/experiment-list/experiment-list.js index 9cfd676aa06716cedbfc8326be77f3e2a915bdfd..737af9e60ef2c1c7145aca46898ab26da135287b 100644 --- a/src/components/experiment-list/experiment-list.js +++ b/src/components/experiment-list/experiment-list.js @@ -10,19 +10,19 @@ export default class ExperimentList extends React.Component { return ( <div className='experiment-list-wrapper'> <div className='experiment-list'> - <ImportExperimentButtons /> - <ol> - {this.props.experiments.map(experiment => { - return ( - <li key={experiment.id} className='nostyle'> - <ExperimentListElement experiment={experiment} - availableServers={this.props.availableServers} - startingExperiment={this.props.startingExperiment} /> - </li> - ); - } - )} - </ol> + {this.props.experiments.length === 0 ? + <div className='no-items-notification'>List is currently empty ...</div> : + <ol> + {this.props.experiments.map(experiment => { + return ( + <li key={experiment.id} className='nostyle'> + <ExperimentListElement experiment={experiment} + availableServers={this.props.availableServers} + startingExperiment={this.props.startingExperiment} /> + </li> + ); + })} + </ol>} </div> </div> ); diff --git a/src/services/experiments/execution/experiment-execution-service.js b/src/services/experiments/execution/experiment-execution-service.js index 360347b4cd7b0ca6bfbae0afec13d6982f09a9d0..c12d93c2dca2077ea76b04a83fffca22e331b1eb 100644 --- a/src/services/experiments/execution/experiment-execution-service.js +++ b/src/services/experiments/execution/experiment-execution-service.js @@ -59,7 +59,7 @@ class ExperimentExecutionService extends HttpService { //TODO: placeholder, register actual progress callback later let progressCallback = (msg) => { - console.info(msg); + //console.info(msg); }; let launchOnNextServer = async () => { @@ -157,10 +157,10 @@ class ExperimentExecutionService extends HttpService { .then((simulation) => { ExperimentServerService.instance.initConfigFiles(serverURL, simulation.simulationID) .then(() => { - ExperimentExecutionService.instance.emit(ExperimentExecutionService.EVENTS.START_EXPERIMENT, undefined); let simulationURL = 'esv-private/experiment-view/' + server + '/' + experimentID + '/' + privateExperiment + '/' + simulation.simulationID; resolve(simulationURL); + ExperimentExecutionService.instance.emit(ExperimentExecutionService.EVENTS.START_EXPERIMENT, undefined); }) .catch(reject); }) diff --git a/src/services/experiments/execution/experiment-server-service.js b/src/services/experiments/execution/experiment-server-service.js index 3e31b5dbf5eb06cec2b0d1dcc304630ee8b1e6b9..b9f17b2a4f8fb83864d3e797837f50794939681c 100644 --- a/src/services/experiments/execution/experiment-server-service.js +++ b/src/services/experiments/execution/experiment-server-service.js @@ -17,9 +17,9 @@ let _instance = null; const SINGLETON_ENFORCER = Symbol(); let rosConnections = new Map(); -const SLURM_MONITOR_POLL_INTERVAL = 5000; -const POLL_INTERVAL_SERVER_AVAILABILITY = 3000; -const CHECK_SIMULATION_READY_INTERVAL = 1000; +const INTERVAL_POLL__SLURM_MONITOR = 5000; +const INTERVAL_POLL_SERVER_AVAILABILITY = 3000; +const INTERVAL_CHECK_SIMULATION_READY = 1000; let clusterAvailability = { free: 'N/A', total: 'N/A' }; /** @@ -33,7 +33,7 @@ class ExperimentServerService extends HttpService { } //TODO: a bit too much code for a constructor, move into its own function - this.clusterAvailabilityObservable = timer(0, SLURM_MONITOR_POLL_INTERVAL) + this.clusterAvailabilityObservable = timer(0, INTERVAL_POLL__SLURM_MONITOR) .pipe(switchMap(() => { try { return this.httpRequestGET(slurmMonitorURL); @@ -82,7 +82,7 @@ class ExperimentServerService extends HttpService { () => { this.getServerAvailability(true); }, - POLL_INTERVAL_SERVER_AVAILABILITY + INTERVAL_POLL_SERVER_AVAILABILITY ); } @@ -190,7 +190,7 @@ class ExperimentServerService extends HttpService { verifySimulation(); } }).catch(reject); - }, CHECK_SIMULATION_READY_INTERVAL); + }, INTERVAL_CHECK_SIMULATION_READY); }; verifySimulation(); @@ -239,6 +239,7 @@ class ExperimentServerService extends HttpService { }); }; + //TODO: maybe move to separate simulation-status-service async getSimulationState(serverURL, simulationID) { let url = serverURL + '/simulation/' + simulationID + '/state'; try { diff --git a/src/services/experiments/storage/experiment-storage-service.js b/src/services/experiments/storage/experiment-storage-service.js index ea88adb6092a5d74353843626721f3b34fc5c868..a63038cff7c8a97e4a7812ca8531bfb4d731a116 100644 --- a/src/services/experiments/storage/experiment-storage-service.js +++ b/src/services/experiments/storage/experiment-storage-service.js @@ -66,6 +66,7 @@ class ExperimentStorageService extends HttpService { * them in the experiments class property. If the experiments are already * there it just returns them, else does an HTTP request. * + * @param {boolean} forceUpdate forces an update of the list * @return experiments - the list of template experiments */ async getExperiments(forceUpdate = false) { @@ -74,6 +75,7 @@ class ExperimentStorageService extends HttpService { this.experiments = await response.json(); this.sortExperiments(); await this.fillExperimentDetails(); + console.info('experiment lsit update'); this.emit(ExperimentStorageService.EVENTS.UPDATE_EXPERIMENTS, this.experiments); }