mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-08 18:06:36 +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 computeDomain from '../../../common/entity/compute_domain.js';
|
||||
import { DOMAINS_HIDE_MORE_INFO } from '../../../common/const.js';
|
||||
import computeConfigEntities from '../common/compute-config-entities';
|
||||
import validateEntitiesConfig from '../common/validate-entities-config';
|
||||
import processConfigEntities from '../common/process-config-entities.js';
|
||||
|
||||
import '../../../components/ha-card.js';
|
||||
import '../components/hui-entities-toggle.js';
|
||||
@ -100,18 +99,14 @@ class HuiEntitiesCard extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
setConfig(config) {
|
||||
if (!validateEntitiesConfig(config)) {
|
||||
throw Error('Error in card config.');
|
||||
}
|
||||
|
||||
this._config = config;
|
||||
this._configEntities = processConfigEntities(config.entities);
|
||||
if (this.$) this._buildConfig();
|
||||
}
|
||||
|
||||
_buildConfig() {
|
||||
const config = this._config;
|
||||
const root = this.$.states;
|
||||
const entities = computeConfigEntities(config);
|
||||
const entities = this._configEntities;
|
||||
|
||||
while (root.lastChild) {
|
||||
root.removeChild(root.lastChild);
|
||||
|
@ -1,7 +1,14 @@
|
||||
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 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 {
|
||||
static get properties() {
|
||||
@ -17,44 +24,13 @@ class HuiEntitiesCard extends PolymerElement {
|
||||
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) {
|
||||
if (!config.filter || !Array.isArray(config.filter)) {
|
||||
if (!config.state_filter || !Array.isArray(config.state_filter)) {
|
||||
throw new Error('Incorrect filter config.');
|
||||
}
|
||||
|
||||
this._config = config;
|
||||
this._configEntities = processConfigEntities(config.entities);
|
||||
|
||||
if (this.lastChild) {
|
||||
this.removeChild(this.lastChild);
|
||||
@ -79,12 +55,14 @@ class HuiEntitiesCard extends PolymerElement {
|
||||
|
||||
_updateCardConfig(element) {
|
||||
if (!element || element.tagName === 'HUI-ERROR-CARD' || !this.hass) return;
|
||||
const entitiesList = this._getEntities(this.hass, this._config.filter);
|
||||
if (entitiesList.length === 0) {
|
||||
this.style.display = (this._config.show_empty === false) ? 'none' : 'block';
|
||||
} else {
|
||||
this.style.display = 'block';
|
||||
const entitiesList = getEntities(this.hass, this._config.state_filter, this._configEntities);
|
||||
|
||||
if (entitiesList.length === 0 && this._config.show_empty === false) {
|
||||
this.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
this.style.display = 'block';
|
||||
element.setConfig(Object.assign(
|
||||
{},
|
||||
element._filterRawConfig,
|
||||
|
@ -3,7 +3,7 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||
|
||||
import computeStateDisplay from '../../../common/entity/compute_state_display.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/ha-card.js';
|
||||
@ -52,7 +52,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
|
||||
<ha-card header$="[[_config.title]]">
|
||||
<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)]]">
|
||||
<div class="entity" on-click="_openDialog">
|
||||
<div>[[_computeName(item, hass.states)]]</div>
|
||||
@ -70,6 +70,7 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
return {
|
||||
hass: Object,
|
||||
_config: Object,
|
||||
_configEntities: Array,
|
||||
};
|
||||
}
|
||||
|
||||
@ -77,16 +78,9 @@ class HuiGlanceCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
_computeEntities(config) {
|
||||
return computeConfigEntities(config);
|
||||
}
|
||||
|
||||
setConfig(config) {
|
||||
if (!config || !config.entities || !Array.isArray(config.entities)) {
|
||||
throw new Error('Error in card configuration.');
|
||||
}
|
||||
|
||||
this._config = config;
|
||||
this._configEntities = processConfigEntities(config.entities);
|
||||
}
|
||||
|
||||
_showEntity(item, states) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 {
|
||||
@ -15,8 +15,12 @@ export default class LegacyWrapperCard extends HTMLElement {
|
||||
}
|
||||
|
||||
setConfig(config) {
|
||||
if (!validateEntityConfig(config, this._domain)) {
|
||||
throw new Error('Error in card configuration.');
|
||||
if (!config.entity) {
|
||||
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;
|
||||
|
@ -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