Add HassIO panel (#267)

* Add HassIO panel

* Add buttons

* Update to new API

* Add initial hassio addon view

* Allow saving options

* Not auto select smb_config addon

* Add logs to addon

* Add OS info to host

* Wrap up panel for now

* Lint

* Fix menu button
This commit is contained in:
Paulus Schoutsen 2017-04-27 00:51:34 -07:00 committed by GitHub
parent 4b38a16848
commit 863ccb5486
16 changed files with 1120 additions and 24 deletions

View File

@ -10,7 +10,7 @@
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../src/components/ha-menu-button.html">
<link rel="import" href="../../../src/components/ha-call-service-button.html">
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
<link rel="import" href="../../../src/resources/ha-style.html">
<link rel="import" href="../ha-config-section.html">
@ -46,10 +46,6 @@
.validate-log {
white-space: pre-wrap;
}
.card-actions.warning ha-call-service-button {
color: var(--google-red-500);
}
</style>
<ha-config-section
is-wide='[[isWide]]'
@ -120,11 +116,13 @@
</div>
<div class='card-actions warning'>
<ha-call-service-button
class='warning'
hass='[[hass]]'
domain='homeassistant'
service='restart'
>Restart</ha-call-service-button>
<ha-call-service-button
class='warning'
hass='[[hass]]'
domain='homeassistant'
service='stop'

View File

@ -0,0 +1,120 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="./hassio-dashboard.html">
<link rel="import" href="./hassio-addon-view.html">
<link rel="import" href="./hassio-loading.html">
<dom-module id="ha-panel-hassio">
<style>
iron-pages {
height: 100%;
}
</style>
<template>
<hassio-data
hass='[[hass]]'
supervisor='{{supervisorInfo}}'
homeassistant='{{hassInfo}}'
host='{{hostInfo}}'
></hassio-data>
<template is='dom-if' if='[[!loaded]]'>
<hassio-loading
narrow='[[narrow]]'
hass='[[hass]]'
show-menu='[[showMenu]]'
></hassio-loading>
</template>
<template is='dom-if' if='[[loaded]]' restamp>
<template is='dom-if' if='[[addon]]'>
<hassio-addon-view
hass='[[hass]]'
supervisor-info='[[supervisorInfo]]'
host-info='[[hostInfo]]'
addon='[[addon]]'
></hassio-addon-view>
</template>
<template is='dom-if' if='[[!addon]]'>
<hassio-dashboard
hass='[[hass]]'
narrow='[[narrow]]'
show-menu='[[showMenu]]'
supervisor-info='{{supervisorInfo}}'
host-info='{{hostInfo}}'
hass-info='[[hassInfo]]'
></hassio-dashboard>
</template>
</template>
</template>
</dom-module>
<script>
Polymer({
is: 'ha-panel-hassio',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
addon: {
type: String,
value: '',
},
supervisorInfo: {
type: Object,
value: null,
},
hostInfo: {
type: Object,
value: null,
},
hassInfo: {
type: Object,
value: null,
},
forceLoading: {
type: Boolean,
value: false,
},
loaded: {
type: Boolean,
computed: 'computeIsLoaded(supervisorInfo, hostInfo, hassInfo, forceLoading)',
}
},
listeners: {
'hassio-select-addon': 'addonSelected',
},
computeIsLoaded: function (supervisorInfo, hostInfo, hassInfo, forceLoading) {
return (supervisorInfo !== null &&
hostInfo !== null &&
hassInfo !== null &&
!forceLoading);
},
addonSelected: function (ev) {
this.forceLoading = true;
setTimeout(function () {
this.addon = ev.detail.addon;
this.forceLoading = false;
}.bind(this), 0);
},
});
</script>

View File

