Migrate cards to use setConfig to get config. (#1363)

* Experiment with setConfig

* More cleanup

* fix filter card

* Wait for DOM to be done

* 1 line

* Lint

* Lint2

* Lint
This commit is contained in:
Paulus Schoutsen 2018-06-29 10:54:52 -04:00 committed by GitHub
parent 05816374a8
commit bb670b76a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 265 additions and 319 deletions

View File

@ -2,8 +2,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../cards/ha-camera-card.js'; import '../../../cards/ha-camera-card.js';
import createCardElement from '../common/create-card-element.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
import validateEntityConfig from '../common/validate-entity-config.js'; import validateEntityConfig from '../common/validate-entity-config.js';
class HuiCameraPreviewCard extends PolymerElement { class HuiCameraPreviewCard extends PolymerElement {
@ -13,10 +11,6 @@ class HuiCameraPreviewCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -24,20 +18,18 @@ class HuiCameraPreviewCard extends PolymerElement {
return 4; return 4;
} }
_configChanged(config) { setConfig(config) {
if (!validateEntityConfig(config, 'camera')) {
throw new Error('Error in card configuration.');
}
this._config = config;
this._entityId = null; this._entityId = null;
if (this.lastChild) { if (this.lastChild) {
this.removeChild(this.lastChild); this.removeChild(this.lastChild);
} }
if (!validateEntityConfig(config, 'camera')) {
const error = 'Error in card configuration.';
const element = createCardElement(createErrorCardConfig(error, config));
this.appendChild(element);
return;
}
const entityId = config.entity; const entityId = config.entity;
if (!(entityId in this.hass.states)) { if (!(entityId in this.hass.states)) {
return; return;
@ -56,8 +48,6 @@ class HuiCameraPreviewCard extends PolymerElement {
const element = this.lastChild; const element = this.lastChild;
element.stateObj = hass.states[entityId]; element.stateObj = hass.states[entityId];
element.hass = hass; element.hass = hass;
} else {
this._configChanged(this.config);
} }
} }
} }

View File

@ -3,7 +3,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import computeCardSize from '../common/compute-card-size.js'; import computeCardSize from '../common/compute-card-size.js';
import createCardElement from '../common/create-card-element.js'; import createCardElement from '../common/create-card-element.js';
import createErrorConfig from '../common/create-error-card-config.js';
class HuiColumnCard extends PolymerElement { class HuiColumnCard extends PolymerElement {
static get template() { static get template() {
@ -29,10 +28,6 @@ class HuiColumnCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -41,6 +36,11 @@ class HuiColumnCard extends PolymerElement {
this._elements = []; this._elements = [];
} }
ready() {
super.ready();
if (this._config) this._buildConfig();
}
getCardSize() { getCardSize() {
let totalSize = 0; let totalSize = 0;
this._elements.forEach((element) => { this._elements.forEach((element) => {
@ -49,7 +49,18 @@ class HuiColumnCard extends PolymerElement {
return totalSize; return totalSize;
} }
_configChanged(config) { setConfig(config) {
if (!config || !config.cards || !Array.isArray(config.cards)) {
throw new Error('Card config incorrect');
}
this._config = config;
if (this.$) this._buildConfig();
}
_buildConfig() {
const config = this._config;
this._elements = []; this._elements = [];
const root = this.$.root; const root = this.$.root;
@ -57,13 +68,6 @@ class HuiColumnCard extends PolymerElement {
root.removeChild(root.lastChild); root.removeChild(root.lastChild);
} }
if (!config || !config.cards || !Array.isArray(config.cards)) {
const error = 'Card config incorrect.';
const element = createCardElement(createErrorConfig(error, config));
root.appendChild(element);
return;
}
const elements = []; const elements = [];
config.cards.forEach((card) => { config.cards.forEach((card) => {
const element = createCardElement(card); const element = createCardElement(card);

View File

@ -50,9 +50,9 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) {
<ha-card> <ha-card>
<div class='header'> <div class='header'>
<div class="name">[[_computeTitle(config)]]</div> <div class="name">[[_computeTitle(_config)]]</div>
<template is="dom-if" if="[[_showHeaderToggle(config.show_header_toggle)]]"> <template is="dom-if" if="[[_showHeaderToggle(_config.show_header_toggle)]]">
<hui-entities-toggle hass="[[hass]]" entities="[[config.entities]]"></hui-entities-toggle> <hui-entities-toggle hass="[[hass]]" entities="[[_config.entities]]"></hui-entities-toggle>
</template> </template>
</div> </div>
<div id="states"></div> <div id="states"></div>
@ -66,10 +66,7 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) {
type: Object, type: Object,
observer: '_hassChanged', observer: '_hassChanged',
}, },
config: { _config: Object,
type: Object,
observer: '_configChanged',
}
}; };
} }
@ -78,9 +75,14 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) {
this._elements = []; this._elements = [];
} }
ready() {
super.ready();
if (this._config) this._buildConfig();
}
getCardSize() { getCardSize() {
// +1 for the header // +1 for the header
return 1 + (this.config ? this.config.entities.length : 0); return 1 + (this._config ? this._config.entities.length : 0);
} }
_computeTitle(config) { _computeTitle(config) {
@ -91,7 +93,13 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) {
return show !== false; return show !== false;
} }
_configChanged(config) { setConfig(config) {
this._config = config;
if (this.$) this._buildConfig();
}
_buildConfig() {
const config = this._config;
const root = this.$.states; const root = this.$.states;
while (root.lastChild) { while (root.lastChild) {

View File

@ -2,7 +2,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import computeStateDomain from '../../../common/entity/compute_state_domain.js'; import computeStateDomain from '../../../common/entity/compute_state_domain.js';
import createCardElement from '../common/create-card-element.js'; import createCardElement from '../common/create-card-element.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
class HuiEntitiesCard extends PolymerElement { class HuiEntitiesCard extends PolymerElement {
static get properties() { static get properties() {
@ -11,10 +10,6 @@ class HuiEntitiesCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -54,35 +49,25 @@ class HuiEntitiesCard extends PolymerElement {
return stateObj.entity_id.search(regEx) === 0; return stateObj.entity_id.search(regEx) === 0;
} }
_configChanged(config) { setConfig(config) {
if (!config.filter || !Array.isArray(config.filter)) {
throw new Error('Incorrect filter config.');
}
this._config = config;
if (this.lastChild) { if (this.lastChild) {
this.removeChild(this.lastChild); this.removeChild(this.lastChild);
} }
let error; const card = 'card' in config ? Object.assign({}, config.card) : {};
if (!card.type) card.type = 'entities';
card.entities = [];
if (!config.filter || !Array.isArray(config.filter)) { const element = createCardElement(card);
error = 'Incorrect filter config.'; element._filterRawConfig = card;
} else if (!config.card) { this._updateCardConfig(element);
config = Object.assign({}, config, { element.hass = this.hass;
card: { type: 'entities' }
});
} else if (!config.card.type) {
config = Object.assign({}, config, {
card: Object.assign({}, config.card, { type: 'entities' })
});
}
let element;
if (error) {
element = createCardElement(createErrorCardConfig(error, config.card));
} else {
element = createCardElement(config.card);
element._filterRawConfig = config.card;
this._updateCardConfig(element);
element.hass = this.hass;
}
this.appendChild(element); this.appendChild(element);
} }
@ -93,12 +78,12 @@ class HuiEntitiesCard extends PolymerElement {
} }
_updateCardConfig(element) { _updateCardConfig(element) {
if (!element || element.tagName === 'HUI-ERROR-CARD') return; if (!element || element.tagName === 'HUI-ERROR-CARD' || !this.hass) return;
element.config = Object.assign( element.setConfig(Object.assign(
{}, {},
element._filterRawConfig, element._filterRawConfig,
{ entities: this._getEntities(this.hass, this.config.filter) } { entities: this._getEntities(this.hass, this._config.filter) }
); ));
} }
} }
customElements.define('hui-entity-filter-card', HuiEntitiesCard); customElements.define('hui-entity-filter-card', HuiEntitiesCard);

View File

@ -12,17 +12,21 @@ class HuiErrorCard extends PolymerElement {
padding: 8px; padding: 8px;
} }
</style> </style>
[[config.error]] [[_config.error]]
<pre>[[_toStr(config.origConfig)]]</pre> <pre>[[_toStr(_config.origConfig)]]</pre>
`; `;
} }
static get properties() { static get properties() {
return { return {
config: Object, _config: Object,
}; };
} }
setConfig(config) {
this._config = config;
}
getCardSize() { getCardSize() {
return 4; return 4;
} }

View File

@ -4,10 +4,7 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import computeStateDisplay from '../../../common/entity/compute_state_display.js'; import computeStateDisplay from '../../../common/entity/compute_state_display.js';
import computeStateName from '../../../common/entity/compute_state_name.js'; import computeStateName from '../../../common/entity/compute_state_name.js';
import computeConfigEntities from '../common/compute-config-entities'; import computeConfigEntities from '../common/compute-config-entities';
import createErrorCardConfig from '../common/create-error-card-config.js';
import validateEntitiesConfig from '../common/validate-entities-config';
import './hui-error-card.js';
import '../../../components/entity/state-badge.js'; import '../../../components/entity/state-badge.js';
import '../../../components/ha-card.js'; import '../../../components/ha-card.js';
@ -50,9 +47,9 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
} }
</style> </style>
<ha-card header="[[config.title]]"> <ha-card header="[[_config.title]]">
<div class="entities"> <div class="entities">
<template is="dom-repeat" items="[[_entities]]"> <template is="dom-repeat" items="[[_computeEntities(_config)]]">
<template is="dom-if" if="[[_showEntity(item, hass.states)]]"> <template is="dom-if" if="[[_showEntity(item, hass.states)]]">
<div class="entity" on-click="_openDialog"> <div class="entity" on-click="_openDialog">
<div>[[_computeName(item, hass.states)]]</div> <div>[[_computeName(item, hass.states)]]</div>
@ -62,9 +59,6 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
</template> </template>
</template> </template>
</div> </div>
<template is="dom-if" if="[[_error]]">
<hui-error-card config="[[_error]]"></hui-error-card>
</template>
</ha-card> </ha-card>
`; `;
} }
@ -72,12 +66,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,
config: Object, _config: Object,
_entities: {
type: Array,
computed: '_computeEntities(config)'
},
_error: Object
}; };
} }
@ -86,14 +75,15 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
} }
_computeEntities(config) { _computeEntities(config) {
if (!validateEntitiesConfig(config)) { return computeConfigEntities(config);
const error = 'Error in card configuration.'; }
this._error = createErrorCardConfig(error, config);
return []; setConfig(config) {
if (!config || !config.entities || !Array.isArray(config.entities)) {
throw new Error('Error in card configuration.');
} }
this._error = null; this._config = config;
return computeConfigEntities(config);
} }
_showEntity(item, states) { _showEntity(item, states) {

View File

@ -1,40 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './hui-error-card.js';
import '../../../components/ha-card.js'; import '../../../components/ha-card.js';
import '../../../components/state-history-charts.js'; import '../../../components/state-history-charts.js';
import '../../../data/ha-state-history-data.js'; import '../../../data/ha-state-history-data.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
class HuiHistoryGraphCard extends PolymerElement { class HuiHistoryGraphCard extends PolymerElement {
static get properties() {
return {
hass: Object,
config: {
type: Object,
observer: '_configChanged',
},
_error: Object,
stateHistory: Object,
stateHistoryLoading: Boolean,
cacheConfig: {
type: Object,
value: {
refresh: 0,
cacheKey: null,
hoursToShow: 24,
},
},
};
}
getCardSize() {
return 4;
}
static get template() { static get template() {
return html` return html`
<style> <style>
@ -43,45 +14,53 @@ class HuiHistoryGraphCard extends PolymerElement {
} }
</style> </style>
<template is="dom-if" if="[[!_error]]"> <ha-card header=[[_config.title]]>
<ha-card header=[[config.title]]> <ha-state-history-data
<ha-state-history-data hass="[[hass]]"
hass="[[hass]]" filter-type="recent-entity"
filter-type="recent-entity" entity-id="[[_config.entities]]"
entity-id="[[config.entities]]" data="{{stateHistory}}"
data="{{stateHistory}}" is-loading="{{stateHistoryLoading}}"
is-loading="{{stateHistoryLoading}}" cache-config="[[_computeCacheConfig(_config)]]"
cache-config="[[cacheConfig]]" ></ha-state-history-data>
></ha-state-history-data> <state-history-charts
<state-history-charts hass="[[hass]]"
hass="[[hass]]" history-data="[[stateHistory]]"
history-data="[[stateHistory]]" is-loading-data="[[stateHistoryLoading]]"
is-loading-data="[[stateHistoryLoading]]" up-to-now
up-to-now no-single
no-single ></state-history-charts>
></state-history-charts> </ha-card>
</ha-card>
</template>
<template is="dom-if" if="[[_error]]">
<hui-error-card config="[[_error]]"></hui-error-card>
</template>
`; `;
} }
_configChanged(config) { static get properties() {
if (config.entities && Array.isArray(config.entities)) { return {
this._error = null; hass: Object,
_config: Object,
stateHistory: Object,
stateHistoryLoading: Boolean,
};
}
this.cacheConfig = { getCardSize() {
cacheKey: config.entities, return 4;
hoursToShow: config.hours_to_show || 24, }
refresh: config.refresh_interval || 0
}; setConfig(config) {
} else { if (!config.entities || !Array.isArray(config.entities)) {
const error = 'Error in card configuration.'; throw new Error('Error in card configuration.');
this._error = createErrorCardConfig(error, config);
} }
this._config = config;
}
_computeCacheConfig(config) {
return {
cacheKey: config.entities,
hoursToShow: config.hours_to_show || 24,
refresh: config.refresh_interval || 0
};
} }
} }

View File

@ -2,15 +2,6 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js';
class HuiIframeCard extends PolymerElement { class HuiIframeCard extends PolymerElement {
static get properties() {
return {
config: {
type: Object,
observer: '_configChanged'
}
};
}
static get template() { static get template() {
return html` return html`
<style> <style>
@ -31,15 +22,33 @@ class HuiIframeCard extends PolymerElement {
height: 100%; height: 100%;
} }
</style> </style>
<ha-card header="[[config.title]]"> <ha-card header="[[_config.title]]">
<div id="root"> <div id="root">
<iframe src="[[config.url]]"></iframe> <iframe src="[[_config.url]]"></iframe>
</div> </div>
</ha-card> </ha-card>
`; `;
} }
_configChanged(config) { static get properties() {
return {
_config: Object,
};
}
ready() {
super.ready();
if (this._config) this._buildConfig();
}
setConfig(config) {
this._config = config;
if (this.$) this._buildConfig();
}
_buildConfig() {
const config = this._config;
this.$.root.style.paddingTop = config.aspect_ratio || '50%'; this.$.root.style.paddingTop = config.aspect_ratio || '50%';
} }

View File

@ -34,15 +34,15 @@ class HuiMarkdownCard extends PolymerElement {
max-width: 100%; max-width: 100%;
} }
</style> </style>
<ha-card header="[[config.title]]"> <ha-card header="[[_config.title]]">
<ha-markdown content='[[config.content]]'></ha-markdown> <ha-markdown content='[[_config.content]]'></ha-markdown>
</ha-card> </ha-card>
`; `;
} }
static get properties() { static get properties() {
return { return {
config: Object, _config: Object,
noTitle: { noTitle: {
type: Boolean, type: Boolean,
reflectToAttribute: true, reflectToAttribute: true,
@ -51,8 +51,12 @@ class HuiMarkdownCard extends PolymerElement {
}; };
} }
setConfig(config) {
this._config = config;
}
getCardSize() { getCardSize() {
return this.config.content.split('\n').length; return this._config.content.split('\n').length;
} }
_computeNoTitle(title) { _computeNoTitle(title) {

View File

@ -2,8 +2,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../cards/ha-media_player-card.js'; import '../../../cards/ha-media_player-card.js';
import createCardElement from '../common/create-card-element.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
import validateEntityConfig from '../common/validate-entity-config.js'; import validateEntityConfig from '../common/validate-entity-config.js';
class HuiMediaControlCard extends PolymerElement { class HuiMediaControlCard extends PolymerElement {
@ -13,10 +11,6 @@ class HuiMediaControlCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -24,20 +18,17 @@ class HuiMediaControlCard extends PolymerElement {
return 3; return 3;
} }
_configChanged(config) { setConfig(config) {
if (!validateEntityConfig(config, 'media_player')) {
throw new Error('Error in card configuration.');
}
this._entityId = null; this._entityId = null;
if (this.lastChild) { if (this.lastChild) {
this.removeChild(this.lastChild); this.removeChild(this.lastChild);
} }
if (!validateEntityConfig(config, 'media_player')) {
const error = 'Error in card configuration.';
const element = createCardElement(createErrorCardConfig(error, config));
this.appendChild(element);
return;
}
const entityId = config.entity; const entityId = config.entity;
if (!(entityId in this.hass.states)) { if (!(entityId in this.hass.states)) {
return; return;
@ -56,8 +47,6 @@ class HuiMediaControlCard extends PolymerElement {
const element = this.lastChild; const element = this.lastChild;
element.stateObj = hass.states[entityId]; element.stateObj = hass.states[entityId];
element.hass = hass; element.hass = hass;
} else {
this._configChanged(this.config);
} }
} }
} }

View File

@ -47,7 +47,7 @@ class HuiPictureElementsCard extends LocalizeMixin(EventsMixin(PolymerElement))
} }
</style> </style>
<ha-card header="[[config.title]]"> <ha-card header="[[_config.title]]">
<div id="root"></div> <div id="root"></div>
</ha-card> </ha-card>
`; `;
@ -59,18 +59,36 @@ class HuiPictureElementsCard extends LocalizeMixin(EventsMixin(PolymerElement))
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: { _config: Object,
type: Object,
observer: '_configChanged'
}
}; };
} }
constructor() {
super();
this._requiresStateObj = [];
this._requiresTextState = [];
}
ready() {
super.ready();
if (this._config) this._buildConfig();
}
getCardSize() { getCardSize() {
return 4; return 4;
} }
_configChanged(config) { setConfig(config) {
if (!config || !config.image || !Array.isArray(config.elements)) {
throw new Error('Invalid card configuration');
}
this._config = config;
if (this.$) this._buildConfig();
}
_buildConfig() {
const config = this._config;
const root = this.$.root; const root = this.$.root;
this._requiresStateObj = []; this._requiresStateObj = [];
this._requiresTextState = []; this._requiresTextState = [];
@ -79,41 +97,43 @@ class HuiPictureElementsCard extends LocalizeMixin(EventsMixin(PolymerElement))
root.removeChild(root.lastChild); root.removeChild(root.lastChild);
} }
if (config && config.image && config.elements) { const img = document.createElement('img');
const img = document.createElement('img'); img.src = config.image;
img.src = config.image; root.appendChild(img);
root.appendChild(img);
config.elements.forEach((element) => { config.elements.forEach((element) => {
let el; let el;
if (element.type === 'state-badge') { if (element.type === 'state-badge') {
const entityId = element.entity; const entityId = element.entity;
el = document.createElement('state-badge'); el = document.createElement('state-badge');
el.addEventListener('click', () => this._handleClick(entityId, element.tap_action === 'toggle')); el.addEventListener('click', () => this._handleClick(entityId, element.tap_action === 'toggle'));
el.classList.add('clickable'); el.classList.add('clickable');
this._requiresStateObj.push({ el, entityId }); this._requiresStateObj.push({ el, entityId });
} else if (element.type === 'state-text') { } else if (element.type === 'state-text') {
const entityId = element.entity; const entityId = element.entity;
el = document.createElement('div'); el = document.createElement('div');
el.addEventListener('click', () => this._handleClick(entityId, false)); el.addEventListener('click', () => this._handleClick(entityId, false));
el.classList.add('clickable', 'state-text'); el.classList.add('clickable', 'state-text');
this._requiresTextState.push({ el, entityId }); this._requiresTextState.push({ el, entityId });
} else if (element.type === 'service-button') { } else if (element.type === 'service-button') {
el = document.createElement('ha-call-service-button'); el = document.createElement('ha-call-service-button');
el.hass = this.hass; el.hass = this.hass;
el.domain = (element.service && element.domain) || 'homeassistant'; el.domain = (element.service && element.domain) || 'homeassistant';
el.service = (element.service && element.service.service) || ''; el.service = (element.service && element.service.service) || '';
el.serviceData = (element.service && element.service.data) || {}; el.serviceData = (element.service && element.service.data) || {};
el.innerText = element.title; el.innerText = element.title;
} }
el.classList.add('element'); el.classList.add('element');
if (element.style) { if (element.style) {
Object.keys(element.style).forEach((prop) => { Object.keys(element.style).forEach((prop) => {
el.style.setProperty(prop, element.style[prop]); el.style.setProperty(prop, element.style[prop]);
}); });
} }
root.appendChild(el); root.appendChild(el);
}); });
if (this.hass) {
this._hassChanged(this.hass);
} }
} }

