From 8222d9796c72844991b1f3e0a09d5e21eb114f4e Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 25 Mar 2026 09:52:19 +0100 Subject: [PATCH] Show related entities warning when deleting helpers (#30302) --- .../settings/entity-settings-helper-tab.ts | 14 +++- .../entities/entity-registry-settings.ts | 71 +++++++------------ .../entities/get-delete-confirmation-text.ts | 48 +++++++++++++ 3 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 src/panels/config/entities/get-delete-confirmation-text.ts diff --git a/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts b/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts index 0bb8948a93..dca650e8ed 100644 --- a/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts +++ b/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts @@ -4,6 +4,7 @@ import { customElement, property, query, state } from "lit/decorators"; import { isComponentLoaded } from "../../../../../common/config/is_component_loaded"; import { dynamicElement } from "../../../../../common/dom/dynamic-element-directive"; import { fireEvent } from "../../../../../common/dom/fire_event"; +import { computeEntityEntryName } from "../../../../../common/entity/compute_entity_name"; import "../../../../../components/ha-button"; import type { ExtEntityRegistryEntry } from "../../../../../data/entity/entity_registry"; import { removeEntityRegistryEntry } from "../../../../../data/entity/entity_registry"; @@ -24,6 +25,7 @@ import "../../../helpers/forms/ha-timer-form"; import "../../../voice-assistants/entity-voice-settings"; import "../../entity-registry-settings-editor"; import type { EntityRegistrySettingsEditor } from "../../entity-registry-settings-editor"; +import { getDeleteConfirmationText } from "../../get-delete-confirmation-text"; @customElement("entity-settings-helper-tab") export class EntitySettingsHelperTab extends LitElement { @@ -162,11 +164,19 @@ export class EntitySettingsHelperTab extends LitElement { } private async _confirmDeleteItem(): Promise { + const name = computeEntityEntryName(this.entry); + const confirmationText = await getDeleteConfirmationText( + this.hass, + this.entry, + name + ); + if ( !(await showConfirmationDialog(this, { - text: this.hass.localize( - "ui.dialogs.entity_registry.editor.confirm_delete" + title: this.hass.localize( + "ui.dialogs.entity_registry.editor.confirm_delete_title" ), + text: confirmationText, confirmText: this.hass.localize("ui.common.delete"), dismissText: this.hass.localize("ui.common.cancel"), destructive: true, diff --git a/src/panels/config/entities/entity-registry-settings.ts b/src/panels/config/entities/entity-registry-settings.ts index 428391eaac..5e25787baf 100644 --- a/src/panels/config/entities/entity-registry-settings.ts +++ b/src/panels/config/entities/entity-registry-settings.ts @@ -1,9 +1,11 @@ import type { HassEntity } from "home-assistant-js-websocket"; -import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit"; +import type { CSSResultGroup, PropertyValues } from "lit"; import { css, html, LitElement } from "lit"; import { customElement, property, query, state } from "lit/decorators"; -import { formatListWithAnds } from "../../../common/string/format-list"; import { fireEvent } from "../../../common/dom/fire_event"; +import { computeDeviceName } from "../../../common/entity/compute_device_name"; +import { computeEntityEntryName } from "../../../common/entity/compute_entity_name"; +import { getEntityEntryContext } from "../../../common/entity/context/get_entity_context"; import "../../../components/ha-alert"; import "../../../components/ha-button"; import type { ConfigEntry } from "../../../data/config_entries"; @@ -17,7 +19,6 @@ import { removeEntityRegistryEntry, updateEntityRegistryEntry, } from "../../../data/entity/entity_registry"; -import { findRelated } from "../../../data/search"; import { fetchIntegrationManifest } from "../../../data/integration"; import { showAlertDialog, @@ -29,9 +30,7 @@ import type { HomeAssistant } from "../../../types"; import { showDeviceRegistryDetailDialog } from "../devices/device-registry-detail/show-dialog-device-registry-detail"; import "./entity-registry-settings-editor"; import type { EntityRegistrySettingsEditor } from "./entity-registry-settings-editor"; -import { computeEntityEntryName } from "../../../common/entity/compute_entity_name"; - -const RELATED_ENTITY_DOMAINS = ["automation", "script", "group", "scene"]; +import { getDeleteConfirmationText } from "./get-delete-confirmation-text"; @customElement("entity-registry-settings") export class EntityRegistrySettings extends SubscribeMixin(LitElement) { @@ -214,7 +213,25 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) { } private async _confirmDeleteEntry(): Promise { - const confirmationText = await this._getDeleteConfirmationText(); + let name = computeEntityEntryName(this.entry); + if (!name) { + const { device } = getEntityEntryContext( + this.entry, + this.hass.entities, + this.hass.devices, + this.hass.areas, + this.hass.floors + ); + if (device) { + name = computeDeviceName(device); + } + } + + const confirmationText = await getDeleteConfirmationText( + this.hass, + this.entry, + name + ); if ( !(await showConfirmationDialog(this, { @@ -244,46 +261,6 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) { } } - private async _getDeleteConfirmationText(): Promise { - const mainText = this.hass.localize( - "ui.dialogs.entity_registry.editor.confirm_delete", - { entity_name: computeEntityEntryName(this.entry) } - ); - - try { - const related = await findRelated( - this.hass, - "entity", - this.entry.entity_id - ); - - const relatedItems = RELATED_ENTITY_DOMAINS.map((domain) => { - const count = related[domain]?.length || 0; - if (count === 0) { - return undefined; - } - return this.hass.localize( - `ui.dialogs.entity_registry.editor.confirm_delete_count.${domain}`, - { count } - ); - }).filter((item): item is string => Boolean(item)); - - if (relatedItems.length === 0) { - return mainText; - } - - return html`${mainText}

- ${this.hass.localize( - "ui.dialogs.entity_registry.editor.confirm_delete_related", - { - items: formatListWithAnds(this.hass.locale, relatedItems), - } - )}`; - } catch (_err) { - return mainText; - } - } - static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/entities/get-delete-confirmation-text.ts b/src/panels/config/entities/get-delete-confirmation-text.ts new file mode 100644 index 0000000000..048e450e2b --- /dev/null +++ b/src/panels/config/entities/get-delete-confirmation-text.ts @@ -0,0 +1,48 @@ +import type { TemplateResult } from "lit"; +import { html } from "lit"; +import { formatListWithAnds } from "../../../common/string/format-list"; +import type { ExtEntityRegistryEntry } from "../../../data/entity/entity_registry"; +import { findRelated } from "../../../data/search"; +import type { HomeAssistant } from "../../../types"; + +const RELATED_ENTITY_DOMAINS = ["automation", "script", "group", "scene"]; + +export const getDeleteConfirmationText = async ( + hass: HomeAssistant, + entry: ExtEntityRegistryEntry, + name: string | undefined +): Promise => { + const mainText = hass.localize( + "ui.dialogs.entity_registry.editor.confirm_delete", + { entity_name: name } + ); + + try { + const related = await findRelated(hass, "entity", entry.entity_id); + + const relatedItems = RELATED_ENTITY_DOMAINS.map((domain) => { + const count = related[domain]?.length || 0; + if (count === 0) { + return undefined; + } + return hass.localize( + `ui.dialogs.entity_registry.editor.confirm_delete_count.${domain}`, + { count } + ); + }).filter((item): item is string => Boolean(item)); + + if (relatedItems.length === 0) { + return mainText; + } + + return html`${mainText}

+ ${hass.localize( + "ui.dialogs.entity_registry.editor.confirm_delete_related", + { + items: formatListWithAnds(hass.locale, relatedItems), + } + )}`; + } catch (_err) { + return mainText; + } +};