@ -0,0 +1,328 @@
<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="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="./hassio-data.html">
<link rel="import" href="./hassio-host-info.html">
<link rel="import" href="./hassio-supervisor-info.html">
<link rel="import" href="./hassio-addons.html">
<dom-module id="hassio-addon-view">
<template>
<style include="iron-flex ha-style">
paper-card {
display: block;
}
.controls paper-card {
margin-bottom: 24px;
}
iron-autogrow-textarea {
width: 100%;
}
.content {
padding: 24px 0 32px;
max-width: 600px;
margin: 0 auto;
}
.status {
@apply(--layout-horizontal);
margin-bottom: 24px;
}
.status > * {
@apply(--layout-flex);
}
.status > *:first-child {
margin-right: 24px;
}
</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>[[addonInfo.name]]</div>
</app-toolbar>
</app-header>
<div class='content'>
<div class='status'>
<paper-card heading='Info'>
<div class="card-content">
<div>[[addonInfo.description]]</div>
<table class='info'>
<tr>
<td>Installed</td>
<td>[[computeInstallStatus(addonInfo)]]</td>
</tr>
<tr>
<td>Version</td>
<td>[[addonInfo.version]]</td>
</tr>
<tr>
<td>Dedicated</td>
<td>[[addonInfo.dedicated]]</td>
</tr>
</table>
</div>
<template is='dom-if' if='[[!addonState]]'>
<div class="card-actions">
<ha-call-api-button
hass='[[hass]]'
path="[[pathInstall(addon)]]"
>Install</ha-call-api-button>
</div>
</template>
</paper-card>
<paper-card heading='Installed'>
<template is='dom-if' if='[[!addonState]]'>
<div class="card-content">
<div>Add-on is not installed.</div>
</div>
</template>
<template is='dom-if' if='[[addonState]]'>
<div class="card-content">
<table class='info'>
<tr>
<td>Version</td>
<td>[[addonState.version]]</td>
</tr>
<tr>
<td>State</td>
<td>[[addonState.state]]</td>
</tr>
<tr>
<td>Boot</td>
<td>[[addonState.boot]]</td>
</tr>
</table>
</div>
<div class="card-actions">
<template is='dom-if' if='[[!isRunning]]'>
<ha-call-api-button
hass='[[hass]]'
path="[[pathStart(addon)]]"
>Start</ha-call-api-button>
</template>
<template is='dom-if' if='[[computeUpdateAvailable(addonInfo)]]'>
<ha-call-api-button
hass='[[hass]]'
path="[[pathUpdate(addon)]]"
>Update</ha-call-api-button>
</template>
<template is='dom-if' if='[[isRunning]]'>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="[[pathStop(addon)]]"
>Stop</ha-call-api-button>
</template>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="[[pathUninstall(addon)]]"
>Uninstall</ha-call-api-button>
</div>
</template>
</paper-card>
</div>
<template is='dom-if' if='[[addonState]]'>
<div class='controls'>
<paper-card heading='Options'>
<div class="card-content">
<iron-autogrow-textarea value="{{options}}"></iron-autogrow-textarea>
</div>
<div class="card-actions">
<ha-call-api-button
hass='[[hass]]'
disabled='[[!optionsParsed]]'
data='[[computeOptionsData(optionsParsed)]]'
path="[[pathOptions(addon)]]"
>Save</ha-call-api-button>
</div>
</paper-card>
<paper-card heading='Logs'>
<div class="card-content">
<pre>[[addonLogs]]</pre>
</div>
<div class="card-actions">
<paper-button on-tap='refreshLogs'>Refresh</paper-button>
</div>
</paper-card>
</div>
</template>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-addon-view',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
addon: {
type: String,
observer: 'addonChanged',
},
options: {
type: String,
value: '',
},
optionsParsed: {
type: Object,
computed: 'parseOptions(options)',
},
supervisorInfo: {
type: Object,
},
hostInfo: {
type: Object,
},
isRunning: {
type: Boolean,
computed: 'computeIsRunning(addonState)',
},
addonInfo: {
type: Object,
computed: 'computeAddonInfo(supervisorInfo, addon)',
},
addonState: {
type: Object,
value: null,
observer: 'addonStateChanged',
},
addonLogs: {
type: String,
value: '',
},
},
addonChanged: function (addon) {
if (!this.hass) {
setTimeout(function () { this.addonChanged(addon); }.bind(this), 0);
return;
}
this.hass.callApi('get', 'hassio/addons/' + addon + '/info')
.then(function (info) {
// Error if addon not installed.
if (info.result !== 'error') {
this.addonState = info.data;
}
}.bind(this));
this.refreshLogs();
},
refreshLogs: function () {
this.hass.callApi('get', 'hassio/addons/' + this.addon + '/logs')
.then(function (info) {
this.addonLogs = info;
}.bind(this));
},
addonStateChanged: function (addonState) {
this.options = addonState ? JSON.stringify(addonState.options, null, 2) : '';
},
computeAddonInfo: function (supervisorInfo, addon) {
if (!supervisorInfo) return null;
for (var i = 0; i < supervisorInfo.addons.length; i++) {
var addonInfo = supervisorInfo.addons[i];
if (addonInfo.slug === addon) return addonInfo;
}
return null;
},
computeIsRunning: function (addonState) {
return addonState && addonState.state === 'started';
},
computeInstallStatus(addon) {
return addon.installed || 'Not installed';
},
computeUpdateAvailable: function (data) {
return data.version !== data.last_version;
},
parseOptions: function (options) {
try {
return JSON.parse(options);
} catch (err) {
return null;
}
},
computeOptionsData: function (optionsParsed) {
return {
options: optionsParsed,
};
},
backTapped: function () {
this.fire('hassio-select-addon', { addon: null });
},
pathStart: function (addon) {
return 'hassio/addons/' + addon + '/start';
},
pathStop: function (addon) {
return 'hassio/addons/' + addon + '/stop';
},
pathInstall: function (addon) {
return 'hassio/addons/' + addon + '/install';
},
pathUninstall: function (addon) {
return 'hassio/addons/' + addon + '/uninstall';
},
pathUpdate: function (addon) {
return 'hassio/addons/' + addon + '/update';
},
pathOptions: function (addon) {
return 'hassio/addons/' + addon + '/options';
},
});
</script>