View File

@ -1,7 +1,6 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './hui-error-card.js';
import '../../../components/ha-card.js'; import '../../../components/ha-card.js';
import { STATES_OFF } from '../../../common/const.js'; import { STATES_OFF } from '../../../common/const.js';
@ -9,7 +8,6 @@ import computeDomain from '../../../common/entity/compute_domain.js';
import computeStateDisplay from '../../../common/entity/compute_state_display.js'; import computeStateDisplay from '../../../common/entity/compute_state_display.js';
import computeStateDomain from '../../../common/entity/compute_state_domain.js'; import computeStateDomain from '../../../common/entity/compute_state_domain.js';
import computeStateName from '../../../common/entity/compute_state_name.js'; import computeStateName from '../../../common/entity/compute_state_name.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
import toggleEntity from '../common/entity/toggle-entity.js'; import toggleEntity from '../common/entity/toggle-entity.js';
import LocalizeMixin from '../../../mixins/localize-mixin.js'; import LocalizeMixin from '../../../mixins/localize-mixin.js';
@ -58,9 +56,6 @@ class HuiPictureEntityCard extends LocalizeMixin(PolymerElement) {
<div id="title"></div> <div id="title"></div>
<div id="state"></div> <div id="state"></div>
</div> </div>
<template is="dom-if" if="[[_error]]">
<hui-error-card config="[[_error]]"></hui-error-card>
</template>
</ha-card> </ha-card>
`; `;
} }
@ -71,11 +66,7 @@ class HuiPictureEntityCard extends LocalizeMixin(PolymerElement) {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: { _config: Object,
type: Object,
observer: '_configChanged'
},
_error: Object
}; };
} }
@ -83,17 +74,15 @@ class HuiPictureEntityCard extends LocalizeMixin(PolymerElement) {
return 3; return 3;
} }
_configChanged(config) { setConfig(config) {
if (!config || !config.entity || (!config.image && !config.state_image)) { if (!config || !config.entity || (!config.image && !config.state_image)) {
const error = 'Error in card configuration.'; throw new Error('Error in card configuration.');
this._error = createErrorCardConfig(error, config);
return;
} }
this._error = null; this._config = config;
} }
_hassChanged(hass) { _hassChanged(hass) {
const config = this.config; const config = this._config;
const entityId = config && config.entity; const entityId = config && config.entity;
if (!entityId) { if (!entityId) {
return; return;
@ -136,7 +125,7 @@ class HuiPictureEntityCard extends LocalizeMixin(PolymerElement) {
} }
_cardClicked() { _cardClicked() {
const entityId = this.config && this.config.entity; const entityId = this._config && this._config.entity;
if (!(entityId in this.hass.states)) { if (!(entityId in this.hass.states)) {
return; return;
} }

View File

@ -2,14 +2,12 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-icon-button/paper-icon-button.js'; import '@polymer/paper-icon-button/paper-icon-button.js';
import './hui-error-card.js';
import '../../../components/ha-card.js'; import '../../../components/ha-card.js';
import { STATES_OFF } from '../../../common/const.js'; import { STATES_OFF } from '../../../common/const.js';
import canToggleState from '../../../common/entity/can_toggle_state.js'; import canToggleState from '../../../common/entity/can_toggle_state.js';
import computeStateDisplay from '../../../common/entity/compute_state_display.js'; import computeStateDisplay from '../../../common/entity/compute_state_display.js';
import computeStateName from '../../../common/entity/compute_state_name.js'; import computeStateName from '../../../common/entity/compute_state_name.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
import stateIcon from '../../../common/entity/state_icon.js'; import stateIcon from '../../../common/entity/state_icon.js';
import toggleEntity from '../common/entity/toggle-entity.js'; import toggleEntity from '../common/entity/toggle-entity.js';
@ -63,9 +61,9 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
</style> </style>
<ha-card> <ha-card>
<img src="[[config.image]]"> <img src="[[_config.image]]">
<div class="box"> <div class="box">
<div class="title">[[config.title]]</div> <div class="title">[[_config.title]]</div>
<div> <div>
<template is="dom-repeat" items="[[_entitiesDialog]]"> <template is="dom-repeat" items="[[_entitiesDialog]]">
<template is="dom-if" if="[[_showEntity(item, hass.states)]]"> <template is="dom-if" if="[[_showEntity(item, hass.states)]]">
@ -91,9 +89,6 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
</template> </template>
</div> </div>
</div> </div>
<template is="dom-if" if="[[_error]]">
<hui-error-card config="[[_error]]"></hui-error-card>
</template>
</ha-card> </ha-card>
`; `;
} }
@ -101,13 +96,9 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,
config: { _config: Object,
type: Object,
observer: '_configChanged'
},
_entitiesDialog: Array, _entitiesDialog: Array,
_entitiesService: Array, _entitiesService: Array,
_error: Object
}; };
} }
@ -115,26 +106,24 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
return 3; return 3;
} }
_configChanged(config) { setConfig(config) {
if (!config || !config.entities || !Array.isArray(config.entities) || !config.image) {
throw new Error('Invalid card configuration');
}
this._config = config;
let dialog = []; let dialog = [];
let service = []; let service = [];
let _error = null; if (config.force_dialog) {
if (config && config.entities && Array.isArray(config.entities) && config.image) { dialog = config.entities;
if (config.force_dialog) {
dialog = config.entities;
} else {
service = config.entities.filter(entity =>
canToggleState(this.hass, this.hass.states[entity]));
dialog = config.entities.filter(entity => !service.includes(entity));
}
} else { } else {
const error = 'Error in card configuration.'; service = config.entities.filter(entity =>
_error = createErrorCardConfig(error, config); canToggleState(this.hass, this.hass.states[entity]));
dialog = config.entities.filter(entity => !service.includes(entity));
} }
this.setProperties({ this.setProperties({
_entitiesDialog: dialog, _entitiesDialog: dialog,
_entitiesService: service, _entitiesService: service,
_error
}); });
} }

View File

@ -2,8 +2,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../cards/ha-plant-card.js'; import '../../../cards/ha-plant-card.js';
import createCardElement from '../common/create-card-element.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
import validateEntityConfig from '../common/validate-entity-config.js'; import validateEntityConfig from '../common/validate-entity-config.js';
class HuiPlantStatusCard extends PolymerElement { class HuiPlantStatusCard extends PolymerElement {
@ -13,10 +11,6 @@ class HuiPlantStatusCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -24,20 +18,17 @@ class HuiPlantStatusCard extends PolymerElement {
return 3; return 3;
} }
_configChanged(config) { setConfig(config) {
if (!validateEntityConfig(config, 'plant')) {
throw new Error('Error in card configuration.');
}
this._entityId = null; this._entityId = null;
if (this.lastChild) { if (this.lastChild) {
this.removeChild(this.lastChild); this.removeChild(this.lastChild);
} }
if (!validateEntityConfig(config, 'plant')) {
const error = 'Error in card configuration.';
const element = createCardElement(createErrorCardConfig(error, config));
this.appendChild(element);
return;
}
const entityId = config.entity; const entityId = config.entity;
if (!(entityId in this.hass.states)) { if (!(entityId in this.hass.states)) {
return; return;
@ -56,8 +47,6 @@ class HuiPlantStatusCard extends PolymerElement {
const element = this.lastChild; const element = this.lastChild;
element.stateObj = hass.states[entityId]; element.stateObj = hass.states[entityId];
element.hass = hass; element.hass = hass;
} else {
this._configChanged(this.config);
} }
} }
} }

