Polymer .9: show basic state cards

pull/132/head
Paulus Schoutsen 2015-05-17 22:08:42 -07:00
parent 313eb71b17
commit 4576a1d245
14 changed files with 574 additions and 333 deletions

View File

@ -1,24 +1,38 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="state-card-display.html">
<link rel="import" href="state-card-toggle.html">
<!-- <link rel="import" href="state-card-toggle.html">
<link rel="import" href="state-card-thermostat.html">
<link rel="import" href="state-card-configurator.html">
<link rel="import" href="state-card-scene.html">
<link rel="import" href="state-card-scene.html"> -->
<polymer-element name="state-card-content" attributes="stateObj">
<template>
<dom-module is="state-card-content">
<style>
:host {
display: block;
}
</style>
<template>
<state-card-display state-obj="[[stateObj]]"></state-card-display>
<!-- <div id='cardContainer'></div> -->
</template>
</dom-module>
<div id='cardContainer'></div>
</template>
<script>
Polymer({
is: 'state-card-content',
properties: {
stateObj: {
type: Object,
value: {},
observe: 'stateObjChanged',
}
},
stateObjChanged: function(oldVal, newVal) {
console.log('stateObjChanged');
return;
var cardContainer = this.$.cardContainer;
if (!newVal) {
@ -45,4 +59,3 @@ Polymer({
},
});
</script>
</polymer-element>

View File

@ -2,21 +2,35 @@
<link rel="import" href="../components/state-info.html">
<polymer-element name="state-card-display" attributes="stateObj" noscript>
<template>
<style>
.state {
margin-left: 16px;
text-transform: capitalize;
font-weight: 300;
font-size: 1.3rem;
text-align: right;
}
</style>
<dom-module is="state-card-display">
<style>
.state {
margin-left: 16px;
text-transform: capitalize;
font-weight: 300;
font-size: 1.3rem;
text-align: right;
}
</style>
<div horizontal justified layout>
<state-info stateObj="{{stateObj}}"></state-info>
<div class='state'>{{stateObj.stateDisplay}}</div>
<template>
<div class='horizontal justified layout'>
<state-info state-obj="[[stateObj]]"></state-info>
<div class='state'>[[stateObj.stateDisplay]]</div>
</div>
</template>
</polymer-element>
</dom-module>
<script>
(function() {
Polymer({
is: 'state-card-display',
properties: {
stateObj: {
type: Object,
},
},
});
})();
</script>

View File

@ -2,8 +2,7 @@
<link rel="import" href="state-card-content.html">
<polymer-element name="state-card" attributes="stateObj" on-click="cardClicked">
<template>
<dom-module is="state-card">
<style>
:host {
border-radius: 2px;
@ -19,15 +18,31 @@
}
</style>
<state-card-content stateObj={{stateObj}}></state-card-content>
</template>
<script>
var uiActions = window.hass.uiActions;
<template>
<state-card-content state-obj="[[stateObj]]"></state-card-content>
</template>
</dom-module>
Polymer({
cardClicked: function() {
uiActions.showMoreInfoDialog(this.stateObj.entityId);
},
});
<script>
(function(){
var uiActions = window.hass.uiActions;
Polymer({
is: 'state-card',
properties: {
stateObj: {
type: Object,
},
},
listeners: {
'click': 'cardClicked',
},
cardClicked: function() {
uiActions.showMoreInfoDialog(this.stateObj.entityId);
},
});
})();
</script>
</polymer-element>

View File

@ -1,24 +1,37 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../resources/home-assistant-icons.html">
<polymer-element name="domain-icon"
attributes="domain state" constructor="DomainIcon">
<dom-module is="domain-icon">
<template>
<core-icon icon="{{icon}}"></core-icon>
<iron-icon icon="[[computeIcon(domain, state)]]"></iron-icon>
</template>
<script>
Polymer({
icon: '',
</dom-module>
observe: {
'domain': 'updateIcon',
'state' : 'updateIcon',
<script>
(function() {
var uiUtil = window.hass.uiUtil;
Polymer({
is: 'domain-icon',
properties: {
domain: {
type: String,
value: '',
},
state: {
type: String,
value: '',
},
},
updateIcon: function() {
this.icon = window.hass.uiUtil.domainIcon(this.domain, this.state);
computeIcon: function(domain, state) {
return uiUtil.domainIcon(domain, state);
},
});
</script>
</polymer-element>
})();
</script>

View File

@ -2,49 +2,81 @@
<link rel="import" href="../resources/moment-js.html">
<polymer-element name="relative-ha-datetime" attributes="datetime datetimeObj">
<dom-module is="relative-ha-datetime">
<template>
{{ relativeTime }}
<span>[[relativeTime]]</span>
</template>
<script>
(function() {
var UPDATE_INTERVAL = 60000; // 60 seconds
</dom-module>
var parseDateTime = window.hass.util.parseDateTime;
<script>
(function() {
var UPDATE_INTERVAL = 60000; // 60 seconds
Polymer({
relativeTime: "",
parsedDateTime: null,
var parseDateTime = window.hass.util.parseDateTime;
created: function() {
this.updateRelative = this.updateRelative.bind(this);
Polymer({
is: 'relative-ha-datetime',
properties: {
datetime: {
type: String,
observe: 'datetimeChanged',
},
attached: function() {
this._interval = setInterval(this.updateRelative, UPDATE_INTERVAL);
datetimeObj: {
type: Object,
observe: 'datetimeObjChanged',
},
detached: function() {
clearInterval(this._interval);
parsedDateTime: {
type: Object,
},
datetimeChanged: function(oldVal, newVal) {
this.parsedDateTime = newVal ? parseDateTime(newVal) : null;
this.updateRelative();
relativeTime: {
type: String,
value: 'not set',
},
},
datetimeObjChanged: function(oldVal, newVal) {
this.parsedDateTime = newVal;
relativeTime: "",
parsedDateTime: null,
this.updateRelative();
},
created: function() {
this.updateRelative = this.updateRelative.bind(this);
},
updateRelative: function() {
this.relativeTime = this.parsedDateTime ?
moment(this.parsedDateTime).fromNow() : "";
},
});
})();
</script>
</polymer-element>
attached: function() {
this._interval = setInterval(this.updateRelative, UPDATE_INTERVAL);
if (this.datetimeObj) {
this.parsedDateTime = this.datetimeObj;
} else if (this.datetime) {
this.parsedDateTime = parseDateTime(this.datetime);
}
this.updateRelative();
},
detached: function() {
clearInterval(this._interval);
},
datetimeChanged: function(oldVal, newVal) {
this.parsedDateTime = newVal ? parseDateTime(newVal) : null;
this.updateRelative();
},
datetimeObjChanged: function(oldVal, newVal) {
this.parsedDateTime = newVal;
this.updateRelative();
},
updateRelative: function() {
this.relativeTime = this.parsedDateTime ?
moment(this.parsedDateTime).fromNow() : "";
},
});
})();
</script>

View File

@ -1,105 +1,107 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-image/core-image.html">
<link rel="import" href="../bower_components/iron-image/iron-image.html">
<link rel="import" href="domain-icon.html">
<polymer-element name="state-badge" attributes="stateObj">
<dom-module is="state-badge">
<style>
:host {
position: relative;
display: inline-block;
width: 45px;
background-color: #4fc3f7;
color: white;
border-radius: 50%;
transition: all .3s ease-in-out;
}
div {
height: 45px;
text-align: center;
}
iron-image {
border-radius: 50%;
}
domain-icon {
margin: 0 auto;
}
/* Color the icon if light or sun is on */
domain-icon[data-domain=light][data-state=on],
domain-icon[data-domain=switch][data-state=on],
domain-icon[data-domain=sun][data-state=above_horizon] {
color: #fff176;
}
</style>
<template>
<style>
:host {
position: relative;
display: inline-block;
width: 45px;
background-color: #4fc3f7;
color: white;
border-radius: 50%;
transition: all .3s ease-in-out;
}
div {
height: 45px;
text-align: center;
}
core-image {
border-radius: 50%;
}
domain-icon {
margin: 0 auto;
}
/* Color the icon if light or sun is on */
domain-icon[data-domain=light][data-state=on],
domain-icon[data-domain=switch][data-state=on],
domain-icon[data-domain=sun][data-state=above_horizon] {
color: #fff176;
}
</style>
<div horizontal layout center>
<div class='layout horizontal center'>
<domain-icon id="icon"
domain="{{stateObj.domain}}" data-domain="{{stateObj.domain}}"
state="{{stateObj.state}}" data-state="{{stateObj.state}}">
domain="[[stateObj.domain]]" data-domain="[[stateObj.domain]]"
state="[[stateObj.state]]" data-state="[[stateObj.state]]">
</domain-icon>
<template if="{{stateObj.attributes.entity_picture}}">
<core-image
sizing="cover" fit
src="{{stateObj.attributes.entity_picture}}"></core-image>
<template is='dom-if' if="[[stateObj.attributes.entity_picture]]">
<iron-image
sizing="cover" class='fit'
src="[[stateObj.attributes.entity_picture]]"></iron-image>
</template>
</div>
</template>
<script>
Polymer({
observe: {
'stateObj.state': 'updateIconColor',
'stateObj.attributes.brightness': 'updateIconColor',
'stateObj.attributes.xy_color[0]': 'updateIconColor',
'stateObj.attributes.xy_color[1]': 'updateIconColor'
</dom-module>
<script>
Polymer({
is: 'state-badge',
properties: {
stateObj: {
type: Object,
observe: 'updateIconColor',
},
},
/**
* Called when an attribute changes that influences the color of the icon.
*/
updateIconColor: function(oldVal, newVal) {
var state = this.stateObj;
/**
* Called when an attribute changes that influences the color of the icon.
*/
updateIconColor: function(oldVal, newVal) {
var state = this.stateObj;
// for domain light, set color of icon to light color if available
if(state.domain == "light" && state.state == "on" &&
state.attributes.brightness && state.attributes.xy_color) {
// for domain light, set color of icon to light color if available
if(state.domain == "light" && state.state == "on" &&
state.attributes.brightness && state.attributes.xy_color) {
var rgb = this.xyBriToRgb(state.attributes.xy_color[0],
state.attributes.xy_color[1],
state.attributes.brightness);
this.$.icon.style.color = "rgb(" + rgb.map(Math.floor).join(",") + ")";
} else {
this.$.icon.style.color = null;
}
},
// from http://stackoverflow.com/questions/22894498/philips-hue-convert-xy-from-api-to-hex-or-rgb
xyBriToRgb: function (x, y, bri) {
z = 1.0 - x - y;
Y = bri / 255.0; // Brightness of lamp
X = (Y / y) * x;
Z = (Y / y) * z;
r = X * 1.612 - Y * 0.203 - Z * 0.302;
g = -X * 0.509 + Y * 1.412 + Z * 0.066;
b = X * 0.026 - Y * 0.072 + Z * 0.962;
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
maxValue = Math.max(r,g,b);
r /= maxValue;
g /= maxValue;
b /= maxValue;
r = r * 255; if (r < 0) { r = 255 };
g = g * 255; if (g < 0) { g = 255 };
b = b * 255; if (b < 0) { b = 255 };
return [r, g, b]
var rgb = this.xyBriToRgb(state.attributes.xy_color[0],
state.attributes.xy_color[1],
state.attributes.brightness);
this.$.icon.style.color = "rgb(" + rgb.map(Math.floor).join(",") + ")";
} else {
this.$.icon.style.color = null;
}
},
});
</script>
</polymer-element>
// from http://stackoverflow.com/questions/22894498/philips-hue-convert-xy-from-api-to-hex-or-rgb
xyBriToRgb: function (x, y, bri) {
z = 1.0 - x - y;
Y = bri / 255.0; // Brightness of lamp
X = (Y / y) * x;
Z = (Y / y) * z;
r = X * 1.612 - Y * 0.203 - Z * 0.302;
g = -X * 0.509 + Y * 1.412 + Z * 0.066;
b = X * 0.026 - Y * 0.072 + Z * 0.962;
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
maxValue = Math.max(r,g,b);
r /= maxValue;
g /= maxValue;
b /= maxValue;
r = r * 255; if (r < 0) { r = 255; }
g = g * 255; if (g < 0) { g = 255; }
b = b * 255; if (b < 0) { b = 255; }
return [r, g, b];
}
});
</script>

View File

@ -2,50 +2,50 @@
<link rel="import" href="../cards/state-card.html">
<polymer-element name="state-cards" attributes="states" noscript>
<dom-module is="state-cards" attributes="states" noscript>
<style>
:host {
display: block;
width: 100%;
}
@media all and (min-width: 1020px) {
.state-card {
width: calc(50% - 44px);
margin: 8px 0 0 8px;
}
}
@media all and (min-width: 1356px) {
.state-card {
width: calc(33% - 38px);
}
}
@media all and (min-width: 1706px) {
.state-card {
width: calc(25% - 42px);
}
}
.no-states-content {
max-width: 500px;
background-color: #fff;
border-radius: 2px;
box-shadow: rgba(0, 0, 0, 0.098) 0px 2px 4px, rgba(0, 0, 0, 0.098) 0px 0px 3px;
padding: 16px;
margin: 16px auto;
}
</style>
<template>
<style>
:host {
display: block;
width: 100%;
}
<div class='horizontal layout wrap'>
@media all and (min-width: 1020px) {
.state-card {
width: calc(50% - 44px);
margin: 8px 0 0 8px;
}
}
@media all and (min-width: 1356px) {
.state-card {
width: calc(33% - 38px);
}
}
@media all and (min-width: 1706px) {
.state-card {
width: calc(25% - 42px);
}
}
.no-states-content {
max-width: 500px;
background-color: #fff;
border-radius: 2px;
box-shadow: rgba(0, 0, 0, 0.098) 0px 2px 4px, rgba(0, 0, 0, 0.098) 0px 0px 3px;
padding: 16px;
margin: 16px auto;
}
</style>
<div horizontal layout wrap>
<template repeat="{{states as state}}">
<state-card class="state-card" stateObj={{state}}></state-card>
<template is='dom-repeat' items="{{states}}">
<state-card class="state-card" state-obj="[[item]]"></state-card>
</template>
<template if="{{states.length == 0}}">
<template if="{{emptyStates}}">
<div class='no-states-content'>
<content></content>
</div>
@ -53,4 +53,28 @@
</div>
</template>
</polymer-element>
</dom-module>
<script>
(function() {
Polymer({
is: 'state-cards',
properties: {
states: {
type: Array,
value: [],
},
emptyStates: {
type: Boolean,
computed: 'computeEmptyStates(states)',
},
},
computeEmptyStates: function(states) {
return states.length == 0;
},
});
})();
</script>

View File

@ -1,48 +1,64 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-tooltip/core-tooltip.html">
<link rel="import" href="../bower_components/core-style/core-style.html">
<!-- <link rel="import" href="../bower_components/core-tooltip/core-tooltip.html"> -->
<link rel="import" href="state-badge.html">
<link rel="import" href="relative-ha-datetime.html">
<polymer-element name="state-info" attributes="stateObj" noscript>
<dom-module is="state-info">
<style>
state-badge {
float: left;
}
.name {
text-transform: capitalize;
font-weight: 300;
font-size: 1.3rem;
}
.info {
margin-left: 60px;
}
.time-ago {
color: darkgrey;
margin-top: -2px;
}
</style>
<template>
<style>
state-badge {
float: left;
}
.name {
text-transform: capitalize;
font-weight: 300;
font-size: 1.3rem;
}
.info {
margin-left: 60px;
}
.time-ago {
color: darkgrey;
margin-top: -2px;
}
</style>
<div>
<state-badge stateObj="{{stateObj}}"></state-badge>
<state-badge state-obj='[[stateObj]]'></state-badge>
<div class='info'>
<div class='name'>
{{stateObj.entityDisplay}}
</div>
<div class='name'>[[stateObj.entityDisplay]]</div>
<div class="time-ago">
<core-tooltip label="{{stateObj.lastChangedAsDate | formatDateTime}}" position="bottom">
<relative-ha-datetime datetimeObj="{{stateObj.lastChangedAsDate}}"></relative-ha-datetime>
</core-tooltip>
<div class='time-ago'>
<!-- <core-tooltip label="[[computeTooltipLabel(stateObj)]]" position="bottom"> -->
<relative-ha-datetime datetime-obj='[[stateObj.lastChangedAsDate]]'></relative-ha-datetime>
<!-- </core-tooltip> -->
</div>
</div>
</div>
</template>
</polymer-element>
</dom-module>
<script>
(function() {
Polymer({
is: 'state-info',
properties: {
stateObj: {
type: Object,
},
},
computeTooltipLabel: function(stateObj) {
// stateObj.lastChangedAsDate | formatDateTime
return 'Label TODO';
},
});
})();
</script>

View File

@ -9,8 +9,8 @@
<link rel="import" href="../bower_components/paper-item/paper-item.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<!-- <link rel="import" href="../layouts/partial-states.html">
<link rel="import" href="../layouts/partial-history.html">
<link rel="import" href="../layouts/partial-states.html">
<!-- <link rel="import" href="../layouts/partial-history.html">
<link rel="import" href="../layouts/partial-logbook.html">
<link rel="import" href="../layouts/partial-dev-fire-event.html">
<link rel="import" href="../layouts/partial-dev-call-service.html">
@ -56,7 +56,7 @@
<!-- <ha-modals></ha-modals> -->
<paper-drawer-panel id="drawer" on-paper-responsive-change="responsiveChanged">
<paper-header-panel mode="scroll" drawer class='sidenav layout fit'>
<paper-header-panel mode="scroll" drawer class='sidenav fit'>
<paper-toolbar>
Home Assistant
</paper-toolbar>
@ -148,12 +148,12 @@
This is the main partial, never remove it from the DOM but hide it
to speed up when people click on states.
-->
<!-- <partial-states hidden?="{{hideStates}}"
<partial-states hidden?="{{hideStates}}"
main narrow="{{narrow}}"
togglePanel="{{togglePanel}}"
filter="{{stateFilter}}">
</partial-states>
<!--
<template is='dom-if' if="{{selected == 'history'}}">
<partial-history main narrow="{{narrow}}" togglePanel="{{togglePanel}}"></partial-history>
</template>
@ -169,10 +169,6 @@
<template is='dom-if' if="{{selected == 'call-service'}}">
<partial-dev-call-service main narrow="{{narrow}}" togglePanel="{{togglePanel}}"></partial-dev-call-service>
</template>-->
<div main>
<p>Selected: <span>[[selected]]</span></p>
<p>Narrow: <span>[[narrow]]</span></p>
</div>
</paper-drawer-panel>
</template>
@ -235,11 +231,6 @@
type: Boolean,
value: false,
},
hasGroupStates: {
type: Boolean,
computed: '',
}
},
listeners: {

View File

@ -1,28 +1,51 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-scroll-header-panel/core-scroll-header-panel.html">
<link rel="import" href="../bower_components/core-toolbar/core-toolbar.html">
<link rel="import" href="../bower_components/paper-header-panel/paper-header-panel.html">
<!-- <link rel="import" href="../bower_components/core-scroll-header-panel/core-scroll-header-panel.html"> -->
<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/core-style/core-style.html">
<!-- <link rel="import" href="../bower_components/core-style/core-style.html"> -->
<polymer-element name="partial-base" attributes="narrow togglePanel" noscript>
<dom-module is="partial-base">
<template>
<core-style ref="ha-headers"></core-style>
<core-scroll-header-panel fit fixed="{{!narrow}}">
<core-toolbar>
<paper-icon-button
id="navicon" icon="menu" hidden?="{{!narrow}}"
on-click="{{togglePanel}}"></paper-icon-button>
<div flex>
<paper-header-panel class='fit'>
<paper-toolbar>
<paper-icon-button icon="menu" hidden$="[[!narrow]]"
on-click="togglePanel"></paper-icon-button>
<div class='flex'>
<content select="[header-title]"></content>
</div>
<content select="[header-buttons]"></content>
</core-toolbar>
</paper-toolbar>
<content></content>
</core-scroll-header-panel>
</paper-header-panel>
</template>
</polymer>
</dom-module>
<script>
(function() {
Polymer({
is: 'partial-base',
properties: {
narrow: {
type: Boolean,
value: false,
},
togglePanel: {
type: Function,
value: function() {},
},
},
});
})();
</script>

View File

@ -1,16 +1,13 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-icon/core-icon.html">
<link rel="import" href="../bower_components/core-style/core-style.html">
<link rel="import" href="../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="./partial-base.html">
<link rel="import" href="../components/state-cards.html">
<polymer-element name="partial-states" attributes="narrow togglePanel filter">
<template>
<core-style ref="ha-animations"></core-style>
<dom-module is="partial-states" attributes="narrow togglePanel filter">
<style>
.listening {
position: absolute;
@ -36,65 +33,132 @@
}
</style>
<partial-base narrow="{{narrow}}" togglePanel="{{togglePanel}}">
<span header-title>{{headerTitle}}</span>
<template>
<!-- <core-style ref="ha-animations"></core-style> -->
<span header-buttons>
<paper-icon-button icon="refresh" class="{{isFetching && 'ha-spin'}}"
on-click="{{handleRefreshClick}}" hidden?="{{isStreaming}}"></paper-icon-button>
<paper-icon-button icon="{{isListening ? 'av:mic-off' : 'av:mic' }}" hidden?={{!canListen}}
on-click="{{handleListenClick}}"></paper-icon-button>
</span>
<partial-base narrow="[[narrow]]" togglePanel="[[togglePanel]]">
<span header-title>{{headerTitle}}</span>
<div class='listening' hidden?="{{!isListening && !isTransmitting}}" on-click={{handleListenClick}}>
<core-icon icon="av:hearing"></core-icon> {{finalTranscript}}
<span class='interimTranscript'>{{interimTranscript}}</span>
<paper-spinner active?="{{isTransmitting}}"></paper-spinner>
</div>
<span header-buttons>
<paper-icon-button icon="refresh" class$="[[computeRefreshButtonClass(isFetching)]]"
on-click="handleRefresh" hidden$="[[isStreaming]]"></paper-icon-button>
<paper-icon-button icon="[[listenButtonIcon]]" hidden$={{!canListen}}
on-click="handleListenClick"></paper-icon-button>
</span>
<div class='listening' hidden$="[[!showListenInterface]]"
on-click="handleListenClick">
<iron-icon icon="av:hearing"></iron-icon> <span>{{finalTranscript}}</span>
<span class='interimTranscript'>[[interimTranscript]]</span>
<paper-spinner active$="[[isTransmitting]]" alt="Sending voice command to Home Assistant"></paper-spinner>
</div>
<state-cards states="[[states]]">
<h3>Hi there!</h3>
<p>
It looks like we have nothing to show you right now. It could be that we have not yet discovered all your devices but it is more likely that you have not configured Home Assistant yet.
</p>
<p>
Please see the <a href='https://home-assistant.io/getting-started/' target='_blank'>Getting Started</a> section on how to setup your devices.
</p>
</state-cards>
</partial-base>
</template>
</dom-module>
<state-cards states="{{states}}">
<h3>Hi there!</h3>
<p>
It looks like we have nothing to show you right now. It could be that we have not yet discovered all your devices but it is more likely that you have not configured Home Assistant yet.
</p>
<p>
Please see the <a href='https://home-assistant.io/getting-started/' target='_blank'>Getting Started</a> section on how to setup your devices.
</p>
</state-cards>
</partial-base>
</template>
<script>
(function(){
var storeListenerMixIn = window.hass.storeListenerMixIn;
var syncActions = window.hass.syncActions;
var voiceActions = window.hass.voiceActions;
var stateStore = window.hass.stateStore;
var uiConstants = window.hass.uiConstants;
Polymer(Polymer.mixin({
headerTitle: "States",
states: [],
isFetching: false,
isStreaming: false,
Polymer({
is: 'partial-states',
canListen: false,
voiceSupported: false,
hasConversationComponent: false,
isListening: false,
isTransmittingVoice: false,
interimTranscript: '',
finalTranscript: '',
behaviors: [StoreListenerBehavior],
ready: function() {
this.voiceSupported = voiceActions.isSupported();
},
properties: {
/**
* Title to show in the header
*/
headerTitle: {
type: String,
value: 'States',
},
attached: function() {
this.listenToStores(true);
},
/**
* If header is to be shown in narrow mode.
*/
narrow: {
type: Boolean,
value: false,
},
detached: function() {
this.stopListeningToStores();
/**
* Function to toggle panel visibility.
*/
togglePanel: {
type: Function,
value: function() {},
},
filter: {
type: String,
value: null,
observer: 'filterChanged',
},
voiceSupported: {
type: Boolean,
value: voiceActions.isSupported(),
},
isFetching: {
type: Boolean,
value: false,
},
isStreaming: {
type: Boolean,
value: false,
},
canListen: {
type: Boolean,
value: false,
},
isListening: {
type: Boolean,
value: false,
},
isTransmitting: {
type: Boolean,
value: false,
},
interimTranscript: {
type: String,
value: '',
},
finalTranscript: {
type: String,
value: '',
},
listenButtonIcon: {
type: String,
computed: 'computeListenButtonIcon(isListening)'
},
showListenInterface: {
type: Boolean,
computed: 'computeShowListenInterface(isListening,isTransmitting)'
}
},
componentStoreChanged: function(componentStore) {
@ -145,10 +209,10 @@
}
this.states = states.toArray().filter(
function (el) {return !el.attributes.hidden});
function (el) {return !el.attributes.hidden;});
},
handleRefreshClick: function() {
handleRefresh: function() {
syncActions.fetchAll();
},
@ -159,7 +223,20 @@
voiceActions.listen();
}
},
}, storeListenerMixIn));
computeListenButtonIcon: function(isListening) {
return isListening ? 'av:mic-off' : 'av:mic';
},
computeShowListenInterface: function(isListening,isTransmitting) {
return isListening || isTransmitting;
},
computeRefreshButtonClass: function(isFetching) {
if (isFetching) {
return 'ha-spin';
}
},
});
})();
</script>
</polymer>

View File

@ -1,4 +1,3 @@
<link rel="import" href="../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../bower_components/iron-iconset-svg/iron-iconset-svg.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
@ -7,18 +6,17 @@
<link rel="import" href="../bower_components/iron-icons/hardware-icons.html">
<link rel="import" href="../bower_components/iron-icons/av-icons.html">
<iron-iconset-svg name="homeassistant-100" iconSize="100">
<iron-iconset-svg name="homeassistant-100" size="100">
<svg><defs>
<g id="thermostat">
<!--
Thermostat icon created by Scott Lewis from the Noun Project
Licensed under CC BY 3.0 - http://creativecommons.org/licenses/by/3.0/us/
-->
<path d="M66.861,60.105V17.453c0-9.06-7.347-16.405-16.408-16.405c-9.06,0-16.404,7.345-16.404,16.405v42.711 c-4.04,4.14-6.533,9.795-6.533,16.035c0,12.684,10.283,22.967,22.967,22.967c12.682,0,22.964-10.283,22.964-22.967 C73.447,69.933,70.933,64.254,66.861,60.105z M60.331,20.38h-13.21v6.536h6.63v6.539h-6.63v6.713h6.63v6.538h-6.63v6.5h6.63v6.536 h-6.63v7.218c-3.775,1.373-6.471,4.993-6.471,9.24h-6.626c0-5.396,2.598-10.182,6.61-13.185V17.446c0-0.038,0.004-0.075,0.004-0.111 l-0.004-0.007c0-5.437,4.411-9.846,9.849-9.846c5.438,0,9.848,4.409,9.848,9.846V20.38z"/></g>
<g id="thermostat"><path d="M66.861,60.105V17.453c0-9.06-7.347-16.405-16.408-16.405c-9.06,0-16.404,7.345-16.404,16.405v42.711 c-4.04,4.14-6.533,9.795-6.533,16.035c0,12.684,10.283,22.967,22.967,22.967c12.682,0,22.964-10.283,22.964-22.967 C73.447,69.933,70.933,64.254,66.861,60.105z M60.331,20.38h-13.21v6.536h6.63v6.539h-6.63v6.713h6.63v6.538h-6.63v6.5h6.63v6.536 h-6.63v7.218c-3.775,1.373-6.471,4.993-6.471,9.24h-6.626c0-5.396,2.598-10.182,6.61-13.185V17.446c0-0.038,0.004-0.075,0.004-0.111 l-0.004-0.007c0-5.437,4.411-9.846,9.849-9.846c5.438,0,9.848,4.409,9.848,9.846V20.38z"/></g>
</defs></svg>
</iron-iconset-svg>
<iron-iconset-svg name="homeassistant-24" iconSize="24">
<iron-iconset-svg name="homeassistant-24" size="24">
<svg><defs>
<!--
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
@ -29,7 +27,6 @@
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<g id="group"><path d="M9 12c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm5-3c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2 2 2-.9 2-2zm-2-7c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g>
</defs></svg>
</iron-iconset-svg>

View File

@ -44,7 +44,7 @@
window.hass.uiActions = {
showMoreInfoDialog: function(entityId) {
dispatcher.dispatch({
actionType: this.ACTION_SHOW_DIALOG_MORE_INFO,
actionType: window.hass.uiConstants.ACTION_SHOW_DIALOG_MORE_INFO,
entityId: entityId,
});
},

View File

@ -1,7 +1,6 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<style is="custom-style">
* {
--dark-primary-color: #0288D1;
--default-primary-color: #03A9F4;
@ -19,6 +18,31 @@
--paper-toggle-button-checked-bar-color: #039be5;
}
@-webkit-keyframes ha-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes ha-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
body /deep/ .ha-spin {
-webkit-animation: ha-spin 2s infinite linear;
animation: ha-spin 2s infinite linear;
}
</style>
<core-style id='ha-main'>