View File

@ -0,0 +1,70 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<dom-module id="hassio-addons">
<template>
<style include="iron-flex ha-style">
paper-card {
display: block;
padding-top: 16px;
padding-right: 16px;
}
paper-item {
cursor: pointer;
}
</style>
<paper-card heading="Addons">
<div class="card-content">
<template is='dom-repeat' items='[[data]]' as='addon'>
<paper-item>
<paper-item-body two-line on-tap='addonTapped'>
<div>[[addon.name]]</div>
<div secondary>[[addon.description]]</div>
</paper-item-body>
[[computeInstallStatus(addon)]]
</paper-item>
</template>
</div>
</paper-card>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-addons',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
data: {
type: Object,
value: [],
},
},
computeInstallStatus(addon) {
return addon.installed || 'Not installed';
},
addonTapped: function (ev) {
this.fire('hassio-select-addon', { addon: this.data[ev.model.index].slug });
ev.target.blur();
},
});
</script>

View File

@ -0,0 +1,109 @@
<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-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="./hassio-data.html">
<link rel="import" href="./hassio-host-info.html">
<link rel="import" href="./hassio-hass-info.html">
<link rel="import" href="./hassio-supervisor-info.html">
<link rel="import" href="./hassio-addons.html">
<dom-module id="hassio-dashboard">
<template>
<style include="iron-flex ha-style">
.content {
padding: 24px 0 32px;
max-width: 600px;
margin: 0 auto;
}
.status {
@apply(--layout-horizontal);
margin-bottom: 24px;
}
.status > * {
@apply(--layout-flex);
}
.status > *:first-child {
margin-right: 24px;
}
</style>
<app-header-layout has-scrolling-region>
<app-header fixed>
<app-toolbar>
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
<div main-title>Hass.io</div>
</app-toolbar>
</app-header>
<div class='content'>
<div class='status'>
<hassio-supervisor-info
hass='[[hass]]'
data='[[supervisorInfo]]'
></hassio-supervisor-info>
<hassio-host-info
hass='[[hass]]'
data='[[hostInfo]]'
></hassio-host-info>
</div>
<div class='status'>
<hassio-hass-info
hass='[[hass]]'
data='[[hassInfo]]'
></hassio-hass-info>
<div></div>
</div>
<hassio-addons
hass='[[hass]]'
data='[[supervisorInfo.addons]]'
></hassio-addons>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-dashboard',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
supervisorInfo: {
type: Object,
value: {},
},
hostInfo: {
type: Object,
value: {},
},
hassInfo: {
type: Object,
value: {},
},
},
});
</script>

View File

@ -0,0 +1,54 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<script>
Polymer({
is: 'hassio-data',
properties: {
supervisor: {
type: Object,
value: {},
notify: true,
},
host: {
type: Object,
value: {},
notify: true,
},
homeassistant: {
type: Object,
value: {},
notify: true,
},
},
attached: function () {
this.fetchSupervisorInfo();
this.fetchHostInfo();
this.fetchHassInfo();
},
fetchSupervisorInfo: function () {
this.hass.callApi('get', 'hassio/supervisor/info')
.then(function (info) {
this.supervisor = info.data;
}.bind(this));
},
fetchHostInfo: function () {
this.hass.callApi('get', 'hassio/host/info')
.then(function (info) {
this.host = info.data;
}.bind(this));
},
fetchHassInfo: function () {
this.hass.callApi('get', 'hassio/homeassistant/info')
.then(function (info) {
this.homeassistant = info.data;
}.bind(this));
},
});
</script>

