Files
homeassistant/www/community/lovelace-multiple-entity-row/multiple-entity-row.js
2019-12-09 12:40:02 +00:00

244 lines
8.2 KiB
JavaScript

class MultipleEntityRow extends Polymer.Element {
static get template() {
return Polymer.html`
<style>
:host {
display: flex;
align-items: center;
}
.flex {
flex: 1;
margin-left: 16px;
display: flex;
justify-content: space-between;
align-items: center;
min-width: 0;
}
.info {
flex: 1 0 60px;
cursor: pointer;
}
.info, .info > * {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.flex ::slotted(*) {
margin-left: 8px;
min-width: 0;
}
.flex ::slotted([slot="secondary"]) {
margin-left: 0;
}
.secondary, ha-relative-time {
display: block;
color: var(--secondary-text-color);
}
state-badge {
flex: 0 0 40px;
cursor: pointer;
}
.entity {
margin-right: 16px;
text-align: center;
cursor: pointer;
}
.entity span {
font-size: 10px;
color: var(--secondary-text-color);
}
.entity:last-of-type {
margin-right: 0;
}
.state {
min-width: 45px;
}
.toggle {
margin-left: 8px;
}
</style>
<state-badge state-obj="[[main.stateObj]]" override-icon="[[main.icon]]" on-click="defaultMoreInfo"></state-badge>
<div class="flex" on-click="defaultMoreInfo">
<div class="info">
[[entityName(main)]]
<div class="secondary">
<template is="dom-if" if="{{info}}">
[[entityName(info)]] [[entityState(info)]]
</template>
<template is="dom-if" if="{{showLastChanged}}">
<ha-relative-time datetime="[[main.stateObj.last_changed]]" hass="[[_hass]]"></ha-relative-time>
</template>
</div>
</div>
<template is="dom-if" if="{{primary}}">
<div class="entity" on-click="primaryMoreInfo">
<span>[[entityName(primary)]]</span>
<div>
<template is="dom-if" if="{{primary.showToggle}}">
<ha-entity-toggle state-obj="[[primary.stateObj]]" hass="[[_hass]]"></ha-entity-toggle>
</template>
<template is="dom-if" if="{{!primary.showToggle}}">[[entityState(primary)]]</template>
</div>
</div>
</template>
<template is="dom-if" if="{{secondary}}">
<div class="entity" on-click="secondaryMoreInfo">
<span>[[entityName(secondary)]]</span>
<div>
<template is="dom-if" if="{{secondary.showToggle}}">
<ha-entity-toggle state-obj="[[secondary.stateObj]]" hass="[[_hass]]"></ha-entity-toggle>
</template>
<template is="dom-if" if="{{!secondary.showToggle}}">[[entityState(secondary)]]</template>
</div>
</div>
</template>
<template is="dom-if" if="{{tertiary}}">
<div class="entity" on-click="tertiaryMoreInfo">
<span>[[entityName(tertiary)]]</span>
<div>
<template is="dom-if" if="{{tertiary.showToggle}}">
<ha-entity-toggle state-obj="[[tertiary.stateObj]]" hass="[[_hass]]"></ha-entity-toggle>
</template>
<template is="dom-if" if="{{!tertiary.showToggle}}">[[entityState(tertiary)]]</template>
</div>
</div>
</template>
<template is="dom-if" if="{{!main.hide_state}}">
<div class="state entity">
<template is="dom-if" if="{{showMainHeader}}">
<span>[[_config.name_state]]</span>
</template>
<template is="dom-if" if="{{main.showToggle}}">
<div class="toggle">
<ha-entity-toggle state-obj="[[main.stateObj]]" hass="[[_hass]]"></ha-entity-toggle>
</div>
</template>
<template is="dom-if" if="{{!main.showToggle}}">
<div>[[entityState(main)]]</div>
</template>
</div>
</template>
</div>`;
}
defaultMoreInfo(e) {
e.stopPropagation();
this.fireEvent(this.main.entity);
}
primaryMoreInfo(e) {
e.stopPropagation();
this.fireEvent(this.primary.entity);
}
secondaryMoreInfo(e) {
e.stopPropagation();
this.fireEvent(this.secondary.entity);
}
tertiaryMoreInfo(e) {
e.stopPropagation();
this.fireEvent(this.tertiary.entity);
}
entityName(data) {
return data && data.stateObj && data.name !== false ? this.computeStateName(data.stateObj, data.name) : null;
}
entityState(data) {
if (!data || !data.stateObj) return this._hass.localize('state.default.unavailable');
return data.attribute
? (data.attribute in data.stateObj.attributes)
? `${data.stateObj.attributes[data.attribute]} ${data.unit ? data.unit : ''}`
: this._hass.localize('state.default.unavailable')
: this.computeStateValue(data.stateObj, data.unit);
}
computeStateName(stateObj, name) {
return name || (stateObj.attributes.friendly_name === undefined
? stateObj.entity_id.substr(stateObj.entity_id.indexOf('.') + 1).replace(/_/g, ' ')
: stateObj.attributes.friendly_name || '');
}
computeStateValue(stateObj, unit) {
let display;
const domain = stateObj.entity_id.substr(0, stateObj.entity_id.indexOf("."));
if (domain === "binary_sensor") {
if (stateObj.attributes.device_class) {
display = this._hass.localize(`state.${domain}.${stateObj.attributes.device_class}.${stateObj.state}`);
}
if (!display) {
display = this._hass.localize(`state.${domain}.default.${stateObj.state}`);
}
} else if (unit !== false && (unit || stateObj.attributes.unit_of_measurement) && !["unknown", "unavailable"].includes(stateObj.state)) {
display = `${stateObj.state} ${unit || stateObj.attributes.unit_of_measurement}`;
} else if (domain === "zwave") {
display = ["initializing", "dead"].includes(stateObj.state)
? this._hass.localize(`state.zwave.query_stage.${stateObj.state}`, 'query_stage', stateObj.attributes.query_stage)
: this._hass.localize(`state.zwave.default.${stateObj.state}`);
} else {
display = this._hass.localize(`state.${domain}.${stateObj.state}`);
}
return display ||
this._hass.localize(`state.default.${stateObj.state}`) ||
this._hass.localize(`component.${domain}.state.${stateObj.state}`) ||
stateObj.state;
}
setConfig(config) {
if (!config.entity) throw new Error('Please define an entity.');
if (config.primary && !config.primary.entity) throw new Error('Please define a primary entity.');
if (config.secondary && !config.secondary.entity) throw new Error('Please define a secondary entity.');
if (config.tertiary && !config.tertiary.entity) throw new Error('Please define a tertiary entity.');
if (config.info && !config.info.entity) throw new Error('Please define an info entity.');
this.showMainHeader = config.name_state;
this.showLastChanged = config.secondary_info === 'last-changed' && !config.info;
this._config = config;
}
set hass(hass) {
this._hass = hass;
if (hass && this._config) {
const stateObj = this._config.entity in hass.states ? hass.states[this._config.entity] : null;
if (stateObj) {
this.main = this.initEntity(this._config);
this.primary = this.initEntity(this._config.primary);
this.secondary = this.initEntity(this._config.secondary);
this.tertiary = this.initEntity(this._config.tertiary);
this.info = this.initEntity(this._config.info);
}
}
}
initEntity(config) {
const stateObj = config && config.entity && this._hass.states[config.entity];
return stateObj ? Object.assign({}, config, {
stateObj: stateObj,
showToggle: this.validateToggle(config, stateObj),
}) : null;
}
validateToggle(config, stateObj) {
return config && config.toggle === true && stateObj && (stateObj.state === "on" || stateObj.state === "off");
}
fireEvent(entity, options = {}) {
const event = new Event('hass-more-info', {
bubbles: options.bubbles || true,
cancelable: options.cancelable || true,
composed: options.composed || true,
});
event.detail = {entityId: entity};
this.shadowRoot.dispatchEvent(event);
return event;
}
}
customElements.define('multiple-entity-row', MultipleEntityRow);