mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
parent
07d76739b4
commit
3442700e1f
@ -60,14 +60,6 @@ export const DOMAINS_MORE_INFO_NO_HISTORY = [
|
|||||||
'scene',
|
'scene',
|
||||||
];
|
];
|
||||||
|
|
||||||
/** States that we consider "on". */
|
|
||||||
export const STATES_ON = [
|
|
||||||
'home',
|
|
||||||
'on',
|
|
||||||
'open',
|
|
||||||
'unlocked'
|
|
||||||
];
|
|
||||||
|
|
||||||
/** States that we consider "off". */
|
/** States that we consider "off". */
|
||||||
export const STATES_OFF = [
|
export const STATES_OFF = [
|
||||||
'closed',
|
'closed',
|
||||||
|
@ -3,7 +3,9 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|||||||
|
|
||||||
import computeStateDisplay from '../../../common/entity/compute_state_display.js';
|
import computeStateDisplay from '../../../common/entity/compute_state_display.js';
|
||||||
import computeStateName from '../../../common/entity/compute_state_name.js';
|
import computeStateName from '../../../common/entity/compute_state_name.js';
|
||||||
|
import createErrorCardConfig from '../common/create-error-card-config.js';
|
||||||
|
|
||||||
|
import './hui-error-card.js';
|
||||||
import '../../../components/entity/state-badge.js';
|
import '../../../components/entity/state-badge.js';
|
||||||
import '../../../components/ha-card.js';
|
import '../../../components/ha-card.js';
|
||||||
|
|
||||||
@ -44,11 +46,6 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
.error {
|
|
||||||
background-color: red;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<ha-card header="[[config.title]]">
|
<ha-card header="[[config.title]]">
|
||||||
@ -64,7 +61,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<template is="dom-if" if="[[_error]]">
|
<template is="dom-if" if="[[_error]]">
|
||||||
<div class="error">[[_error]]</div>
|
<hui-error-card config="[[_error]]"></hui-error-card>
|
||||||
</template>
|
</template>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
@ -78,7 +75,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
type: Array,
|
type: Array,
|
||||||
computed: '_computeEntities(config)'
|
computed: '_computeEntities(config)'
|
||||||
},
|
},
|
||||||
_error: String
|
_error: Object
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,13 +84,15 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_computeEntities(config) {
|
_computeEntities(config) {
|
||||||
if (config && config.entities && Array.isArray(config.entities)) {
|
if (!config || !config.entities || !Array.isArray(config.entities)) {
|
||||||
|
const error = 'Error in card configuration.';
|
||||||
|
this._error = createErrorCardConfig(error, config);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
this._error = null;
|
this._error = null;
|
||||||
return config.entities;
|
return config.entities;
|
||||||
}
|
}
|
||||||
this._error = 'Error in card configuration.';
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
_showEntity(item, states) {
|
_showEntity(item, states) {
|
||||||
return item in states;
|
return item in states;
|
||||||
|
@ -5,10 +5,9 @@ import '../../../components/buttons/ha-call-service-button.js';
|
|||||||
import '../../../components/entity/state-badge.js';
|
import '../../../components/entity/state-badge.js';
|
||||||
import '../../../components/ha-card.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 computeStateDisplay from '../../../common/entity/compute_state_display.js';
|
||||||
import computeStateName from '../../../common/entity/compute_state_name.js';
|
import computeStateName from '../../../common/entity/compute_state_name.js';
|
||||||
|
import toggleEntity from '../common/entity/toggle-entity.js';
|
||||||
|
|
||||||
import EventsMixin from '../../../mixins/events-mixin.js';
|
import EventsMixin from '../../../mixins/events-mixin.js';
|
||||||
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
||||||
@ -140,23 +139,7 @@ class HuiPictureElementsCard extends LocalizeMixin(EventsMixin(PolymerElement))
|
|||||||
|
|
||||||
_handleClick(entityId, toggle) {
|
_handleClick(entityId, toggle) {
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
const turnOn = !STATES_ON.includes(this.hass.states[entityId].state);
|
toggleEntity(this.hass, entityId);
|
||||||
const stateDomain = computeDomain(entityId);
|
|
||||||
const serviceDomain = stateDomain === 'lock' || stateDomain === 'cover' ?
|
|
||||||
stateDomain : 'homeassistant';
|
|
||||||
|
|
||||||
let service;
|
|
||||||
switch (stateDomain) {
|
|
||||||
case 'lock':
|
|
||||||
service = turnOn ? 'unlock' : 'lock';
|
|
||||||
break;
|
|
||||||
case 'cover':
|
|
||||||
service = turnOn ? 'open_cover' : 'close_cover';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
service = turnOn ? 'turn_on' : 'turn_off';
|
|
||||||
}
|
|
||||||
this.hass.callService(serviceDomain, service, { entity_id: entityId });
|
|
||||||
} else {
|
} else {
|
||||||
this.fire('hass-more-info', { entityId });
|
this.fire('hass-more-info', { entityId });
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,16 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
|||||||
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||||
import '@polymer/paper-icon-button/paper-icon-button.js';
|
import '@polymer/paper-icon-button/paper-icon-button.js';
|
||||||
|
|
||||||
|
import './hui-error-card.js';
|
||||||
import '../../../components/ha-card.js';
|
import '../../../components/ha-card.js';
|
||||||
|
|
||||||
import { STATES_ON } from '../../../common/const.js';
|
import { STATES_OFF } from '../../../common/const.js';
|
||||||
import canToggleState from '../../../common/entity/can_toggle_state.js';
|
import canToggleState from '../../../common/entity/can_toggle_state.js';
|
||||||
import computeDomain from '../../../common/entity/compute_domain.js';
|
|
||||||
import computeStateDisplay from '../../../common/entity/compute_state_display.js';
|
import computeStateDisplay from '../../../common/entity/compute_state_display.js';
|
||||||
import computeStateName from '../../../common/entity/compute_state_name.js';
|
import computeStateName from '../../../common/entity/compute_state_name.js';
|
||||||
|
import createErrorCardConfig from '../common/create-error-card-config.js';
|
||||||
import stateIcon from '../../../common/entity/state_icon.js';
|
import stateIcon from '../../../common/entity/state_icon.js';
|
||||||
|
import toggleEntity from '../common/entity/toggle-entity.js';
|
||||||
|
|
||||||
import EventsMixin from '../../../mixins/events-mixin.js';
|
import EventsMixin from '../../../mixins/events-mixin.js';
|
||||||
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
||||||
@ -25,12 +27,12 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
ha-card {
|
ha-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
line-height: 0;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
border-radius: 2px;
|
|
||||||
}
|
}
|
||||||
.box {
|
.box {
|
||||||
@apply --paper-font-common-nowrap;
|
@apply --paper-font-common-nowrap;
|
||||||
@ -43,8 +45,6 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
color: white;
|
color: white;
|
||||||
border-bottom-left-radius: 2px;
|
|
||||||
border-bottom-right-radius: 2px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
@ -60,11 +60,6 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
iron-icon {
|
iron-icon {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
.error {
|
|
||||||
background-color: red;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<ha-card>
|
<ha-card>
|
||||||
@ -97,7 +92,7 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template is="dom-if" if="[[_error]]">
|
<template is="dom-if" if="[[_error]]">
|
||||||
<div class="error">[[_error]]</div>
|
<hui-error-card config="[[_error]]"></hui-error-card>
|
||||||
</template>
|
</template>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
@ -112,7 +107,7 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
},
|
},
|
||||||
_entitiesDialog: Array,
|
_entitiesDialog: Array,
|
||||||
_entitiesService: Array,
|
_entitiesService: Array,
|
||||||
_error: String
|
_error: Object
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +128,8 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
dialog = config.entities.filter(entity => !service.includes(entity));
|
dialog = config.entities.filter(entity => !service.includes(entity));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_error = 'Error in card configuration.';
|
const error = 'Error in card configuration.';
|
||||||
|
_error = createErrorCardConfig(error, config);
|
||||||
}
|
}
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
_entitiesDialog: dialog,
|
_entitiesDialog: dialog,
|
||||||
@ -151,7 +147,7 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_computeClass(entityId, states) {
|
_computeClass(entityId, states) {
|
||||||
return STATES_ON.includes(states[entityId].state) ? 'state-on' : '';
|
return STATES_OFF.includes(states[entityId].state) ? '' : 'state-on';
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeTooltip(entityId, states) {
|
_computeTooltip(entityId, states) {
|
||||||
@ -164,24 +160,7 @@ class HuiPictureGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
|
|
||||||
_callService(ev) {
|
_callService(ev) {
|
||||||
const entityId = ev.model.item;
|
const entityId = ev.model.item;
|
||||||
let domain = computeDomain(entityId);
|
toggleEntity(this.hass, entityId);
|
||||||
const turnOn = !STATES_ON.includes(this.hass.states[entityId].state);
|
|
||||||
let service;
|
|
||||||
switch (domain) {
|
|
||||||
case 'lock':
|
|
||||||
service = turnOn ? 'unlock' : 'lock';
|
|
||||||
break;
|
|
||||||
case 'cover':
|
|
||||||
service = turnOn ? 'open_cover' : 'close_cover';
|
|
||||||
break;
|
|
||||||
case 'group':
|
|
||||||
domain = 'homeassistant';
|
|
||||||
service = turnOn ? 'turn_on' : 'turn_off';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
service = turnOn ? 'turn_on' : 'turn_off';
|
|
||||||
}
|
|
||||||
this.hass.callService(domain, service, { entity_id: entityId });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
src/panels/lovelace/common/entity/toggle-entity.js
Normal file
7
src/panels/lovelace/common/entity/toggle-entity.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { STATES_OFF } from '../../../../common/const.js';
|
||||||
|
import turnOnOffEntity from './turn-on-off-entity.js';
|
||||||
|
|
||||||
|
export default function toggleEntity(hass, entityId) {
|
||||||
|
const turnOn = STATES_OFF.includes(hass.states[entityId].state);
|
||||||
|
turnOnOffEntity(hass, entityId, turnOn);
|
||||||
|
}
|
33
src/panels/lovelace/common/entity/turn-on-off-entities.js
Normal file
33
src/panels/lovelace/common/entity/turn-on-off-entities.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { STATES_OFF } from '../../../../common/const.js';
|
||||||
|
import computeDomain from '../../../../common/entity/compute_domain.js';
|
||||||
|
|
||||||
|
export default function turnOnOffEntities(hass, entityIds, turnOn = true) {
|
||||||
|
const domainsToCall = {};
|
||||||
|
entityIds.forEach((entityId) => {
|
||||||
|
if ((STATES_OFF.includes(hass.states[entityId].state)) === turnOn) {
|
||||||
|
const stateDomain = computeDomain(entityId);
|
||||||
|
const serviceDomain = ['cover', 'lock'].includes(stateDomain) ?
|
||||||
|
stateDomain : 'homeassistant';
|
||||||
|
|
||||||
|
if (!(serviceDomain in domainsToCall)) domainsToCall[serviceDomain] = [];
|
||||||
|
domainsToCall[serviceDomain].push(entityId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(domainsToCall).forEach((domain) => {
|
||||||
|
let service;
|
||||||
|
switch (domain) {
|
||||||
|
case 'lock':
|
||||||
|
service = turnOn ? 'unlock' : 'lock';
|
||||||
|
break;
|
||||||
|
case 'cover':
|
||||||
|
service = turnOn ? 'open_cover' : 'close_cover';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
service = turnOn ? 'turn_on' : 'turn_off';
|
||||||
|
}
|
||||||
|
|
||||||
|
const entities = domainsToCall[domain];
|
||||||
|
hass.callService(domain, service, { entity_id: entities });
|
||||||
|
});
|
||||||
|
}
|
20
src/panels/lovelace/common/entity/turn-on-off-entity.js
Normal file
20
src/panels/lovelace/common/entity/turn-on-off-entity.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import computeDomain from '../../../../common/entity/compute_domain.js';
|
||||||
|
|
||||||
|
export default function turnOnOffEntity(hass, entityId, turnOn = true) {
|
||||||
|
const stateDomain = computeDomain(entityId);
|
||||||
|
const serviceDomain = stateDomain === 'group' ? 'homeassistant' : stateDomain;
|
||||||
|
|
||||||
|
let service;
|
||||||
|
switch (stateDomain) {
|
||||||
|
case 'lock':
|
||||||
|
service = turnOn ? 'unlock' : 'lock';
|
||||||
|
break;
|
||||||
|
case 'cover':
|
||||||
|
service = turnOn ? 'open_cover' : 'close_cover';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
service = turnOn ? 'turn_on' : 'turn_off';
|
||||||
|
}
|
||||||
|
|
||||||
|
hass.callService(serviceDomain, service, { entity_id: entityId });
|
||||||
|
}
|
@ -3,8 +3,8 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|||||||
import '@polymer/paper-toggle-button/paper-toggle-button.js';
|
import '@polymer/paper-toggle-button/paper-toggle-button.js';
|
||||||
|
|
||||||
import canToggleState from '../../../common/entity/can_toggle_state.js';
|
import canToggleState from '../../../common/entity/can_toggle_state.js';
|
||||||
import computeDomain from '../../../common/entity/compute_domain.js';
|
import turnOnOffEntities from '../common/entity/turn-on-off-entities.js';
|
||||||
import { STATES_ON } from '../../../common/const.js';
|
import { STATES_OFF } from '../../../common/const.js';
|
||||||
|
|
||||||
class HuiEntitiesToggle extends PolymerElement {
|
class HuiEntitiesToggle extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
@ -38,46 +38,18 @@ class HuiEntitiesToggle extends PolymerElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeToggleEntities(hass, entities) {
|
_computeToggleEntities(hass, entityIds) {
|
||||||
return entities.filter(entity => (entity in hass.states ?
|
return entityIds.filter(entityId => (entityId in hass.states ?
|
||||||
canToggleState(hass, hass.states[entity]) : false));
|
canToggleState(hass, hass.states[entityId]) : false));
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeIsChecked(hass, entities) {
|
_computeIsChecked(hass, entityIds) {
|
||||||
return entities.some(entity => STATES_ON.includes(hass.states[entity].state));
|
return entityIds.some(entityId => !STATES_OFF.includes(hass.states[entityId].state));
|
||||||
}
|
}
|
||||||
|
|
||||||
_callService(ev) {
|
_callService(ev) {
|
||||||
const turnOn = ev.target.checked;
|
const turnOn = ev.target.checked;
|
||||||
const toCall = {};
|
turnOnOffEntities(this.hass, this._toggleEntities, turnOn);
|
||||||
|
|
||||||
this.entities.forEach((entity) => {
|
|
||||||
if ((STATES_ON.includes(this.hass.states[entity].state)) !== turnOn) {
|
|
||||||
const stateDomain = computeDomain(entity);
|
|
||||||
const serviceDomain = stateDomain === 'lock' || stateDomain === 'cover' ?
|
|
||||||
stateDomain : 'homeassistant';
|
|
||||||
|
|
||||||
if (!(serviceDomain in toCall)) toCall[serviceDomain] = [];
|
|
||||||
toCall[serviceDomain].push(entity);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(toCall).forEach((domain) => {
|
|
||||||
let service;
|
|
||||||
switch (domain) {
|
|
||||||
case 'lock':
|
|
||||||
service = turnOn ? 'unlock' : 'lock';
|
|
||||||
break;
|
|
||||||
case 'cover':
|
|
||||||
service = turnOn ? 'open_cover' : 'close_cover';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
service = turnOn ? 'turn_on' : 'turn_off';
|
|
||||||
}
|
|
||||||
|
|
||||||
const entities = toCall[domain];
|
|
||||||
this.hass.callService(domain, service, { entity_id: entities });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user