diff --git a/src/components/entity/state-info.js b/src/components/entity/state-info.js index ef8c34627f..f0dddbd9b0 100644 --- a/src/components/entity/state-info.js +++ b/src/components/entity/state-info.js @@ -82,13 +82,12 @@ class StateInfo extends PolymerElement { }, hass: Object, stateObj: Object, - inDialog: Boolean, - overrideName: String + inDialog: Boolean }; } computeStateName(stateObj) { - return this.overrideName || computeStateName(stateObj); + return computeStateName(stateObj); } } diff --git a/src/panels/lovelace/cards/hui-entities-card.js b/src/panels/lovelace/cards/hui-entities-card.js index b4335932df..9cd625f818 100644 --- a/src/panels/lovelace/cards/hui-entities-card.js +++ b/src/panels/lovelace/cards/hui-entities-card.js @@ -2,20 +2,16 @@ 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 processConfigEntities from '../common/process-config-entities.js'; - import '../../../components/ha-card.js'; import '../components/hui-entities-toggle.js'; -// just importing this now as shortcut to import correct state-card-* -import '../../../state-summary/state-card-content.js'; +import createEntityRowElement from '../common/create-entity-row-element.js'; +import processConfigEntities from '../common/process-config-entities.js'; +import computeDomain from '../../../common/entity/compute_domain.js'; +import { DOMAINS_HIDE_MORE_INFO } from '../../../common/const.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 */ @@ -70,7 +66,7 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) { type: Object, observer: '_hassChanged', }, - _config: Object, + _config: Object }; } @@ -117,14 +113,13 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) { for (const entity of entities) { const entityId = entity.entity; - - const element = createEntityRowElement(entity, this.hass); + const element = createEntityRowElement(entity); if (entityId && !DOMAINS_HIDE_MORE_INFO.includes(computeDomain(entityId))) { element.classList.add('state-card-dialog'); element.addEventListener('click', () => this.fire('hass-more-info', { entityId })); } - - this._elements.push({ entityId, element }); + element.hass = this.hass; + this._elements.push(element); const container = document.createElement('div'); container.appendChild(element); root.appendChild(container); @@ -132,12 +127,9 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) { } _hassChanged(hass) { - for (let i = 0; i < this._elements.length; i++) { - const { entityId, element } = this._elements[i]; - const stateObj = hass.states[entityId]; - element.stateObj = stateObj; + this._elements.forEach((element) => { element.hass = hass; - } + }); } } diff --git a/src/panels/lovelace/common/create-entity-row-element.js b/src/panels/lovelace/common/create-entity-row-element.js index 4497a9b577..26fcdecdf5 100644 --- a/src/panels/lovelace/common/create-entity-row-element.js +++ b/src/panels/lovelace/common/create-entity-row-element.js @@ -1,12 +1,36 @@ import fireEvent from '../../../common/dom/fire_event.js'; -import stateCardType from '../../../common/entity/state_card_type.js'; +import '../entity-rows/hui-cover-entity-row.js'; +import '../entity-rows/hui-input-number-entity-row.js'; +import '../entity-rows/hui-input-select-entity-row.js'; +import '../entity-rows/hui-input-text-entity-row.js'; +import '../entity-rows/hui-lock-entity-row.js'; +import '../entity-rows/hui-scene-entity-row.js'; +import '../entity-rows/hui-script-entity-row.js'; +import '../entity-rows/hui-text-entity-row.js'; +import '../entity-rows/hui-timer-entity-row.js'; +import '../entity-rows/hui-toggle-entity-row.js'; import createErrorCardConfig from './create-error-card-config.js'; const CUSTOM_TYPE_PREFIX = 'custom:'; +const DOMAIN_TO_ELEMENT_TYPE = { + cover: 'cover', + fan: 'toggle', + group: 'toggle', + input_boolean: 'toggle', + input_number: 'input-number', + input_select: 'input-select', + input_text: 'input-text', + light: 'toggle', + lock: 'lock', + scene: 'scene', + script: 'script', + timer: 'timer', + switch: 'toggle' +}; -function _createElement(tag, config, stateObj, hass) { +function _createElement(tag, config) { const element = document.createElement(tag); try { if ('setConfig' in element) element.setConfig(config); @@ -17,12 +41,6 @@ function _createElement(tag, config, stateObj, hass) { return _createErrorElement(err.message, config); } - element.stateObj = stateObj; - element.hass = hass; - if (config.name) { - element.overrideName = config.name; - } - return element; } @@ -30,25 +48,19 @@ function _createErrorElement(error, config) { return _createElement('hui-error-card', createErrorCardConfig(error, config)); } -export default function createEntityRowElement(config, hass) { +export default function createEntityRowElement(config) { let tag; - if (!config || typeof config !== 'object') { + if (!config || typeof config !== 'object' || !config.entity) { 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); + return _createElement(tag, config); } const element = _createErrorElement(`Custom element doesn't exist: ${tag}.`, config); @@ -58,7 +70,8 @@ export default function createEntityRowElement(config, hass) { return element; } - tag = stateObj ? `state-card-${stateCardType(hass, stateObj)}` : 'state-card-display'; + const domain = config.entity.split('.', 1)[0]; + tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || 'text'}-entity-row`; - return _createElement(tag, config, stateObj, hass); + return _createElement(tag, config); } diff --git a/src/panels/lovelace/components/hui-generic-entity-row.js b/src/panels/lovelace/components/hui-generic-entity-row.js new file mode 100644 index 0000000000..f6c9a5bdce --- /dev/null +++ b/src/panels/lovelace/components/hui-generic-entity-row.js @@ -0,0 +1,92 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import '../../../components/entity/state-badge.js'; +import '../../../components/ha-relative-time.js'; + +import computeStateName from '../../../common/entity/compute_state_name.js'; + +import EventsMixin from '../../../mixins/events-mixin.js'; + +/* + * @appliesMixin EventsMixin + */ +class HuiGenericEntityRow extends EventsMixin(PolymerElement) { + static get template() { + return html` + + + + + + [[_computeName(config.name, _stateObj)]] + + + + [[_stateObj.entity_id]] + + + + + + + + + + + + + Entity not available: [[config.entity]] + + + `; + } + + static get properties() { + return { + hass: Object, + config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, config.entity)' + } + }; + } + + _equals(a, b) { + return a === b; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + _computeName(name, stateObj) { + return name || computeStateName(stateObj); + } +} +customElements.define('hui-generic-entity-row', HuiGenericEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-cover-entity-row.js b/src/panels/lovelace/entity-rows/hui-cover-entity-row.js new file mode 100644 index 0000000000..0e2a50363e --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-cover-entity-row.js @@ -0,0 +1,56 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import '../components/hui-generic-entity-row.js'; +import '../../../components/ha-cover-controls.js'; +import '../../../components/ha-cover-tilt-controls.js'; +import CoverEntity from '../../../util/cover-model.js'; + +class HuiCoverEntityRow extends PolymerElement { + static get template() { + return html` + + + + + + + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)' + }, + _entityObj: { + type: Object, + computed: '_computeEntityObj(hass, _stateObj)' + }, + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + _computeEntityObj(hass, stateObj) { + return stateObj ? new CoverEntity(hass, stateObj) : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } +} +customElements.define('hui-cover-entity-row', HuiCoverEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.js b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.js new file mode 100644 index 0000000000..9788c034f7 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.js @@ -0,0 +1,147 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-input/paper-input.js'; +import '@polymer/paper-slider/paper-slider.js'; +import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js'; +import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js'; + +import '../components/hui-generic-entity-row.js'; + +class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], PolymerElement) { + static get template() { + return html` + + + + + + + [[_value]] [[_stateObj.attributes.unit_of_measurement]] + + + + + + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)', + observer: '_stateObjChanged' + }, + _min: { + type: Number, + value: 0 + }, + _max: { + type: Number, + value: 100 + }, + _step: Number, + _value: Number + }; + } + + ready() { + super.ready(); + if (typeof ResizeObserver === 'function') { + const ro = new ResizeObserver((entries) => { + entries.forEach(() => { + this._hiddenState(); + }); + }); + ro.observe(this.$.input_number_card); + } else { + this.addEventListener('iron-resize', this._hiddenState); + } + } + + _equals(a, b) { + return a === b; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _hiddenState() { + if (this._stateObj.attributes.mode !== 'slider') return; + const sliderwidth = this.shadowRoot.querySelector('paper-slider').offsetWidth; + const stateElement = this.shadowRoot.querySelector('.state'); + if (sliderwidth < 100) { + stateElement.style.display = 'none'; + } else if (sliderwidth >= 145) { + stateElement.style.display = 'inline'; + } + } + + _stateObjChanged(stateObj, oldStateObj) { + this.setProperties({ + _min: Number(stateObj.attributes.min), + _max: Number(stateObj.attributes.max), + _step: Number(stateObj.attributes.step), + _value: Number(stateObj.state) + }); + if (oldStateObj && stateObj.attributes.mode === 'slider' && oldStateObj.attributes.mode !== 'slider') { + this._hiddenState(); + } + } + + _selectedValueChanged() { + if (this._value === Number(this._stateObj.state)) return; + + this.hass.callService('input_number', 'set_value', { + value: this._value, + entity_id: this._stateObj.entity_id, + }); + } +} +customElements.define('hui-input-number-entity-row', HuiInputNumberEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.js b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.js new file mode 100644 index 0000000000..ca98eb40d3 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.js @@ -0,0 +1,101 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js'; +import '@polymer/paper-item/paper-item.js'; +import '@polymer/paper-listbox/paper-listbox.js'; + +import '../../../components/entity/state-badge.js'; + +import computeStateName from '../../../common/entity/compute_state_name.js'; + +import EventsMixin from '../../../mixins/events-mixin.js'; + +/* + * @appliesMixin EventsMixin + */ +class HuiInputSelectEntityRow extends EventsMixin(PolymerElement) { + static get template() { + return html` + + + + + + + [[item]] + + + + + + + Entity not available: [[_config.entity]] + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)' + }, + _selected: { + type: String, + observer: '_selectedChanged', + }, + }; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + _computeName(name, stateObj) { + return name || computeStateName(stateObj); + } + + _computeSelected(stateObj) { + return stateObj.attributes.options.indexOf(stateObj.state); + } + + _selectedChanged(option) { + // Selected Option will transition to '' before transitioning to new value + if (option === '' || option === this._stateObj.state) { + return; + } + this.hass.callService('input_select', 'select_option', { + option: option, + entity_id: this._stateObj.entity_id, + }); + } + + _stopPropagation(ev) { + ev.stopPropagation(); + } +} +customElements.define('hui-input-select-entity-row', HuiInputSelectEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-input-text-entity-row.js b/src/panels/lovelace/entity-rows/hui-input-text-entity-row.js new file mode 100644 index 0000000000..f7229fc28b --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-input-text-entity-row.js @@ -0,0 +1,67 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-input/paper-input.js'; + +import '../components/hui-generic-entity-row.js'; + +class HuiInputTextEntityRow extends PolymerElement { + static get template() { + return html` + + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)', + observer: '_stateObjChanged', + }, + _value: String + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _stateObjChanged(stateObj) { + this._value = stateObj.state; + } + + _selectedValueChanged() { + if (this._value === this._stateObj.state) { + return; + } + this.hass.callService('input_text', 'set_value', { + value: this._value, + entity_id: this._stateObj.entity_id, + }); + } +} +customElements.define('hui-input-text-entity-row', HuiInputTextEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-lock-entity-row.js b/src/panels/lovelace/entity-rows/hui-lock-entity-row.js new file mode 100644 index 0000000000..ff71a74380 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-lock-entity-row.js @@ -0,0 +1,67 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-button/paper-button.js'; + +import '../components/hui-generic-entity-row.js'; + +import LocalizeMixin from '../../../mixins/localize-mixin.js'; + +/* + * @appliesMixin LocalizeMixin + */ +class HuiLockEntityRow extends LocalizeMixin(PolymerElement) { + static get template() { + return html` + + + + [[_computeButtonTitle(_stateObj.state)]] + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)' + } + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _computeButtonTitle(state) { + return state === 'locked' ? + this.localize('ui.card.lock.unlock') : this.localize('ui.card.lock.lock'); + } + + _callService(ev) { + ev.stopPropagation(); + const stateObj = this._stateObj; + this.hass.callService('lock', stateObj.state === 'locked' ? + 'unlock' : 'lock', { entity_id: stateObj.entity_id }); + } +} +customElements.define('hui-lock-entity-row', HuiLockEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-scene-entity-row.js b/src/panels/lovelace/entity-rows/hui-scene-entity-row.js new file mode 100644 index 0000000000..c5fb0a954f --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-scene-entity-row.js @@ -0,0 +1,56 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-button/paper-button.js'; + +import '../components/hui-generic-entity-row.js'; + +import LocalizeMixin from '../../../mixins/localize-mixin.js'; + +/* + * @appliesMixin LocalizeMixin + */ +class HuiSceneEntityRow extends LocalizeMixin(PolymerElement) { + static get template() { + return html` + + + + [[localize('ui.card.scene.activate')]] + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _callService(ev) { + ev.stopPropagation(); + this.hass.callService('scene', 'turn_on', { entity_id: this._config.entity }); + } +} +customElements.define('hui-scene-entity-row', HuiSceneEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-script-entity-row.js b/src/panels/lovelace/entity-rows/hui-script-entity-row.js new file mode 100644 index 0000000000..0cbb5f5931 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-script-entity-row.js @@ -0,0 +1,64 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-button/paper-button.js'; + +import '../components/hui-generic-entity-row.js'; +import '../../../components/entity/ha-entity-toggle.js'; + +import LocalizeMixin from '../../../mixins/localize-mixin.js'; + +/* + * @appliesMixin LocalizeMixin + */ +class HuiScriptEntityRow extends LocalizeMixin(PolymerElement) { + static get template() { + return html` + + + + + + + [[localize('ui.card.script.execute')]] + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)' + } + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _callService(ev) { + ev.stopPropagation(); + this.hass.callService('script', 'turn_on', { entity_id: this._config.entity }); + } +} +customElements.define('hui-script-entity-row', HuiScriptEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-text-entity-row.js b/src/panels/lovelace/entity-rows/hui-text-entity-row.js new file mode 100644 index 0000000000..6f5debe34e --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-text-entity-row.js @@ -0,0 +1,53 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import '../components/hui-generic-entity-row.js'; + +import computeStateDisplay from '../../../common/entity/compute_state_display.js'; + +import LocalizeMixin from '../../../mixins/localize-mixin.js'; + +/* + * @appliesMixin LocalizeMixin + */ +class HuiTextEntityRow extends LocalizeMixin(PolymerElement) { + static get template() { + return html` + + + [[_computeState(_stateObj)]] + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)' + } + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } + + _computeState(stateObj) { + return computeStateDisplay(this.localize, stateObj); + } +} +customElements.define('hui-text-entity-row', HuiTextEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.js b/src/panels/lovelace/entity-rows/hui-timer-entity-row.js new file mode 100644 index 0000000000..bd65c5ba86 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.js @@ -0,0 +1,92 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import '../components/hui-generic-entity-row.js'; + +import timerTimeRemaining from '../../../common/entity/timer_time_remaining.js'; +import secondsToDuration from '../../../common/datetime/seconds_to_duration.js'; + +class HuiTimerEntityRow extends PolymerElement { + static get template() { + return html` + + + [[_computeDisplay(_stateObj, _timeRemaining)]] + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object, + _stateObj: { + type: Object, + computed: '_computeStateObj(hass.states, _config.entity)', + observer: '_stateObjChanged' + }, + _timeRemaining: Number + }; + } + + disconnectedCallback() { + super.disconnectedCallback(); + this._clearInterval(); + } + + _stateObjChanged(stateObj) { + if (stateObj) { + this._startInterval(stateObj); + } else { + this._clearInterval(); + } + } + + _clearInterval() { + if (this._updateRemaining) { + clearInterval(this._updateRemaining); + this._updateRemaining = null; + } + } + + _startInterval(stateObj) { + this._clearInterval(); + this._calculateRemaining(stateObj); + + if (stateObj.state === 'active') { + this._updateRemaining = setInterval(() => this._calculateRemaining(this._stateObj), 1000); + } + } + + _calculateRemaining(stateObj) { + this._timeRemaining = timerTimeRemaining(stateObj); + } + + _computeDisplay(stateObj, time) { + if (stateObj.state === 'idle' || time === 0) return stateObj.state; + + let display = secondsToDuration(time); + + if (stateObj.state === 'paused') { + display += ' (paused)'; + } + + return display; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } +} +customElements.define('hui-timer-entity-row', HuiTimerEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-toggle-entity-row.js b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.js new file mode 100644 index 0000000000..dd412595d3 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.js @@ -0,0 +1,37 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + +import '../components/hui-generic-entity-row.js'; +import '../../../components/entity/ha-entity-toggle.js'; + +class HuiToggleEntityRow extends PolymerElement { + static get template() { + return html` + + + + `; + } + + static get properties() { + return { + hass: Object, + _config: Object + }; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + setConfig(config) { + if (!config || !config.entity) { + throw new Error('Entity not configured.'); + } + this._config = config; + } +} +customElements.define('hui-toggle-entity-row', HuiToggleEntityRow); diff --git a/src/panels/lovelace/hui-unused-entities.js b/src/panels/lovelace/hui-unused-entities.js index 28a88264e5..b9ba92197f 100644 --- a/src/panels/lovelace/hui-unused-entities.js +++ b/src/panels/lovelace/hui-unused-entities.js @@ -37,7 +37,8 @@ class HuiUnusedEntities extends PolymerElement { const root = this.$.root; if (root.lastChild) root.removeChild(root.lastChild); - const entities = computeUnusedEntities(this.hass, config); + const entities = computeUnusedEntities(this.hass, config).map(entity => + ({ entity, secondary_info: 'entity-id' })); const cardConfig = { type: 'entities', title: 'Unused entities', diff --git a/src/state-summary/state-card-climate.js b/src/state-summary/state-card-climate.js index 109f4e7107..8c78655115 100644 --- a/src/state-summary/state-card-climate.js +++ b/src/state-summary/state-card-climate.js @@ -30,12 +30,11 @@ class StateCardClimate extends PolymerElement { static get stateInfoTemplate() { return html` - - + `; } @@ -46,8 +45,7 @@ class StateCardClimate extends PolymerElement { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } } diff --git a/src/state-summary/state-card-configurator.js b/src/state-summary/state-card-configurator.js index 4bb44b70af..34cf7a79a9 100644 --- a/src/state-summary/state-card-configurator.js +++ b/src/state-summary/state-card-configurator.js @@ -38,12 +38,11 @@ class StateCardConfigurator extends LocalizeMixin(PolymerElement) { static get stateInfoTemplate() { return html` - - + `; } @@ -54,8 +53,7 @@ class StateCardConfigurator extends LocalizeMixin(PolymerElement) { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-cover.js b/src/state-summary/state-card-cover.js index a94ddbcd1f..d25196b6be 100644 --- a/src/state-summary/state-card-cover.js +++ b/src/state-summary/state-card-cover.js @@ -29,12 +29,11 @@ class StateCardCover extends PolymerElement { static get stateInfoTemplate() { return html` - - + `; } @@ -49,8 +48,7 @@ class StateCardCover extends PolymerElement { entityObj: { type: Object, computed: 'computeEntityObj(hass, stateObj)', - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-display.js b/src/state-summary/state-card-display.js index 57fb7743cf..9ed0cd86cd 100644 --- a/src/state-summary/state-card-display.js +++ b/src/state-summary/state-card-display.js @@ -46,12 +46,11 @@ class StateCardDisplay extends LocalizeMixin(PolymerElement) { static get stateInfoTemplate() { return html` - - + `; } @@ -62,8 +61,7 @@ class StateCardDisplay extends LocalizeMixin(PolymerElement) { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-input_number.js b/src/state-summary/state-card-input_number.js index 115e57e0d4..a02ac579b5 100644 --- a/src/state-summary/state-card-input_number.js +++ b/src/state-summary/state-card-input_number.js @@ -51,12 +51,11 @@ class StateCardInputNumber extends mixinBehaviors([ static get stateInfoTemplate() { return html` - - + `; } @@ -105,16 +104,9 @@ class StateCardInputNumber extends mixinBehaviors([ type: Number, value: 3 }, - step: { - type: Number, - }, - value: { - type: Number, - }, - mode: { - type: String, - }, - overrideName: String + step: Number, + value: Number, + mode: String }; } diff --git a/src/state-summary/state-card-input_select.js b/src/state-summary/state-card-input_select.js index 2b8fbd6d36..412a9ee971 100644 --- a/src/state-summary/state-card-input_select.js +++ b/src/state-summary/state-card-input_select.js @@ -59,13 +59,12 @@ class StateCardInputSelect extends PolymerElement { selectedOption: { type: String, observer: 'selectedOptionChanged', - }, - overrideName: String + } }; } _computeStateName(stateObj) { - return this.overrideName || computeStateName(stateObj); + return computeStateName(stateObj); } computeSelected(stateObj) { diff --git a/src/state-summary/state-card-input_text.js b/src/state-summary/state-card-input_text.js index f0778b6c4a..133fde68ae 100644 --- a/src/state-summary/state-card-input_text.js +++ b/src/state-summary/state-card-input_text.js @@ -25,12 +25,11 @@ class StateCardInputText extends PolymerElement { static get stateInfoTemplate() { return html` - - + `; } @@ -50,8 +49,7 @@ class StateCardInputText extends PolymerElement { }, pattern: String, - value: String, - overrideName: String + value: String }; } diff --git a/src/state-summary/state-card-lock.js b/src/state-summary/state-card-lock.js index 138fcab64e..6a06c67156 100644 --- a/src/state-summary/state-card-lock.js +++ b/src/state-summary/state-card-lock.js @@ -38,8 +38,7 @@ class StateCardLock extends LocalizeMixin(PolymerElement) { hass="[[hass]]" state-obj="[[stateObj]]" in-dialog="[[inDialog]]" - override-name="[[overrideName]]"> - + > `; } @@ -54,8 +53,7 @@ class StateCardLock extends LocalizeMixin(PolymerElement) { type: Boolean, value: false, }, - isLocked: Boolean, - overrideName: String + isLocked: Boolean }; } diff --git a/src/state-summary/state-card-media_player.js b/src/state-summary/state-card-media_player.js index f751d59c0c..53dfbc3842 100644 --- a/src/state-summary/state-card-media_player.js +++ b/src/state-summary/state-card-media_player.js @@ -53,12 +53,11 @@ class StateCardMediaPlayer extends LocalizeMixin(PolymerElement) { static get stateInfoTemplate() { return html` - - + `; } @@ -73,8 +72,7 @@ class StateCardMediaPlayer extends LocalizeMixin(PolymerElement) { playerObj: { type: Object, computed: 'computePlayerObj(hass, stateObj)', - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-scene.js b/src/state-summary/state-card-scene.js index f64374dfea..84b95b085d 100644 --- a/src/state-summary/state-card-scene.js +++ b/src/state-summary/state-card-scene.js @@ -32,12 +32,11 @@ class StateCardScene extends LocalizeMixin(PolymerElement) { static get stateInfoTemplate() { return html` - - + `; } @@ -48,8 +47,7 @@ class StateCardScene extends LocalizeMixin(PolymerElement) { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-script.js b/src/state-summary/state-card-script.js index 3d39d854ad..6eb5158d48 100644 --- a/src/state-summary/state-card-script.js +++ b/src/state-summary/state-card-script.js @@ -43,12 +43,11 @@ class StateCardScript extends LocalizeMixin(PolymerElement) { static get stateInfoTemplate() { return html` - - + `; } @@ -59,8 +58,7 @@ class StateCardScript extends LocalizeMixin(PolymerElement) { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-timer.js b/src/state-summary/state-card-timer.js index cea5e627ca..6944f5a9f6 100644 --- a/src/state-summary/state-card-timer.js +++ b/src/state-summary/state-card-timer.js @@ -7,12 +7,8 @@ import '../components/entity/state-info.js'; import timerTimeRemaining from '../common/entity/timer_time_remaining.js'; import secondsToDuration from '../common/datetime/seconds_to_duration.js'; -import LocalizeMixin from '../mixins/localize-mixin.js'; -/* - * @appliesMixin LocalizeMixin - */ -class StateCardTimer extends LocalizeMixin(PolymerElement) { +class StateCardTimer extends PolymerElement { static get template() { return html` @@ -36,12 +32,11 @@ class StateCardTimer extends LocalizeMixin(PolymerElement) { static get stateInfoTemplate() { return html` - - + `; } @@ -56,8 +51,7 @@ class StateCardTimer extends LocalizeMixin(PolymerElement) { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } diff --git a/src/state-summary/state-card-toggle.js b/src/state-summary/state-card-toggle.js index 84474ea183..72d777585e 100644 --- a/src/state-summary/state-card-toggle.js +++ b/src/state-summary/state-card-toggle.js @@ -25,12 +25,11 @@ class StateCardToggle extends PolymerElement { static get stateInfoTemplate() { return html` - - + `; } @@ -41,8 +40,7 @@ class StateCardToggle extends PolymerElement { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } } diff --git a/src/state-summary/state-card-weblink.js b/src/state-summary/state-card-weblink.js index 583e140699..6f68b85873 100644 --- a/src/state-summary/state-card-weblink.js +++ b/src/state-summary/state-card-weblink.js @@ -40,8 +40,7 @@ class StateCardWeblink extends PolymerElement { inDialog: { type: Boolean, value: false, - }, - overrideName: String + } }; } @@ -51,7 +50,7 @@ class StateCardWeblink extends PolymerElement { } _computeStateName(stateObj) { - return this.overrideName || computeStateName(stateObj); + return computeStateName(stateObj); } onTap(ev) {