From f58c612018046b2653439cbb98fe3415835b7215 Mon Sep 17 00:00:00 2001 From: quthla Date: Sat, 7 Jul 2018 21:04:11 +0200 Subject: [PATCH] Lovelace custom ui (#1404) * Lovelace custom ui * Allow ForOf * Move code --- .eslintrc-hound.json | 3 +- .../lovelace/cards/hui-entities-card.js | 24 +++---- .../common/create-entity-row-element.js | 64 +++++++++++++++++++ 3 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 src/panels/lovelace/common/create-entity-row-element.js diff --git a/.eslintrc-hound.json b/.eslintrc-hound.json index dc71cc4267..b6762294d0 100644 --- a/.eslintrc-hound.json +++ b/.eslintrc-hound.json @@ -71,7 +71,8 @@ "react/jsx-curly-spacing": 2, "react/jsx-no-undef": 2, "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2 + "react/jsx-uses-vars": 2, + "no-restricted-syntax": [0, "ForOfStatement"] }, "plugins": [ "react" diff --git a/src/panels/lovelace/cards/hui-entities-card.js b/src/panels/lovelace/cards/hui-entities-card.js index c99cfeeb6f..b4335932df 100644 --- a/src/panels/lovelace/cards/hui-entities-card.js +++ b/src/panels/lovelace/cards/hui-entities-card.js @@ -2,9 +2,6 @@ import '@polymer/iron-flex-layout/iron-flex-layout-classes.js'; import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js'; -import stateCardType from '../../../common/entity/state_card_type.js'; -import computeDomain from '../../../common/entity/compute_domain.js'; -import { DOMAINS_HIDE_MORE_INFO } from '../../../common/const.js'; import processConfigEntities from '../common/process-config-entities.js'; import '../../../components/ha-card.js'; @@ -15,6 +12,10 @@ import '../../../state-summary/state-card-content.js'; import EventsMixin from '../../../mixins/events-mixin.js'; +import createEntityRowElement from '../common/create-entity-row-element.js'; +import { DOMAINS_HIDE_MORE_INFO } from '../../../common/const.js'; +import computeDomain from '../../../common/entity/compute_domain.js'; + /* * @appliesMixin EventsMixin */ @@ -114,22 +115,15 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) { this._elements = []; - for (let i = 0; i < entities.length; i++) { - const entity = entities[i]; + for (const entity of entities) { const entityId = entity.entity; - if (!(entityId in this.hass.states)) continue; - const stateObj = this.hass.states[entityId]; - const tag = stateObj ? `state-card-${stateCardType(this.hass, stateObj)}` : 'state-card-display'; - const element = document.createElement(tag); - if (!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(entityId))) { + + const element = createEntityRowElement(entity, this.hass); + if (entityId && !DOMAINS_HIDE_MORE_INFO.includes(computeDomain(entityId))) { element.classList.add('state-card-dialog'); element.addEventListener('click', () => this.fire('hass-more-info', { entityId })); } - element.stateObj = stateObj; - element.hass = this.hass; - if (entity.name) { - element.overrideName = entity.name; - } + this._elements.push({ entityId, element }); const container = document.createElement('div'); container.appendChild(element); diff --git a/src/panels/lovelace/common/create-entity-row-element.js b/src/panels/lovelace/common/create-entity-row-element.js new file mode 100644 index 0000000000..4497a9b577 --- /dev/null +++ b/src/panels/lovelace/common/create-entity-row-element.js @@ -0,0 +1,64 @@ +import fireEvent from '../../../common/dom/fire_event.js'; + +import stateCardType from '../../../common/entity/state_card_type.js'; + +import createErrorCardConfig from './create-error-card-config.js'; + +const CUSTOM_TYPE_PREFIX = 'custom:'; + +function _createElement(tag, config, stateObj, hass) { + const element = document.createElement(tag); + try { + if ('setConfig' in element) element.setConfig(config); + } catch (err) { + // eslint-disable-next-line + console.error(tag, err); + // eslint-disable-next-line + return _createErrorElement(err.message, config); + } + + element.stateObj = stateObj; + element.hass = hass; + if (config.name) { + element.overrideName = config.name; + } + + return element; +} + +function _createErrorElement(error, config) { + return _createElement('hui-error-card', createErrorCardConfig(error, config)); +} + +export default function createEntityRowElement(config, hass) { + let tag; + + if (!config || typeof config !== 'object') { + return _createErrorElement('Invalid config given.', config); + } + + const entityId = config.entity; + if (!(entityId in hass.states)) { + return _createErrorElement('Entity not found.', config); + } + + const type = config.type || 'default'; + const stateObj = hass.states[entityId]; + if (type.startsWith(CUSTOM_TYPE_PREFIX)) { + tag = type.substr(CUSTOM_TYPE_PREFIX.length); + + if (customElements.get(tag)) { + return _createElement(tag, config, stateObj, hass); + } + const element = _createErrorElement(`Custom element doesn't exist: ${tag}.`, config); + + customElements.whenDefined(tag) + .then(() => fireEvent(element, 'rebuild-view')); + + return element; + } + + tag = stateObj ? `state-card-${stateCardType(hass, stateObj)}` : 'state-card-display'; + + return _createElement(tag, config, stateObj, hass); +}