Nice update/register panels
This commit is contained in:
@@ -111,9 +111,10 @@ nav.navbar.navbar-inverse.navbar-fixed-top(role = 'navigation')
|
||||
li
|
||||
a(ui-sref="settings.update")
|
||||
i.fa.fa-question-circle.text-warning(ng-if = '!navbar.updater.state', tooltip = 'No update information available')
|
||||
i.fa.fa-question-circle.text-info(ng-if = 'navbar.updater.state == "connected"', tooltip = 'Update information may be available')
|
||||
i.fa.fa-check.text-success(ng-if = 'navbar.updater.state == "upToDate"', tooltip = 'Your XOA is up-to-date (*.*)')
|
||||
i.fa.fa-bell.text-primary(ng-if = 'navbar.updater.state == "updateNeeded"', tooltip = 'You need to update your XOA (new version *.* is available)')
|
||||
i.fa.fa-bell-slash.text-info(ng-if = 'navbar.updater.state == "registerNeeded"', tooltip = 'Your XOA is not registered for updates')
|
||||
i.fa.fa-bell.text-primary(ng-if = 'navbar.updater.state == "upgradeNeeded"', tooltip = 'You need to update your XOA (new version *.* is available)')
|
||||
i.fa.fa-bell-slash.text-warning(ng-if = 'navbar.updater.state == "registerNeeded"', tooltip = 'Your XOA is not registered for updates')
|
||||
i.fa.fa-exclamation-triangle.text-danger(ng-if = 'navbar.updater.state == "error"', tooltip = 'Can\'t fetch update information')
|
||||
|
||||
li
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import angular from 'angular';
|
||||
import uiRouter from 'angular-ui-router';
|
||||
import angular from 'angular'
|
||||
import uiRouter from 'angular-ui-router'
|
||||
|
||||
import ansiUp from 'ansi_up'
|
||||
import updater from '../../updater';
|
||||
import xoApi from 'xo-api';
|
||||
import xoServices from 'xo-services';
|
||||
import updater from '../../updater'
|
||||
import {AuthenticationFailed} from '../../updater'
|
||||
import xoApi from 'xo-api'
|
||||
import xoServices from 'xo-services'
|
||||
|
||||
import view from './view';
|
||||
import view from './view'
|
||||
|
||||
export default angular.module('settings.update', [
|
||||
uiRouter,
|
||||
@@ -29,8 +30,24 @@ export default angular.module('settings.update', [
|
||||
return $sce.trustAsHtml(ansiUp.ansi_to_html(input))
|
||||
}
|
||||
})
|
||||
.controller('SettingsUpdate', function (xoApi, xo, updater) {
|
||||
.controller('SettingsUpdate', function (xoApi, xo, updater, register) {
|
||||
this.updater = updater
|
||||
this.register = register
|
||||
this.register.isRegistered()
|
||||
.then(() => this.updater.on('end', () => {
|
||||
if (this.updater.state === 'registerNeeded' && this.register.state !== 'unregistered' && this.register.state !== 'error') {
|
||||
this.register.isRegistered()
|
||||
}
|
||||
}))
|
||||
|
||||
this.authFailed = false
|
||||
|
||||
this.registerXoa = (email, password) => {
|
||||
this.regPwd = ''
|
||||
this.register.register(email, password)
|
||||
.then(() => this.updater.verify())
|
||||
.catch(AuthenticationFailed, () => {})
|
||||
}
|
||||
})
|
||||
.name
|
||||
;
|
||||
|
||||
@@ -9,13 +9,25 @@
|
||||
i.fa.fa-globe(style="color: #e25440;")
|
||||
| Status
|
||||
.panel-body
|
||||
p(ng-if = '!ctrl.updater.state') No update information available
|
||||
p(ng-if = '!ctrl.updater.state')
|
||||
a.btn.btn-warning: i.fa.fa-question-circle(ng-if = '!ctrl.updater.state', tooltip = 'No update information available')
|
||||
| No update information available
|
||||
.form-group(ng-if = 'ctrl.updater.state && ctrl.updater.state === "registerNeeded"')
|
||||
p registerNeeded
|
||||
a.btn.btn-warning(ng-if = 'ctrl.updater.state === "registerNeeded"'): i.fa.fa-bell-slash(tooltip = 'Your XOA is not registered for updates')
|
||||
| Register needed
|
||||
.form-group(ng-if = 'ctrl.updater.state && ctrl.updater.state !== "registerNeeded"')
|
||||
button.btn.btn-info(type = 'button', ng-click = 'ctrl.updater.verify()') Check for updates
|
||||
a.btn.btn-info(ng-if = 'ctrl.updater.state === "connected"'): i.fa.fa-question-circle(tooltip = 'Update information may be available')
|
||||
a.btn.btn-success(ng-if = 'ctrl.updater.state === "upToDate"'): i.fa.fa-check(tooltip = 'Your XOA is up-to-date (*.*)')
|
||||
a.btn.btn-primary(ng-if = 'ctrl.updater.state === "upgradeNeeded"'): i.fa.fa-bell(tooltip = 'You need to update your XOA (new version *.* is available)')
|
||||
a.btn.btn-danger(ng-if = 'ctrl.updater.state === "error"'): i.fa.fa-exclamation-triangle(tooltip = 'Can\'t fetch update information')
|
||||
|
|
||||
button.btn.primary(type = 'button', ng-click = 'ctrl.updater.update()', ng-class = '{disabled: ctrl.updater.state !== "updateNeeded"}') Update
|
||||
button.btn.btn-info(type = 'button', ng-click = 'ctrl.updater.verify()')
|
||||
| Check for updates
|
||||
i.fa.fa-refresh
|
||||
|
|
||||
button.btn.btn-primary(ng-if = 'ctrl.updater.state === "upgradeNeeded"', type = 'button', ng-click = 'ctrl.updater.update()')
|
||||
| Upgrade
|
||||
i.fa.fa-cogs
|
||||
div
|
||||
p(ng-repeat = 'entry in ctrl.updater._log')
|
||||
strong(ng-class = '{"text-danger": entry.level === "error", "text-muted": entry.level === "info", "text-warning": entry.level === "warning", "text-success": entry.level === "success"}') {{ entry.date }}
|
||||
@@ -27,5 +39,28 @@
|
||||
i.fa.fa-star(style="color: #e25440;")
|
||||
| Registration
|
||||
.panel-body.text-center
|
||||
p Registration needed.
|
||||
p Or Regitration status (OK etc.)
|
||||
//- p {{ ctrl.register.state }} {{ ctrl.register.state === "error" }}
|
||||
.text-warning(ng-if = 'ctrl.register.state === "unknown"') No registration information available.
|
||||
div(ng-if = 'ctrl.register.state === "error"')
|
||||
.text-danger Can't fetch registration information.
|
||||
br
|
||||
.text-danger {{ ctrl.register.error }}
|
||||
br
|
||||
button.btn.btn-default(type = 'button', ng-click = 'ctrl.register.isRegistered()')
|
||||
| Refresh
|
||||
i.fa.fa-refresh
|
||||
form(ng-if = 'ctrl.register.state === "unregistered"', ng-submit = 'ctrl.registerXoa(ctrl.regEmail, ctrl.regPwd)')
|
||||
p.form-static-control Your Xen Orchestra appliance is not registered.
|
||||
.form-group
|
||||
label.sr-only(for = 'regEmail') Email
|
||||
input#regEmail.form-control(type = 'email', placeholder = 'Email', ng-model = 'ctrl.regEmail', required)
|
||||
.form-group
|
||||
label.sr-only(for = 'regPwd') Email
|
||||
input#regPwd.form-control(type = 'password', placeholder = 'Password', ng-model = 'ctrl.regPwd', required)
|
||||
.form-group
|
||||
button.btn.btn-primary(type = 'submit') Register
|
||||
p.form-static-control.text-danger {{ ctrl.register.error }}
|
||||
p(ng-if = 'ctrl.register.state === "registered"')
|
||||
| Your Xen Orchestra appliance is registered to
|
||||
span.text-primary {{ ctrl.register.token.registrationEmail }}
|
||||
| .
|
||||
|
||||
@@ -1,8 +1,43 @@
|
||||
import angular from 'angular'
|
||||
import Bluebird from 'bluebird'
|
||||
import {EventEmitter} from 'events'
|
||||
import * as format from '@julien-f/json-rpc/format'
|
||||
import makeError from 'make-error'
|
||||
import parse from '@julien-f/json-rpc/parse'
|
||||
import Socket from 'socket.io-client'
|
||||
|
||||
function jsonRpcCall (socket, method, params = {}) {
|
||||
let resolver, rejecter
|
||||
const promise = new Bluebird((resolve, reject) => {
|
||||
resolver = resolve
|
||||
rejecter = reject
|
||||
})
|
||||
socket.emit(
|
||||
'jsonrpc',
|
||||
format.request(method, params),
|
||||
message => {
|
||||
const {result, error} = parse(message)
|
||||
if (result) {
|
||||
resolver(result)
|
||||
} else if (error) {
|
||||
rejecter(error)
|
||||
} else {
|
||||
throw new Error('Unexpected response')
|
||||
}
|
||||
}
|
||||
)
|
||||
return promise
|
||||
}
|
||||
|
||||
function jsonRpcNotify (socket, method, params = {}) {
|
||||
socket.emit(
|
||||
'jsonrpc',
|
||||
format.notification(method, params)
|
||||
)
|
||||
}
|
||||
|
||||
export const NotRegistered = makeError('NotRegistered')
|
||||
export const AuthenticationFailed = makeError('AuthenticationFailed')
|
||||
export default angular.module('updater', [])
|
||||
|
||||
.factory('updater', function ($interval) {
|
||||
@@ -30,12 +65,11 @@ export default angular.module('updater', [])
|
||||
this._connection = new Bluebird((resolve, reject) => {
|
||||
const socket = new Socket('http://localhost:9001')
|
||||
socket.on('print', content => {
|
||||
this.emit('print', content)
|
||||
Array.isArray(content) || (content = [content])
|
||||
content.forEach(elem => this.log('info', elem))
|
||||
this.emit('print', content)
|
||||
})
|
||||
socket.on('end', end => {
|
||||
this.emit('end', end)
|
||||
this._lowState = end
|
||||
switch (this._lowState.state) {
|
||||
case 'xoa-up-to-date':
|
||||
@@ -45,7 +79,7 @@ export default angular.module('updater', [])
|
||||
break
|
||||
case 'xoa-update-needed':
|
||||
case 'updater-update-needed':
|
||||
this.state = 'updateNeeded'
|
||||
this.state = 'upgradeNeeded'
|
||||
break
|
||||
case 'register-needed':
|
||||
this.state = 'registerNeeded'
|
||||
@@ -58,21 +92,24 @@ export default angular.module('updater', [])
|
||||
}
|
||||
this.log(end.level, end.message)
|
||||
this._lastRun = Date.now()
|
||||
this.emit('end', end)
|
||||
})
|
||||
socket.on('error', error => {
|
||||
this.log('error', error.message)
|
||||
this.emit('error', error)
|
||||
this._lowState = error
|
||||
this.state = 'error'
|
||||
this.emit('error', error)
|
||||
})
|
||||
socket.on('connected', connected => {
|
||||
this.log('info', connected)
|
||||
this.emit('connected', connected)
|
||||
this.state = 'connected'
|
||||
resolve(socket)
|
||||
this.emit('connected', connected)
|
||||
})
|
||||
socket.on('disconnect', () => {
|
||||
socket.removeAllListeners()
|
||||
this._connection = null
|
||||
this._lowState = null
|
||||
this.state = null
|
||||
this.emit('disconnect')
|
||||
})
|
||||
})
|
||||
return this._connection
|
||||
@@ -81,7 +118,7 @@ export default angular.module('updater', [])
|
||||
|
||||
_update (update = false) {
|
||||
this._open()
|
||||
.then(socket => socket.emit('jsonrpc', '{"jsonrpc":"2.0","method":"main", "params": {"update": ' + update + '}}'))
|
||||
.then(socket => jsonRpcNotify(socket, 'main', {update}))
|
||||
}
|
||||
|
||||
start () {
|
||||
@@ -123,4 +160,73 @@ export default angular.module('updater', [])
|
||||
return new Updater()
|
||||
})
|
||||
|
||||
.factory('register', function () {
|
||||
class Register {
|
||||
constructor () {
|
||||
this._connection = null
|
||||
this.token = null
|
||||
this.state = 'unknown'
|
||||
this.error = ''
|
||||
}
|
||||
|
||||
_open () {
|
||||
if (this._connection) {
|
||||
return this._connection
|
||||
} else {
|
||||
this._connection = new Bluebird((resolve, reject) => {
|
||||
const socket = new Socket('http://localhost:9002')
|
||||
socket.on('connected', connected => {
|
||||
resolve(socket)
|
||||
})
|
||||
})
|
||||
return this._connection
|
||||
}
|
||||
}
|
||||
|
||||
isRegistered () {
|
||||
return this._open()
|
||||
.then(socket => {
|
||||
return jsonRpcCall(socket, 'isRegistered')
|
||||
.then(token => {
|
||||
if (token.registrationToken === undefined) {
|
||||
throw new NotRegistered('Your Xen Orchestra Appliance is not registered')
|
||||
} else {
|
||||
this.state = 'registered'
|
||||
this.token = token
|
||||
return token
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(NotRegistered, () => this.state = 'unregistered')
|
||||
.catch(error => {
|
||||
this.error = error.message
|
||||
this.state = 'error'
|
||||
})
|
||||
}
|
||||
|
||||
register (email, password) {
|
||||
return this._open()
|
||||
.then(socket => {
|
||||
return jsonRpcCall(socket, 'register', {email, password})
|
||||
.then(token => {
|
||||
this.state = 'registered'
|
||||
this.token = token
|
||||
return token
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.code && error.code === 1) {
|
||||
this.error = 'Authentication failed'
|
||||
throw new AuthenticationFailed('Authentication failed')
|
||||
} else {
|
||||
this.error = error.message
|
||||
this.state = 'error'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return new Register()
|
||||
})
|
||||
|
||||
.name
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"web"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@julien-f/json-rpc": "^0.4.3",
|
||||
"angular": "^1.3.15",
|
||||
"angular-animate": "^1.3.15",
|
||||
"angular-bootstrap": "^0.12.0",
|
||||
@@ -49,6 +50,7 @@
|
||||
"lodash.indexof": "^3.0.2",
|
||||
"lodash.sortby": "^3.1.0",
|
||||
"lodash.throttle": "^3.0.1",
|
||||
"make-error": "^1.0.2",
|
||||
"novnc-node": "^0.5.1",
|
||||
"rimraf": "^2.3.2",
|
||||
"socket.io-client": "^1.3.5",
|
||||
|
||||
Reference in New Issue
Block a user