View File

@ -0,0 +1,65 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<dom-module id="hassio-hass-info">
<style include="iron-flex ha-style">
paper-card {
display: block;
height: 100%;
}
.info {
width: 100%;
}
.info td:nth-child(2) {
text-align: right;
}
</style>
<template>
<paper-card heading="Home Assistant">
<div class="card-content">
<table class='info'>
<tr>
<td>Current version</td>
<td>[[data.version]]</td>
</tr>
<tr>
<td>Latest version</td>
<td>[[data.last_version]]</td>
</tr>
</table>
</div>
<template is='dom-if' if='[[computeUpdateAvailable(data)]]'>
<div class="card-actions">
<ha-call-api-button
hass='[[hass]]'
path="hassio/homeassistant/update"
>Update</ha-call-api-button>
</div>
</template>
</paper-card>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-hass-info',
properties: {
hass: {
type: Object,
},
data: {
type: Object,
value: {},
},
},
computeUpdateAvailable: function (data) {
return data.version !== data.last_version;
},
});
</script>

View File

@ -0,0 +1,72 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<dom-module id="hassio-host-info">
<style include="iron-flex ha-style">
paper-card {
display: block;
height: 100%;
}
.info {
width: 100%;
}
.info td:nth-child(2) {
text-align: right;
}
</style>
<template>
<paper-card heading="Host OS">
<div class="card-content">
<table class='info'>
<tr>
<td>Hostname</td>
<td>[[data.hostname]]</td>
</tr>
<tr>
<td>Control version</td>
<td>[[data.version]]</td>
</tr>
<tr>
<td>Type</td>
<td>[[data.type]]</td>
</tr>
<tr>
<td>OS</td>
<td>[[data.os]]</td>
</tr>
</table>
</div>
<div class="card-actions">
<ha-call-api-button
hass='[[hass]]'
path="hassio/host/update"
>Update</ha-call-api-button>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="hassio/host/reboot"
>Reboot</ha-call-api-button>
</div>
</paper-card>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-host-info',
properties: {
hass: {
type: Object,
},
data: {
type: Object,
value: {},
},
},
});
</script>

View File

@ -0,0 +1,55 @@
<link rel='import' href='../../bower_components/paper-spinner/paper-spinner.html'>
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<dom-module id='hassio-loading'>
<template>
<style include='iron-flex ha-style'>
[hidden] {
display: none !important;
}
.placeholder {
height: 100%;
}
.layout {
height: calc(100% - 64px);
}
</style>
<div class='placeholder'>
<app-toolbar>
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
<div main-title>Hass.io</div>
</app-toolbar>
<div class='layout horizontal center-center'>
<paper-spinner active></paper-spinner>
</div>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-loading',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
value: false,
},
showMenu: {
type: Boolean,
value: false,
},
},
});
</script>

View File

@ -0,0 +1,74 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<dom-module id="hassio-supervisor-info">
<style include="iron-flex ha-style">
paper-card {
display: block;
height: 100%;
}
.info {
width: 100%;
}
.info td:nth-child(2) {
text-align: right;
}
</style>
<template>
<paper-card heading="Supervisor">
<div class="card-content">
<table class='info'>
<tr>
<td>Version</td>
<td>[[data.version]]</td>
</tr>
<tr>
<td>Beta channel</td>
<td>[[data.beta_channel]]</td>
</tr>
<tr>
<td>Latest available version</td>
<td>[[data.last_version]]</td>
</tr>
</table>
</div>
<div class="card-actions">
<template is='dom-if' if='[[computeUpdateAvailable(data)]]'>
<ha-call-api-button
hass='[[hass]]'
path="hassio/supervisor/update"
>Update</ha-call-api-button>
</template>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="hassio/supervisor/reload"
>Restart</ha-call-api-button>
</div>
</paper-card>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-supervisor-info',
properties: {
hass: {
type: Object,
},
data: {
type: Object,
value: {},
},
},
computeUpdateAvailable: function (data) {
return data.version !== data.last_version;
},
});
</script>

