Merge pull request #280 from home-assistant/hassio-fixes

Hassio fixes
This commit is contained in:
Paulus Schoutsen 2017-05-11 22:07:34 -07:00 committed by GitHub
commit 3f68619e3a
10 changed files with 278 additions and 36 deletions

View File

@ -13,21 +13,26 @@
paper-card { paper-card {
display: block; display: block;
} }
.errors {
color: var(--google-red-500);
margin-bottom: 16px;
}
iron-autogrow-textarea { iron-autogrow-textarea {
width: 100%; width: 100%;
} }
</style> </style>
<paper-card heading='Options'> <paper-card heading='Options'>
<div class="card-content"> <div class="card-content">
<template is='dom-if' if='[[errors]]'>
<div class='errors'>[[errors]]</div>
</template>
<iron-autogrow-textarea value="{{options}}"></iron-autogrow-textarea> <iron-autogrow-textarea value="{{options}}"></iron-autogrow-textarea>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<ha-call-api-button <paper-button
hass='[[hass]]' on-tap='saveTapped'
disabled='[[!optionsParsed]]' disabled='[[!optionsParsed]]'
data='[[computeOptionsData(optionsParsed)]]' >Save</paper-button>
path="[[pathOptions(addon)]]"
>Save</ha-call-api-button>
</div> </div>
</paper-card> </paper-card>
</template> </template>
@ -56,6 +61,11 @@ Polymer({
computed: 'parseOptions(options)', computed: 'parseOptions(options)',
}, },
errors: {
type: String,
value: null,
},
addonState: { addonState: {
type: Object, type: Object,
value: null, value: null,
@ -75,6 +85,16 @@ Polymer({
} }
}, },
saveTapped: function () {
this.errors = null;
this.hass.callApi('post', 'hassio/addons/' + this.addon + '/options', {
options: this.optionsParsed
}).catch(function (resp) {
this.errors = resp.body.message;
}.bind(this));
},
computeOptionsData: function (optionsParsed) { computeOptionsData: function (optionsParsed) {
return { return {
options: optionsParsed, options: optionsParsed,

View File

@ -51,6 +51,11 @@
>Start</ha-call-api-button> >Start</ha-call-api-button>
</template> </template>
<template is='dom-if' if='[[isRunning]]'> <template is='dom-if' if='[[isRunning]]'>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="[[pathRestart(addon)]]"
>Restart</ha-call-api-button>
<ha-call-api-button <ha-call-api-button
class='warning' class='warning'
hass='[[hass]]' hass='[[hass]]'
@ -119,6 +124,10 @@ Polymer({
return 'hassio/addons/' + addon + '/stop'; return 'hassio/addons/' + addon + '/stop';
}, },
pathRestart: function (addon) {
return 'hassio/addons/' + addon + '/restart';
},
pathInstall: function (addon) { pathInstall: function (addon) {
return 'hassio/addons/' + addon + '/install'; return 'hassio/addons/' + addon + '/install';
}, },

View File

@ -107,7 +107,7 @@ Polymer({
}, },
storeTapped: function () { storeTapped: function () {
this.fire('hassio-show-store'); this.fire('hassio-show-page', { page: 'addon-store' });
}, },
}); });
</script> </script>

View File

@ -16,6 +16,10 @@
.info td:nth-child(2) { .info td:nth-child(2) {
text-align: right; text-align: right;
} }
.errors {
color: var(--google-red-500);
margin-top: 16px;
}
</style> </style>
<template> <template>
<paper-card heading="Home Assistant"> <paper-card heading="Home Assistant">
@ -30,6 +34,9 @@
<td>[[data.last_version]]</td> <td>[[data.last_version]]</td>
</tr> </tr>
</table> </table>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>Error: [[errors]]</div>
</template>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<template is='dom-if' if='[[computeUpdateAvailable(data)]]'> <template is='dom-if' if='[[computeUpdateAvailable(data)]]'>
@ -38,12 +45,11 @@
path="hassio/homeassistant/update" path="hassio/homeassistant/update"
>Update</ha-call-api-button> >Update</ha-call-api-button>
</template> </template>
<ha-call-service-button <ha-call-api-button
class="warning" class="warning"
hass="[[hass]]" hass="[[hass]]"
domain="homeassistant" path="hassio/homeassistant/restart"
service="restart" >Restart</ha-call-api-button>
>Restart</ha-call-service-button>
</div> </div>
</paper-card> </paper-card>
</template> </template>
@ -64,6 +70,25 @@ Polymer({
}, },
}, },
listeners: {
'hass-api-called': 'apiCalled',
},
apiCalled: function (ev) {
if (ev.detail.success) {
this.errors = null;
return;
}
var response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
} else {
this.errors = response.body;
}
},
computeUpdateAvailable: function (data) { computeUpdateAvailable: function (data) {
return data.version !== data.last_version; return data.version !== data.last_version;
}, },

View File

