diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts index 50c280fdf5..440f756696 100644 --- a/src/panels/config/helpers/ha-config-helpers.ts +++ b/src/panels/config/helpers/ha-config-helpers.ts @@ -5,6 +5,7 @@ import { mdiCancel, mdiChevronRight, mdiCog, + mdiDelete, mdiDotsVertical, mdiMenuDown, mdiPencilOff, @@ -109,10 +110,11 @@ import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; import { renderConfigEntryError } from "../integrations/ha-config-integration-page"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; -import { isHelperDomain } from "./const"; +import { isHelperDomain, type HelperDomain } from "./const"; import { showHelperDetailDialog } from "./show-dialog-helper-detail"; import { slugify } from "../../../common/string/slugify"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; +import { HELPERS_CRUD } from "../../../data/helpers_crud"; import { fetchDiagnosticHandlers, getConfigEntryDiagnosticsDownloadUrl, @@ -451,6 +453,19 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { }, ] : []), + ...(helper.editable && helper.entity + ? [ + { + divider: true, + }, + { + path: mdiDelete, + label: this.hass.localize("ui.common.delete"), + warning: true, + action: () => this._deleteHelper(helper), + }, + ] + : []), ]} > @@ -1280,6 +1295,62 @@ ${rejected } } + private async _deleteHelper(helper: HelperItem) { + if (!helper.entity_id) { + return; + } + + const confirmed = await showConfirmationDialog(this, { + title: this.hass.localize( + "ui.panel.config.helpers.picker.delete_confirm_title" + ), + text: this.hass.localize( + "ui.panel.config.helpers.picker.delete_confirm_text", + { name: helper.name } + ), + confirmText: this.hass.localize("ui.common.delete"), + dismissText: this.hass.localize("ui.common.cancel"), + destructive: true, + }); + + if (!confirmed) { + return; + } + + try { + // For old-style helpers (input_boolean, etc.), use HELPERS_CRUD + if (isHelperDomain(helper.type)) { + const entityReg = this._entityReg.find( + (e) => e.entity_id === helper.entity_id + ); + if ( + !entityReg?.unique_id || + !isComponentLoaded(this.hass, helper.type) + ) { + throw new Error( + this.hass.localize("ui.panel.config.helpers.picker.delete_failed") + ); + } + await HELPERS_CRUD[helper.type as HelperDomain].delete( + this.hass, + entityReg.unique_id + ); + return; + } + + // For config entry-based helpers, delete the config entry + if (helper.configEntry) { + await deleteConfigEntry(this.hass, helper.configEntry.entry_id); + } + } catch (err: any) { + showAlertDialog(this, { + text: + err.message || + this.hass.localize("ui.panel.config.helpers.picker.delete_failed"), + }); + } + } + private _createHelper() { showHelperDetailDialog(this, {}); } diff --git a/src/translations/en.json b/src/translations/en.json index bd247e829c..3c950d0169 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3265,7 +3265,10 @@ "create_helper": "Create helper", "no_helpers": "Looks like you don't have any helpers yet!", "search": "Search {number} {number, plural,\n one {helper}\n other {helpers}\n}", - "error_information": "Error information" + "error_information": "Error information", + "delete_confirm_title": "Delete helper?", + "delete_confirm_text": "Are you sure you want to delete {name}?", + "delete_failed": "Failed to delete helper" }, "dialog": { "create": "Create",