Update frontend to use NuclearJS
This commit is contained in:
parent
4221eef428
commit
7ef0dec185
34 changed files with 1691 additions and 1542 deletions
|
@ -102,8 +102,8 @@ def setup(hass, config):
|
||||||
{
|
{
|
||||||
"auto": True,
|
"auto": True,
|
||||||
ATTR_ENTITY_ID: [
|
ATTR_ENTITY_ID: [
|
||||||
"device_tracker.Paulus",
|
"device_tracker.paulus",
|
||||||
"device_tracker.Anne_Therese"
|
"device_tracker.anne_therese"
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
""" DO NOT MODIFY. Auto-generated by build_frontend script """
|
""" DO NOT MODIFY. Auto-generated by build_frontend script """
|
||||||
VERSION = "010d9683fa9d210abd199b3cde4edbc0"
|
VERSION = "18d02dc9820b907ac4159da09cd20c4b"
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -37,7 +37,8 @@
|
||||||
"layout": "Polymer/layout",
|
"layout": "Polymer/layout",
|
||||||
"color-picker-element": "~0.0.3",
|
"color-picker-element": "~0.0.3",
|
||||||
"paper-styles": "polymerelements/paper-styles#^1.0.0",
|
"paper-styles": "polymerelements/paper-styles#^1.0.0",
|
||||||
"paper-date-picker": "vsimonian/paper-date-picker#master"
|
"paper-date-picker": "vsimonian/paper-date-picker#master",
|
||||||
|
"lodash": "~3.9.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"polymer": "^1.0.0",
|
"polymer": "^1.0.0",
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
var uiActions = window.hass.uiActions;
|
var moreInfoActions = window.hass.moreInfoActions;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'state-card',
|
is: 'state-card',
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
cardTapped: function(ev) {
|
cardTapped: function(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.debounce('show-more-info-dialog', function() {
|
this.debounce('show-more-info-dialog', function() {
|
||||||
uiActions.showMoreInfoDialog(this.stateObj.entityId);
|
moreInfoActions.selectEntity(this.stateObj.entityId);
|
||||||
}.bind(this), 100);
|
}.bind(this), 100);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<template is='dom-repeat' items='[[entities]]' as='entity'>
|
<template is='dom-repeat' items='[[entities]]' as='entity'>
|
||||||
<li><a href='#' on-click='entitySelected'>[[entity]]</a></li>
|
<li><a href='#' on-click='entitySelected'>[[entity.entityId]]</a></li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
@ -28,25 +28,30 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var entityGetters = window.hass.entityGetters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'entity-list',
|
is: 'entity-list',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
entities: {
|
entities: {
|
||||||
type: Array,
|
type: Array,
|
||||||
value: [],
|
bindNuclear: [
|
||||||
|
entityGetters.entityMap,
|
||||||
|
function(map) {
|
||||||
|
return map.valueSeq().
|
||||||
|
sortBy(function(entity) { return entity.entityId; })
|
||||||
|
.toArray();
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
stateStoreChanged: function(stateStore) {
|
|
||||||
this.entities = stateStore.entityIDs.toArray();
|
|
||||||
},
|
|
||||||
|
|
||||||
entitySelected: function(ev) {
|
entitySelected: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.fire('entity-selected', {entityId: ev.model.entity});
|
this.fire('entity-selected', {entityId: ev.model.entity.entityId});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -31,22 +31,27 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var eventGetters = window.hass.eventGetters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'events-list',
|
is: 'events-list',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
events: {
|
events: {
|
||||||
type: Array,
|
type: Array,
|
||||||
value: [],
|
bindNuclear: [
|
||||||
|
eventGetters.entityMap,
|
||||||
|
function(map) {
|
||||||
|
return map.valueSeq()
|
||||||
|
.sortBy(function(event) { return event.event; })
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
eventStoreChanged: function(eventStore) {
|
|
||||||
this.events = eventStore.all.toArray();
|
|
||||||
},
|
|
||||||
|
|
||||||
eventSelected: function(ev) {
|
eventSelected: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.fire('event-selected', {eventType: ev.model.event.event});
|
this.fire('event-selected', {eventType: ev.model.event.event});
|
||||||
|
|
|
@ -54,14 +54,14 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var uiActions = window.hass.uiActions;
|
var moreInfoActions = window.hass.moreInfoActions;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'logbook-entry',
|
is: 'logbook-entry',
|
||||||
|
|
||||||
entityClicked: function(ev) {
|
entityClicked: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
uiActions.showMoreInfoDialog(this.entryObj.entityId);
|
moreInfoActions.selectEntity(this.entryObj.entityId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<template is='dom-repeat' items="[[domains]]" as="domain">
|
<template is='dom-repeat' items="[[serviceDomains]]" as="domain">
|
||||||
<template is='dom-repeat' items="[[computeServices(domain)]]" as="service">
|
<template is='dom-repeat' items="[[domain.services]]" as="service">
|
||||||
<li><a href='#' on-click='serviceClicked'>
|
<li><a href='#' on-click='serviceClicked'>
|
||||||
<span>[[domain]]</span>/<span>[[service]]</span>
|
<span>[[domain.domain]]</span>/<span>[[service]]</span>
|
||||||
</a></li>
|
</a></li>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
@ -36,19 +36,24 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var serviceGetters = window.hass.serviceGetters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'services-list',
|
is: 'services-list',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
domains: {
|
serviceDomains: {
|
||||||
type: Array,
|
type: Array,
|
||||||
value: [],
|
bindNuclear: [
|
||||||
},
|
serviceGetters.entityMap,
|
||||||
|
function(map) {
|
||||||
services: {
|
return map.valueSeq()
|
||||||
type: Object,
|
.sortBy(function(domain) { return domain.domain; })
|
||||||
|
.toJS();
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -56,15 +61,10 @@
|
||||||
return this.services.get(domain).toArray();
|
return this.services.get(domain).toArray();
|
||||||
},
|
},
|
||||||
|
|
||||||
serviceStoreChanged: function(serviceStore) {
|
|
||||||
this.services = serviceStore.all;
|
|
||||||
this.domains = this.services.keySeq().sort().toArray();
|
|
||||||
},
|
|
||||||
|
|
||||||
serviceClicked: function(ev) {
|
serviceClicked: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.fire(
|
this.fire(
|
||||||
'service-selected', {domain: ev.model.domain, service: ev.model.service});
|
'service-selected', {domain: ev.model.domain.domain, service: ev.model.service});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<link rel="import" href="../bower_components/polymer/polymer.html">
|
<link rel="import" href="../bower_components/polymer/polymer.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../resources/lodash.html">
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
Polymer({
|
Polymer({
|
||||||
|
|
|
@ -39,12 +39,11 @@
|
||||||
if (!this.isAttached) {
|
if (!this.isAttached) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var root = Polymer.dom(this);
|
var root = Polymer.dom(this);
|
||||||
var stateHistory = this.data;
|
var stateHistory = this.data;
|
||||||
|
|
||||||
while (root.lastChild) {
|
while (root.node.lastChild) {
|
||||||
root.removeChild(root.lastChild);
|
root.node.removeChild(root.node.lastChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stateHistory || stateHistory.length === 0) {
|
if (!stateHistory || stateHistory.length === 0) {
|
||||||
|
@ -64,11 +63,12 @@
|
||||||
dataTable.addRow([entityDisplay, stateStr, start, end]);
|
dataTable.addRow([entityDisplay, stateStr, start, end]);
|
||||||
};
|
};
|
||||||
|
|
||||||
var startTime = new Date(stateHistory.map(function(stateInfo) {
|
var startTime = new Date(
|
||||||
return stateInfo[0].lastChangedAsDate;
|
stateHistory.reduce(function(minTime, stateInfo) {
|
||||||
}).reduce(function(prev, cur) {
|
return Math.min(
|
||||||
return Math.min(prev, cur);
|
minTime, stateInfo[0].lastChangedAsDate);
|
||||||
}, new Date()));
|
}, new Date())
|
||||||
|
);
|
||||||
|
|
||||||
// end time is Math.min(curTime, start time + 1 day)
|
// end time is Math.min(curTime, start time + 1 day)
|
||||||
var endTime = new Date(startTime);
|
var endTime = new Date(startTime);
|
||||||
|
|
|
@ -34,8 +34,9 @@
|
||||||
No state history found.
|
No state history found.
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<state-history-chart-timeline data='[[groupedStateHistory.timeline]]'
|
<state-history-chart-timeline
|
||||||
is-single-device='[[isSingleDevice]]'>
|
data='[[groupedStateHistory.timeline]]'
|
||||||
|
is-single-device='[[isSingleDevice]]'>
|
||||||
</state-history-chart-timeline>
|
</state-history-chart-timeline>
|
||||||
|
|
||||||
<template is='dom-repeat' items='[[groupedStateHistory.line]]'>
|
<template is='dom-repeat' items='[[groupedStateHistory.line]]'>
|
||||||
|
@ -84,36 +85,35 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
computeIsSingleDevice: function(stateHistory) {
|
computeIsSingleDevice: function(stateHistory) {
|
||||||
return stateHistory && stateHistory.length == 1;
|
return stateHistory && stateHistory.size == 1;
|
||||||
},
|
},
|
||||||
|
|
||||||
computeGroupedStateHistory: function(isLoading, stateHistory) {
|
computeGroupedStateHistory: function(isLoading, stateHistory) {
|
||||||
|
if (isLoading || !stateHistory) {
|
||||||
|
return {line: [], timeline: []};
|
||||||
|
}
|
||||||
|
|
||||||
var lineChartDevices = {};
|
var lineChartDevices = {};
|
||||||
var timelineDevices = [];
|
var timelineDevices = [];
|
||||||
|
|
||||||
if (isLoading || !stateHistory) {
|
|
||||||
return {line: unitStates, timeline: timelineDevices};
|
|
||||||
}
|
|
||||||
|
|
||||||
stateHistory.forEach(function(stateInfo) {
|
stateHistory.forEach(function(stateInfo) {
|
||||||
if (!stateInfo || stateInfo.length === 0) {
|
if (!stateInfo || stateInfo.size === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var unit;
|
var stateWithUnit = stateInfo.find(function(state) {
|
||||||
|
return 'unit_of_measurement' in state.attributes;
|
||||||
|
});
|
||||||
|
|
||||||
for (var i = 0; i < stateInfo.length && !unit; i++) {
|
var unit = stateWithUnit ?
|
||||||
unit = stateInfo[i].attributes.unit_of_measurement;
|
stateWithUnit.attributes.unit_of_measurement : false;
|
||||||
}
|
|
||||||
|
|
||||||
if (unit) {
|
if (!unit) {
|
||||||
if (!(unit in lineChartDevices)) {
|
timelineDevices.push(stateInfo.toArray());
|
||||||
lineChartDevices[unit] = [stateInfo];
|
} else if(unit in lineChartDevices) {
|
||||||
} else {
|
lineChartDevices[unit].push(stateInfo.toArray());
|
||||||
lineChartDevices[unit].push(stateInfo);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
timelineDevices.push(stateInfo);
|
lineChartDevices[unit] = [stateInfo.toArray()];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
computeIsEmpty: function(stateHistory) {
|
computeIsEmpty: function(stateHistory) {
|
||||||
return stateHistory && stateHistory.length === 0;
|
return stateHistory && stateHistory.size === 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
extractUnit: function(arr) {
|
extractUnit: function(arr) {
|
||||||
|
|
|
@ -17,42 +17,37 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<template>
|
<template>
|
||||||
<iron-icon icon="warning" hidden$="{{!hasError}}"></iron-icon>
|
<iron-icon icon="warning" hidden$="[[!hasError]]"></iron-icon>
|
||||||
<paper-toggle-button id="toggle" on-change='toggleChanged' hidden$="{{hasError}}"></paper-toggle-button>
|
<paper-toggle-button id="toggle" on-change='toggleChanged' checked$='[[isStreaming]]' hidden$="[[hasError]]"></paper-toggle-button>
|
||||||
</template>
|
</template>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var streamGetters = window.hass.streamGetters;
|
||||||
var streamActions = window.hass.streamActions;
|
var streamActions = window.hass.streamActions;
|
||||||
var authStore = window.hass.authStore;
|
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'stream-status',
|
is: 'stream-status',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
isStreaming: {
|
isStreaming: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: streamGetters.isStreamingEvents,
|
||||||
},
|
},
|
||||||
|
|
||||||
hasError: {
|
hasError: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: streamGetters.hasStreamingEventsError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
streamStoreChanged: function(streamStore) {
|
toggleChanged: function() {
|
||||||
this.hasError = streamStore.hasError;
|
|
||||||
this.$.toggle.checked = this.isStreaming = streamStore.isStreaming;
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleChanged: function(ev) {
|
|
||||||
if (this.isStreaming) {
|
if (this.isStreaming) {
|
||||||
streamActions.stop();
|
streamActions.stop();
|
||||||
} else {
|
} else {
|
||||||
streamActions.start(authStore.authToken);
|
streamActions.start();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -49,36 +49,51 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var stateStore = window.hass.stateStore;
|
|
||||||
var stateHistoryStore = window.hass.stateHistoryStore;
|
var configGetters = window.hass.configGetters;
|
||||||
var stateHistoryActions = window.hass.stateHistoryActions;
|
var entityHistoryGetters = window.hass.entityHistoryGetters;
|
||||||
|
|
||||||
|
var entityHistoryActions = window.hass.entityHistoryActions;
|
||||||
|
var moreInfoGetters = window.hass.moreInfoGetters;
|
||||||
|
var moreInfoActions = window.hass.moreInfoActions;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'more-info-dialog',
|
is: 'more-info-dialog',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
entityId: {
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
stateObj: {
|
stateObj: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
bindNuclear: moreInfoGetters.currentEntity,
|
||||||
|
observer: 'fetchHistoryData',
|
||||||
},
|
},
|
||||||
|
|
||||||
stateHistory: {
|
stateHistory: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
bindNuclear: [
|
||||||
|
moreInfoGetters.currentEntityHistory,
|
||||||
|
function(history) {
|
||||||
|
return history ? [history] : false;
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
isLoadingHistoryData: {
|
isLoadingHistoryData: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: entityHistoryGetters.isLoadingEntityHistory,
|
||||||
},
|
},
|
||||||
|
|
||||||
hasHistoryComponent: {
|
hasHistoryComponent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: configGetters.isComponentLoaded('history'),
|
||||||
|
observer: 'fetchHistoryData',
|
||||||
|
},
|
||||||
|
|
||||||
|
shouldFetchHistory: {
|
||||||
|
type: Boolean,
|
||||||
|
bindNuclear: moreInfoGetters.isCurrentEntityHistoryStale,
|
||||||
|
observer: 'fetchHistoryData',
|
||||||
},
|
},
|
||||||
|
|
||||||
dialogOpen: {
|
dialogOpen: {
|
||||||
|
@ -92,31 +107,10 @@
|
||||||
'iron-overlay-closed': 'onIronOverlayClosed'
|
'iron-overlay-closed': 'onIronOverlayClosed'
|
||||||
},
|
},
|
||||||
|
|
||||||
componentStoreChanged: function(componentStore) {
|
fetchHistoryData: function(newVal) {
|
||||||
this.hasHistoryComponent = componentStore.isLoaded('history');
|
if (this.stateObj && this.hasHistoryComponent &&
|
||||||
},
|
this.shouldFetchHistory) {
|
||||||
|
entityHistoryActions.fetchRecent(this.stateObj.entityId);
|
||||||
stateStoreChanged: function() {
|
|
||||||
var newState = this.entityId ? stateStore.get(this.entityId) : null;
|
|
||||||
|
|
||||||
if (newState !== this.stateObj) {
|
|
||||||
this.stateObj = newState;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
stateHistoryStoreChanged: function() {
|
|
||||||
var newHistory;
|
|
||||||
|
|
||||||
if (this.hasHistoryComponent && this.entityId) {
|
|
||||||
newHistory = [stateHistoryStore.get(this.entityId)];
|
|
||||||
} else {
|
|
||||||
newHistory = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isLoadingHistoryData = false;
|
|
||||||
|
|
||||||
if (newHistory !== this.stateHistory) {
|
|
||||||
this.stateHistory = newHistory;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -126,30 +120,13 @@
|
||||||
|
|
||||||
onIronOverlayClosed: function() {
|
onIronOverlayClosed: function() {
|
||||||
this.dialogOpen = false;
|
this.dialogOpen = false;
|
||||||
|
moreInfoActions.deselectEntity();
|
||||||
},
|
},
|
||||||
|
|
||||||
changeEntityId: function(entityId) {
|
show: function() {
|
||||||
if (entityId == this.entityId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.entityId = entityId;
|
|
||||||
|
|
||||||
this.stateStoreChanged();
|
|
||||||
this.stateHistoryStoreChanged();
|
|
||||||
|
|
||||||
if (this.hasHistoryComponent && stateHistoryStore.shouldFetchEntity(entityId)) {
|
|
||||||
this.isLoadingHistoryData = true;
|
|
||||||
stateHistoryActions.fetch(entityId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function(entityId) {
|
|
||||||
this.changeEntityId(entityId);
|
|
||||||
|
|
||||||
this.debounce('showDialogAfterRender', function() {
|
this.debounce('showDialogAfterRender', function() {
|
||||||
this.$.dialog.toggle();
|
this.$.dialog.open();
|
||||||
}.bind(this));
|
}.bind(this), 1);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5a7165b272fe2ed3e1b1432e2e621c3b971cc4bf
|
Subproject commit 53941ad076fa5d453370cb6922cf6770202dc76e
|
|
@ -21,9 +21,8 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<home-assistant-icons></home-assistant-icons>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<home-assistant-icons></home-assistant-icons>
|
||||||
<template is='dom-if' if='[[!loaded]]'>
|
<template is='dom-if' if='[[!loaded]]'>
|
||||||
<login-form></login-form>
|
<login-form></login-form>
|
||||||
</template>
|
</template>
|
||||||
|
@ -37,10 +36,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var uiActions = window.hass.uiActions;
|
||||||
var storeListenerMixIn = window.hass.storeListenerMixIn,
|
var authGetters = window.hass.authGetters;
|
||||||
uiActions = window.hass.uiActions,
|
var syncGetters = window.hass.syncGetters;
|
||||||
preferenceStore = window.hass.preferenceStore;
|
var uiPreferences = window.hass.uiPreferences;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'home-assistant',
|
is: 'home-assistant',
|
||||||
|
@ -49,15 +48,24 @@
|
||||||
auth: null,
|
auth: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
|
auth: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
loaded: {
|
loaded: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
|
observer: 'loadedChanged',
|
||||||
|
bindNuclear: syncGetters.isDataLoaded,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadedChanged: function(newVal, oldVal) {
|
||||||
|
console.log("Loaded changed", newVal);
|
||||||
|
},
|
||||||
|
|
||||||
ready: function() {
|
ready: function() {
|
||||||
// remove the HTML init message
|
// remove the HTML init message
|
||||||
document.getElementById('init').remove();
|
document.getElementById('init').remove();
|
||||||
|
@ -65,13 +73,11 @@
|
||||||
// if auth was given, tell the backend
|
// if auth was given, tell the backend
|
||||||
if(this.auth) {
|
if(this.auth) {
|
||||||
uiActions.validateAuth(this.auth, false);
|
uiActions.validateAuth(this.auth, false);
|
||||||
} else if (preferenceStore.hasAuthToken) {
|
} else if (uiPreferences.authToken) {
|
||||||
uiActions.validateAuth(preferenceStore.authToken, false);
|
uiActions.validateAuth(uiPreferences.authToken, false);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
syncStoreChanged: function(syncStore) {
|
uiPreferences.startSync();
|
||||||
this.loaded = syncStore.initialLoadDone;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
<iron-icon item-icon icon='apps'></iron-icon> States
|
<iron-icon item-icon icon='apps'></iron-icon> States
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
|
|
||||||
<template is='dom-repeat' items='{{activeFilters}}'>
|
<template is='dom-repeat' items='{{possibleFilters}}'>
|
||||||
<paper-icon-item data-panel$='[[filterType(item)]]'>
|
<paper-icon-item data-panel$='[[filterType(item)]]'>
|
||||||
<iron-icon item-icon icon='[[filterIcon(item)]]'></iron-icon>
|
<iron-icon item-icon icon='[[filterIcon(item)]]'></iron-icon>
|
||||||
<span>[[filterName(item)]]</span>
|
<span>[[filterName(item)]]</span>
|
||||||
|
@ -110,25 +110,22 @@
|
||||||
<div class='text label divider'>Developer Tools</div>
|
<div class='text label divider'>Developer Tools</div>
|
||||||
<div class='dev-tools layout horizontal justified'>
|
<div class='dev-tools layout horizontal justified'>
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon='settings-remote' data-panel$='[[selectedDevService]]'
|
icon='settings-remote' data-panel='devService'
|
||||||
on-click='handleDevClick'></paper-icon-button>
|
on-click='handleDevClick'></paper-icon-button>
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon='settings-ethernet' data-panel$='[[selectedDevState]]'
|
icon='settings-ethernet' data-panel='devState'
|
||||||
on-click='handleDevClick'></paper-icon-button>
|
on-click='handleDevClick'></paper-icon-button>
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon='settings-input-antenna' data-panel$='[[selectedDevEvent]]'
|
icon='settings-input-antenna' data-panel='devEvent'
|
||||||
on-click='handleDevClick'></paper-icon-button>
|
on-click='handleDevClick'></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
</paper-menu>
|
</paper-menu>
|
||||||
</paper-header-panel>
|
</paper-header-panel>
|
||||||
|
|
||||||
<template is='dom-if' if='[[!hideStates]]'>
|
<template is='dom-if' if='[[isSelectedStates]]'>
|
||||||
<partial-states
|
<partial-states main narrow='[[narrow]]'>
|
||||||
main narrow='[[narrow]]'
|
|
||||||
filter='[[stateFilter]]'>
|
|
||||||
</partial-states>
|
</partial-states>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template is='dom-if' if='[[isSelectedLogbook]]'>
|
<template is='dom-if' if='[[isSelectedLogbook]]'>
|
||||||
<partial-logbook main narrow='[[narrow]]'></partial-logbook>
|
<partial-logbook main narrow='[[narrow]]'></partial-logbook>
|
||||||
</template>
|
</template>
|
||||||
|
@ -151,117 +148,86 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var configGetters = window.hass.configGetters;
|
||||||
|
var entityGetters = window.hass.entityGetters;
|
||||||
|
var navigationGetters = window.hass.navigationGetters;
|
||||||
|
|
||||||
var authActions = window.hass.authActions;
|
var authActions = window.hass.authActions;
|
||||||
|
var navigationActions = window.hass.navigationActions;
|
||||||
|
|
||||||
var uiUtil = window.hass.uiUtil;
|
var uiUtil = window.hass.uiUtil;
|
||||||
var uiConstants = window.hass.uiConstants;
|
var entityDomainFilters = window.hass.util.entityDomainFilters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'home-assistant-main',
|
is: 'home-assistant-main',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
selected: {
|
|
||||||
type: String,
|
|
||||||
value: 'states',
|
|
||||||
},
|
|
||||||
|
|
||||||
stateFilter: {
|
|
||||||
type: String,
|
|
||||||
value: null,
|
|
||||||
},
|
|
||||||
|
|
||||||
narrow: {
|
narrow: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
|
|
||||||
activeFilters: {
|
selected: {
|
||||||
|
type: String,
|
||||||
|
bindNuclear: [
|
||||||
|
navigationGetters.activePane,
|
||||||
|
navigationGetters.activeFilter,
|
||||||
|
function(pane, filter) {
|
||||||
|
return filter ? pane + '/' + filter : pane;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
observer: 'selectedChanged',
|
||||||
|
},
|
||||||
|
|
||||||
|
possibleFilters: {
|
||||||
type: Array,
|
type: Array,
|
||||||
value: [],
|
value: [],
|
||||||
|
bindNuclear: [
|
||||||
|
navigationGetters.possibleEntityDomainFilters,
|
||||||
|
function(domains) { return domains.toArray(); }
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
hasHistoryComponent: {
|
hasHistoryComponent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: configGetters.isComponentLoaded('history'),
|
||||||
},
|
},
|
||||||
|
|
||||||
hasLogbookComponent: {
|
hasLogbookComponent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: configGetters.isComponentLoaded('logbook'),
|
||||||
},
|
},
|
||||||
|
|
||||||
isStreaming: {
|
isSelectedStates: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: navigationGetters.isActivePane('states'),
|
||||||
},
|
|
||||||
|
|
||||||
hasStreamError: {
|
|
||||||
type: Boolean,
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
hideStates: {
|
|
||||||
type: Boolean,
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
selectedHistory: {
|
|
||||||
type: String,
|
|
||||||
value: 'history',
|
|
||||||
readOnly: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isSelectedHistory: {
|
isSelectedHistory: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: 'computeIsSelected(selected, selectedHistory)',
|
bindNuclear: navigationGetters.isActivePane('history'),
|
||||||
},
|
|
||||||
|
|
||||||
selectedLogbook: {
|
|
||||||
type: String,
|
|
||||||
value: 'logbook',
|
|
||||||
readOnly: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isSelectedLogbook: {
|
isSelectedLogbook: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: 'computeIsSelected(selected, selectedLogbook)',
|
bindNuclear: navigationGetters.isActivePane('logbook'),
|
||||||
},
|
|
||||||
|
|
||||||
selectedDevEvent: {
|
|
||||||
type: String,
|
|
||||||
value: 'devEvent',
|
|
||||||
readOnly: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isSelectedDevEvent: {
|
isSelectedDevEvent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: 'computeIsSelected(selected, selectedDevEvent)',
|
bindNuclear: navigationGetters.isActivePane('devEvent'),
|
||||||
},
|
|
||||||
|
|
||||||
selectedDevState: {
|
|
||||||
type: String,
|
|
||||||
value: 'devState',
|
|
||||||
readOnly: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isSelectedDevState: {
|
isSelectedDevState: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: 'computeIsSelected(selected, selectedDevState)',
|
bindNuclear: navigationGetters.isActivePane('devState'),
|
||||||
},
|
|
||||||
|
|
||||||
selectedDevService: {
|
|
||||||
type: String,
|
|
||||||
value: 'devService',
|
|
||||||
readOnly: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isSelectedDevService: {
|
isSelectedDevService: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: 'computeIsSelected(selected, selectedDevService)',
|
bindNuclear: navigationGetters.isActivePane('devService'),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
listeners: {
|
listeners: {
|
||||||
|
@ -269,17 +235,6 @@
|
||||||
'open-menu': 'openDrawer',
|
'open-menu': 'openDrawer',
|
||||||
},
|
},
|
||||||
|
|
||||||
stateStoreChanged: function(stateStore) {
|
|
||||||
this.activeFilters = stateStore.domains.filter(function(domain) {
|
|
||||||
return domain in uiConstants.STATE_FILTERS;
|
|
||||||
}).toArray();
|
|
||||||
},
|
|
||||||
|
|
||||||
componentStoreChanged: function(componentStore) {
|
|
||||||
this.hasHistoryComponent = componentStore.isLoaded('history');
|
|
||||||
this.hasLogbookComponent = componentStore.isLoaded('logbook');
|
|
||||||
},
|
|
||||||
|
|
||||||
menuSelect: function(ev, detail, sender) {
|
menuSelect: function(ev, detail, sender) {
|
||||||
this.selectPanel(this.$.menu.selected);
|
this.selectPanel(this.$.menu.selected);
|
||||||
},
|
},
|
||||||
|
@ -299,15 +254,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
this.closeDrawer();
|
this.closeDrawer();
|
||||||
this.selected = newChoice;
|
|
||||||
|
|
||||||
if (newChoice.substr(0, 7) === 'states_') {
|
navigationActions.navigate.apply(
|
||||||
this.hideStates = false;
|
null, newChoice.split('/'));
|
||||||
this.stateFilter = newChoice.substr(7);
|
|
||||||
} else {
|
|
||||||
this.hideStates = newChoice !== 'states';
|
|
||||||
this.stateFilter = null;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
openDrawer: function() {
|
openDrawer: function() {
|
||||||
|
@ -322,21 +271,41 @@
|
||||||
authActions.logOut();
|
authActions.logOut();
|
||||||
},
|
},
|
||||||
|
|
||||||
computeIsSelected: function(selected, selectedType) {
|
|
||||||
return selected === selectedType;
|
|
||||||
},
|
|
||||||
|
|
||||||
filterIcon: function(filter) {
|
filterIcon: function(filter) {
|
||||||
return uiUtil.domainIcon(filter);
|
return uiUtil.domainIcon(filter);
|
||||||
},
|
},
|
||||||
|
|
||||||
filterName: function(filter) {
|
filterName: function(filter) {
|
||||||
return uiConstants.STATE_FILTERS[filter];
|
return entityDomainFilters[filter];
|
||||||
},
|
},
|
||||||
|
|
||||||
filterType: function(filter) {
|
filterType: function(filter) {
|
||||||
return 'states_' + filter;
|
return 'states/' + filter;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
hashChanged: function(ev) {
|
||||||
|
var parts = ev.newURL.split('#');
|
||||||
|
if (parts[1]) {
|
||||||
|
this.selectPanel(parts[1]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedChanged: function(newVal) {
|
||||||
|
window.location.hash = newVal;
|
||||||
|
},
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
this.hashChanged({newURL: window.location.toString()});
|
||||||
|
},
|
||||||
|
|
||||||
|
attached: function() {
|
||||||
|
this.hashChanged = this.hashChanged.bind(this);
|
||||||
|
window.addEventListener('hashchange', this.hashChanged);
|
||||||
|
},
|
||||||
|
|
||||||
|
detached: function() {
|
||||||
|
window.removeEventListener('hashchange', this.hashChanged);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -86,27 +86,29 @@
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var uiActions = window.hass.uiActions;
|
var uiActions = window.hass.uiActions;
|
||||||
|
var authGetters = window.hass.authGetters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'login-form',
|
is: 'login-form',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
isValidating: {
|
isValidating: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
observer: 'isValidatingChanged',
|
||||||
|
bindNuclear: authGetters.isValidating,
|
||||||
},
|
},
|
||||||
|
|
||||||
isInvalid: {
|
isInvalid: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: authGetters.isInvalidAttempt,
|
||||||
},
|
},
|
||||||
|
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
type: String,
|
type: String,
|
||||||
value: '',
|
bindNuclear: authGetters.attemptErrorMessage,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
listeners: {
|
listeners: {
|
||||||
|
@ -114,19 +116,12 @@
|
||||||
'loginButton.click': 'validatePassword',
|
'loginButton.click': 'validatePassword',
|
||||||
},
|
},
|
||||||
|
|
||||||
attached: function() {
|
// attached: function() {
|
||||||
this.focusPassword();
|
// this.focusPassword();
|
||||||
},
|
// },
|
||||||
|
|
||||||
authStoreChanged: function(authStore) {
|
isValidatingChanged: function(newVal) {
|
||||||
this.isValidating = authStore.isValidating;
|
if (!newVal) {
|
||||||
|
|
||||||
if (authStore.lastAttemptInvalid) {
|
|
||||||
this.errorMessage = authStore.lastAttemptMessage;
|
|
||||||
this.isInvalid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isValidating) {
|
|
||||||
setTimeout(this.focusPassword.bind(this), 0);
|
setTimeout(this.focusPassword.bind(this), 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventActions.fire(this.eventType, eventData);
|
eventActions.fireEvent(this.eventType, eventData);
|
||||||
},
|
},
|
||||||
|
|
||||||
computeFormClasses: function(narrow) {
|
computeFormClasses: function(narrow) {
|
||||||
|
|
|
@ -50,8 +50,9 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var stateStore = window.hass.stateStore;
|
var reactor = window.hass.reactor;
|
||||||
var stateActions = window.hass.stateActions;
|
var entityGetters = window.hass.entityGetters;
|
||||||
|
var entityActions = window.hass.entityActions;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'partial-dev-set-state',
|
is: 'partial-dev-set-state',
|
||||||
|
@ -83,7 +84,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
entitySelected: function(ev) {
|
entitySelected: function(ev) {
|
||||||
var state = stateStore.get(ev.detail.entityId);
|
var state = reactor.evaluate(entityGetters.byId(ev.detail.entityId));
|
||||||
|
|
||||||
this.entityId = state.entityId;
|
this.entityId = state.entityId;
|
||||||
this.state = state.state;
|
this.state = state.state;
|
||||||
|
@ -99,7 +100,11 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stateActions.set(this.entityId, this.state, attr);
|
entityActions.save({
|
||||||
|
entityId: this.entityId,
|
||||||
|
state: this.state,
|
||||||
|
attributes: attr,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
computeFormClasses: function(narrow) {
|
computeFormClasses: function(narrow) {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
<div class$="[[computeContentClasses(narrow)]]">
|
<div class$="[[computeContentClasses(narrow)]]">
|
||||||
<paper-input label='Showing entries for' on-click='handleShowDatePicker'
|
<paper-input label='Showing entries for' on-click='handleShowDatePicker'
|
||||||
value='[[computeDateCaption(selectedDate)]]'></paper-input>
|
value='[[selectedDate]]'></paper-input>
|
||||||
|
|
||||||
<state-history-charts state-history="[[stateHistory]]"
|
<state-history-charts state-history="[[stateHistory]]"
|
||||||
is-loading-data="[[isLoadingData]]"></state-history-charts>
|
is-loading-data="[[isLoadingData]]"></state-history-charts>
|
||||||
|
@ -43,68 +43,57 @@
|
||||||
</dom-module>
|
</dom-module>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var stateHistoryActions = window.hass.stateHistoryActions;
|
var entityHistoryGetters = window.hass.entityHistoryGetters;
|
||||||
var stateHistoryStore = window.hass.stateHistoryStore;
|
var entityHistoryActions = window.hass.entityHistoryActions;
|
||||||
var uiActions = window.hass.uiActions;
|
var uiActions = window.hass.uiActions;
|
||||||
|
|
||||||
function date_to_str(date) {
|
|
||||||
return date.getFullYear() + '-' + (date.getMonth()+1) + '-' + date.getDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'partial-history',
|
is: 'partial-history',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
narrow: {
|
narrow: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isDataLoaded: {
|
||||||
|
type: Boolean,
|
||||||
|
bindNuclear: entityHistoryGetters.hasDataForCurrentDate,
|
||||||
|
observer: 'isDataLoadedChanged',
|
||||||
|
},
|
||||||
|
|
||||||
stateHistory: {
|
stateHistory: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
bindNuclear: entityHistoryGetters.entityHistoryForCurrentDate,
|
||||||
},
|
},
|
||||||
|
|
||||||
isLoadingData: {
|
isLoadingData: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: entityHistoryGetters.isLoadingEntityHistory,
|
||||||
},
|
},
|
||||||
|
|
||||||
selectedDate: {
|
selectedDate: {
|
||||||
type: String,
|
type: String,
|
||||||
value: null,
|
value: null,
|
||||||
observer: 'fetchIfNeeded',
|
bindNuclear: entityHistoryGetters.currentDate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
stateHistoryStoreChanged: function() {
|
isDataLoadedChanged: function(newVal) {
|
||||||
this.isLoadingData = this.fetchIfNeeded();
|
if (!newVal) {
|
||||||
this.stateHistory = this.isLoadingData ?
|
entityHistoryActions.fetchSelectedDate();
|
||||||
[] : stateHistoryStore.all(this.selectedDate);
|
|
||||||
},
|
|
||||||
|
|
||||||
computeDateCaption: function(selectedDate) {
|
|
||||||
return selectedDate || 'today';
|
|
||||||
},
|
|
||||||
|
|
||||||
fetchIfNeeded: function() {
|
|
||||||
if (stateHistoryStore.shouldFetch(this.selectedDate)) {
|
|
||||||
this.isLoadingData = true;
|
|
||||||
stateHistoryActions.fetchAll(this.selectedDate);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRefreshClick: function() {
|
handleRefreshClick: function() {
|
||||||
this.isLoadingData = true;
|
entityHistoryActions.fetchSelectedDate();
|
||||||
stateHistoryActions.fetchAll(this.selectedDate);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleShowDatePicker: function() {
|
handleShowDatePicker: function() {
|
||||||
uiActions.showDatePicker(function(selectedDate) {
|
uiActions.showDatePicker(
|
||||||
this.selectedDate = date_to_str(selectedDate);
|
entityHistoryActions.changeCurrentDate,
|
||||||
}.bind(this), this.selectedDate);
|
this.selectedDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
computeContentClasses: function(narrow) {
|
computeContentClasses: function(narrow) {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<div>
|
<div>
|
||||||
<div class='selected-date-container'>
|
<div class='selected-date-container'>
|
||||||
<paper-input label='Showing entries for' on-click='handleShowDatePicker'
|
<paper-input label='Showing entries for' on-click='handleShowDatePicker'
|
||||||
value='[[computeDateCaption(selectedDate)]]'></paper-input>
|
value='[[selectedDate]]'></paper-input>
|
||||||
|
|
||||||
<loading-box hidden$='[[!isLoading]]'>Loading logbook entries</loading-box>
|
<loading-box hidden$='[[!isLoading]]'>Loading logbook entries</loading-box>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,19 +40,15 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var storeListenerMixIn = window.hass.storeListenerMixIn;
|
var logbookGetters = window.hass.logbookGetters;
|
||||||
var logbookActions = window.hass.logbookActions;
|
var logbookActions = window.hass.logbookActions;
|
||||||
var logbookStore = window.hass.logbookStore;
|
|
||||||
var uiActions = window.hass.uiActions;
|
var uiActions = window.hass.uiActions;
|
||||||
|
var dateToStr = window.hass.util.dateToStr;
|
||||||
function date_to_str(date) {
|
|
||||||
return date.getFullYear() + '-' + (date.getMonth()+1) + '-' + date.getDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'partial-logbook',
|
is: 'partial-logbook',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
narrow: {
|
narrow: {
|
||||||
|
@ -62,48 +58,46 @@
|
||||||
|
|
||||||
selectedDate: {
|
selectedDate: {
|
||||||
type: String,
|
type: String,
|
||||||
value: null,
|
bindNuclear: logbookGetters.currentDate,
|
||||||
observer: 'fetchIfNeeded',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isLoading: {
|
isLoading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: true,
|
bindNuclear: logbookGetters.isLoadingEntries,
|
||||||
|
},
|
||||||
|
|
||||||
|
isStale: {
|
||||||
|
type: Boolean,
|
||||||
|
bindNuclear: logbookGetters.isCurrentStale,
|
||||||
|
observer: 'isStaleChanged',
|
||||||
},
|
},
|
||||||
|
|
||||||
entries: {
|
entries: {
|
||||||
type: Array,
|
type: Array,
|
||||||
value: null,
|
bindNuclear: [
|
||||||
|
logbookGetters.currentEntries,
|
||||||
|
function(entries) { return entries.toArray(); },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
logbookStoreChanged: function() {
|
isStaleChanged: function(newVal) {
|
||||||
this.isLoading = this.fetchIfNeeded();
|
if (newVal) {
|
||||||
var entries = logbookStore.all.toArray();
|
// isLoading wouldn't update without debounce <_<
|
||||||
this.entries = entries.length > 0 ? entries : false;
|
this.debounce('fetch-logbook-entries', function() {
|
||||||
},
|
logbookActions.fetchDate(this.selectedDate);
|
||||||
|
}, 0);
|
||||||
computeDateCaption: function(selectedDate) {
|
|
||||||
return selectedDate || 'today';
|
|
||||||
},
|
|
||||||
|
|
||||||
fetchIfNeeded: function() {
|
|
||||||
if (logbookStore.shouldFetch(this.selectedDate)) {
|
|
||||||
this.isLoading = true;
|
|
||||||
logbookActions.fetch(this.selectedDate);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleShowDatePicker: function() {
|
handleShowDatePicker: function() {
|
||||||
uiActions.showDatePicker(function(selectedDate) {
|
uiActions.showDatePicker(
|
||||||
this.selectedDate = date_to_str(selectedDate);
|
logbookActions.changeCurrentDate,
|
||||||
}.bind(this), this.selectedDate);
|
this.selectedDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRefresh: function() {
|
handleRefresh: function() {
|
||||||
logbookActions.fetch(this.selectedDate);
|
logbookActions.fetchDate(this.selectedDate);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -41,12 +41,17 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<partial-base narrow="[[narrow]]">
|
<partial-base narrow="[[narrow]]">
|
||||||
<span header-title>{{headerTitle}}</span>
|
<span header-title>[[computeHeaderTitle(filter)]]</span>
|
||||||
|
|
||||||
<span header-buttons>
|
<span header-buttons>
|
||||||
<paper-icon-button icon="refresh" class$="[[computeRefreshButtonClass(isFetching)]]"
|
<paper-icon-button
|
||||||
on-click="handleRefresh" hidden$="[[isStreaming]]"></paper-icon-button>
|
icon="refresh"
|
||||||
<paper-icon-button icon="[[listenButtonIcon]]" hidden$={{!canListen}}
|
class$="[[computeRefreshButtonClass(isFetching)]]"
|
||||||
|
on-click="handleRefresh" hidden$="[[isStreaming]]"
|
||||||
|
></paper-icon-button>
|
||||||
|
<paper-icon-button
|
||||||
|
icon="[[computeListenButtonIcon(isListening)]]"
|
||||||
|
hidden$='[[!canListen]]'
|
||||||
on-click="handleListenClick"></paper-icon-button>
|
on-click="handleListenClick"></paper-icon-button>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -75,139 +80,93 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
|
var configGetters = window.hass.configGetters;
|
||||||
|
var entityGetters = window.hass.entityGetters;
|
||||||
|
var navigationGetters = window.hass.navigationGetters;
|
||||||
|
var voiceGetters = window.hass.voiceGetters;
|
||||||
|
var streamGetters = window.hass.streamGetters;
|
||||||
|
var serviceGetters = window.hass.serviceGetters;
|
||||||
|
var syncGetters = window.hass.syncGetters;
|
||||||
|
|
||||||
var syncActions = window.hass.syncActions;
|
var syncActions = window.hass.syncActions;
|
||||||
var voiceActions = window.hass.voiceActions;
|
var voiceActions = window.hass.voiceActions;
|
||||||
var stateStore = window.hass.stateStore;
|
|
||||||
var uiConstants = window.hass.uiConstants;
|
var uiConstants = window.hass.uiConstants;
|
||||||
|
|
||||||
|
var entityDomainFilters = window.hass.util.entityDomainFilters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'partial-states',
|
is: 'partial-states',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
/**
|
|
||||||
* Title to show in the header
|
|
||||||
*/
|
|
||||||
headerTitle: {
|
|
||||||
type: String,
|
|
||||||
value: 'States',
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If header is to be shown in narrow mode.
|
|
||||||
*/
|
|
||||||
narrow: {
|
narrow: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
filter: {
|
|
||||||
type: String,
|
|
||||||
value: null,
|
|
||||||
observer: 'filterChanged',
|
|
||||||
},
|
|
||||||
|
|
||||||
voiceSupported: {
|
|
||||||
type: Boolean,
|
|
||||||
value: voiceActions.isSupported(),
|
|
||||||
},
|
|
||||||
|
|
||||||
isFetching: {
|
isFetching: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: syncGetters.isFetching,
|
||||||
},
|
},
|
||||||
|
|
||||||
isStreaming: {
|
isStreaming: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: streamGetters.isStreamingEvents,
|
||||||
},
|
},
|
||||||
|
|
||||||
canListen: {
|
canListen: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: [
|
||||||
|
voiceGetters.isVoiceSupported,
|
||||||
|
configGetters.isComponentLoaded('conversation'),
|
||||||
|
function(isVoiceSupported, componentLoaded) {
|
||||||
|
return isVoiceSupported && componentLoaded;
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
isListening: {
|
isListening: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: voiceGetters.isListening,
|
||||||
},
|
},
|
||||||
|
|
||||||
isTransmitting: {
|
isTransmitting: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: voiceGetters.isTransmitting,
|
||||||
},
|
},
|
||||||
|
|
||||||
interimTranscript: {
|
interimTranscript: {
|
||||||
type: String,
|
type: String,
|
||||||
value: '',
|
bindNuclear: voiceGetters.extraInterimTranscript,
|
||||||
},
|
},
|
||||||
|
|
||||||
finalTranscript: {
|
finalTranscript: {
|
||||||
type: String,
|
type: String,
|
||||||
value: '',
|
bindNuclear: voiceGetters.finalTranscript,
|
||||||
},
|
|
||||||
|
|
||||||
listenButtonIcon: {
|
|
||||||
type: String,
|
|
||||||
computed: 'computeListenButtonIcon(isListening)'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showListenInterface: {
|
showListenInterface: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: 'computeShowListenInterface(isListening,isTransmitting)'
|
bindNuclear: [
|
||||||
}
|
voiceGetters.isListening,
|
||||||
},
|
voiceGetters.isTransmitting,
|
||||||
|
function(isListening, isTransmitting) {
|
||||||
|
return isListening || isTransmitting;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
componentStoreChanged: function(componentStore) {
|
states: {
|
||||||
this.canListen = this.voiceSupported &&
|
type: Array,
|
||||||
componentStore.isLoaded('conversation');
|
bindNuclear: [
|
||||||
},
|
navigationGetters.filteredStates,
|
||||||
|
// are here so a change to services causes a re-render.
|
||||||
stateStoreChanged: function() {
|
// we need this to decide if we show toggles for states.
|
||||||
this.refreshStates();
|
serviceGetters.entityMap,
|
||||||
},
|
function(states) { return states.toArray(); },
|
||||||
|
],
|
||||||
syncStoreChanged: function(syncStore) {
|
},
|
||||||
this.isFetching = syncStore.isFetching;
|
|
||||||
},
|
|
||||||
|
|
||||||
streamStoreChanged: function(streamStore) {
|
|
||||||
this.isStreaming = streamStore.isStreaming;
|
|
||||||
},
|
|
||||||
|
|
||||||
voiceStoreChanged: function(voiceStore) {
|
|
||||||
this.isListening = voiceStore.isListening;
|
|
||||||
this.isTransmitting = voiceStore.isTransmitting;
|
|
||||||
this.finalTranscript = voiceStore.finalTranscript;
|
|
||||||
this.interimTranscript = voiceStore.interimTranscript.slice(
|
|
||||||
this.finalTranscript.length);
|
|
||||||
},
|
|
||||||
|
|
||||||
filterChanged: function() {
|
|
||||||
this.refreshStates();
|
|
||||||
|
|
||||||
this.headerTitle = uiConstants.STATE_FILTERS[this.filter] || 'States';
|
|
||||||
},
|
|
||||||
|
|
||||||
refreshStates: function() {
|
|
||||||
var states;
|
|
||||||
|
|
||||||
if (this.filter) {
|
|
||||||
var filter = this.filter;
|
|
||||||
states = stateStore.all.filter(function(state) {
|
|
||||||
return state.domain === filter;
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// all but the STATE_FILTER keys
|
|
||||||
states = stateStore.all.filter(function(state) {
|
|
||||||
return !(state.domain in uiConstants.STATE_FILTERS);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.states = states.toArray().filter(
|
|
||||||
function (el) {return !el.attributes.hidden;});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRefresh: function() {
|
handleRefresh: function() {
|
||||||
|
@ -222,12 +181,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computeListenButtonIcon: function(isListening) {
|
computeHeaderTitle: function(filter) {
|
||||||
return isListening ? 'av:mic-off' : 'av:mic';
|
return filter ? entityDomainFilters[filter] : 'States';
|
||||||
},
|
},
|
||||||
|
|
||||||
computeShowListenInterface: function(isListening,isTransmitting) {
|
computeListenButtonIcon: function(isListening) {
|
||||||
return isListening || isTransmitting;
|
return isListening ? 'av:mic-off' : 'av:mic';
|
||||||
},
|
},
|
||||||
|
|
||||||
computeRefreshButtonClass: function(isFetching) {
|
computeRefreshButtonClass: function(isFetching) {
|
||||||
|
|
|
@ -14,33 +14,38 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var uiConstants = window.hass.uiConstants,
|
var moreInfoGetters = window.hass.moreInfoGetters;
|
||||||
dispatcher = window.hass.dispatcher;
|
var uiActions = window.hass.uiActions;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'modal-manager',
|
is: 'modal-manager',
|
||||||
|
|
||||||
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
|
moreInfoEntityId: {
|
||||||
|
type: String,
|
||||||
|
observer: 'moreInfoEntityIdChanged',
|
||||||
|
bindNuclear: moreInfoGetters.currentEntityId,
|
||||||
|
},
|
||||||
datePickerCallback: {
|
datePickerCallback: {
|
||||||
type: Function,
|
type: Function,
|
||||||
value: null,
|
value: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ready: function() {
|
moreInfoEntityIdChanged: function(newVal) {
|
||||||
dispatcher.register(function(payload) {
|
if (newVal) {
|
||||||
switch (payload.actionType) {
|
this.$.moreInfoDialog.show(newVal);
|
||||||
case uiConstants.ACTION_SHOW_DIALOG_MORE_INFO:
|
}
|
||||||
this.$.moreInfoDialog.show(payload.entityId);
|
},
|
||||||
break;
|
|
||||||
|
|
||||||
case uiConstants.ACTION_SHOW_DATE_PICKER:
|
ready: function() {
|
||||||
this.datePickerCallback = payload.dateSelectedCallback;
|
uiActions.showDatePicker = function(dateSelectedCallback, startDate) {
|
||||||
this.$.date = payload.date;
|
this.datePickerCallback = dateSelectedCallback;
|
||||||
this.$.datePicker.toggle();
|
this.$.date = startDate;
|
||||||
break;
|
this.$.datePicker.toggle();
|
||||||
}
|
}.bind(this);
|
||||||
}.bind(this));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
datePickerValueChanged: function(ev) {
|
datePickerValueChanged: function(ev) {
|
||||||
|
|
|
@ -15,33 +15,26 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var notificationGetters = window.hass.notificationGetters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'notification-manager',
|
is: 'notification-manager',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
text: {
|
text: {
|
||||||
type: String,
|
type: String,
|
||||||
value: '',
|
bindNuclear: notificationGetters.lastNotificationMessage,
|
||||||
},
|
observer: 'showNotification',
|
||||||
|
|
||||||
lastId: {
|
|
||||||
type: Number,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
notificationStoreChanged: function(notificationStore) {
|
showNotification: function(newText) {
|
||||||
if (notificationStore.hasNewNotifications(this.lastId)) {
|
if (newText) {
|
||||||
var notification = notificationStore.lastNotification;
|
|
||||||
|
|
||||||
this.lastId = notification.id;
|
|
||||||
this.text = notification.message;
|
|
||||||
|
|
||||||
this.$.toast.show();
|
this.$.toast.show();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<link rel="import" href="../bower_components/polymer/polymer.html">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var authGetters = window.hass.authGetters;
|
||||||
|
var streamGetters = window.hass.streamGetters;
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'preferences-manager',
|
||||||
|
|
||||||
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
authToken: {
|
||||||
|
type: String,
|
||||||
|
bindNuclear: authGetters.currentAuthToken,
|
||||||
|
observer: 'updateStorage',
|
||||||
|
},
|
||||||
|
useStreaming: {
|
||||||
|
type: String,
|
||||||
|
bindNuclear: ,
|
||||||
|
observer: 'updateStorage',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
updateStorage: function() {
|
||||||
|
if (!('localStorage' in window)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var storage = localStorage;
|
||||||
|
|
||||||
|
Object.keys(this.properties).forEach(function(prop) {
|
||||||
|
storage[prop] = this.prop;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
|
@ -52,13 +52,14 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
var streamGetters = window.hass.streamGetters;
|
||||||
var syncActions = window.hass.syncActions;
|
var syncActions = window.hass.syncActions;
|
||||||
var serviceActions = window.hass.serviceActions;
|
var serviceActions = window.hass.serviceActions;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'more-info-configurator',
|
is: 'more-info-configurator',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
stateObj: {
|
stateObj: {
|
||||||
|
@ -72,7 +73,7 @@
|
||||||
|
|
||||||
isStreaming: {
|
isStreaming: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
bindNuclear: streamGetters.isStreamingEvents,
|
||||||
},
|
},
|
||||||
|
|
||||||
isConfigurable: {
|
isConfigurable: {
|
||||||
|
@ -99,10 +100,6 @@
|
||||||
return stateObj.attributes.submit_caption || 'Set configuration';
|
return stateObj.attributes.submit_caption || 'Set configuration';
|
||||||
},
|
},
|
||||||
|
|
||||||
streamStoreChanged: function(streamStore) {
|
|
||||||
this.isStreaming = streamStore.isStreaming;
|
|
||||||
},
|
|
||||||
|
|
||||||
submitClicked: function() {
|
submitClicked: function() {
|
||||||
this.isConfiguring = true;
|
this.isConfiguring = true;
|
||||||
|
|
||||||
|
|
|
@ -23,28 +23,36 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var stateStore = window.hass.stateStore;
|
var entityGetters = window.hass.entityGetters;
|
||||||
|
var moreInfoGetters = window.hass.moreInfoGetters;
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'more-info-group',
|
is: 'more-info-group',
|
||||||
|
|
||||||
behaviors: [StoreListenerBehavior],
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
stateObj: {
|
stateObj: {
|
||||||
type: Object,
|
type: Object,
|
||||||
observer: 'updateStates',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
states: {
|
states: {
|
||||||
type: Array,
|
type: Array,
|
||||||
value: [],
|
bindNuclear: [
|
||||||
|
moreInfoGetters.currentEntity,
|
||||||
|
entityGetters.entityMap,
|
||||||
|
function(currentEntity, entities) {
|
||||||
|
// weird bug??
|
||||||
|
if (!currentEntity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return currentEntity.attributes.entity_id.map(
|
||||||
|
entities.get.bind(entities));
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
stateStoreChanged: function() {
|
|
||||||
this.updateStates();
|
|
||||||
},
|
|
||||||
|
|
||||||
updateStates: function() {
|
updateStates: function() {
|
||||||
this.states = this.stateObj && this.stateObj.attributes.entity_id ?
|
this.states = this.stateObj && this.stateObj.attributes.entity_id ?
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var constants = window.hass.constants;
|
var temperatureUnits = window.hass.util.temperatureUnits;
|
||||||
var serviceActions = window.hass.serviceActions;
|
var serviceActions = window.hass.serviceActions;
|
||||||
var uiUtil = window.hass.uiUtil;
|
var uiUtil = window.hass.uiUtil;
|
||||||
var ATTRIBUTE_CLASSES = ['away_mode'];
|
var ATTRIBUTE_CLASSES = ['away_mode'];
|
||||||
|
@ -76,7 +76,8 @@
|
||||||
this.targetTemperatureSliderValue = this.stateObj.state;
|
this.targetTemperatureSliderValue = this.stateObj.state;
|
||||||
this.awayToggleChecked = this.stateObj.attributes.away_mode == 'on';
|
this.awayToggleChecked = this.stateObj.attributes.away_mode == 'on';
|
||||||
|
|
||||||
if (this.stateObj.attributes.unit_of_measurement === constants.UNIT_TEMP_F) {
|
if (this.stateObj.attributes.unit_of_measurement ===
|
||||||
|
temperatureUnits.UNIT_TEMP_F) {
|
||||||
this.tempMin = 45;
|
this.tempMin = 45;
|
||||||
this.tempMax = 95;
|
this.tempMax = 95;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var reactor = window.hass.reactor;
|
||||||
|
var authGetters = window.hass.authGetters;
|
||||||
|
var streamGetters = window.hass.streamGetters;
|
||||||
|
|
||||||
|
var storage = 'localStorage' in window ? localStorage : {};
|
||||||
|
|
||||||
|
var observe = {
|
||||||
|
authToken: {
|
||||||
|
bindNuclear: [
|
||||||
|
authGetters.currentAuthToken,
|
||||||
|
authGetters.rememberAuth,
|
||||||
|
function(authToken, rememberAuth) {
|
||||||
|
return rememberAuth ? authToken : null;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: null,
|
||||||
|
},
|
||||||
|
useStreaming: {
|
||||||
|
bindNuclear: streamGetters.useStreaming,
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var uiPreferences = {};
|
||||||
|
|
||||||
|
Object.keys(observe).forEach(function(prop) {
|
||||||
|
if (!(prop in storage)) {
|
||||||
|
storage[prop] = observe[prop].defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(uiPreferences, prop, {
|
||||||
|
get: function() { return JSON.parse(storage[prop]); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
uiPreferences.startSync = function startSync() {
|
||||||
|
Object.keys(observe).forEach(function(prop) {
|
||||||
|
var getter = observe[prop].bindNuclear;
|
||||||
|
var valueChanged = function valueChanged(value) {
|
||||||
|
storage[prop] = JSON.stringify(value);
|
||||||
|
};
|
||||||
|
reactor.observe(getter, valueChanged);
|
||||||
|
valueChanged(reactor.evaluate(getter));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
window.hass.uiPreferences = uiPreferences;
|
||||||
|
})();
|
||||||
|
</script>
|
|
@ -1,4 +1,5 @@
|
||||||
<script src="../home-assistant-js/dist/homeassistant.min.js"></script>
|
<script src="../home-assistant-js/dist/homeassistant.min.js"></script>
|
||||||
|
<link rel="import" href="./ha-preferences.html">
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -10,63 +11,16 @@
|
||||||
'sensor',
|
'sensor',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Add some frontend specific helpers to the models
|
var reactor = window.hass.reactor;
|
||||||
Object.defineProperties(window.hass.stateModel.prototype, {
|
var serviceGetters = window.hass.serviceGetters;
|
||||||
// how to render the card for this state
|
var authActions = window.hass.authActions;
|
||||||
cardType: {
|
var uiPreferences = window.hass.uiPreferences;
|
||||||
get: function() {
|
|
||||||
console.warn('Deprecated method. Please use hass.uiUtil.stateCardType');
|
|
||||||
return window.hass.uiUtil.stateCardType(this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// how to render the more info of this state
|
|
||||||
moreInfoType: {
|
|
||||||
get: function() {
|
|
||||||
console.warn('Deprecated method. Please use hass.uiUtil.stateMoreInfoType');
|
|
||||||
return window.hass.uiUtil.stateMoreInfoType(this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var dispatcher = window.hass.dispatcher,
|
|
||||||
constants = window.hass.constants,
|
|
||||||
preferenceStore = window.hass.preferenceStore,
|
|
||||||
authActions = window.hass.authActions;
|
|
||||||
|
|
||||||
window.hass.uiConstants = {
|
|
||||||
ACTION_SHOW_DIALOG_MORE_INFO: 'ACTION_SHOW_DIALOG_MORE_INFO',
|
|
||||||
ACTION_SHOW_DATE_PICKER: 'ACTION_SHOW_DATE_PICKER',
|
|
||||||
|
|
||||||
STATE_FILTERS: {
|
|
||||||
'group': 'Groups',
|
|
||||||
'script': 'Scripts',
|
|
||||||
'scene': 'Scenes',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
window.hass.uiActions = {
|
window.hass.uiActions = {
|
||||||
showMoreInfoDialog: function(entityId) {
|
validateAuth: function(authToken, rememberAuth) {
|
||||||
dispatcher.dispatch({
|
|
||||||
actionType: window.hass.uiConstants.ACTION_SHOW_DIALOG_MORE_INFO,
|
|
||||||
entityId: entityId,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
showDatePicker: function(dateSelectedCallback, startDate) {
|
|
||||||
startDate = startDate || null;
|
|
||||||
|
|
||||||
dispatcher.dispatch({
|
|
||||||
actionType: window.hass.uiConstants.ACTION_SHOW_DATE_PICKER,
|
|
||||||
dateSelectedCallback: dateSelectedCallback,
|
|
||||||
startDate: startDate,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
validateAuth: function(authToken, rememberLogin) {
|
|
||||||
authActions.validate(authToken, {
|
authActions.validate(authToken, {
|
||||||
useStreaming: preferenceStore.useStreaming,
|
useStreaming: uiPreferences.useStreaming,
|
||||||
rememberLogin: rememberLogin,
|
rememberAuth: rememberAuth,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -76,7 +30,7 @@
|
||||||
stateCardType: function(state) {
|
stateCardType: function(state) {
|
||||||
if(DOMAINS_WITH_CARD.indexOf(state.domain) !== -1) {
|
if(DOMAINS_WITH_CARD.indexOf(state.domain) !== -1) {
|
||||||
return state.domain;
|
return state.domain;
|
||||||
} else if(state.canToggle) {
|
} else if(reactor.evaluate(serviceGetters.canToggle(state.entityId))) {
|
||||||
return "toggle";
|
return "toggle";
|
||||||
} else {
|
} else {
|
||||||
return "display";
|
return "display";
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<!--
|
||||||
|
Wrapping JS in an HTML file will prevent it from being loaded twice.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script src="../bower_components/lodash/lodash.min.js"></script>
|
|
@ -1,21 +1,42 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
var NuclearObserver = function NuclearObserver(reactor) {
|
||||||
|
return {
|
||||||
|
|
||||||
var StoreListenerMixIn = window.hass.storeListenerMixIn;
|
attached: function() {
|
||||||
|
var component = this;
|
||||||
|
this.__unwatchFns = Object.keys(component.properties).reduce(
|
||||||
|
function(unwatchFns, key) {
|
||||||
|
if (!('bindNuclear' in component.properties[key])) {
|
||||||
|
return unwatchFns;
|
||||||
|
}
|
||||||
|
var getter = component.properties[key].bindNuclear;
|
||||||
|
|
||||||
window.StoreListenerBehavior = {
|
if (!getter) {
|
||||||
|
throw 'Undefined getter specified for key ' + key;
|
||||||
|
}
|
||||||
|
|
||||||
attached: function() {
|
// console.log(key, getter);
|
||||||
StoreListenerMixIn.listenToStores(true, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
detached: function() {
|
component[key] = reactor.evaluate(getter);
|
||||||
StoreListenerMixIn.stopListeningToStores(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
return unwatchFns.concat(reactor.observe(getter, function(val) {
|
||||||
|
// console.log('New value for', key, val);
|
||||||
|
component[key] = val;
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
},
|
||||||
|
|
||||||
|
detached: function() {
|
||||||
|
while (this.__unwatchFns.length) {
|
||||||
|
this.__unwatchFns.shift()();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
window.nuclearObserver = NuclearObserver(window.hass.reactor);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue