diff --git a/public/images/config_flows/config_homematicip_cloud.png b/public/images/config_flows/config_homematicip_cloud.png old mode 100755 new mode 100644 diff --git a/src/panels/lovelace/cards/hui-entity-filter-card.js b/src/panels/lovelace/cards/hui-entity-filter-card.js index b85b9fd220..95509231bf 100644 --- a/src/panels/lovelace/cards/hui-entity-filter-card.js +++ b/src/panels/lovelace/cards/hui-entity-filter-card.js @@ -1,17 +1,9 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js'; -import './hui-camera-preview-card.js'; -import './hui-entities-card.js'; -import './hui-entity-filter-card.js'; -import './hui-glance-card'; -import './hui-history-graph-card.js'; -import './hui-media-control-card.js'; -import './hui-picture-glance-card'; -import './hui-plant-status-card.js'; -import './hui-weather-forecast-card'; +import './hui-error-card'; import computeStateDomain from '../../../common/entity/compute_state_domain.js'; -import computeCardElement from '../common/compute-card-element.js'; +import createCardElement from '../common/create-card-element'; class HuiEntitiesCard extends PolymerElement { static get properties() { @@ -30,6 +22,7 @@ class HuiEntitiesCard extends PolymerElement { constructor() { super(); this._whenDefined = {}; + this.elementNotDefinedCallback = this.elementNotDefinedCallback.bind(this); } getCardSize() { @@ -72,48 +65,49 @@ class HuiEntitiesCard extends PolymerElement { if (this.lastChild) { this.removeChild(this.lastChild); } - let error = null; - let cardConfig; - let tag = config.card ? computeCardElement(config.card) : 'hui-entities-card'; + let error; + let element; - if (tag === null) { - error = `Unknown card type encountered: "${config.card}".`; - } else if (!customElements.get(tag)) { - error = `Custom element doesn't exist: "${tag}".`; - if (!(tag in this._whenDefined)) { - this._whenDefined[tag] = customElements.whenDefined(tag) - .then(() => this._configChanged(this.config)); - } - } else if (!config.filter || !Array.isArray(config.filter)) { - error = 'No or incorrect filter.'; + if (!config.filter || !Array.isArray(config.filter)) { + error = 'Incorrect filter config.'; + } else if (!config.card) { + config.card = { type: 'entities' }; + } else if (!config.card.type) { + config.card.type = 'entities'; } + + if (error) { - tag = 'hui-error-card'; - cardConfig = { error }; + element = createCardElement(config, this.elementNotDefinedCallback, error); } else { - cardConfig = this._computeCardConfig(config); + element = createCardElement(config.card, this.elementNotDefinedCallback, null); + element.config = this._computeCardConfig(config); + element.hass = this.hass; } - - const element = document.createElement(tag); - element.config = cardConfig; - element.hass = this.hass; this.appendChild(element); } _hassChanged(hass) { const element = this.lastChild; - if (element) { - element.hass = hass; - element.config = this._computeCardConfig(this.config); - } + if (!element || element.tagName === 'HUI-ERROR-CARD') return; + + element.hass = hass; + element.config = this._computeCardConfig(this.config); } _computeCardConfig(config) { return Object.assign( {}, - config.card_config, + config.card, { entities: this._getEntities(this.hass, config.filter) } ); } + + elementNotDefinedCallback(tag) { + if (!(tag in this._whenDefined)) { + this._whenDefined[tag] = customElements.whenDefined(tag) + .then(() => this._configChanged(this.config)); + } + } } customElements.define('hui-entity-filter-card', HuiEntitiesCard); diff --git a/src/panels/lovelace/cards/hui-error-card.js b/src/panels/lovelace/cards/hui-error-card.js index 729da50a03..60dfecac56 100644 --- a/src/panels/lovelace/cards/hui-error-card.js +++ b/src/panels/lovelace/cards/hui-error-card.js @@ -9,23 +9,28 @@ class HuiErrorCard extends PolymerElement { display: block; background-color: red; color: white; - text-align: center; padding: 8px; } - [[config.error]] + [[error]] +
[[_toStr(config)]]
`; } static get properties() { return { - config: Object + config: Object, + error: String }; } getCardSize() { return 1; } + + _toStr(obj) { + return JSON.stringify(obj, null, 2); + } } customElements.define('hui-error-card', HuiErrorCard); diff --git a/src/panels/lovelace/common/compute-card-element.js b/src/panels/lovelace/common/compute-card-element.js deleted file mode 100644 index 722c71cd61..0000000000 --- a/src/panels/lovelace/common/compute-card-element.js +++ /dev/null @@ -1,38 +0,0 @@ -import '../cards/hui-camera-preview-card.js'; -import '../cards/hui-entities-card.js'; -import '../cards/hui-entity-filter-card.js'; -import '../cards/hui-glance-card'; -import '../cards/hui-history-graph-card.js'; -import '../cards/hui-markdown-card.js'; -import '../cards/hui-media-control-card.js'; -import '../cards/hui-entity-picture-card.js'; -import '../cards/hui-picture-glance-card'; -import '../cards/hui-plant-status-card.js'; -import '../cards/hui-weather-forecast-card'; -import '../cards/hui-error-card.js'; -import '../cards/hui-iframe-card.js'; - -const CARD_TYPES = [ - 'camera-preview', - 'entities', - 'entity-filter', - 'entity-picture', - 'glance', - 'history-graph', - 'iframe', - 'markdown', - 'media-control', - 'picture-glance', - 'plant-status', - 'weather-forecast' -]; -const CUSTOM_TYPE_PREFIX = 'custom:'; - -export default function computeCardElement(type) { - if (CARD_TYPES.includes(type)) { - return `hui-${type}-card`; - } else if (type.startsWith(CUSTOM_TYPE_PREFIX)) { - return type.substr(CUSTOM_TYPE_PREFIX.length); - } - return null; -} diff --git a/src/panels/lovelace/common/create-card-element.js b/src/panels/lovelace/common/create-card-element.js new file mode 100644 index 0000000000..65021f79dd --- /dev/null +++ b/src/panels/lovelace/common/create-card-element.js @@ -0,0 +1,61 @@ +import '../cards/hui-camera-preview-card.js'; +import '../cards/hui-entities-card.js'; +import '../cards/hui-entity-filter-card.js'; +import '../cards/hui-glance-card'; +import '../cards/hui-history-graph-card.js'; +import '../cards/hui-iframe-card.js'; +import '../cards/hui-markdown-card.js'; +import '../cards/hui-media-control-card.js'; +import '../cards/hui-entity-picture-card.js'; +import '../cards/hui-picture-glance-card'; +import '../cards/hui-plant-status-card.js'; +import '../cards/hui-weather-forecast-card'; +import '../cards/hui-error-card.js'; + +const CARD_TYPES = [ + 'camera-preview', + 'entities', + 'entity-filter', + 'entity-picture', + 'glance', + 'history-graph', + 'iframe', + 'markdown', + 'media-control', + 'picture-glance', + 'plant-status', + 'weather-forecast' +]; + +const CUSTOM_TYPE_PREFIX = 'custom:'; + +export default function +createCardElement(config, elementNotDefinedCallback = null, invalidConfig = null) { + let error = invalidConfig; + let tag; + + if (!error && config && typeof config === 'object' && config.type) { + if (CARD_TYPES.includes(config.type)) { + tag = `hui-${config.type}-card`; + } else if (config.type.startsWith(CUSTOM_TYPE_PREFIX)) { + tag = config.type.substr(CUSTOM_TYPE_PREFIX.length); + } + + if (tag) { + if (!customElements.get(tag)) { + error = 'Custom element doesn\'t exist.'; + if (elementNotDefinedCallback) elementNotDefinedCallback(tag); + } + } else { + error = 'Unknown card type encountered.'; + } + } else { + error = 'No card type configured.'; + } + + if (error) tag = 'hui-error-card'; + const element = document.createElement(tag); + if (error) element.error = error; + element.config = config; + return element; +} diff --git a/src/panels/lovelace/hui-view.js b/src/panels/lovelace/hui-view.js index 36f2c47a65..8e943f32ff 100644 --- a/src/panels/lovelace/hui-view.js +++ b/src/panels/lovelace/hui-view.js @@ -2,7 +2,7 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import applyThemesOnElement from '../../common/dom/apply_themes_on_element.js'; -import computeCardElement from './common/compute-card-element.js'; +import createCardElement from './common/create-card-element'; class HUIView extends PolymerElement { static get template() { @@ -77,35 +77,14 @@ class HUIView extends PolymerElement { super(); this._elements = []; this._whenDefined = {}; + this.elementNotDefinedCallback = this.elementNotDefinedCallback.bind(this); } _getElements(cards) { const elements = []; for (let i = 0; i < cards.length; i++) { - let error = null; - let cardConfig = cards[i]; - let tag; - if (!cardConfig.type) { - error = 'Card type not configured.'; - } else { - tag = computeCardElement(cardConfig.type); - if (tag === null) { - error = `Unknown card type encountered: "${cardConfig.type}".`; - } else if (!customElements.get(tag)) { - error = `Custom element doesn't exist: "${tag}".`; - if (!(tag in this._whenDefined)) { - this._whenDefined[tag] = customElements.whenDefined(tag) - .then(() => this._configChanged()); - } - } - } - if (error) { - tag = 'hui-error-card'; - cardConfig = { error }; - } - const element = document.createElement(tag); - element.config = cardConfig; + const element = createCardElement(cards[i], this.elementNotDefinedCallback, null); element.hass = this.hass; elements.push(element); } @@ -180,6 +159,13 @@ class HUIView extends PolymerElement { this._elements[i].hass = hass; } } + + elementNotDefinedCallback(tag) { + if (!(tag in this._whenDefined)) { + this._whenDefined[tag] = customElements.whenDefined(tag) + .then(() => this._configChanged()); + } + } } customElements.define('hui-view', HUIView);