@ -15,6 +15,10 @@
.info td:nth-child(2) { .info td:nth-child(2) {
text-align: right; text-align: right;
} }
.errors {
color: var(--google-red-500);
margin-top: 16px;
}
</style> </style>
<template> <template>
<paper-card heading="Host OS"> <paper-card heading="Host OS">
@ -24,10 +28,6 @@
<td>Hostname</td> <td>Hostname</td>
<td>[[data.hostname]]</td> <td>[[data.hostname]]</td>
</tr> </tr>
<tr>
<td>Control version</td>
<td>[[data.version]]</td>
</tr>
<tr> <tr>
<td>Type</td> <td>Type</td>
<td>[[data.type]]</td> <td>[[data.type]]</td>
@ -36,18 +36,33 @@
<td>OS</td> <td>OS</td>
<td>[[data.os]]</td> <td>[[data.os]]</td>
</tr> </tr>
<tr>
<td>Host Control version</td>
<td>[[data.version]]</td>
</tr>
<tr>
<td>Latest available version</td>
<td>[[data.last_version]]</td>
</tr>
</table> </table>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>Error: [[errors]]</div>
</template>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<ha-call-api-button <template is='dom-if' if='[[computeUpdateAvailable(data)]]'>
hass='[[hass]]' <ha-call-api-button
path="hassio/host/update" hass='[[hass]]'
>Update</ha-call-api-button> path="hassio/host/update"
<ha-call-api-button >Update</ha-call-api-button>
class='warning' </template>
hass='[[hass]]' <template is='dom-if' if='[[computeRebootAvailable(data)]]'>
path="hassio/host/reboot" <ha-call-api-button
>Reboot</ha-call-api-button> class='warning'
hass='[[hass]]'
path="hassio/host/reboot"
>Reboot</ha-call-api-button>
</template>
</div> </div>
</paper-card> </paper-card>
</template> </template>
@ -66,6 +81,35 @@ Polymer({
type: Object, type: Object,
value: {}, value: {},
}, },
errors: String,
},
listeners: {
'hass-api-called': 'apiCalled',
},
apiCalled: function (ev) {
if (ev.detail.success) {
this.errors = null;
return;
}
var response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
} else {
this.errors = response.body;
}
},
computeUpdateAvailable: function (data) {
return data.version !== data.last_version;
},
computeRebootAvailable: function (data) {
return data.features && data.features.indexOf('reboot') !== -1;
}, },
}); });
</script> </script>

View File

@ -15,6 +15,10 @@
.info td:nth-child(2) { .info td:nth-child(2) {
text-align: right; text-align: right;
} }
.errors {
color: var(--google-red-500);
margin-top: 16px;
}
</style> </style>
<template> <template>
<paper-card heading="Supervisor"> <paper-card heading="Supervisor">
@ -33,8 +37,12 @@
<td>[[data.last_version]]</td> <td>[[data.last_version]]</td>
</tr> </tr>
</table> </table>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>Error: [[errors]]</div>
</template>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<paper-button on-tap='supervisorLogsTapped'>View logs</paper-button>
<template is='dom-if' if='[[computeUpdateAvailable(data)]]'> <template is='dom-if' if='[[computeUpdateAvailable(data)]]'>
<ha-call-api-button <ha-call-api-button
hass='[[hass]]' hass='[[hass]]'
@ -64,10 +72,35 @@ Polymer({
type: Object, type: Object,
value: {}, value: {},
}, },
errors: String,
},
listeners: {
'hass-api-called': 'apiCalled',
},
apiCalled: function (ev) {
if (ev.detail.success) {
this.errors = null;
return;
}
var response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
} else {
this.errors = response.body;
}
}, },
computeUpdateAvailable: function (data) { computeUpdateAvailable: function (data) {
return data.version !== data.last_version; return data.version !== data.last_version;
}, },
supervisorLogsTapped: function () {
this.fire('hassio-show-page', { page: 'supervisor' });
}
}); });
</script> </script>

View File

