mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-09 10:26:35 +00:00
Only allow state filter for filter card (#1387)
* Only allow state filter for filter card * Lint * Address comments
This commit is contained in:
parent
25fddad446
commit
c868df2718
@ -5,8 +5,7 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|||||||
import stateCardType from '../../../common/entity/state_card_type.js';
|
import stateCardType from '../../../common/entity/state_card_type.js';
|
||||||
import computeDomain from '../../../common/entity/compute_domain.js';
|
import computeDomain from '../../../common/entity/compute_domain.js';
|
||||||
import { DOMAINS_HIDE_MORE_INFO } from '../../../common/const.js';
|
import { DOMAINS_HIDE_MORE_INFO } from '../../../common/const.js';
|
||||||
import computeConfigEntities from '../common/compute-config-entities';
|
import processConfigEntities from '../common/process-config-entities.js';
|
||||||
import validateEntitiesConfig from '../common/validate-entities-config';
|
|
||||||
|
|
||||||
import '../../../components/ha-card.js';
|
import '../../../components/ha-card.js';
|
||||||
import '../components/hui-entities-toggle.js';
|
import '../components/hui-entities-toggle.js';
|
||||||
@ -100,18 +99,14 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setConfig(config) {
|
setConfig(config) {
|
||||||
if (!validateEntitiesConfig(config)) {
|
|
||||||
throw Error('Error in card config.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = config;
|
this._config = config;
|
||||||
|
this._configEntities = processConfigEntities(config.entities);
|
||||||
if (this.$) this._buildConfig();
|
if (this.$) this._buildConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildConfig() {
|
_buildConfig() {
|
||||||
const config = this._config;
|
|
||||||
const root = this.$.states;
|
const root = this.$.states;
|
||||||
const entities = computeConfigEntities(config);
|
const entities = this._configEntities;
|
||||||
|
|
||||||
while (root.lastChild) {
|
while (root.lastChild) {
|
||||||
root.removeChild(root.lastChild);
|
root.removeChild(root.lastChild);
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||||
|
|
||||||
import computeStateDomain from '../../../common/entity/compute_state_domain.js';
|
|
||||||
import createCardElement from '../common/create-card-element.js';
|
import createCardElement from '../common/create-card-element.js';
|
||||||
|
import processConfigEntities from '../common/process-config-entities.js';
|
||||||
|
|
||||||
|
function getEntities(hass, filterState, entities) {
|
||||||
|
return entities.filter((entityConf) => {
|
||||||
|
const stateObj = hass.states[entityConf.entity];
|
||||||
|
return stateObj && filterState.includes(stateObj.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class HuiEntitiesCard extends PolymerElement {
|
class HuiEntitiesCard extends PolymerElement {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
@ -17,44 +24,13 @@ class HuiEntitiesCard extends PolymerElement {
|
|||||||
return this.lastChild ? this.lastChild.getCardSize() : 1;
|
return this.lastChild ? this.lastChild.getCardSize() : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a list of entities based on filters.
|
|
||||||
_getEntities(hass, filterList) {
|
|
||||||
const entities = new Set();
|
|
||||||
filterList.forEach((filter) => {
|
|
||||||
const filters = [];
|
|
||||||
if (filter.domain) {
|
|
||||||
filters.push(stateObj => computeStateDomain(stateObj) === filter.domain);
|
|
||||||
}
|
|
||||||
if (filter.entity_id) {
|
|
||||||
filters.push(stateObj => this._filterEntityId(stateObj, filter.entity_id));
|
|
||||||
}
|
|
||||||
if (filter.state) {
|
|
||||||
filters.push(stateObj => stateObj.state === filter.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.values(hass.states).forEach((stateObj) => {
|
|
||||||
if (filters.every(filterFunc => filterFunc(stateObj))) {
|
|
||||||
entities.add(stateObj.entity_id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return Array.from(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
_filterEntityId(stateObj, pattern) {
|
|
||||||
if (pattern.indexOf('*') === -1) {
|
|
||||||
return stateObj.entity_id === pattern;
|
|
||||||
}
|
|
||||||
const regEx = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`);
|
|
||||||
return stateObj.entity_id.search(regEx) === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
setConfig(config) {
|
setConfig(config) {
|
||||||
if (!config.filter || !Array.isArray(config.filter)) {
|
if (!config.state_filter || !Array.isArray(config.state_filter)) {
|
||||||
throw new Error('Incorrect filter config.');
|
throw new Error('Incorrect filter config.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._config = config;
|
this._config = config;
|
||||||
|
this._configEntities = processConfigEntities(config.entities);
|
||||||
|
|
||||||
if (this.lastChild) {
|
if (this.lastChild) {
|
||||||
this.removeChild(this.lastChild);
|
this.removeChild(this.lastChild);
|
||||||
@ -79,12 +55,14 @@ class HuiEntitiesCard extends PolymerElement {
|
|||||||
|
|
||||||
_updateCardConfig(element) {
|
_updateCardConfig(element) {
|
||||||
if (!element || element.tagName === 'HUI-ERROR-CARD' || !this.hass) return;
|
if (!element || element.tagName === 'HUI-ERROR-CARD' || !this.hass) return;
|
||||||
const entitiesList = this._getEntities(this.hass, this._config.filter);
|
const entitiesList = getEntities(this.hass, this._config.state_filter, this._configEntities);
|
||||||
if (entitiesList.length === 0) {
|
|
||||||
this.style.display = (this._config.show_empty === false) ? 'none' : 'block';
|
if (entitiesList.length === 0 && this._config.show_empty === false) {
|
||||||
} else {
|
this.style.display = 'none';
|
||||||
this.style.display = 'block';
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.style.display = 'block';
|
||||||
element.setConfig(Object.assign(
|
element.setConfig(Object.assign(
|
||||||
{},
|
{},
|
||||||
element._filterRawConfig,
|
element._filterRawConfig,
|
||||||
|
@ -3,7 +3,7 @@ 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 computeConfigEntities from '../common/compute-config-entities';
|
import processConfigEntities from '../common/process-config-entities';
|
||||||
|
|
||||||
import '../../../components/entity/state-badge.js';
|
import '../../../components/entity/state-badge.js';
|
||||||
import '../../../components/ha-card.js';
|
import '../../../components/ha-card.js';
|
||||||
@ -52,7 +52,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
|
|
||||||
<ha-card header$="[[_config.title]]">
|
<ha-card header$="[[_config.title]]">
|
||||||
<div class="entities">
|
<div class="entities">
|
||||||
<template is="dom-repeat" items="[[_computeEntities(_config)]]">
|
<template is="dom-repeat" items="[[_configEntities]]">
|
||||||
<template is="dom-if" if="[[_showEntity(item, hass.states)]]">
|
<template is="dom-if" if="[[_showEntity(item, hass.states)]]">
|
||||||
<div class="entity" on-click="_openDialog">
|
<div class="entity" on-click="_openDialog">
|
||||||
<div>[[_computeName(item, hass.states)]]</div>
|
<div>[[_computeName(item, hass.states)]]</div>
|
||||||
@ -70,6 +70,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
return {
|
return {
|
||||||
hass: Object,
|
hass: Object,
|
||||||
_config: Object,
|
_config: Object,
|
||||||
|
_configEntities: Array,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,16 +78,9 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeEntities(config) {
|
|
||||||
return computeConfigEntities(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
setConfig(config) {
|
setConfig(config) {
|
||||||
if (!config || !config.entities || !Array.isArray(config.entities)) {
|
|
||||||
throw new Error('Error in card configuration.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = config;
|
this._config = config;
|
||||||
|
this._configEntities = processConfigEntities(config.entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
_showEntity(item, states) {
|
_showEntity(item, states) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import createErrorCardConfig from '../common/create-error-card-config.js';
|
import createErrorCardConfig from '../common/create-error-card-config.js';
|
||||||
import validateEntityConfig from '../common/validate-entity-config.js';
|
import computeDomain from '../../../common/entity/compute_domain.js';
|
||||||
|
|
||||||
|
|
||||||
export default class LegacyWrapperCard extends HTMLElement {
|
export default class LegacyWrapperCard extends HTMLElement {
|
||||||
@ -15,8 +15,12 @@ export default class LegacyWrapperCard extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setConfig(config) {
|
setConfig(config) {
|
||||||
if (!validateEntityConfig(config, this._domain)) {
|
if (!config.entity) {
|
||||||
throw new Error('Error in card configuration.');
|
throw new Error('No entity specified');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (computeDomain(config.entity) !== this._domain) {
|
||||||
|
throw new Error(`Specified entity needs to be of domain ${this._domain}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._config = config;
|
this._config = config;
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
// Parse array of entity objects from config
|
|
||||||
export default function computeConfigEntities(config) {
|
|
||||||
const entities = config && config.entities;
|
|
||||||
|
|
||||||
if (!entities || !Array.isArray(entities)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entities.map((entity) => {
|
|
||||||
if (typeof entity === 'string') {
|
|
||||||
return { entity };
|
|
||||||
} else if (typeof entity === 'object' && !Array.isArray(entity)) {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
26
src/panels/lovelace/common/process-config-entities.js
Normal file
26
src/panels/lovelace/common/process-config-entities.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Parse array of entity objects from config
|
||||||
|
import isValidEntityId from '../../../common/entity/valid_entity_id.js';
|
||||||
|
|
||||||
|
export default function processConfigEntities(entities) {
|
||||||
|
if (!entities || !Array.isArray(entities)) {
|
||||||
|
throw new Error('Entities need to be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities.map((entityConf, index) => {
|
||||||
|
if (typeof entityConf === 'string') {
|
||||||
|
entityConf = { entity: entityConf };
|
||||||
|
} else if (typeof entityConf === 'object' && !Array.isArray(entityConf)) {
|
||||||
|
if (!entityConf.entity) {
|
||||||
|
throw new Error(`Entity object at position ${index} is missing entity field.`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Invalid entity specified at position ${index}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidEntityId(entityConf.entity)) {
|
||||||
|
throw new Error(`Invalid entity ID at position ${index}: ${entityConf.entity}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entityConf;
|
||||||
|
});
|
||||||
|
}
|
@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
* Check that all items in array are objects with an entity property containing a valid entity_id.
|
|
||||||
*
|
|
||||||
* Optionally provide an array of additional keys that must be present in every object
|
|
||||||
*/
|
|
||||||
|
|
||||||
import validEntityId from '../../../common/entity/valid_entity_id';
|
|
||||||
|
|
||||||
export default function validateEntitiesConfig(config, additionalKeys = []) {
|
|
||||||
const entities = config && config.entities;
|
|
||||||
|
|
||||||
if (!entities || !Array.isArray(entities)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entities.every((entity) => {
|
|
||||||
if (typeof entity === 'string') {
|
|
||||||
return validEntityId(entity) && !additionalKeys.length;
|
|
||||||
}
|
|
||||||
return entity && typeof entity === 'object' && !Array.isArray(entity) &&
|
|
||||||
'entity' in entity && validEntityId(entity.entity) && additionalKeys.every(key => key in entity);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// check for valid value of config.entity with optinal entity dommain check
|
|
||||||
import computeDomain from '../../../common/entity/compute_domain.js';
|
|
||||||
import validEntityId from '../../../common/entity/valid_entity_id';
|
|
||||||
|
|
||||||
export default function validateEntityConfig(config, domain = null) {
|
|
||||||
const entityId = config && config.entity;
|
|
||||||
|
|
||||||
if (!entityId || typeof entityId !== 'string' || !validEntityId(entityId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domain) {
|
|
||||||
return computeDomain(entityId) === domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user