Fix device integration filter for entityless devices (#21136)

* Fix device integration filter for entityless devices

* code review
This commit is contained in:
karwosts 2024-06-27 03:40:09 -07:00 committed by GitHub
parent b2a55dd737
commit 7aa005e0ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 59 additions and 11 deletions

View File

@ -11,6 +11,7 @@ import {
fetchEntitySourcesWithCache, fetchEntitySourcesWithCache,
} from "../../data/entity_sources"; } from "../../data/entity_sources";
import type { AreaSelector } from "../../data/selector"; import type { AreaSelector } from "../../data/selector";
import { ConfigEntry, getConfigEntries } from "../../data/config_entries";
import { import {
filterSelectorDevices, filterSelectorDevices,
filterSelectorEntities, filterSelectorEntities,
@ -37,6 +38,8 @@ export class HaAreaSelector extends LitElement {
@state() private _entitySources?: EntitySources; @state() private _entitySources?: EntitySources;
@state() private _configEntries?: ConfigEntry[];
private _deviceIntegrationLookup = memoizeOne(getDeviceIntegrationLookup); private _deviceIntegrationLookup = memoizeOne(getDeviceIntegrationLookup);
private _hasIntegration(selector: AreaSelector) { private _hasIntegration(selector: AreaSelector) {
@ -72,6 +75,12 @@ export class HaAreaSelector extends LitElement {
this._entitySources = sources; this._entitySources = sources;
}); });
} }
if (!this._configEntries && this._hasIntegration(this.selector)) {
this._configEntries = [];
getConfigEntries(this.hass).then((entries) => {
this._configEntries = entries;
});
}
} }
protected render() { protected render() {
@ -136,7 +145,9 @@ export class HaAreaSelector extends LitElement {
const deviceIntegrations = this._entitySources const deviceIntegrations = this._entitySources
? this._deviceIntegrationLookup( ? this._deviceIntegrationLookup(
this._entitySources, this._entitySources,
Object.values(this.hass.entities) Object.values(this.hass.entities),
Object.values(this.hass.devices),
this._configEntries
) )
: undefined; : undefined;

View File

@ -11,6 +11,7 @@ import {
fetchEntitySourcesWithCache, fetchEntitySourcesWithCache,
} from "../../data/entity_sources"; } from "../../data/entity_sources";
import type { DeviceSelector } from "../../data/selector"; import type { DeviceSelector } from "../../data/selector";
import { ConfigEntry, getConfigEntries } from "../../data/config_entries";
import { import {
filterSelectorDevices, filterSelectorDevices,
filterSelectorEntities, filterSelectorEntities,
@ -27,6 +28,8 @@ export class HaDeviceSelector extends LitElement {
@state() private _entitySources?: EntitySources; @state() private _entitySources?: EntitySources;
@state() private _configEntries?: ConfigEntry[];
@property() public value?: any; @property() public value?: any;
@property() public label?: string; @property() public label?: string;
@ -75,6 +78,12 @@ export class HaDeviceSelector extends LitElement {
this._entitySources = sources; this._entitySources = sources;
}); });
} }
if (!this._configEntries && this._hasIntegration(this.selector)) {
this._configEntries = [];
getConfigEntries(this.hass).then((entries) => {
this._configEntries = entries;
});
}
} }
protected render() { protected render() {
@ -123,7 +132,9 @@ export class HaDeviceSelector extends LitElement {
const deviceIntegrations = this._entitySources const deviceIntegrations = this._entitySources
? this._deviceIntegrationLookup( ? this._deviceIntegrationLookup(
this._entitySources, this._entitySources,
Object.values(this.hass.entities) Object.values(this.hass.entities),
Object.values(this.hass.devices),
this._configEntries
) )
: undefined; : undefined;

View File

@ -11,6 +11,7 @@ import {
fetchEntitySourcesWithCache, fetchEntitySourcesWithCache,
} from "../../data/entity_sources"; } from "../../data/entity_sources";
import type { FloorSelector } from "../../data/selector"; import type { FloorSelector } from "../../data/selector";
import { ConfigEntry, getConfigEntries } from "../../data/config_entries";
import { import {
filterSelectorDevices, filterSelectorDevices,
filterSelectorEntities, filterSelectorEntities,
@ -37,6 +38,8 @@ export class HaFloorSelector extends LitElement {
@state() private _entitySources?: EntitySources; @state() private _entitySources?: EntitySources;
@state() private _configEntries?: ConfigEntry[];
private _deviceIntegrationLookup = memoizeOne(getDeviceIntegrationLookup); private _deviceIntegrationLookup = memoizeOne(getDeviceIntegrationLookup);
private _hasIntegration(selector: FloorSelector) { private _hasIntegration(selector: FloorSelector) {
@ -72,6 +75,12 @@ export class HaFloorSelector extends LitElement {
this._entitySources = sources; this._entitySources = sources;
}); });
} }
if (!this._configEntries && this._hasIntegration(this.selector)) {
this._configEntries = [];
getConfigEntries(this.hass).then((entries) => {
this._configEntries = entries;
});
}
} }
protected render() { protected render() {
@ -136,7 +145,9 @@ export class HaFloorSelector extends LitElement {
const deviceIntegrations = this._entitySources const deviceIntegrations = this._entitySources
? this._deviceIntegrationLookup( ? this._deviceIntegrationLookup(
this._entitySources, this._entitySources,
Object.values(this.hass.entities) Object.values(this.hass.entities),
Object.values(this.hass.devices),
this._configEntries
) )
: undefined; : undefined;

View File

@ -5,6 +5,7 @@ import type {
EntityRegistryDisplayEntry, EntityRegistryDisplayEntry,
EntityRegistryEntry, EntityRegistryEntry,
} from "./entity_registry"; } from "./entity_registry";
import { ConfigEntry } from "./config_entries";
import type { EntitySources } from "./entity_sources"; import type { EntitySources } from "./entity_sources";
export { export {
@ -142,9 +143,11 @@ export const getDeviceEntityDisplayLookup = (
export const getDeviceIntegrationLookup = ( export const getDeviceIntegrationLookup = (
entitySources: EntitySources, entitySources: EntitySources,
entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[] entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[],
): Record<string, string[]> => { devices?: DeviceRegistryEntry[],
const deviceIntegrations: Record<string, string[]> = {}; configEntries?: ConfigEntry[]
): Record<string, Set<string>> => {
const deviceIntegrations: Record<string, Set<string>> = {};
for (const entity of entities) { for (const entity of entities) {
const source = entitySources[entity.entity_id]; const source = entitySources[entity.entity_id];
@ -152,10 +155,22 @@ export const getDeviceIntegrationLookup = (
continue; continue;
} }
if (!deviceIntegrations[entity.device_id!]) { deviceIntegrations[entity.device_id!] =
deviceIntegrations[entity.device_id!] = []; deviceIntegrations[entity.device_id!] || new Set<string>();
deviceIntegrations[entity.device_id!].add(source.domain);
}
// Lookup devices that have no entities
if (devices && configEntries) {
for (const device of devices) {
for (const config_entry_id of device.config_entries) {
const entry = configEntries.find((e) => e.entry_id === config_entry_id);
if (entry?.domain) {
deviceIntegrations[device.id] =
deviceIntegrations[device.id] || new Set<string>();
deviceIntegrations[device.id].add(entry.domain);
}
}
} }
deviceIntegrations[entity.device_id!].push(source.domain);
} }
return deviceIntegrations; return deviceIntegrations;
}; };

View File

@ -696,7 +696,7 @@ export const entityMeetsTargetSelector = (
export const filterSelectorDevices = ( export const filterSelectorDevices = (
filterDevice: DeviceSelectorFilter, filterDevice: DeviceSelectorFilter,
device: DeviceRegistryEntry, device: DeviceRegistryEntry,
deviceIntegrationLookup?: Record<string, string[]> | undefined deviceIntegrationLookup?: Record<string, Set<string>> | undefined
): boolean => { ): boolean => {
const { const {
manufacturer: filterManufacturer, manufacturer: filterManufacturer,
@ -713,7 +713,7 @@ export const filterSelectorDevices = (
} }
if (filterIntegration && deviceIntegrationLookup) { if (filterIntegration && deviceIntegrationLookup) {
if (!deviceIntegrationLookup?.[device.id]?.includes(filterIntegration)) { if (!deviceIntegrationLookup?.[device.id]?.has(filterIntegration)) {
return false; return false;
} }
} }