From c0cc163636bb829a9650485479ff8794f7706470 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Tue, 14 Jan 2025 21:14:48 +0100 Subject: [PATCH 1/2] Sort related on device info page --- src/components/ha-related-items.ts | 45 +---- src/data/search.ts | 16 ++ .../config/devices/ha-config-device-page.ts | 172 +++++++++--------- 3 files changed, 110 insertions(+), 123 deletions(-) diff --git a/src/components/ha-related-items.ts b/src/components/ha-related-items.ts index cce81fba7644..6319af2e6be5 100644 --- a/src/components/ha-related-items.ts +++ b/src/components/ha-related-items.ts @@ -11,13 +11,12 @@ import { customElement, property, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { fireEvent } from "../common/dom/fire_event"; -import { caseInsensitiveStringCompare } from "../common/string/compare"; import type { Blueprints } from "../data/blueprint"; import { fetchBlueprints } from "../data/blueprint"; import type { ConfigEntry } from "../data/config_entries"; import { getConfigEntries } from "../data/config_entries"; import type { ItemType, RelatedResult } from "../data/search"; -import { findRelated } from "../data/search"; +import { sortRelated, findRelated } from "../data/search"; import { haStyle } from "../resources/styles"; import type { HomeAssistant } from "../types"; import { brandsUrl } from "../util/brands-url"; @@ -74,38 +73,6 @@ export class HaRelatedItems extends LitElement { } } - private _relatedEntities = memoizeOne((entityIds: string[]) => - this._toEntities(entityIds) - ); - - private _relatedAutomations = memoizeOne((automationEntityIds: string[]) => - this._toEntities(automationEntityIds) - ); - - private _relatedScripts = memoizeOne((scriptEntityIds: string[]) => - this._toEntities(scriptEntityIds) - ); - - private _relatedGroups = memoizeOne((groupEntityIds: string[]) => - this._toEntities(groupEntityIds) - ); - - private _relatedScenes = memoizeOne((sceneEntityIds: string[]) => - this._toEntities(sceneEntityIds) - ); - - private _toEntities = (entityIds: string[]) => - entityIds - .map((entityId) => this.hass.states[entityId]) - .filter((entity) => entity) - .sort((a, b) => - caseInsensitiveStringCompare( - a.attributes.friendly_name ?? a.entity_id, - b.attributes.friendly_name ?? b.entity_id, - this.hass.language - ) - ); - private _getConfigEntries = memoizeOne( ( relatedConfigEntries: string[] | undefined, @@ -275,7 +242,7 @@ export class HaRelatedItems extends LitElement { ? html`

${this.hass.localize("ui.components.related-items.entity")}

- ${this._relatedEntities(this._related.entity).map( + ${sortRelated(this.hass, this._related.entity).map( (entity) => html` ${this.hass.localize("ui.components.related-items.group")} - ${this._relatedGroups(this._related.group).map( + ${sortRelated(this.hass, this._related.group).map( (group) => html` ${this.hass.localize("ui.components.related-items.scene")} - ${this._relatedScenes(this._related.scene).map( + ${sortRelated(this.hass, this._related.scene).map( (scene) => html` - ${this._relatedAutomations(this._related.automation).map( + ${sortRelated(this.hass, this._related.automation).map( (automation) => html` ${this.hass.localize("ui.components.related-items.script")} - ${this._relatedScripts(this._related.script).map( + ${sortRelated(this.hass, this._related.script).map( (script) => html` + entityIds + .map((entityId) => hass.states[entityId]) + .filter((entity) => entity) + .sort((a, b) => + caseInsensitiveStringCompare( + a.attributes.friendly_name ?? a.entity_id, + b.attributes.friendly_name ?? b.entity_id, + hass.language + ) + ) +); diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index ad7e23738fcc..9a4bf4db9563 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -63,7 +63,7 @@ import { domainToName } from "../../../data/integration"; import type { SceneEntities } from "../../../data/scene"; import { showSceneEditor } from "../../../data/scene"; import type { RelatedResult } from "../../../data/search"; -import { findRelated } from "../../../data/search"; +import { sortRelated, findRelated } from "../../../data/search"; import { showAlertDialog, showConfirmationDialog, @@ -441,38 +441,38 @@ export class HaConfigDevicePage extends LitElement { ${this._related?.automation?.length ? html`
- ${this._related.automation.map((automation) => { - const entityState = this.hass.states[automation]; - return entityState - ? html`
- - + automationState + ? html`
+ - ${computeStateName(entityState)} - - - - ${!entityState.attributes.id - ? html` - - ${this.hass.localize( - "ui.panel.config.devices.cant_edit" - )} - - ` - : ""} -
` - : ""; - })} + + ${computeStateName(automationState)} + + + + ${!automationState.attributes.id + ? html` + + ${this.hass.localize( + "ui.panel.config.devices.cant_edit" + )} + + ` + : ""} +
` + : "" + )}
` : html` @@ -532,40 +532,40 @@ export class HaConfigDevicePage extends LitElement { ${this._related?.scene?.length ? html`
- ${this._related.scene.map((scene) => { - const entityState = this.hass.states[scene]; - return entityState - ? html` -
- - + sceneState + ? html` +
+ - ${computeStateName(entityState)} - - - - ${!entityState.attributes.id - ? html` - - ${this.hass.localize( - "ui.panel.config.devices.cant_edit" - )} - - ` - : ""} -
- ` - : ""; - })} + + ${computeStateName(sceneState)} + + + + ${!sceneState.attributes.id + ? html` + + ${this.hass.localize( + "ui.panel.config.devices.cant_edit" + )} + + ` + : ""} +
+ ` + : "" + )}
` : html` @@ -626,26 +626,30 @@ export class HaConfigDevicePage extends LitElement { ${this._related?.script?.length ? html`
- ${this._related.script.map((script) => { - const entityState = this.hass.states[script]; - const entry = this._entityReg.find( - (e) => e.entity_id === script - ); - let url = `/config/script/show/${entityState.entity_id}`; - if (entry) { - url = `/config/script/edit/${entry.unique_id}`; + ${sortRelated(this.hass, this._related.script).map( + (scriptState) => { + const entry = this._entityReg.find( + (e) => e.entity_id === scriptState.entity_id + ); + let url = `/config/script/show/${scriptState.entity_id}`; + if (entry) { + url = `/config/script/edit/${entry.unique_id}`; + } + return scriptState + ? html` + + + ${computeStateName(scriptState)} + + + + ` + : ""; } - return entityState - ? html` - - - ${computeStateName(entityState)} - - - - ` - : ""; - })} + )}
` : html` From e189c0289fc45e658c472a5fa6760a3b5bcc6c38 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Wed, 15 Jan 2025 08:48:03 +0100 Subject: [PATCH 2/2] Always sort in findRelated --- src/components/ha-related-items.ts | 16 +- src/data/search.ts | 25 +-- .../config/devices/ha-config-device-page.ts | 172 +++++++++--------- 3 files changed, 108 insertions(+), 105 deletions(-) diff --git a/src/components/ha-related-items.ts b/src/components/ha-related-items.ts index 6319af2e6be5..017a3164b956 100644 --- a/src/components/ha-related-items.ts +++ b/src/components/ha-related-items.ts @@ -16,7 +16,7 @@ import { fetchBlueprints } from "../data/blueprint"; import type { ConfigEntry } from "../data/config_entries"; import { getConfigEntries } from "../data/config_entries"; import type { ItemType, RelatedResult } from "../data/search"; -import { sortRelated, findRelated } from "../data/search"; +import { findRelated } from "../data/search"; import { haStyle } from "../resources/styles"; import type { HomeAssistant } from "../types"; import { brandsUrl } from "../util/brands-url"; @@ -73,6 +73,10 @@ export class HaRelatedItems extends LitElement { } } + private _toEntities = memoizeOne((entityIds: string[]) => + entityIds.map((entityId) => this.hass.states[entityId]) + ); + private _getConfigEntries = memoizeOne( ( relatedConfigEntries: string[] | undefined, @@ -242,7 +246,7 @@ export class HaRelatedItems extends LitElement { ? html`

${this.hass.localize("ui.components.related-items.entity")}

- ${sortRelated(this.hass, this._related.entity).map( + ${this._toEntities(this._related.entity).map( (entity) => html` ${this.hass.localize("ui.components.related-items.group")} - ${sortRelated(this.hass, this._related.group).map( + ${this._toEntities(this._related.group).map( (group) => html` ${this.hass.localize("ui.components.related-items.scene")} - ${sortRelated(this.hass, this._related.scene).map( + ${this._toEntities(this._related.scene).map( (scene) => html` - ${sortRelated(this.hass, this._related.automation).map( + ${this._toEntities(this._related.automation).map( (automation) => html` ${this.hass.localize("ui.components.related-items.script")} - ${sortRelated(this.hass, this._related.script).map( + ${this._toEntities(this._related.script).map( (script) => html` => - hass.callWS({ +): Promise => { + const related = await hass.callWS({ type: "search/related", item_type: itemType, item_id: itemId, }); -export const sortRelated = memoizeOne( - (hass: HomeAssistant, entityIds: string[]) => - entityIds - .map((entityId) => hass.states[entityId]) - .filter((entity) => entity) - .sort((a, b) => + Object.keys(related).forEach((key) => { + related[key] = related[key] + .map((id: string) => hass.states[id]) + .filter(Boolean) + .sort((a: HassEntity, b: HassEntity) => caseInsensitiveStringCompare( a.attributes.friendly_name ?? a.entity_id, b.attributes.friendly_name ?? b.entity_id, hass.language ) ) -); + .map((entity: HassEntity) => entity.entity_id); + }); + + return related; +}; diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 9a4bf4db9563..ad7e23738fcc 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -63,7 +63,7 @@ import { domainToName } from "../../../data/integration"; import type { SceneEntities } from "../../../data/scene"; import { showSceneEditor } from "../../../data/scene"; import type { RelatedResult } from "../../../data/search"; -import { sortRelated, findRelated } from "../../../data/search"; +import { findRelated } from "../../../data/search"; import { showAlertDialog, showConfirmationDialog, @@ -441,38 +441,38 @@ export class HaConfigDevicePage extends LitElement { ${this._related?.automation?.length ? html`
- ${sortRelated(this.hass, this._related.automation).map( - (automationState) => - automationState - ? html`
- { + const entityState = this.hass.states[automation]; + return entityState + ? html`
+ + - - ${computeStateName(automationState)} - - - - ${!automationState.attributes.id - ? html` - - ${this.hass.localize( - "ui.panel.config.devices.cant_edit" - )} - - ` - : ""} -
` - : "" - )} + ${computeStateName(entityState)} + + + + ${!entityState.attributes.id + ? html` + + ${this.hass.localize( + "ui.panel.config.devices.cant_edit" + )} + + ` + : ""} +
` + : ""; + })}
` : html` @@ -532,40 +532,40 @@ export class HaConfigDevicePage extends LitElement { ${this._related?.scene?.length ? html`
- ${sortRelated(this.hass, this._related.scene).map( - (sceneState) => - sceneState - ? html` -
- { + const entityState = this.hass.states[scene]; + return entityState + ? html` +
+ + - - ${computeStateName(sceneState)} - - - - ${!sceneState.attributes.id - ? html` - - ${this.hass.localize( - "ui.panel.config.devices.cant_edit" - )} - - ` - : ""} -
- ` - : "" - )} + ${computeStateName(entityState)} + + + + ${!entityState.attributes.id + ? html` + + ${this.hass.localize( + "ui.panel.config.devices.cant_edit" + )} + + ` + : ""} +
+ ` + : ""; + })}
` : html` @@ -626,30 +626,26 @@ export class HaConfigDevicePage extends LitElement { ${this._related?.script?.length ? html`
- ${sortRelated(this.hass, this._related.script).map( - (scriptState) => { - const entry = this._entityReg.find( - (e) => e.entity_id === scriptState.entity_id - ); - let url = `/config/script/show/${scriptState.entity_id}`; - if (entry) { - url = `/config/script/edit/${entry.unique_id}`; - } - return scriptState - ? html` - - - ${computeStateName(scriptState)} - - - - ` - : ""; + ${this._related.script.map((script) => { + const entityState = this.hass.states[script]; + const entry = this._entityReg.find( + (e) => e.entity_id === script + ); + let url = `/config/script/show/${entityState.entity_id}`; + if (entry) { + url = `/config/script/edit/${entry.unique_id}`; } - )} + return entityState + ? html` + + + ${computeStateName(entityState)} + + + + ` + : ""; + })}
` : html`