Polymer .9: show basic state cards
parent
313eb71b17
commit
4576a1d245
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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: {
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -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'>
|
||||
|
|
Loading…
Reference in New Issue