View File

@ -3,7 +3,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import computeCardSize from '../common/compute-card-size.js'; import computeCardSize from '../common/compute-card-size.js';
import createCardElement from '../common/create-card-element.js'; import createCardElement from '../common/create-card-element.js';
import createErrorConfig from '../common/create-error-card-config.js';
class HuiRowCard extends PolymerElement { class HuiRowCard extends PolymerElement {
static get template() { static get template() {
@ -29,10 +28,6 @@ class HuiRowCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -41,6 +36,11 @@ class HuiRowCard extends PolymerElement {
this._elements = []; this._elements = [];
} }
ready() {
super.ready();
if (this._config) this._buildConfig();
}
getCardSize() { getCardSize() {
let size = 1; let size = 1;
this._elements.forEach((element) => { this._elements.forEach((element) => {
@ -50,7 +50,15 @@ class HuiRowCard extends PolymerElement {
return size; return size;
} }
_configChanged(config) { setConfig(config) {
if (!config || !config.cards || !Array.isArray(config.cards)) {
throw new Error('Card config incorrect.');
}
if (this.$) this._buildConfig();
}
_buildConfig() {
const config = this._config;
this._elements = []; this._elements = [];
const root = this.$.root; const root = this.$.root;
@ -58,13 +66,6 @@ class HuiRowCard extends PolymerElement {
root.removeChild(root.lastChild); root.removeChild(root.lastChild);
} }
if (!config || !config.cards || !Array.isArray(config.cards)) {
const error = 'Card config incorrect.';
const element = createCardElement(createErrorConfig(error, config));
root.appendChild(element);
return;
}
const elements = []; const elements = [];
config.cards.forEach((card) => { config.cards.forEach((card) => {
const element = createCardElement(card); const element = createCardElement(card);

View File

@ -2,8 +2,6 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../cards/ha-weather-card.js'; import '../../../cards/ha-weather-card.js';
import createCardElement from '../common/create-card-element.js';
import createErrorCardConfig from '../common/create-error-card-config.js';
import validateEntityConfig from '../common/validate-entity-config.js'; import validateEntityConfig from '../common/validate-entity-config.js';
class HuiWeatherForecastCard extends PolymerElement { class HuiWeatherForecastCard extends PolymerElement {
@ -13,10 +11,6 @@ class HuiWeatherForecastCard extends PolymerElement {
type: Object, type: Object,
observer: '_hassChanged' observer: '_hassChanged'
}, },
config: {
type: Object,
observer: '_configChanged'
}
}; };
} }
@ -24,20 +18,17 @@ class HuiWeatherForecastCard extends PolymerElement {
return 4; return 4;
} }
_configChanged(config) { setConfig(config) {
if (!validateEntityConfig(config, 'weather')) {
throw new Error('Error in card configuration.');
}
this._entityId = null; this._entityId = null;
if (this.lastChild) { if (this.lastChild) {
this.removeChild(this.lastChild); this.removeChild(this.lastChild);
} }
if (!validateEntityConfig(config, 'weather')) {
const error = 'Error in card configuration.';
const element = createCardElement(createErrorCardConfig(error, config));
this.appendChild(element);
return;
}
const entityId = config.entity; const entityId = config.entity;
if (!(entityId in this.hass.states)) { if (!(entityId in this.hass.states)) {
return; return;
@ -56,8 +47,6 @@ class HuiWeatherForecastCard extends PolymerElement {
const element = this.lastChild; const element = this.lastChild;
element.stateObj = hass.states[entityId]; element.stateObj = hass.states[entityId];
element.hass = hass; element.hass = hass;
} else {
this._configChanged(this.config);
} }
} }
} }

View File

@ -42,7 +42,14 @@ const CUSTOM_TYPE_PREFIX = 'custom:';
function _createElement(tag, config) { function _createElement(tag, config) {
const element = document.createElement(tag); const element = document.createElement(tag);
element.config = config; try {
element.setConfig(config);
} catch (err) {
// eslint-disable-next-line
console.error(tag, err);
// eslint-disable-next-line
return _createErrorElement(err.message, config);
}
return element; return element;
} }

View File

@ -13,11 +13,11 @@ export default function validateEntitiesConfig(config, additionalKeys = []) {
return false; return false;
} }
return entities.every(entity => { return entities.every((entity) => {
if (typeof entity === 'string') { if (typeof entity === 'string') {
return validEntityId(entity) && !additionalKeys.length; return validEntityId(entity) && !additionalKeys.length;
} }
return entity && typeof entity === 'object' && !Array.isArray(entity) && return entity && typeof entity === 'object' && !Array.isArray(entity) &&
'entity' in entity && validEntityId(entity.entity) && additionalKeys.every(key => key in entity) 'entity' in entity && validEntityId(entity.entity) && additionalKeys.every(key => key in entity);
}); });
} }