Skip to content
Snippets Groups Projects
Commit 20b706a2 authored by Sandro Weber's avatar Sandro Weber
Browse files

experiment overview and tabs

parent c0fd0871
No related branches found
No related tags found
No related merge requests found
...@@ -3,7 +3,7 @@ import React from 'react'; ...@@ -3,7 +3,7 @@ import React from 'react';
import { HashRouter, Switch, Route } from 'react-router-dom'; import { HashRouter, Switch, Route } from 'react-router-dom';
import EntryPage from './components/entry-page/entry-page.js'; import EntryPage from './components/entry-page/entry-page.js';
import ExperimentList from './components/experiment-list/experiment-list.js'; import ExperimentOverview from './components/experiment-overview/experiment-overview.js';
class App extends React.Component { class App extends React.Component {
render() { render() {
...@@ -11,7 +11,7 @@ class App extends React.Component { ...@@ -11,7 +11,7 @@ class App extends React.Component {
<HashRouter> <HashRouter>
<Switch> <Switch>
<Route path='/experiments-overview'> <Route path='/experiments-overview'>
<ExperimentList /> <ExperimentOverview />
</Route> </Route>
<Route path='/'> <Route path='/'>
<EntryPage /> <EntryPage />
......
...@@ -2,21 +2,16 @@ li.nostyle { ...@@ -2,21 +2,16 @@ li.nostyle {
list-style-type: none; list-style-type: none;
} }
.experiment-page { .experiment-list-wrapper {
height: 100vh; height: 100vh;
display: grid; display: grid;
grid-template-rows: 200px auto; grid-template-rows: auto;
grid-template-columns: auto minmax(250px, 500px) minmax(250px, 500px) auto; grid-template-columns: auto;
grid-template-areas: grid-template-areas:
"header header header header" "experiments";
"experiments experiments experiments experiments";
}
.experiment-list-header {
grid-area: header;
} }
.experiment-page-experiments { .experiment-list {
text-align: left; text-align: left;
grid-area: experiments; grid-area: experiments;
color: black; color: black;
......
...@@ -4,7 +4,6 @@ import ExperimentStorageService from '../../services/experiments/storage/experim ...@@ -4,7 +4,6 @@ import ExperimentStorageService from '../../services/experiments/storage/experim
import ExperimentServerService from '../../services/experiments/execution/experiment-server-service.js'; import ExperimentServerService from '../../services/experiments/execution/experiment-server-service.js';
import ExperimentExecutionService from '../../services/experiments/execution/experiment-execution-service.js'; import ExperimentExecutionService from '../../services/experiments/execution/experiment-execution-service.js';
import NrpHeader from '../nrp-header/nrp-header.js';
import ExperimentListElement from './experiment-list-element.js'; import ExperimentListElement from './experiment-list-element.js';
import './experiment-list.css'; import './experiment-list.css';
...@@ -14,6 +13,8 @@ export default class ExperimentList extends React.Component { ...@@ -14,6 +13,8 @@ export default class ExperimentList extends React.Component {
super(props); super(props);
this.state = { this.state = {
experiments: [], experiments: [],
availableServers: [],
startingExperiment: undefined,
pageState: {} pageState: {}
}; };
} }
...@@ -48,7 +49,7 @@ export default class ExperimentList extends React.Component { ...@@ -48,7 +49,7 @@ export default class ExperimentList extends React.Component {
this.onUpdateServerAvailability this.onUpdateServerAvailability
); );
ExperimentServerService.instance.removeListener( ExperimentExecutionService.instance.removeListener(
ExperimentExecutionService.EVENTS.START_EXPERIMENT, ExperimentExecutionService.EVENTS.START_EXPERIMENT,
this.onStartExperiment this.onStartExperiment
); );
...@@ -64,12 +65,8 @@ export default class ExperimentList extends React.Component { ...@@ -64,12 +65,8 @@ export default class ExperimentList extends React.Component {
render() { render() {
return ( return (
<div className='experiment-page'> <div className='experiment-list-wrapper'>
<div className='experiment-list-header'> <div className='experiment-list'>
<NrpHeader title1='EXPERIMENT' title2='OVERVIEW' />
</div>
<div className='experiment-page-experiments'>
<ol> <ol>
{this.state.experiments.map(experiment => { {this.state.experiments.map(experiment => {
return ( return (
......
.experiment-overview-wrapper {
height: 100vh;
display: grid;
grid-template-rows: 200px auto;
grid-template-columns: auto;
grid-template-areas:
"header"
"tabs-view";
}
.experiment-overview-header {
grid-area: header;
}
.tabs-view {
grid-area: tabs-view;
}
\ No newline at end of file
import React from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import 'react-tabs/style/react-tabs.css';
import ExperimentStorageService from '../../services/experiments/storage/experiment-storage-service.js';
//import ExperimentServerService from '../../services/experiments/execution/experiment-server-service.js';
//import ExperimentExecutionService from '../../services/experiments/execution/experiment-execution-service.js';
import ExperimentList from '../experiment-list/experiment-list.js';
import NrpHeader from '../nrp-header/nrp-header.js';
import './experiment-overview.css';
export default class ExperimentOverview extends React.Component {
constructor(props) {
super(props);
this.state = {
experiments: [],
pageState: {}
};
}
async componentDidMount() {
try {
const experiments = await ExperimentStorageService.instance.getExperiments();
this.setState({
experiments: experiments
});
}
catch (error) {
console.error(`Failed to fetch the list of experiments. Error: ${error}`);
}
/*this.onUpdateServerAvailability = this.onUpdateServerAvailability.bind(this);
ExperimentServerService.instance.addListener(
ExperimentServerService.EVENTS.UPDATE_SERVER_AVAILABILITY,
this.onUpdateServerAvailability
);
this.onStartExperiment = this.onStartExperiment.bind(this);
ExperimentExecutionService.instance.addListener(
ExperimentExecutionService.EVENTS.START_EXPERIMENT,
this.onStartExperiment
);*/
}
componentWillUnmount() {
/*ExperimentServerService.instance.removeListener(
ExperimentServerService.EVENTS.UPDATE_SERVER_AVAILABILITY,
this.onUpdateServerAvailability
);
ExperimentServerService.instance.removeListener(
ExperimentExecutionService.EVENTS.START_EXPERIMENT,
this.onStartExperiment
);*/
}
/*onUpdateServerAvailability(availableServers) {
this.setState({availableServers: availableServers});
};
onStartExperiment(experiment) {
this.setState({startingExperiment: experiment});
};*/
render() {
return (
<div className='experiment-overview-wrapper'>
<div className='experiment-overview-header'>
<NrpHeader title1='EXPERIMENT' title2='OVERVIEW' />
</div>
<Tabs className="tabs-view">
<TabList>
<Tab>My Experiments</Tab>
<Tab>New Experiment</Tab>
<Tab>Model Libraries</Tab>
<Tab>Experiment Files</Tab>
<Tab>Templates</Tab>
<Tab>Running Simulations</Tab>
</TabList>
<TabPanel>
<ExperimentList />
</TabPanel>
<TabPanel>
<h2>"New Experiment" tab coming soon ...</h2>
</TabPanel>
<TabPanel>
<h2>"Model Libraries" tab coming soon ...</h2>
</TabPanel>
<TabPanel>
<h2>"Experiment Files" tab coming soon ...</h2>
</TabPanel>
<TabPanel>
<h2>"Templates" tab coming soon ...</h2>
</TabPanel>
<TabPanel>
<h2>"Running Simulations" tab coming soon ...</h2>
</TabPanel>
</Tabs>
</div>
);
}
}
...@@ -45,7 +45,6 @@ class ExperimentExecutionService extends HttpService { ...@@ -45,7 +45,6 @@ class ExperimentExecutionService extends HttpService {
NrpAnalyticsService.instance.eventTrack('Start', { category: 'Experiment' }); NrpAnalyticsService.instance.eventTrack('Start', { category: 'Experiment' });
NrpAnalyticsService.instance.tickDurationEvent('Server-initialization'); NrpAnalyticsService.instance.tickDurationEvent('Server-initialization');
//this.startingExperiment = experiment;
ExperimentExecutionService.instance.emit(ExperimentExecutionService.EVENTS.START_EXPERIMENT, experiment); ExperimentExecutionService.instance.emit(ExperimentExecutionService.EVENTS.START_EXPERIMENT, experiment);
let fatalErrorOccurred = false, let fatalErrorOccurred = false,
...@@ -155,7 +154,6 @@ class ExperimentExecutionService extends HttpService { ...@@ -155,7 +154,6 @@ class ExperimentExecutionService extends HttpService {
.then((simulation) => { .then((simulation) => {
ExperimentServerService.instance.initConfigFiles(serverURL, simulation.simulationID) ExperimentServerService.instance.initConfigFiles(serverURL, simulation.simulationID)
.then(() => { .then(() => {
//this.startingExperiment = undefined;
ExperimentExecutionService.instance.emit(ExperimentExecutionService.EVENTS.START_EXPERIMENT, undefined); ExperimentExecutionService.instance.emit(ExperimentExecutionService.EVENTS.START_EXPERIMENT, undefined);
resolve( resolve(
'esv-private/experiment-view/' + 'esv-private/experiment-view/' +
......
...@@ -18,7 +18,7 @@ const SINGLETON_ENFORCER = Symbol(); ...@@ -18,7 +18,7 @@ const SINGLETON_ENFORCER = Symbol();
let rosConnections = new Map(); let rosConnections = new Map();
const SLURM_MONITOR_POLL_INTERVAL = 5000; const SLURM_MONITOR_POLL_INTERVAL = 5000;
const SERVER_AVAILABILITY_POLL_INTERVAL = 3000; const POLL_INTERVAL_SERVER_AVAILABILITY = 3000;
let clusterAvailability = { free: 'N/A', total: 'N/A' }; let clusterAvailability = { free: 'N/A', total: 'N/A' };
/** /**
...@@ -31,6 +31,7 @@ class ExperimentServerService extends HttpService { ...@@ -31,6 +31,7 @@ class ExperimentServerService extends HttpService {
throw new Error('Use ' + this.constructor.name + '.instance'); throw new Error('Use ' + this.constructor.name + '.instance');
} }
//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, SLURM_MONITOR_POLL_INTERVAL)
.pipe(switchMap(() => { .pipe(switchMap(() => {
try { try {
...@@ -80,7 +81,7 @@ class ExperimentServerService extends HttpService { ...@@ -80,7 +81,7 @@ class ExperimentServerService extends HttpService {
() => { () => {
this.getServerAvailability(true); this.getServerAvailability(true);
}, },
SERVER_AVAILABILITY_POLL_INTERVAL POLL_INTERVAL_SERVER_AVAILABILITY
); );
} }
......
...@@ -7,6 +7,8 @@ const storageExperimentsURL = `${config.api.proxy.url}${endpoints.proxy.storage. ...@@ -7,6 +7,8 @@ const storageExperimentsURL = `${config.api.proxy.url}${endpoints.proxy.storage.
let _instance = null; let _instance = null;
const SINGLETON_ENFORCER = Symbol(); const SINGLETON_ENFORCER = Symbol();
const POLL_INTERVAL_EXPERIMENTS = 3000;
/** /**
* Service that fetches the template experiments list from the proxy given * Service that fetches the template experiments list from the proxy given
* that the user has authenticated successfully. * that the user has authenticated successfully.
...@@ -17,6 +19,11 @@ class ExperimentStorageService extends HttpService { ...@@ -17,6 +19,11 @@ class ExperimentStorageService extends HttpService {
if (enforcer !== SINGLETON_ENFORCER) { if (enforcer !== SINGLETON_ENFORCER) {
throw new Error('Use ' + this.constructor.name + '.instance'); throw new Error('Use ' + this.constructor.name + '.instance');
} }
this.startUpdates();
window.onbeforeunload = () => {
this.stopUpdates();
};
} }
static get instance() { static get instance() {
...@@ -27,6 +34,26 @@ class ExperimentStorageService extends HttpService { ...@@ -27,6 +34,26 @@ class ExperimentStorageService extends HttpService {
return _instance; return _instance;
} }
/**
* Start polling updates.
*/
startUpdates() {
this.getExperiments(true);
this.timerPollExperiments = setInterval(
() => {
this.getExperiments(true);
},
POLL_INTERVAL_EXPERIMENTS
);
}
/**
* Stop polling updates.
*/
stopUpdates() {
this.timerPollExperiments && clearInterval(this.timerPollExperiments);
}
/** /**
* Retrieves the list of template experiments from the proxy and stores * Retrieves the list of template experiments from the proxy and stores
* them in the experiments class property. If the experiments are already * them in the experiments class property. If the experiments are already
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment