Optimize entities config performance (#21974)

* Optimize entities config performance

* review
This commit is contained in:
Bram Kragten 2024-09-16 14:40:52 +02:00 committed by GitHub
parent 39a1844991
commit 1cdfb746bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 75 deletions

View File

@ -1,10 +1,20 @@
export interface DataTableFilters { export interface DataTableFilters {
[key: string]: { [key: string]: {
value: string[] | { key: string[] } | undefined; value: DataTableFiltersValue;
items: Set<string> | undefined; items: Set<string> | undefined;
}; };
} }
export type DataTableFiltersValue = string[] | { key: string[] } | undefined;
export interface DataTableFiltersValues {
[key: string]: DataTableFiltersValue;
}
export interface DataTableFiltersItems {
[key: string]: Set<string> | undefined;
}
export const serializeFilters = (value: DataTableFilters) => { export const serializeFilters = (value: DataTableFilters) => {
const serializedValue = {}; const serializedValue = {};
Object.entries(value).forEach(([key, val]) => { Object.entries(value).forEach(([key, val]) => {

View File

@ -99,9 +99,8 @@ import "../integrations/ha-integration-overflow-menu";
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { import {
serializeFilters, DataTableFiltersValues,
deserializeFilters, DataTableFiltersItems,
DataTableFilters,
} from "../../../data/data_table_filters"; } from "../../../data/data_table_filters";
import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { formatShortDateTime } from "../../../common/datetime/format_date_time";
@ -157,13 +156,13 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
@storage({ @storage({
storage: "sessionStorage", storage: "sessionStorage",
key: "entities-table-filters-full", key: "entities-table-filters",
state: true, state: true,
subscribe: false, subscribe: false,
serializer: serializeFilters,
deserializer: deserializeFilters,
}) })
private _filters: DataTableFilters = {}; private _filters: DataTableFiltersValues = {};
@state() private _filteredItems: DataTableFiltersItems = {};
@state() private _selected: string[] = []; @state() private _selected: string[] = [];
@ -460,13 +459,14 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
devices: HomeAssistant["devices"], devices: HomeAssistant["devices"],
areas: HomeAssistant["areas"], areas: HomeAssistant["areas"],
stateEntities: StateEntity[], stateEntities: StateEntity[],
filters: DataTableFilters, filters: DataTableFiltersValues,
filteredItems: DataTableFiltersItems,
entries?: ConfigEntry[], entries?: ConfigEntry[],
labelReg?: LabelRegistryEntry[] labelReg?: LabelRegistryEntry[]
) => { ) => {
const result: EntityRow[] = []; const result: EntityRow[] = [];
const stateFilters = filters["ha-filter-states"]?.value as string[]; const stateFilters = filters["ha-filter-states"] as string[];
const showEnabled = const showEnabled =
!stateFilters?.length || stateFilters.includes("enabled"); !stateFilters?.length || stateFilters.includes("enabled");
@ -491,15 +491,11 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
const filteredDomains = new Set<string>(); const filteredDomains = new Set<string>();
Object.entries(filters).forEach(([key, filter]) => { Object.entries(filters).forEach(([key, filter]) => {
if ( if (key === "config_entry" && Array.isArray(filter) && filter.length) {
key === "config_entry" &&
Array.isArray(filter.value) &&
filter.value.length
) {
filteredEntities = filteredEntities.filter( filteredEntities = filteredEntities.filter(
(entity) => (entity) =>
entity.config_entry_id && entity.config_entry_id &&
(filter.value as string[]).includes(entity.config_entry_id) (filter as string[]).includes(entity.config_entry_id)
); );
if (!entries) { if (!entries) {
@ -509,8 +505,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
const configEntries = entries.filter( const configEntries = entries.filter(
(entry) => (entry) =>
entry.entry_id && entry.entry_id && (filter as string[]).includes(entry.entry_id)
(filter.value as string[]).includes(entry.entry_id)
); );
configEntries.forEach((configEntry) => { configEntries.forEach((configEntry) => {
@ -521,17 +516,15 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
} }
} else if ( } else if (
key === "ha-filter-integrations" && key === "ha-filter-integrations" &&
Array.isArray(filter.value) && Array.isArray(filter) &&
filter.value.length filter.length
) { ) {
if (!entries) { if (!entries) {
this._loadConfigEntries(); this._loadConfigEntries();
return; return;
} }
const entryIds = entries const entryIds = entries
.filter((entry) => .filter((entry) => (filter as string[]).includes(entry.domain))
(filter.value as string[]).includes(entry.domain)
)
.map((entry) => entry.entry_id); .map((entry) => entry.entry_id);
const filteredEntitiesByDomain = new Set<string>(); const filteredEntitiesByDomain = new Set<string>();
@ -547,7 +540,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
entitiesByDomain[source.domain].push(entity); entitiesByDomain[source.domain].push(entity);
} }
for (const val of filter.value) { for (const val of filter) {
if (val in entitiesByDomain) { if (val in entitiesByDomain) {
entitiesByDomain[val].forEach((item) => entitiesByDomain[val].forEach((item) =>
filteredEntitiesByDomain.add(item) filteredEntitiesByDomain.add(item)
@ -558,32 +551,34 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
filteredEntities = filteredEntities.filter( filteredEntities = filteredEntities.filter(
(entity) => (entity) =>
filteredEntitiesByDomain.has(entity.entity_id) || filteredEntitiesByDomain.has(entity.entity_id) ||
(filter.value as string[]).includes(entity.platform) || (filter as string[]).includes(entity.platform) ||
(entity.config_entry_id && (entity.config_entry_id &&
entryIds.includes(entity.config_entry_id)) entryIds.includes(entity.config_entry_id))
); );
filter.value!.forEach((domain) => filteredDomains.add(domain)); filter!.forEach((domain) => filteredDomains.add(domain));
} else if ( } else if (
key === "ha-filter-domains" && key === "ha-filter-domains" &&
Array.isArray(filter.value) && Array.isArray(filter) &&
filter.value.length filter.length
) { ) {
filteredEntities = filteredEntities.filter((entity) => filteredEntities = filteredEntities.filter((entity) =>
(filter.value as string[]).includes(computeDomain(entity.entity_id)) (filter as string[]).includes(computeDomain(entity.entity_id))
); );
} else if ( } else if (
key === "ha-filter-labels" && key === "ha-filter-labels" &&
Array.isArray(filter.value) && Array.isArray(filter) &&
filter.value.length filter.length
) { ) {
filteredEntities = filteredEntities.filter((entity) => filteredEntities = filteredEntities.filter((entity) =>
entity.labels.some((lbl) => entity.labels.some((lbl) => (filter as string[]).includes(lbl))
(filter.value as string[]).includes(lbl)
)
); );
} else if (filter.items) { }
});
Object.values(filteredItems).forEach((items) => {
if (items) {
filteredEntities = filteredEntities.filter((entity) => filteredEntities = filteredEntities.filter((entity) =>
filter.items!.has(entity.entity_id) items.has(entity.entity_id)
); );
} }
}); });
@ -684,6 +679,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
this.hass.areas, this.hass.areas,
this._stateEntities, this._stateEntities,
this._filters, this._filters,
this._filteredItems,
this._entries, this._entries,
this._labels this._labels
); );
@ -749,10 +745,10 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
hasFilters hasFilters
.filters=${ .filters=${
Object.values(this._filters).filter((filter) => Object.values(this._filters).filter((filter) =>
Array.isArray(filter.value) Array.isArray(filter)
? filter.value.length ? filter.length
: filter.value && : filter &&
Object.values(filter.value).some((val) => Object.values(filter).some((val) =>
Array.isArray(val) ? val.length : val Array.isArray(val) ? val.length : val
) )
).length ).length
@ -897,21 +893,20 @@ ${
</ha-button-menu-new> </ha-button-menu-new>
${ ${
Array.isArray(this._filters.config_entry?.value) && Array.isArray(this._filters.config_entry) &&
this._filters.config_entry?.value.length this._filters.config_entry?.length
? html`<ha-alert slot="filter-pane"> ? html`<ha-alert slot="filter-pane">
Filtering by config entry Filtering by config entry
${this._entries?.find( ${this._entries?.find(
(entry) => (entry) => entry.entry_id === this._filters.config_entry![0]
entry.entry_id === this._filters.config_entry!.value![0] )?.title || this._filters.config_entry[0]}
)?.title || this._filters.config_entry.value[0]}
</ha-alert>` </ha-alert>`
: nothing : nothing
} }
<ha-filter-floor-areas <ha-filter-floor-areas
.hass=${this.hass} .hass=${this.hass}
type="entity" type="entity"
.value=${this._filters["ha-filter-floor-areas"]?.value} .value=${this._filters["ha-filter-floor-areas"]}
@data-table-filter-changed=${this._filterChanged} @data-table-filter-changed=${this._filterChanged}
slot="filter-pane" slot="filter-pane"
.expanded=${this._expandedFilter === "ha-filter-floor-areas"} .expanded=${this._expandedFilter === "ha-filter-floor-areas"}
@ -921,7 +916,7 @@ ${
<ha-filter-devices <ha-filter-devices
.hass=${this.hass} .hass=${this.hass}
.type=${"entity"} .type=${"entity"}
.value=${this._filters["ha-filter-devices"]?.value} .value=${this._filters["ha-filter-devices"]}
@data-table-filter-changed=${this._filterChanged} @data-table-filter-changed=${this._filterChanged}
slot="filter-pane" slot="filter-pane"
.expanded=${this._expandedFilter === "ha-filter-devices"} .expanded=${this._expandedFilter === "ha-filter-devices"}
@ -930,7 +925,7 @@ ${
></ha-filter-devices> ></ha-filter-devices>
<ha-filter-domains <ha-filter-domains
.hass=${this.hass} .hass=${this.hass}
.value=${this._filters["ha-filter-domains"]?.value} .value=${this._filters["ha-filter-domains"]}
@data-table-filter-changed=${this._filterChanged} @data-table-filter-changed=${this._filterChanged}
slot="filter-pane" slot="filter-pane"
.expanded=${this._expandedFilter === "ha-filter-domains"} .expanded=${this._expandedFilter === "ha-filter-domains"}
@ -939,7 +934,7 @@ ${
></ha-filter-domains> ></ha-filter-domains>
<ha-filter-integrations <ha-filter-integrations
.hass=${this.hass} .hass=${this.hass}
.value=${this._filters["ha-filter-integrations"]?.value} .value=${this._filters["ha-filter-integrations"]}
@data-table-filter-changed=${this._filterChanged} @data-table-filter-changed=${this._filterChanged}
slot="filter-pane" slot="filter-pane"
.expanded=${this._expandedFilter === "ha-filter-integrations"} .expanded=${this._expandedFilter === "ha-filter-integrations"}
@ -951,7 +946,7 @@ ${
.label=${this.hass.localize( .label=${this.hass.localize(
"ui.panel.config.entities.picker.headers.status" "ui.panel.config.entities.picker.headers.status"
)} )}
.value=${this._filters["ha-filter-states"]?.value} .value=${this._filters["ha-filter-states"]}
.states=${this._states(this.hass.localize)} .states=${this._states(this.hass.localize)}
@data-table-filter-changed=${this._filterChanged} @data-table-filter-changed=${this._filterChanged}
slot="filter-pane" slot="filter-pane"
@ -961,7 +956,7 @@ ${
></ha-filter-states> ></ha-filter-states>
<ha-filter-labels <ha-filter-labels
.hass=${this.hass} .hass=${this.hass}
.value=${this._filters["ha-filter-labels"]?.value} .value=${this._filters["ha-filter-labels"]}
@data-table-filter-changed=${this._filterChanged} @data-table-filter-changed=${this._filterChanged}
slot="filter-pane" slot="filter-pane"
.expanded=${this._expandedFilter === "ha-filter-labels"} .expanded=${this._expandedFilter === "ha-filter-labels"}
@ -996,7 +991,9 @@ ${
private _filterChanged(ev) { private _filterChanged(ev) {
const type = ev.target.localName; const type = ev.target.localName;
this._filters = { ...this._filters, [type]: ev.detail };
this._filters = { ...this._filters, [type]: ev.detail.value };
this._filteredItems = { ...this._filteredItems, [type]: ev.detail.items };
} }
protected firstUpdated() { protected firstUpdated() {
@ -1008,10 +1005,7 @@ ${
return; return;
} }
this._filters = { this._filters = {
"ha-filter-states": { "ha-filter-states": ["enabled"],
value: ["enabled"],
items: undefined,
},
}; };
} }
@ -1026,18 +1020,9 @@ ${
this._filter = history.state?.filter || ""; this._filter = history.state?.filter || "";
this._filters = { this._filters = {
"ha-filter-states": { "ha-filter-states": [],
value: [], "ha-filter-integrations": domain ? [domain] : [],
items: undefined, config_entry: configEntry ? [configEntry] : [],
},
"ha-filter-integrations": {
value: domain ? [domain] : [],
items: undefined,
},
config_entry: {
value: configEntry ? [configEntry] : [],
items: undefined,
},
}; };
if (this._searchParms.has("label")) { if (this._searchParms.has("label")) {
@ -1052,15 +1037,13 @@ ${
} }
this._filters = { this._filters = {
...this._filters, ...this._filters,
"ha-filter-labels": { "ha-filter-labels": [label],
value: [label],
items: undefined,
},
}; };
} }
private _clearFilter() { private _clearFilter() {
this._filters = {}; this._filters = {};
this._filteredItems = {};
} }
public willUpdate(changedProps: PropertyValues): void { public willUpdate(changedProps: PropertyValues): void {
@ -1070,8 +1053,10 @@ ${
if (!this.hass || !this._entities) { if (!this.hass || !this._entities) {
return; return;
} }
if ( if (
changedProps.has("hass") || (changedProps.has("hass") &&
(!oldHass || oldHass.states !== this.hass.states)) ||
changedProps.has("_entities") || changedProps.has("_entities") ||
changedProps.has("_entitySources") changedProps.has("_entitySources")
) { ) {
@ -1084,9 +1069,9 @@ ${
continue; continue;
} }
if ( if (
!oldHass ||
changedProps.has("_entitySources") || changedProps.has("_entitySources") ||
this.hass.states[entityId] !== oldHass.states[entityId] (changedProps.has("hass") && !oldHass) ||
!oldHass.states[entityId]
) { ) {
changed = true; changed = true;
} }
@ -1357,6 +1342,7 @@ ${rejected
this.hass.areas, this.hass.areas,
this._stateEntities, this._stateEntities,
this._filters, this._filters,
this._filteredItems,
this._entries, this._entries,
this._labels this._labels
); );