diff --git a/src/common/const.js b/src/common/const.js index ddd57cda75..f9ee04ec30 100644 --- a/src/common/const.js +++ b/src/common/const.js @@ -60,6 +60,14 @@ export const DOMAINS_MORE_INFO_NO_HISTORY = [ 'scene', ]; +/** States that we consider "on". */ +export const STATES_ON = [ + 'home', + 'locked', + 'on', + 'open', +]; + /** States that we consider "off". */ export const STATES_OFF = [ 'closed', diff --git a/src/panels/lovelace/hui-picture-glance-card.js b/src/panels/lovelace/hui-picture-glance-card.js new file mode 100644 index 0000000000..5b6dbf217d --- /dev/null +++ b/src/panels/lovelace/hui-picture-glance-card.js @@ -0,0 +1,188 @@ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { PolymerElement } from '@polymer/polymer/polymer-element.js'; +import '@polymer/paper-icon-button/paper-icon-button.js'; + +import '../../components/ha-card.js'; + +import { STATES_ON } from '../../common/const.js'; +import computeDomain from '../../common/entity/compute_domain.js'; +import computeStateDisplay from '../../common/entity/compute_state_display.js'; +import computeStateName from '../../common/entity/compute_state_name.js'; +import stateIcon from '../../common/entity/state_icon.js'; + +import EventsMixin from '../../mixins/events-mixin.js'; +import LocalizeMixin from '../../mixins/localize-mixin.js'; + +const DOMAINS_FORCE_DIALOG = ['binary_sensor', 'device_tracker', 'sensor']; + +/* + * @appliesMixin EventsMixin + * @appliesMixin LocalizeMixin + */ +class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) { + static get template() { + return html` + + + + +
+
[[config.title]]
+
+ +
+
+ +
+
+ +
+ `; + } + + static get properties() { + return { + hass: Object, + config: { + type: Object, + observer: '_configChanged' + }, + _entitiesDialog: Array, + _entitiesService: Array, + _error: String + }; + } + + getCardSize() { + return 3; + } + + _configChanged(config) { + let dialog = []; + let service = []; + let _error = null; + if (config && config.entities && Array.isArray(config.entities) && config.image) { + if (config.force_dialog) { + dialog = config.entities; + } else { + dialog = config.entities + .filter(entity => DOMAINS_FORCE_DIALOG.includes(computeDomain(entity))); + service = config.entities.filter(entity => !dialog.includes(entity)); + } + } else { + _error = 'Error in card configuration.'; + } + this.setProperties({ + _entitiesDialog: dialog, + _entitiesService: service, + _error + }); + } + + _showEntity(entityId, states) { + return entityId in states; + } + + _computeIcon(entityId, states) { + return stateIcon(states[entityId]); + } + + _computeClass(entityId, states) { + return STATES_ON.includes(states[entityId].state) ? 'state-on' : ''; + } + + _computeTooltip(entityId, states) { + return `${computeStateName(states[entityId])}: ${computeStateDisplay(this.localize, states[entityId])}`; + } + + _openDialog(ev) { + this.fire('hass-more-info', { entityId: ev.model.item }); + } + + _callService(ev) { + const entityId = ev.model.item; + const domain = computeDomain(entityId); + const isOn = STATES_ON.includes(this.hass.states[entityId].state); + let service; + switch (domain) { + case 'lock': + service = isOn ? 'unlock' : 'lock'; + break; + case 'cover': + service = isOn ? 'close' : 'open'; + break; + case 'scene': + service = 'turn_on'; + break; + default: + service = isOn ? 'turn_off' : 'turn_on'; + } + this.hass.callService(domain, service, { entity_id: entityId }); + } +} + +customElements.define('hui-picture-glance-card', HuiPictureGlanceCard); diff --git a/src/panels/lovelace/hui-view.js b/src/panels/lovelace/hui-view.js index b0a03ef743..09facc3659 100644 --- a/src/panels/lovelace/hui-view.js +++ b/src/panels/lovelace/hui-view.js @@ -7,6 +7,7 @@ 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.js'; @@ -20,6 +21,7 @@ const VALID_TYPES = [ 'glance', 'history-graph', 'media-control', + 'picture-glance', 'plant-status', 'weather-forecast' ];