const url = window.baseUrl + '/api/system/info'; | const url = window.baseUrl + '/api/system/info'; | ||||
return getJSON(url); | return getJSON(url); | ||||
} | } | ||||
export function getStatus () { | |||||
const url = window.baseUrl + '/api/system/status'; | |||||
return getJSON(url); | |||||
} | |||||
export function restart () { | |||||
const url = window.baseUrl + '/api/system/restart'; | |||||
return post(url); | |||||
} | |||||
const POLLING_INTERVAL = 2000; | |||||
function pollStatus (cb) { | |||||
setTimeout(() => { | |||||
getStatus() | |||||
.then(() => cb()) | |||||
.catch(() => pollStatus(cb)); | |||||
}, POLLING_INTERVAL); | |||||
} | |||||
function promiseStatus () { | |||||
return new Promise(resolve => pollStatus(resolve)); | |||||
} | |||||
export function restartAndWait () { | |||||
return restart().then(promiseStatus); | |||||
} |
*/ | */ | ||||
import _ from 'underscore'; | import _ from 'underscore'; | ||||
import React from 'react'; | import React from 'react'; | ||||
import { getSystemInfo } from '../../api/system'; | |||||
import { getSystemInfo, restartAndWait } from '../../api/system'; | |||||
import Section from './section'; | import Section from './section'; | ||||
import { translate } from '../../helpers/l10n'; | import { translate } from '../../helpers/l10n'; | ||||
'ComputeEngine']; | 'ComputeEngine']; | ||||
export default React.createClass({ | export default React.createClass({ | ||||
getInitialState() { | |||||
return { restarting: false }; | |||||
}, | |||||
componentDidMount() { | componentDidMount() { | ||||
getSystemInfo().then(info => this.setState({ sections: this.parseSections(info) })); | getSystemInfo().then(info => this.setState({ sections: this.parseSections(info) })); | ||||
}, | }, | ||||
return _.sortBy(items, 'name'); | return _.sortBy(items, 'name'); | ||||
}, | }, | ||||
handleServerRestart () { | |||||
this.setState({ restarting: true }); | |||||
restartAndWait().then(() => { | |||||
document.location.reload(); | |||||
}); | |||||
}, | |||||
render() { | render() { | ||||
let sections = null; | let sections = null; | ||||
if (this.state && this.state.sections) { | |||||
if (this.state.sections) { | |||||
sections = this.state.sections.map(section => { | sections = this.state.sections.map(section => { | ||||
return <Section key={section.name} section={section.name} items={section.items}/>; | return <Section key={section.name} section={section.name} items={section.items}/>; | ||||
}); | }); | ||||
<div className="page-actions"> | <div className="page-actions"> | ||||
<a className="spacer-right" href={window.baseUrl + '/api/system/logs'} id="logs-link">Logs</a> | <a className="spacer-right" href={window.baseUrl + '/api/system/logs'} id="logs-link">Logs</a> | ||||
<a href={window.baseUrl + '/api/system/info'} id="download-link">Download</a> | <a href={window.baseUrl + '/api/system/info'} id="download-link">Download</a> | ||||
{this.state.restarting ? ( | |||||
<i className="spinner"/> | |||||
) : ( | |||||
<button | |||||
id="restart-server-button" | |||||
className="big-spacer-left" | |||||
onClick={this.handleServerRestart}> | |||||
Restart Server | |||||
</button> | |||||
)} | |||||
</div> | </div> | ||||
</header> | </header> | ||||
{sections} | {sections} |
import _ from 'underscore'; | import _ from 'underscore'; | ||||
import Marionette from 'backbone.marionette'; | import Marionette from 'backbone.marionette'; | ||||
import Template from './templates/update-center-header.hbs'; | import Template from './templates/update-center-header.hbs'; | ||||
import { restartAndWait } from '../../api/system'; | |||||
export default Marionette.ItemView.extend({ | export default Marionette.ItemView.extend({ | ||||
template: Template, | template: Template, | ||||
}, | }, | ||||
events: { | events: { | ||||
'click .js-restart': 'restart', | |||||
'click .js-cancel-all': 'cancelAll' | 'click .js-cancel-all': 'cancelAll' | ||||
}, | }, | ||||
cancelAll: function () { | |||||
initialize () { | |||||
this.restarting = false; | |||||
}, | |||||
restart () { | |||||
this.restarting = true; | |||||
this.render(); | |||||
restartAndWait().then(() => { | |||||
document.location.reload(true); | |||||
}); | |||||
}, | |||||
cancelAll () { | |||||
this.collection.cancelAll(); | this.collection.cancelAll(); | ||||
}, | }, | ||||
serializeData: function () { | |||||
serializeData () { | |||||
return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { | return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { | ||||
installing: this.collection._installedCount, | installing: this.collection._installedCount, | ||||
uninstalling: this.collection._uninstalledCount | |||||
uninstalling: this.collection._uninstalledCount, | |||||
restarting: this.restarting | |||||
}); | }); | ||||
} | } | ||||
}); | }); |
{{/if}} | {{/if}} | ||||
</p> | </p> | ||||
</div> | </div> | ||||
<div class="button-group pull-right"> | |||||
<button class="js-cancel-all button-red">Revert</button> | |||||
<div class="pull-right"> | |||||
{{#if restarting}} | |||||
<i class="spinner"></i> | |||||
{{else}} | |||||
<button class="js-restart">Restart</button> | |||||
<button class="js-cancel-all button-red">Revert</button> | |||||
{{/if}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{/any}} | {{/any}} |
float: right; | float: right; | ||||
margin-bottom: 10px; | margin-bottom: 10px; | ||||
margin-left: 10px; | margin-left: 10px; | ||||
line-height: @formControlHeight; | |||||
.badge { | .badge { | ||||
margin: 3px 0; | margin: 3px 0; | ||||
} | } | ||||
.spinner { | |||||
top: 0 !important; | |||||
} | |||||
} | } | ||||
.page-description { | .page-description { |