mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 04:16:34 +00:00
Merge pull request #63 from home-assistant/inline-javascript
Clean up - step 2: Break up app in core + ui and inline some scripts
This commit is contained in:
commit
c1cbd33d41
11
.eslintrc
11
.eslintrc
@ -2,6 +2,15 @@
|
||||
"extends": "airbnb-base",
|
||||
"globals": {
|
||||
"__DEV__": false,
|
||||
"__DEMO__": false
|
||||
"Polymer": true
|
||||
},
|
||||
"rules": {
|
||||
"new-cap": 0,
|
||||
"prefer-template": 0,
|
||||
"object-shorthand": 0,
|
||||
"func-names": 0,
|
||||
"prefer-arrow-callback": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-var": 0
|
||||
}
|
||||
}
|
||||
|
23
src/app-core.js
Normal file
23
src/app-core.js
Normal file
@ -0,0 +1,23 @@
|
||||
import moment from 'moment';
|
||||
|
||||
import HomeAssistant from 'home-assistant-js';
|
||||
|
||||
window.moment = moment;
|
||||
|
||||
// While we figure out how ha-entity-marker can keep it's references
|
||||
window.hass = new HomeAssistant();
|
||||
|
||||
window.validateAuth = function validateAuth(hass, authToken, rememberAuth) {
|
||||
hass.authActions.validate(authToken, {
|
||||
rememberAuth,
|
||||
useStreaming: hass.localStoragePreferences.useStreaming,
|
||||
});
|
||||
};
|
||||
|
||||
window.removeInitMsg = function removeInitMessage() {
|
||||
// remove the HTML init message
|
||||
const initMsg = document.getElementById('ha-init-skeleton');
|
||||
if (initMsg) {
|
||||
initMsg.parentElement.removeChild(initMsg);
|
||||
}
|
||||
};
|
@ -4,7 +4,6 @@ import dynamicContentUpdater from '../util/dynamic-content-updater';
|
||||
|
||||
require('./ha-camera-card');
|
||||
require('./ha-entities-card');
|
||||
require('./ha-introduction-card');
|
||||
require('./ha-media_player-card');
|
||||
|
||||
export default new Polymer({
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Polymer from '../polymer';
|
||||
import canToggle from '../util/can-toggle';
|
||||
|
||||
require('../components/ha-card');
|
||||
require('../components/entity/ha-entity-toggle');
|
||||
require('../state-summary/state-card-content');
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
<template>
|
||||
<ha-card header="Welcome Home!">
|
||||
<div class='content'>
|
||||
<template is='dom-if' if='[[showInstallInstruction]]'>
|
||||
<template is='dom-if' if='[[hass.demo]]'>
|
||||
To install Home Assistant, run:<br />
|
||||
<code class='install'>
|
||||
pip3 install homeassistant<br />
|
||||
@ -39,7 +39,7 @@
|
||||
</template>
|
||||
Here are some resources to get started.
|
||||
<ul>
|
||||
<template is='dom-if' if='[[showInstallInstruction]]'>
|
||||
<template is='dom-if' if='[[hass.demo]]'>
|
||||
<li><a href='https://home-assistant.io/getting-started/'>Home Assistant website</a></li>
|
||||
<li><a href='https://home-assistant.io/getting-started/'>Installation instructions</a></li>
|
||||
<li><a href='https://home-assistant.io/getting-started/troubleshooting/'>Troubleshooting your installation</a></li>
|
||||
@ -64,3 +64,20 @@
|
||||
</ha-card>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-introduction-card',
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
showHideInstruction: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,18 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('../components/ha-card');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-introduction-card',
|
||||
|
||||
properties: {
|
||||
showInstallInstruction: {
|
||||
type: Boolean,
|
||||
value: __DEMO__,
|
||||
},
|
||||
showHideInstruction: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
});
|
@ -25,3 +25,34 @@
|
||||
</ul>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'entity-list',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
entities: {
|
||||
type: Array,
|
||||
bindNuclear: function (hass) {
|
||||
return [
|
||||
hass.entityGetters.entityMap,
|
||||
function (map) {
|
||||
return map.valueSeq().sortBy(function (entity) { return entity.entityId; }).toArray();
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
entitySelected: function (ev) {
|
||||
ev.preventDefault();
|
||||
this.fire('entity-selected', { entityId: ev.model.entity.entityId });
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,26 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'entity-list',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
entities: {
|
||||
type: Array,
|
||||
bindNuclear: hass => [
|
||||
hass.entityGetters.entityMap,
|
||||
(map) => map.valueSeq().sortBy((entity) => entity.entityId).toArray(),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
entitySelected(ev) {
|
||||
ev.preventDefault();
|
||||
this.fire('entity-selected', { entityId: ev.model.entity.entityId });
|
||||
},
|
||||
});
|
@ -1,7 +1,5 @@
|
||||
import Polymer from '../../polymer';
|
||||
|
||||
require('../../components/ha-label-badge');
|
||||
|
||||
/*
|
||||
Leaflet clones this element before adding it to the map. This messes up
|
||||
our Poylmer object and we lose the reference to the `hass` object.
|
||||
|
@ -2,8 +2,6 @@ import Polymer from '../../polymer';
|
||||
import domainIcon from '../../util/domain-icon';
|
||||
import stateIcon from '../../util/state-icon';
|
||||
|
||||
require('../../components/ha-label-badge');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-state-label-badge',
|
||||
|
||||
|
@ -28,3 +28,34 @@
|
||||
</ul>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'events-list',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
events: {
|
||||
type: Array,
|
||||
bindNuclear: function (hass) {
|
||||
return [
|
||||
hass.eventGetters.entityMap,
|
||||
function (map) {
|
||||
return map.valueSeq().sortBy(function (event) { return event.event; }).toArray();
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
eventSelected: function (ev) {
|
||||
ev.preventDefault();
|
||||
this.fire('event-selected', { eventType: ev.model.event.event });
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,26 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'events-list',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
events: {
|
||||
type: Array,
|
||||
bindNuclear: hass => [
|
||||
hass.eventGetters.entityMap,
|
||||
(map) => map.valueSeq().sortBy((event) => event.event).toArray(),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
eventSelected(ev) {
|
||||
ev.preventDefault();
|
||||
this.fire('event-selected', { eventType: ev.model.event.event });
|
||||
},
|
||||
});
|
@ -25,3 +25,23 @@
|
||||
<content></content>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-card',
|
||||
|
||||
properties: {
|
||||
header: {
|
||||
type: String,
|
||||
},
|
||||
/**
|
||||
* The z-depth of the card, from 0-5.
|
||||
*/
|
||||
elevation: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
reflectToAttribute: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,19 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-card',
|
||||
|
||||
properties: {
|
||||
header: {
|
||||
type: String,
|
||||
},
|
||||
/**
|
||||
* The z-depth of the card, from 0-5.
|
||||
*/
|
||||
elevation: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
reflectToAttribute: true,
|
||||
},
|
||||
},
|
||||
});
|
@ -1,6 +1,5 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('.//ha-demo-badge');
|
||||
require('../cards/ha-badges-card');
|
||||
require('../cards/ha-card-chooser');
|
||||
|
||||
@ -109,8 +108,9 @@ export default new Polymer({
|
||||
}
|
||||
if (showIntroduction) {
|
||||
cards.columns[getIndex(5)].push({
|
||||
hass,
|
||||
cardType: 'introduction',
|
||||
showHideInstruction: states.size > 0 && !__DEMO__,
|
||||
showHideInstruction: states.size > 0 && !hass.demo,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -10,3 +10,134 @@
|
||||
<canvas width='[[width]]' height='[[height]]'></canvas>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Color-picker custom element
|
||||
* Originally created by bbrewer97202 (Ben Brewer). MIT Licensed.
|
||||
* https://github.com/bbrewer97202/color-picker-element
|
||||
*
|
||||
* Adapted to work with Polymer.
|
||||
*/
|
||||
Polymer({
|
||||
is: 'ha-color-picker',
|
||||
|
||||
properties: {
|
||||
color: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
width: {
|
||||
type: Number,
|
||||
},
|
||||
|
||||
height: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
|
||||
listeners: {
|
||||
mousedown: 'onMouseDown',
|
||||
mouseup: 'onMouseUp',
|
||||
touchstart: 'onTouchStart',
|
||||
touchend: 'onTouchEnd',
|
||||
},
|
||||
|
||||
onMouseDown: function (ev) {
|
||||
this.onMouseMove(ev);
|
||||
this.addEventListener('mousemove', this.onMouseMove);
|
||||
},
|
||||
|
||||
onMouseUp: function () {
|
||||
this.removeEventListener('mousemove', this.onMouseMove);
|
||||
},
|
||||
|
||||
onTouchStart: function (ev) {
|
||||
this.onTouchMove(ev);
|
||||
this.addEventListener('touchmove', this.onTouchMove);
|
||||
},
|
||||
|
||||
onTouchEnd: function () {
|
||||
this.removeEventListener('touchmove', this.onTouchMove);
|
||||
},
|
||||
|
||||
onTouchMove: function (ev) {
|
||||
if (!this.mouseMoveIsThrottled) {
|
||||
return;
|
||||
}
|
||||
this.mouseMoveIsThrottled = false;
|
||||
this.processColorSelect(ev.touches[0]);
|
||||
this.async(function () { this.mouseMoveIsThrottled = true; }.bind(this), 100);
|
||||
},
|
||||
|
||||
onMouseMove: function (ev) {
|
||||
if (!this.mouseMoveIsThrottled) {
|
||||
return;
|
||||
}
|
||||
this.mouseMoveIsThrottled = false;
|
||||
this.processColorSelect(ev);
|
||||
this.async(function () { this.mouseMoveIsThrottled = true; }.bind(this), 100);
|
||||
},
|
||||
|
||||
processColorSelect: function (ev) {
|
||||
var rect = this.canvas.getBoundingClientRect();
|
||||
|
||||
// boundary check because people can move off-canvas.
|
||||
if (ev.clientX < rect.left || ev.clientX >= rect.left + rect.width ||
|
||||
ev.clientY < rect.top || ev.clientY >= rect.top + rect.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onColorSelect(ev.clientX - rect.left, ev.clientY - rect.top);
|
||||
},
|
||||
|
||||
onColorSelect: function (x, y) {
|
||||
var data = this.context.getImageData(x, y, 1, 1).data;
|
||||
|
||||
this.setColor({ r: data[0], g: data[1], b: data[2] });
|
||||
},
|
||||
|
||||
setColor: function (rgb) {
|
||||
this.color = rgb;
|
||||
|
||||
this.fire('colorselected', { rgb: this.color });
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this.setColor = this.setColor.bind(this);
|
||||
this.mouseMoveIsThrottled = true;
|
||||
this.canvas = this.children[0];
|
||||
this.context = this.canvas.getContext('2d');
|
||||
this.drawGradient();
|
||||
},
|
||||
|
||||
drawGradient: function () {
|
||||
var style;
|
||||
if (!this.width || !this.height) {
|
||||
style = getComputedStyle(this);
|
||||
}
|
||||
var width = this.width || parseInt(style.width, 10);
|
||||
var height = this.height || parseInt(style.height, 10);
|
||||
|
||||
var colorGradient = this.context.createLinearGradient(0, 0, width, 0);
|
||||
colorGradient.addColorStop(0, 'rgb(255,0,0)');
|
||||
colorGradient.addColorStop(0.16, 'rgb(255,0,255)');
|
||||
colorGradient.addColorStop(0.32, 'rgb(0,0,255)');
|
||||
colorGradient.addColorStop(0.48, 'rgb(0,255,255)');
|
||||
colorGradient.addColorStop(0.64, 'rgb(0,255,0)');
|
||||
colorGradient.addColorStop(0.80, 'rgb(255,255,0)');
|
||||
colorGradient.addColorStop(1, 'rgb(255,0,0)');
|
||||
this.context.fillStyle = colorGradient;
|
||||
this.context.fillRect(0, 0, width, height);
|
||||
|
||||
var bwGradient = this.context.createLinearGradient(0, 0, 0, height);
|
||||
bwGradient.addColorStop(0, 'rgba(255,255,255,1)');
|
||||
bwGradient.addColorStop(0.5, 'rgba(255,255,255,0)');
|
||||
bwGradient.addColorStop(0.5, 'rgba(0,0,0,0)');
|
||||
bwGradient.addColorStop(1, 'rgba(0,0,0,1)');
|
||||
|
||||
this.context.fillStyle = bwGradient;
|
||||
this.context.fillRect(0, 0, width, height);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,130 +0,0 @@
|
||||
/**
|
||||
* Color-picker custom element
|
||||
* Originally created by bbrewer97202 (Ben Brewer). MIT Licensed.
|
||||
* https://github.com/bbrewer97202/color-picker-element
|
||||
*
|
||||
* Adapted to work with Polymer.
|
||||
*/
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-color-picker',
|
||||
|
||||
properties: {
|
||||
color: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
width: {
|
||||
type: Number,
|
||||
},
|
||||
|
||||
height: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
|
||||
listeners: {
|
||||
mousedown: 'onMouseDown',
|
||||
mouseup: 'onMouseUp',
|
||||
touchstart: 'onTouchStart',
|
||||
touchend: 'onTouchEnd',
|
||||
},
|
||||
|
||||
onMouseDown(ev) {
|
||||
this.onMouseMove(ev);
|
||||
this.addEventListener('mousemove', this.onMouseMove);
|
||||
},
|
||||
|
||||
onMouseUp() {
|
||||
this.removeEventListener('mousemove', this.onMouseMove);
|
||||
},
|
||||
|
||||
onTouchStart(ev) {
|
||||
this.onTouchMove(ev);
|
||||
this.addEventListener('touchmove', this.onTouchMove);
|
||||
},
|
||||
|
||||
onTouchEnd() {
|
||||
this.removeEventListener('touchmove', this.onTouchMove);
|
||||
},
|
||||
|
||||
onTouchMove(ev) {
|
||||
if (!this.mouseMoveIsThrottled) {
|
||||
return;
|
||||
}
|
||||
this.mouseMoveIsThrottled = false;
|
||||
this.processColorSelect(ev.touches[0]);
|
||||
this.async(() => { this.mouseMoveIsThrottled = true; }, 100);
|
||||
},
|
||||
|
||||
onMouseMove(ev) {
|
||||
if (!this.mouseMoveIsThrottled) {
|
||||
return;
|
||||
}
|
||||
this.mouseMoveIsThrottled = false;
|
||||
this.processColorSelect(ev);
|
||||
this.async(() => { this.mouseMoveIsThrottled = true; }, 100);
|
||||
},
|
||||
|
||||
processColorSelect(ev) {
|
||||
const rect = this.canvas.getBoundingClientRect();
|
||||
|
||||
// boundary check because people can move off-canvas.
|
||||
if (ev.clientX < rect.left || ev.clientX >= rect.left + rect.width ||
|
||||
ev.clientY < rect.top || ev.clientY >= rect.top + rect.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onColorSelect(ev.clientX - rect.left, ev.clientY - rect.top);
|
||||
},
|
||||
|
||||
onColorSelect(x, y) {
|
||||
const data = this.context.getImageData(x, y, 1, 1).data;
|
||||
|
||||
this.setColor({ r: data[0], g: data[1], b: data[2] });
|
||||
},
|
||||
|
||||
setColor(rgb) {
|
||||
this.color = rgb;
|
||||
|
||||
this.fire('colorselected', { rgb: this.color });
|
||||
},
|
||||
|
||||
ready() {
|
||||
this.setColor = this.setColor.bind(this);
|
||||
this.mouseMoveIsThrottled = true;
|
||||
this.canvas = this.children[0];
|
||||
this.context = this.canvas.getContext('2d');
|
||||
this.drawGradient();
|
||||
},
|
||||
|
||||
drawGradient() {
|
||||
let style;
|
||||
if (!this.width || !this.height) {
|
||||
style = getComputedStyle(this);
|
||||
}
|
||||
const width = this.width || parseInt(style.width, 10);
|
||||
const height = this.height || parseInt(style.height, 10);
|
||||
|
||||
const colorGradient = this.context.createLinearGradient(0, 0, width, 0);
|
||||
colorGradient.addColorStop(0, 'rgb(255,0,0)');
|
||||
colorGradient.addColorStop(0.16, 'rgb(255,0,255)');
|
||||
colorGradient.addColorStop(0.32, 'rgb(0,0,255)');
|
||||
colorGradient.addColorStop(0.48, 'rgb(0,255,255)');
|
||||
colorGradient.addColorStop(0.64, 'rgb(0,255,0)');
|
||||
colorGradient.addColorStop(0.80, 'rgb(255,255,0)');
|
||||
colorGradient.addColorStop(1, 'rgb(255,0,0)');
|
||||
this.context.fillStyle = colorGradient;
|
||||
this.context.fillRect(0, 0, width, height);
|
||||
|
||||
const bwGradient = this.context.createLinearGradient(0, 0, 0, height);
|
||||
bwGradient.addColorStop(0, 'rgba(255,255,255,1)');
|
||||
bwGradient.addColorStop(0.5, 'rgba(255,255,255,0)');
|
||||
bwGradient.addColorStop(0.5, 'rgba(0,0,0,0)');
|
||||
bwGradient.addColorStop(1, 'rgba(0,0,0,1)');
|
||||
|
||||
this.context.fillStyle = bwGradient;
|
||||
this.context.fillRect(0, 0, width, height);
|
||||
},
|
||||
});
|
@ -16,3 +16,9 @@
|
||||
></ha-label-badge>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-demo-badge',
|
||||
});
|
||||
</script>
|
||||
|
@ -1,7 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./ha-label-badge');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-demo-badge',
|
||||
});
|
@ -83,3 +83,54 @@
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
// Beware: Polymer will not call computeHideIcon and computeHideValue if any of
|
||||
// the parameters are undefined. Set to null if not using.
|
||||
Polymer({
|
||||
is: 'ha-label-badge',
|
||||
|
||||
properties: {
|
||||
value: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
icon: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
label: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
image: {
|
||||
type: String,
|
||||
value: null,
|
||||
observer: 'imageChanged',
|
||||
},
|
||||
},
|
||||
|
||||
computeClasses: function (value) {
|
||||
return value && value.length > 4 ? 'value big' : 'value';
|
||||
},
|
||||
|
||||
computeHideIcon: function (icon, value, image) {
|
||||
return !icon || value || image;
|
||||
},
|
||||
|
||||
computeHideValue: function (value, image) {
|
||||
return !value || image;
|
||||
},
|
||||
|
||||
imageChanged: function (newVal) {
|
||||
this.$.badge.style.backgroundImage = newVal ? `url(${newVal})` : '';
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,50 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
// Beware: Polymer will not call computeHideIcon and computeHideValue if any of
|
||||
// the parameters are undefined. Set to null if not using.
|
||||
export default new Polymer({
|
||||
is: 'ha-label-badge',
|
||||
|
||||
properties: {
|
||||
value: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
icon: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
label: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
image: {
|
||||
type: String,
|
||||
value: null,
|
||||
observer: 'imageChanged',
|
||||
},
|
||||
},
|
||||
|
||||
computeClasses(value) {
|
||||
return value && value.length > 4 ? 'value big' : 'value';
|
||||
},
|
||||
|
||||
computeHideIcon(icon, value, image) {
|
||||
return !icon || value || image;
|
||||
},
|
||||
|
||||
computeHideValue(value, image) {
|
||||
return !value || image;
|
||||
},
|
||||
|
||||
imageChanged(newVal) {
|
||||
this.$.badge.style.backgroundImage = newVal ? `url(${newVal})` : '';
|
||||
},
|
||||
});
|
@ -14,7 +14,28 @@
|
||||
No logbook entries found.
|
||||
</template>
|
||||
<template is='dom-repeat' items="[[entries]]">
|
||||
<logbook-entry entry-obj="[[item]]"></logbook-entry>
|
||||
<logbook-entry entry-obj="[[item]]" hass='[[hass]]'></logbook-entry>
|
||||
</template>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-logbook',
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
entries: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
},
|
||||
|
||||
noEntries: function (entries) {
|
||||
return !entries.length;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,18 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./logbook-entry');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-logbook',
|
||||
|
||||
properties: {
|
||||
entries: {
|
||||
type: Object,
|
||||
value: [],
|
||||
},
|
||||
},
|
||||
|
||||
noEntries(entries) {
|
||||
return !entries.length;
|
||||
},
|
||||
});
|
@ -169,3 +169,86 @@
|
||||
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-sidebar',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
menuShown: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
||||
menuSelected: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
narrow: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
||||
selected: {
|
||||
type: String,
|
||||
bindNuclear: function (hass) { return hass.navigationGetters.activePane; },
|
||||
},
|
||||
|
||||
hasHistoryComponent: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) { return hass.configGetters.isComponentLoaded('history'); },
|
||||
},
|
||||
|
||||
hasLogbookComponent: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) { return hass.configGetters.isComponentLoaded('logbook'); },
|
||||
},
|
||||
},
|
||||
|
||||
created: function () {
|
||||
this._boundUpdateStyles = this.updateStyles.bind(this);
|
||||
},
|
||||
|
||||
menuSelect: function () {
|
||||
this.debounce('updateStyles', this._boundUpdateStyles, 1);
|
||||
},
|
||||
|
||||
menuClicked: function (ev) {
|
||||
var target = ev.target;
|
||||
var checks = 5;
|
||||
|
||||
// find panel to select
|
||||
while (checks && !target.getAttribute('data-panel')) {
|
||||
target = target.parentElement;
|
||||
checks--;
|
||||
}
|
||||
|
||||
if (checks) {
|
||||
this.selectPanel(target.getAttribute('data-panel'));
|
||||
}
|
||||
},
|
||||
|
||||
toggleMenu: function () {
|
||||
this.fire('close-menu');
|
||||
},
|
||||
|
||||
selectPanel: function (newChoice) {
|
||||
if (newChoice === this.selected) {
|
||||
return;
|
||||
} else if (newChoice === 'logout') {
|
||||
this.handleLogOut();
|
||||
return;
|
||||
}
|
||||
this.hass.navigationActions.navigate.apply(null, newChoice.split('/'));
|
||||
this.debounce('updateStyles', this._boundUpdateStyles, 1);
|
||||
},
|
||||
|
||||
handleLogOut: function () {
|
||||
this.hass.authActions.logOut();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,80 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./stream-status');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-sidebar',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
menuShown: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
||||
menuSelected: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
narrow: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
||||
selected: {
|
||||
type: String,
|
||||
bindNuclear: hass => hass.navigationGetters.activePane,
|
||||
},
|
||||
|
||||
hasHistoryComponent: {
|
||||
type: Boolean,
|
||||
bindNuclear: hass => hass.configGetters.isComponentLoaded('history'),
|
||||
},
|
||||
|
||||
hasLogbookComponent: {
|
||||
type: Boolean,
|
||||
bindNuclear: hass => hass.configGetters.isComponentLoaded('logbook'),
|
||||
},
|
||||
},
|
||||
|
||||
menuSelect() {
|
||||
this.debounce('updateStyles', () => this.updateStyles(), 1);
|
||||
},
|
||||
|
||||
menuClicked(ev) {
|
||||
let target = ev.target;
|
||||
let checks = 5;
|
||||
|
||||
// find panel to select
|
||||
while (checks && !target.getAttribute('data-panel')) {
|
||||
target = target.parentElement;
|
||||
checks--;
|
||||
}
|
||||
|
||||
if (checks) {
|
||||
this.selectPanel(target.getAttribute('data-panel'));
|
||||
}
|
||||
},
|
||||
|
||||
toggleMenu() {
|
||||
this.fire('close-menu');
|
||||
},
|
||||
|
||||
selectPanel(newChoice) {
|
||||
if (newChoice === this.selected) {
|
||||
return;
|
||||
} else if (newChoice === 'logout') {
|
||||
this.handleLogOut();
|
||||
return;
|
||||
}
|
||||
this.hass.navigationActions.navigate.apply(null, newChoice.split('/'));
|
||||
this.debounce('updateStyles', () => this.updateStyles(), 1);
|
||||
},
|
||||
|
||||
handleLogOut() {
|
||||
this.hass.authActions.logOut();
|
||||
},
|
||||
});
|
@ -23,3 +23,58 @@
|
||||
</paper-tabs>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-view-tabs',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
locationName: {
|
||||
type: String,
|
||||
bindNuclear: function (hass) { return hass.configGetters.locationName; },
|
||||
},
|
||||
|
||||
currentView: {
|
||||
type: String,
|
||||
bindNuclear: function (hass) {
|
||||
return [
|
||||
hass.viewGetters.currentView,
|
||||
function (view) { return view || ''; },
|
||||
];
|
||||
},
|
||||
},
|
||||
|
||||
views: {
|
||||
type: Array,
|
||||
bindNuclear: function (hass) {
|
||||
return [
|
||||
hass.viewGetters.views,
|
||||
function (views) {
|
||||
return views.valueSeq()
|
||||
.sortBy(function (view) { return view.attributes.order; })
|
||||
.toArray();
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
viewTapped() {
|
||||
this.fire('view-tapped');
|
||||
},
|
||||
|
||||
viewSelected(ev) {
|
||||
var view = ev.detail.item.getAttribute('data-entity') || null;
|
||||
var current = this.currentView || null;
|
||||
if (view !== current) {
|
||||
this.async(function () { this.hass.viewActions.selectView(view); }.bind(this), 0);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,49 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-view-tabs',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
locationName: {
|
||||
type: String,
|
||||
bindNuclear: hass => hass.configGetters.locationName,
|
||||
},
|
||||
|
||||
currentView: {
|
||||
type: String,
|
||||
bindNuclear: hass => [
|
||||
hass.viewGetters.currentView,
|
||||
view => view || '',
|
||||
],
|
||||
},
|
||||
|
||||
views: {
|
||||
type: Array,
|
||||
bindNuclear: hass => [
|
||||
hass.viewGetters.views,
|
||||
views => views.valueSeq()
|
||||
.sortBy(view => view.attributes.order)
|
||||
.toArray(),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
viewTapped() {
|
||||
this.fire('view-tapped');
|
||||
},
|
||||
|
||||
viewSelected(ev) {
|
||||
const view = ev.detail.item.getAttribute('data-entity') || null;
|
||||
const current = this.currentView || null;
|
||||
this.expectChange = true;
|
||||
if (view !== current) {
|
||||
this.async(() => this.hass.viewActions.selectView(view), 0);
|
||||
}
|
||||
},
|
||||
});
|
@ -18,3 +18,9 @@
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'loading-box',
|
||||
});
|
||||
</script>
|
||||
|
@ -1,5 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'loading-box',
|
||||
});
|
@ -2,7 +2,6 @@ import Polymer from '../polymer';
|
||||
|
||||
require('./domain-icon');
|
||||
require('./display-time');
|
||||
require('./relative-ha-datetime');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'logbook-entry',
|
||||
|
@ -5,3 +5,60 @@
|
||||
<span>[[relativeTime]]</span>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'relative-ha-datetime',
|
||||
|
||||
properties: {
|
||||
datetime: {
|
||||
type: String,
|
||||
observer: 'datetimeChanged',
|
||||
},
|
||||
|
||||
datetimeObj: {
|
||||
type: Object,
|
||||
observer: 'datetimeObjChanged',
|
||||
},
|
||||
|
||||
parsedDateTime: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
relativeTime: {
|
||||
type: String,
|
||||
value: 'not set',
|
||||
},
|
||||
},
|
||||
|
||||
created: function () {
|
||||
this.updateRelative = this.updateRelative.bind(this);
|
||||
},
|
||||
|
||||
attached: function () {
|
||||
// update every 60 seconds
|
||||
this.updateInterval = setInterval(this.updateRelative, 60000);
|
||||
},
|
||||
|
||||
detached: function () {
|
||||
clearInterval(this.updateInterval);
|
||||
},
|
||||
|
||||
datetimeChanged: function (newVal) {
|
||||
this.parsedDateTime = newVal ? new Date(newVal) : null;
|
||||
|
||||
this.updateRelative();
|
||||
},
|
||||
|
||||
datetimeObjChanged: function (newVal) {
|
||||
this.parsedDateTime = newVal;
|
||||
|
||||
this.updateRelative();
|
||||
},
|
||||
|
||||
updateRelative: function () {
|
||||
this.relativeTime = this.parsedDateTime ?
|
||||
window.moment(this.parsedDateTime).fromNow() : '';
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,57 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
const UPDATE_INTERVAL = 60000; // 60 seconds
|
||||
|
||||
export default new Polymer({
|
||||
is: 'relative-ha-datetime',
|
||||
|
||||
properties: {
|
||||
datetime: {
|
||||
type: String,
|
||||
observer: 'datetimeChanged',
|
||||
},
|
||||
|
||||
datetimeObj: {
|
||||
type: Object,
|
||||
observer: 'datetimeObjChanged',
|
||||
},
|
||||
|
||||
parsedDateTime: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
relativeTime: {
|
||||
type: String,
|
||||
value: 'not set',
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.updateRelative = this.updateRelative.bind(this);
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.updateInterval = setInterval(this.updateRelative, UPDATE_INTERVAL);
|
||||
},
|
||||
|
||||
detached() {
|
||||
clearInterval(this.updateInterval);
|
||||
},
|
||||
|
||||
datetimeChanged(newVal) {
|
||||
this.parsedDateTime = newVal ? new Date(newVal) : null;
|
||||
|
||||
this.updateRelative();
|
||||
},
|
||||
|
||||
datetimeObjChanged(newVal) {
|
||||
this.parsedDateTime = newVal;
|
||||
|
||||
this.updateRelative();
|
||||
},
|
||||
|
||||
updateRelative() {
|
||||
this.relativeTime = this.parsedDateTime ?
|
||||
window.moment(this.parsedDateTime).fromNow() : '';
|
||||
},
|
||||
});
|
@ -1,6 +1,5 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./loading-box');
|
||||
require('./state-history-chart-timeline');
|
||||
require('./state-history-chart-line');
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./entity/state-badge');
|
||||
require('./relative-ha-datetime');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'state-info',
|
||||
|
@ -25,3 +25,35 @@
|
||||
<paper-toggle-button id="toggle" on-change='toggleChanged' checked$='[[isStreaming]]' hidden$="[[hasError]]"></paper-toggle-button>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'stream-status',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
isStreaming: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) { return hass.streamGetters.isStreamingEvents; },
|
||||
},
|
||||
|
||||
hasError: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) { return hass.streamGetters.hasStreamingEventsError; },
|
||||
},
|
||||
},
|
||||
|
||||
toggleChanged: function () {
|
||||
if (this.isStreaming) {
|
||||
this.hass.streamActions.stop();
|
||||
} else {
|
||||
this.hass.streamActions.start();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,31 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'stream-status',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
isStreaming: {
|
||||
type: Boolean,
|
||||
bindNuclear: hass => hass.streamGetters.isStreamingEvents,
|
||||
},
|
||||
|
||||
hasError: {
|
||||
type: Boolean,
|
||||
bindNuclear: hass => hass.streamGetters.hasStreamingEventsError,
|
||||
},
|
||||
},
|
||||
|
||||
toggleChanged() {
|
||||
if (this.isStreaming) {
|
||||
this.hass.streamActions.stop();
|
||||
} else {
|
||||
this.hass.streamActions.start();
|
||||
}
|
||||
},
|
||||
});
|
@ -1,14 +1,17 @@
|
||||
<link rel='import' href='../bower_components/polymer/polymer.html'>
|
||||
<link rel='import' href='../bower_components/paper-spinner/paper-spinner.html'>
|
||||
|
||||
<script src='../build/_app_core_compiled.js'></script>
|
||||
|
||||
<link rel='import' href='../bower_components/iron-flex-layout/iron-flex-layout-classes.html'>
|
||||
<link rel='import' href='./util/roboto.html'>
|
||||
<link rel='import' href='../bower_components/paper-styles/typography.html'>
|
||||
<link rel="import" href="../bower_components/iron-iconset-svg/iron-iconset-svg.html">
|
||||
|
||||
<link rel='import' href='./util/hass-behavior.html'>
|
||||
<link rel='import' href='./layouts/login-form.html'>
|
||||
<link rel='import' href='./layouts/home-assistant-main.html'>
|
||||
|
||||
<link rel='import' href='resources/home-assistant-style.html'>
|
||||
<link rel='import' href='./resources/home-assistant-style.html'>
|
||||
|
||||
<dom-module id='home-assistant'>
|
||||
<style>
|
||||
@ -29,9 +32,94 @@
|
||||
</template>
|
||||
|
||||
<template is='dom-if' if='[[loaded]]'>
|
||||
<home-assistant-main hass='[[hass]]'></home-assistant-main>
|
||||
<home-assistant-main hass='[[hass]]' hidden$='[[!loaded]]'></home-assistant-main>
|
||||
</template>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'home-assistant',
|
||||
|
||||
hostAttributes: {
|
||||
auth: null,
|
||||
icons: null,
|
||||
},
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
value: window.hass,
|
||||
},
|
||||
auth: {
|
||||
type: String,
|
||||
},
|
||||
icons: {
|
||||
type: String,
|
||||
},
|
||||
dataLoaded: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) { return hass.syncGetters.isDataLoaded; },
|
||||
},
|
||||
iconsLoaded: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
loaded: {
|
||||
type: Boolean,
|
||||
computed: 'computeLoaded(dataLoaded, iconsLoaded)',
|
||||
},
|
||||
},
|
||||
|
||||
computeLoaded: function (dataLoaded, iconsLoaded) {
|
||||
return dataLoaded && iconsLoaded;
|
||||
},
|
||||
|
||||
computeForceShowLoading: function (dataLoaded, iconsLoaded) {
|
||||
return dataLoaded && !iconsLoaded;
|
||||
},
|
||||
|
||||
loadIcons: function () {
|
||||
// If the import fails, we'll try to import again, must be a server glitch
|
||||
// Since HTML imports only resolve once, we import another url.
|
||||
var success = function () {
|
||||
this.iconsLoaded = true;
|
||||
}.bind(this);
|
||||
|
||||
this.importHref(`/static/mdi-${this.icons}.html`,
|
||||
success,
|
||||
function () {
|
||||
this.importHref('/static/mdi.html', success, success);
|
||||
});
|
||||
},
|
||||
|
||||
created: function () {
|
||||
if (!('serviceWorker' in navigator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register('/service_worker.js');
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
var hass = this.hass;
|
||||
hass.reactor.batch(function () {
|
||||
// if auth was given, tell the backend
|
||||
if (this.auth) {
|
||||
window.validateAuth(this.hass, this.auth, false);
|
||||
} else if (hass.localStoragePreferences.authToken) {
|
||||
window.validateAuth(this.hass, hass.localStoragePreferences.authToken, true);
|
||||
}
|
||||
hass.navigationActions.showSidebar(hass.localStoragePreferences.showSidebar);
|
||||
});
|
||||
|
||||
hass.startLocalStoragePreferencesSync();
|
||||
|
||||
this.loadIcons();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src='../build/_app_compiled.js'></script>
|
||||
|
@ -1,99 +1 @@
|
||||
import moment from 'moment';
|
||||
import Polymer from './polymer';
|
||||
|
||||
import HomeAssistant from 'home-assistant-js';
|
||||
import validateAuth from './util/validate-auth';
|
||||
import hassBehavior from './util/hass-behavior';
|
||||
|
||||
window.hassBehavior = hassBehavior;
|
||||
window.moment = moment;
|
||||
|
||||
require('./layouts/login-form');
|
||||
require('./layouts/home-assistant-main');
|
||||
|
||||
// While we figure out how ha-entity-marker can keep it's references
|
||||
window.hass = new HomeAssistant();
|
||||
|
||||
export default new Polymer({
|
||||
is: 'home-assistant',
|
||||
|
||||
hostAttributes: {
|
||||
auth: null,
|
||||
icons: null,
|
||||
},
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
value: window.hass,
|
||||
},
|
||||
auth: {
|
||||
type: String,
|
||||
},
|
||||
icons: {
|
||||
type: String,
|
||||
},
|
||||
dataLoaded: {
|
||||
type: Boolean,
|
||||
bindNuclear: hass => hass.syncGetters.isDataLoaded,
|
||||
},
|
||||
iconsLoaded: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
loaded: {
|
||||
type: Boolean,
|
||||
computed: 'computeLoaded(dataLoaded, iconsLoaded)',
|
||||
},
|
||||
},
|
||||
|
||||
computeLoaded(dataLoaded, iconsLoaded) {
|
||||
return dataLoaded && iconsLoaded;
|
||||
},
|
||||
|
||||
computeForceShowLoading(dataLoaded, iconsLoaded) {
|
||||
return dataLoaded && !iconsLoaded;
|
||||
},
|
||||
|
||||
loadIcons() {
|
||||
// If the import fails, we'll try to import again, must be a server glitch
|
||||
// Since HTML imports only resolve once, we import another url.
|
||||
const success = () => { this.iconsLoaded = true; };
|
||||
this.importHref(`/static/mdi-${this.icons}.html`,
|
||||
success,
|
||||
() => this.importHref('/static/mdi.html', success, success));
|
||||
},
|
||||
|
||||
created() {
|
||||
if (!('serviceWorker' in navigator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register('/service_worker.js').catch(err => {
|
||||
if (__DEV__) {
|
||||
/* eslint-disable no-console */
|
||||
console.warn('Unable to register service worker', err);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ready() {
|
||||
const hass = this.hass;
|
||||
hass.reactor.batch(() => {
|
||||
// if auth was given, tell the backend
|
||||
if (this.auth) {
|
||||
validateAuth(this.hass, this.auth, false);
|
||||
} else if (hass.localStoragePreferences.authToken) {
|
||||
validateAuth(this.hass, hass.localStoragePreferences.authToken, true);
|
||||
}
|
||||
hass.navigationActions.showSidebar(hass.localStoragePreferences.showSidebar);
|
||||
});
|
||||
|
||||
hass.startLocalStoragePreferencesSync();
|
||||
|
||||
this.loadIcons();
|
||||
},
|
||||
});
|
||||
|
@ -1,8 +1,5 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
import removeInitMsg from '../util/remove-init-message';
|
||||
|
||||
require('../components/ha-sidebar');
|
||||
require('../layouts/partial-cards');
|
||||
require('../layouts/partial-logbook');
|
||||
require('../layouts/partial-history');
|
||||
@ -16,13 +13,6 @@ require('../managers/notification-manager');
|
||||
require('../dialogs/more-info-dialog');
|
||||
require('../dialogs/ha-voice-command-dialog');
|
||||
|
||||
// const {
|
||||
// navigationActions,
|
||||
// navigationGetters,
|
||||
// startUrlSync,
|
||||
// stopUrlSync,
|
||||
// } = hass;
|
||||
|
||||
export default new Polymer({
|
||||
is: 'home-assistant-main',
|
||||
|
||||
@ -35,7 +25,7 @@ export default new Polymer({
|
||||
|
||||
narrow: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
value: true,
|
||||
},
|
||||
|
||||
activePane: {
|
||||
@ -91,6 +81,7 @@ export default new Polymer({
|
||||
|
||||
showSidebar: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
bindNuclear: hass => hass.navigationGetters.showSidebar,
|
||||
},
|
||||
},
|
||||
@ -122,7 +113,7 @@ export default new Polymer({
|
||||
},
|
||||
|
||||
attached() {
|
||||
removeInitMsg();
|
||||
window.removeInitMsg();
|
||||
this.hass.startUrlSync();
|
||||
},
|
||||
|
||||
|
@ -65,3 +65,95 @@
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'login-form',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
errorMessage: {
|
||||
type: String,
|
||||
bindNuclear: function (hass) { return hass.authGetters.attemptErrorMessage; },
|
||||
},
|
||||
|
||||
isInvalid: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) { return hass.authGetters.isInvalidAttempt; },
|
||||
},
|
||||
|
||||
isValidating: {
|
||||
type: Boolean,
|
||||
observer: 'isValidatingChanged',
|
||||
bindNuclear: function (hass) { return hass.authGetters.isValidating; },
|
||||
},
|
||||
|
||||
loadingResources: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
forceShowLoading: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
showLoading: {
|
||||
type: Boolean,
|
||||
computed: 'computeShowSpinner(forceShowLoading, isValidating)',
|
||||
},
|
||||
},
|
||||
|
||||
listeners: {
|
||||
keydown: 'passwordKeyDown',
|
||||
'loginButton.tap': 'validatePassword',
|
||||
},
|
||||
|
||||
observers: [
|
||||
'validatingChanged(isValidating, isInvalid)',
|
||||
],
|
||||
|
||||
attached: function () {
|
||||
window.removeInitMsg();
|
||||
},
|
||||
|
||||
computeShowSpinner: function (forceShowLoading, isValidating) {
|
||||
return forceShowLoading || isValidating;
|
||||
},
|
||||
|
||||
validatingChanged: function (isValidating, isInvalid) {
|
||||
if (!isValidating && !isInvalid) {
|
||||
this.$.passwordInput.value = '';
|
||||
}
|
||||
},
|
||||
|
||||
isValidatingChanged: function (newVal) {
|
||||
if (!newVal) {
|
||||
this.async(function () { this.$.passwordInput.focus(); }.bind(this), 10);
|
||||
}
|
||||
},
|
||||
|
||||
passwordKeyDown: function (ev) {
|
||||
// validate on enter
|
||||
if (ev.keyCode === 13) {
|
||||
this.validatePassword();
|
||||
ev.preventDefault();
|
||||
// clear error after we start typing again
|
||||
} else if (this.isInvalid) {
|
||||
this.isInvalid = false;
|
||||
}
|
||||
},
|
||||
|
||||
validatePassword: function () {
|
||||
this.$.hideKeyboardOnFocus.focus();
|
||||
|
||||
window.validateAuth(this.hass, this.$.passwordInput.value,
|
||||
this.$.rememberLogin.checked);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,93 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
import validateAuth from '../util/validate-auth';
|
||||
import removeInitMsg from '../util/remove-init-message';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'login-form',
|
||||
|
||||
behaviors: [window.hassBehavior],
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
errorMessage: {
|
||||
type: String,
|
||||
bindNuclear: hass => hass.authGetters.attemptErrorMessage,
|
||||
},
|
||||
|
||||
isInvalid: {
|
||||
type: Boolean,
|
||||
bindNuclear: hass => hass.authGetters.isInvalidAttempt,
|
||||
},
|
||||
|
||||
isValidating: {
|
||||
type: Boolean,
|
||||
observer: 'isValidatingChanged',
|
||||
bindNuclear: hass => hass.authGetters.isValidating,
|
||||
},
|
||||
|
||||
loadingResources: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
forceShowLoading: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
showLoading: {
|
||||
type: Boolean,
|
||||
computed: 'computeShowSpinner(forceShowLoading, isValidating)',
|
||||
},
|
||||
},
|
||||
|
||||
listeners: {
|
||||
keydown: 'passwordKeyDown',
|
||||
'loginButton.tap': 'validatePassword',
|
||||
},
|
||||
|
||||
observers: [
|
||||
'validatingChanged(isValidating, isInvalid)',
|
||||
],
|
||||
|
||||
attached() {
|
||||
removeInitMsg();
|
||||
},
|
||||
|
||||
computeShowSpinner(forceShowLoading, isValidating) {
|
||||
return forceShowLoading || isValidating;
|
||||
},
|
||||
|
||||
validatingChanged(isValidating, isInvalid) {
|
||||
if (!isValidating && !isInvalid) {
|
||||
this.$.passwordInput.value = '';
|
||||
}
|
||||
},
|
||||
|
||||
isValidatingChanged(newVal) {
|
||||
if (!newVal) {
|
||||
this.async(() => this.$.passwordInput.focus(), 10);
|
||||
}
|
||||
},
|
||||
|
||||
passwordKeyDown(ev) {
|
||||
// validate on enter
|
||||
if (ev.keyCode === 13) {
|
||||
this.validatePassword();
|
||||
ev.preventDefault();
|
||||
// clear error after we start typing again
|
||||
} else if (this.isInvalid) {
|
||||
this.isInvalid = false;
|
||||
}
|
||||
},
|
||||
|
||||
validatePassword() {
|
||||
this.$.hideKeyboardOnFocus.focus();
|
||||
|
||||
validateAuth(this.hass, this.$.passwordInput.value, this.$.rememberLogin.checked);
|
||||
},
|
||||
});
|
@ -2,7 +2,6 @@ import Polymer from '../polymer';
|
||||
|
||||
require('./partial-base');
|
||||
require('../components/ha-cards');
|
||||
require('../components/ha-view-tabs');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'partial-cards',
|
||||
|
@ -55,7 +55,7 @@
|
||||
|
||||
<div>
|
||||
<div class='header'>Available services</div>
|
||||
<services-list on-service-selected='serviceSelected'></services-list>
|
||||
<services-list on-service-selected='serviceSelected' hass='[[hass]]'></services-list>
|
||||
</div>
|
||||
</div>
|
||||
</partial-base>
|
||||
|
@ -49,7 +49,7 @@
|
||||
|
||||
<div>
|
||||
<div class='header'>Available Events</div>
|
||||
<events-list on-event-selected='eventSelected'></event-list>
|
||||
<events-list on-event-selected='eventSelected' hass='[[hass]]'></event-list>
|
||||
</div>
|
||||
</div>
|
||||
</partial-base>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./partial-base');
|
||||
require('../components/events-list');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'partial-dev-fire-event',
|
||||
|
@ -51,7 +51,7 @@
|
||||
|
||||
<div>
|
||||
<div class='header'>Current entities</div>
|
||||
<entity-list on-entity-selected='entitySelected'></entity-list>
|
||||
<entity-list on-entity-selected='entitySelected' hass='[[hass]]'></entity-list>
|
||||
</div>
|
||||
</div>
|
||||
</partial-base>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./partial-base');
|
||||
require('../components/entity-list');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'partial-dev-set-state',
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
<loading-box hidden$='[[!isLoading]]'>Loading logbook entries</loading-box>
|
||||
</div>
|
||||
<ha-logbook entries="[[entries]]" hidden$='[[isLoading]]'></ha-logbook>
|
||||
<ha-logbook hass='[[hass]]' entries="[[entries]]" hidden$='[[isLoading]]'></ha-logbook>
|
||||
</div>
|
||||
</partial-base>
|
||||
</template>
|
||||
|
@ -1,8 +1,7 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('./partial-base');
|
||||
require('../components/ha-logbook');
|
||||
require('../components/loading-box');
|
||||
require('../components/logbook-entry');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'partial-logbook',
|
||||
|
@ -12,7 +12,38 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<img class='camera-image' src="[[computeCameraImageUrl(stateObj)]]"
|
||||
<img class='camera-image' src="[[computeCameraImageUrl(hass, stateObj)]]"
|
||||
on-load='imageLoaded' />
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'more-info-camera',
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
stateObj: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
|
||||
imageLoaded: function () {
|
||||
this.fire('iron-resize');
|
||||
},
|
||||
|
||||
computeCameraImageUrl: function (hass, stateObj) {
|
||||
if (hass.demo) {
|
||||
return '/demo/webcam.jpg';
|
||||
} else if (stateObj) {
|
||||
return `/api/camera_proxy_stream/${stateObj.entityId}` +
|
||||
`?token=${stateObj.attributes.access_token}`;
|
||||
}
|
||||
// Return an empty image if no stateObj (= dialog not open)
|
||||
return 'data:image/gif;base64,R0lGODlhAQABAAAAACw=';
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,26 +0,0 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
export default new Polymer({
|
||||
is: 'more-info-camera',
|
||||
|
||||
properties: {
|
||||
stateObj: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
|
||||
imageLoaded() {
|
||||
this.fire('iron-resize');
|
||||
},
|
||||
|
||||
computeCameraImageUrl(stateObj) {
|
||||
if (__DEMO__) {
|
||||
return '/demo/webcam.jpg';
|
||||
} else if (stateObj) {
|
||||
return `/api/camera_proxy_stream/${stateObj.entityId}` +
|
||||
`?token=${stateObj.attributes.access_token}`;
|
||||
}
|
||||
// Return an empty image if no stateObj (= dialog not open)
|
||||
return 'data:image/gif;base64,R0lGODlhAQABAAAAACw=';
|
||||
},
|
||||
});
|
@ -1,7 +1,5 @@
|
||||
import Polymer from '../polymer';
|
||||
|
||||
require('../components/loading-box');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'more-info-configurator',
|
||||
|
||||
|
@ -11,7 +11,6 @@ require('./more-info-thermostat');
|
||||
require('./more-info-script');
|
||||
require('./more-info-light');
|
||||
require('./more-info-media_player');
|
||||
require('./more-info-camera');
|
||||
require('./more-info-updater');
|
||||
require('./more-info-alarm_control_panel');
|
||||
require('./more-info-lock');
|
||||
|
@ -1,8 +1,6 @@
|
||||
import Polymer from '../polymer';
|
||||
import attributeClassNames from '../util/attribute-class-names';
|
||||
|
||||
require('../components/ha-color-picker');
|
||||
|
||||
const ATTRIBUTE_CLASSES = ['brightness', 'rgb_color', 'color_temp'];
|
||||
|
||||
function pickColor(hass, entityId, color) {
|
||||
|
36
src/util/hass-behavior.html
Normal file
36
src/util/hass-behavior.html
Normal file
@ -0,0 +1,36 @@
|
||||
<script>
|
||||
window.hassBehavior = {
|
||||
attached: function attached() {
|
||||
var hass = this.hass;
|
||||
|
||||
if (!hass) {
|
||||
throw new Error('No hass property found on ' + this.nodeName);
|
||||
}
|
||||
|
||||
this.nuclearUnwatchFns = Object.keys(this.properties).reduce(
|
||||
function bindGetters(unwatchFns, key) {
|
||||
if (!('bindNuclear' in this.properties[key])) {
|
||||
return unwatchFns;
|
||||
}
|
||||
|
||||
var getter = this.properties[key].bindNuclear(hass);
|
||||
|
||||
if (!getter) {
|
||||
throw new Error(`Undefined getter specified for key ${key}`);
|
||||
}
|
||||
|
||||
this[key] = hass.reactor.evaluate(getter);
|
||||
|
||||
return unwatchFns.concat(hass.reactor.observe(getter, function updateAttribute(val) {
|
||||
this[key] = val;
|
||||
}.bind(this)));
|
||||
}.bind(this), []);
|
||||
},
|
||||
|
||||
detached: function detached() {
|
||||
while (this.nuclearUnwatchFns.length) {
|
||||
this.nuclearUnwatchFns.shift()();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1,44 +0,0 @@
|
||||
export default {
|
||||
|
||||
attached() {
|
||||
const hass = this.hass;
|
||||
|
||||
if (!hass) {
|
||||
throw new Error(`No hass property found on ${this.nodeName}`);
|
||||
}
|
||||
|
||||
this.nuclearUnwatchFns = Object.keys(this.properties).reduce(
|
||||
(unwatchFns, key) => {
|
||||
if (!('bindNuclear' in this.properties[key])) {
|
||||
return unwatchFns;
|
||||
}
|
||||
|
||||
let getter = this.properties[key].bindNuclear;
|
||||
|
||||
if (typeof getter !== 'function') {
|
||||
/* eslint-disable no-console */
|
||||
console.warn(`Component ${this.nodeName} uses old style bindNuclear`);
|
||||
/* eslint-enable no-console */
|
||||
} else {
|
||||
getter = getter(hass);
|
||||
}
|
||||
|
||||
if (!getter) {
|
||||
throw new Error(`Undefined getter specified for key ${key}`);
|
||||
}
|
||||
|
||||
this[key] = hass.reactor.evaluate(getter);
|
||||
|
||||
return unwatchFns.concat(hass.reactor.observe(getter, (val) => {
|
||||
this[key] = val;
|
||||
}));
|
||||
}, []);
|
||||
},
|
||||
|
||||
detached() {
|
||||
while (this.nuclearUnwatchFns.length) {
|
||||
this.nuclearUnwatchFns.shift()();
|
||||
}
|
||||
},
|
||||
|
||||
};
|
@ -1,7 +0,0 @@
|
||||
export default function removeInitMessage() {
|
||||
// remove the HTML init message
|
||||
const initMsg = document.getElementById('ha-init-skeleton');
|
||||
if (initMsg) {
|
||||
initMsg.parentElement.removeChild(initMsg);
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
export default function (hass, authToken, rememberAuth) {
|
||||
hass.authActions.validate(authToken, {
|
||||
rememberAuth,
|
||||
useStreaming: hass.localStoragePreferences.useStreaming,
|
||||
});
|
||||
}
|
@ -9,6 +9,7 @@ var definePlugin = new webpack.DefinePlugin({
|
||||
module.exports = {
|
||||
entry: {
|
||||
_app_compiled: './src/home-assistant.js',
|
||||
_app_core_compiled: './src/app-core.js',
|
||||
},
|
||||
output: {
|
||||
path: 'build',
|
||||
|
Loading…
x
Reference in New Issue
Block a user