19
panels/hassio/todo.md Normal file
View File

@ -0,0 +1,19 @@
General:
- Refresh data after API call
Host:
- Use feature detection
Supervisor:
- logs
- toggle beta channel (/options)
Addon View:
- break up UI in smaller custom elements to organize code
Network:
- show
- update
Home Assistant:
- Logs

View File

@ -5,7 +5,7 @@
<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="../../src/components/ha-call-service-button.html">
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
<link rel="import" href="../../src/resources/ha-style.html">
<dom-module id="ha-panel-zwave">

View File

@ -0,0 +1,63 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="./ha-progress-button.html">
<dom-module id='ha-call-api-button'>
<template>
<ha-progress-button
id='progress'
progress='[[progress]]'
on-tap='buttonTapped'
disabled='[[disabled]]'
><slot></slot></ha-progress-button>
</template>
</dom-module>
<script>
Polymer({
is: 'ha-call-api-button',
properties: {
hass: {
type: Object,
},
progress: {
type: Boolean,
value: false,
},
path: {
type: String,
},
method: {
type: String,
value: 'POST',
},
data: {
type: Object,
value: {},
},
disabled: {
type: Boolean,
value: false,
},
},
buttonTapped: function () {
this.progress = true;
var el = this;
this.hass.callApi(this.method, this.path, this.data)
.then(function () {
el.progress = false;
el.$.progress.actionSuccess();
}, function () {
el.progress = false;
el.$.progress.actionError();
});
}
});
</script>

View File

@ -0,0 +1,56 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="./ha-progress-button.html">
<dom-module id='ha-call-service-button'>
<template>
<ha-progress-button
id='progress'
progress='[[progress]]'
on-tap='buttonTapped'
><slot></slot></ha-progress-button>
</template>
</dom-module>
<script>
Polymer({
is: 'ha-call-service-button',
properties: {
hass: {
type: Object,
},
progress: {
type: Boolean,
value: false,
},
domain: {
type: String,
},
service: {
type: String,
},
serviceData: {
type: Object,
value: {},
},
},
buttonTapped: function () {
this.progress = true;
var el = this;
this.hass.callService(this.domain, this.service, this.serviceData)
.then(function () {
el.progress = false;
el.$.progress.actionSuccess();
}, function () {
el.progress = false;
el.$.progress.actionError();
});
}
});
</script>

View File

@ -1,8 +1,8 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../../bower_components/paper-spinner/paper-spinner.html">
<dom-module id='ha-call-service-button'>
<dom-module id='ha-progress-button'>
<template>
<style>
.container {
@ -43,7 +43,7 @@
<div class='container' id='container'>
<paper-button
id='button'
disabled='[[progress]]'
disabled='[[computeDisabled(disabled, progress)]]'
on-tap='buttonTapped'
>
<slot></slot>
@ -59,7 +59,7 @@
<script>
Polymer({
is: 'ha-call-service-button',
is: 'ha-progress-button',
properties: {
hass: {
@ -83,6 +83,11 @@ Polymer({
type: Object,
value: {},
},
disabled: {
type: Boolean,
value: false,
},
},
tempClass: function (className) {
@ -93,18 +98,24 @@ Polymer({
}, 1000);
},
buttonTapped: function () {
this.progress = true;
var el = this;
listeners: {
tap: 'buttonTapped',
},
this.hass.callService(this.domain, this.service, this.serviceData)
.then(function () {
el.tempClass('success');
el.progress = false;
}, function () {
el.tempClass('error');
el.progress = false;
});
}
buttonTapped: function (ev) {
if (this.progress) ev.stopPropagation();
},
actionSuccess: function () {
this.tempClass('success');
},
actionError: function () {
this.tempClass('error');
},
computeDisabled: function (disabled, progress) {
return disabled || progress;
},
});
</script>

View File

@ -86,12 +86,14 @@
}
.card-actions > paper-button:not([disabled]),
.card-actions > ha-call-api-button:not([disabled]),
.card-actions > ha-call-service-button:not([disabled]) {
color: var(--default-primary-color);
font-weight: 500;
}
.card-actions > paper-button.warning:not([disabled]),
.card-actions > ha-call-api-button.warning:not([disabled]),
.card-actions > ha-call-service-button.warning:not([disabled]) {
color: var(--google-red-500);
}