@ -3,6 +3,7 @@
<link rel="import" href="./dashboard/hassio-dashboard.html"> <link rel="import" href="./dashboard/hassio-dashboard.html">
<link rel="import" href="./addon-view/hassio-addon-view.html"> <link rel="import" href="./addon-view/hassio-addon-view.html">
<link rel="import" href="./addon-store/hassio-addon-store.html"> <link rel="import" href="./addon-store/hassio-addon-store.html">
<link rel="import" href="./supervisor/hassio-supervisor.html">
<link rel="import" href="./hassio-loading.html"> <link rel="import" href="./hassio-loading.html">
<link rel="import" href="./hassio-data.html"> <link rel="import" href="./hassio-data.html">
@ -52,11 +53,17 @@
<template is='dom-if' if='[[addonStoreSelected(currentPage)]]'> <template is='dom-if' if='[[addonStoreSelected(currentPage)]]'>
<hassio-addon-store <hassio-addon-store
id='addon-store'
hass='[[hass]]' hass='[[hass]]'
supervisor-info='[[supervisorInfo]]' supervisor-info='[[supervisorInfo]]'
></hassio-addon-store> ></hassio-addon-store>
</template> </template>
<template is='dom-if' if='[[supervisorSelected(currentPage)]]'>
<hassio-supervisor
hass='[[hass]]'
supervisor-info='[[supervisorInfo]]'
></hassio-supervisor>
</template>
</template> </template>
</dom-module> </dom-module>
@ -121,13 +128,22 @@ Polymer({
listeners: { listeners: {
'hassio-select-addon': 'addonSelected', 'hassio-select-addon': 'addonSelected',
'hassio-show-store': 'showStore', 'hassio-show-page': 'showPage',
'hass-api-called': 'apiCalled', 'hass-api-called': 'apiCalled',
}, },
apiCalled: function (ev) { apiCalled: function (ev) {
if (ev.detail.success) { if (ev.detail.success) {
this.$.data.refresh(); var tries = 1;
var tryUpdate = function () {
this.$.data.refresh().catch(function () {
tries += 1;
setTimeout(tryUpdate, Math.min(tries, 5) * 1000);
});
}.bind(this);
tryUpdate();
} }
}, },
@ -158,8 +174,8 @@ Polymer({
} }
}, },
showStore: function () { showPage: function (ev) {
this.currentPage = 'addon-store'; this.currentPage = ev.detail.page;
}, },
dashboardSelected: function (currentPage) { dashboardSelected: function (currentPage) {
@ -174,5 +190,9 @@ Polymer({
return currentPage === 'addon-view'; return currentPage === 'addon-view';
}, },
supervisorSelected: function (currentPage) {
return currentPage === 'supervisor';
},
}); });
</script> </script>

View File

@ -29,27 +29,29 @@ Polymer({
}, },
refresh: function () { refresh: function () {
this.fetchSupervisorInfo(); return Promise.all([
this.fetchHostInfo(); this.fetchSupervisorInfo(),
this.fetchHassInfo(); this.fetchHostInfo(),
this.fetchHassInfo(),
]);
}, },
fetchSupervisorInfo: function () { fetchSupervisorInfo: function () {
this.hass.callApi('get', 'hassio/supervisor/info') return this.hass.callApi('get', 'hassio/supervisor/info')
.then(function (info) { .then(function (info) {
this.supervisor = info.data; this.supervisor = info.data;
}.bind(this)); }.bind(this));
}, },
fetchHostInfo: function () { fetchHostInfo: function () {
this.hass.callApi('get', 'hassio/host/info') return this.hass.callApi('get', 'hassio/host/info')
.then(function (info) { .then(function (info) {
this.host = info.data; this.host = info.data;
}.bind(this)); }.bind(this));
}, },
fetchHassInfo: function () { fetchHassInfo: function () {
this.hass.callApi('get', 'hassio/homeassistant/info') return this.hass.callApi('get', 'hassio/homeassistant/info')
.then(function (info) { .then(function (info) {
this.homeassistant = info.data; this.homeassistant = info.data;
}.bind(this)); }.bind(this));

View File

@ -0,0 +1,87 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../src/components/ha-menu-button.html">
<dom-module id="hassio-supervisor">
<template>
<style include="iron-flex ha-style">
.content {
padding: 16px;
margin: 0;
white-space: pre-wrap;
}
</style>
<app-header-layout has-scrolling-region>
<app-header fixed>
<app-toolbar>
<paper-icon-button
icon='mdi:arrow-left'
on-tap='backTapped'
></paper-icon-button>
<div main-title>Supervisor Logs</div>
<paper-icon-button
icon="mdi:refresh"
on-tap="refreshTapped"
></paper-icon-button>
</app-toolbar>
</app-header>
<pre class='content'>[[logs]]</pre>
</app-header-layout>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-supervisor',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
supervisorInfo: {
type: Object,
},
logs: {
type: String,
value: '',
},
},
attached: function () {
this.loadData();
},
loadData: function () {
this.hass.callApi('get', 'hassio/supervisor/logs')
.then(function (info) {
this.logs = info;
}.bind(this), function () {
this.logs = 'Error fetching logs';
}.bind(this));
},
refreshTapped: function () {
this.loadData();
},
backTapped: function () {
this.fire('hassio-select-addon', { addon: null });
},
});
</script>

View File

@ -56,14 +56,16 @@ Polymer({
}; };
this.hass.callApi(this.method, this.path, this.data) this.hass.callApi(this.method, this.path, this.data)
.then(function () { .then(function (resp) {
el.progress = false; el.progress = false;
el.$.progress.actionSuccess(); el.$.progress.actionSuccess();
eventData.success = true; eventData.success = true;
}, function () { eventData.response = resp;
}, function (resp) {
el.progress = false; el.progress = false;
el.$.progress.actionError(); el.$.progress.actionError();
eventData.success = false; eventData.success = false;
eventData.response = resp;
}).then(function () { }).then(function () {
el.fire('hass-api-called', eventData); el.fire('hass-api-called', eventData);
}); });