diff --git a/gallery/src/pages/misc/integration-card.ts b/gallery/src/pages/misc/integration-card.ts index e9d74f2f1b..53f16a16b2 100644 --- a/gallery/src/pages/misc/integration-card.ts +++ b/gallery/src/pages/misc/integration-card.ts @@ -29,6 +29,7 @@ const createConfigEntry = ( source: "zeroconf", state: "loaded", supports_options: false, + supports_remove_device: false, supports_unload: true, disabled_by: null, pref_disable_new_entities: false, diff --git a/src/data/config_entries.ts b/src/data/config_entries.ts index 78cbe6105a..f2e84ddac0 100644 --- a/src/data/config_entries.ts +++ b/src/data/config_entries.ts @@ -13,6 +13,7 @@ export interface ConfigEntry { | "not_loaded" | "failed_unload"; supports_options: boolean; + supports_remove_device: boolean; supports_unload: boolean; pref_disable_new_entities: boolean; pref_disable_polling: boolean; diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts index 65c0bcec56..64e29d3a20 100644 --- a/src/data/device_registry.ts +++ b/src/data/device_registry.ts @@ -77,6 +77,17 @@ export const updateDeviceRegistryEntry = ( ...updates, }); +export const removeConfigEntryFromDevice = ( + hass: HomeAssistant, + deviceId: string, + configEntryId: string +) => + hass.callWS({ + type: "config/device_registry/remove_config_entry", + device_id: deviceId, + config_entry_id: configEntryId, + }); + export const fetchDeviceRegistry = (conn) => conn.sendMessagePromise({ type: "config/device_registry/list", diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index b29aa39951..5572834106 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -27,6 +27,7 @@ import { computeDeviceName, DeviceRegistryEntry, updateDeviceRegistryEntry, + removeConfigEntryFromDevice, } from "../../../data/device_registry"; import { fetchDiagnosticHandler, @@ -95,6 +96,8 @@ export class HaConfigDevicePage extends LitElement { | number | (TemplateResult | string)[]; + @state() private _deleteButtons?: (TemplateResult | string)[]; + private _device = memoizeOne( ( deviceId: string, @@ -186,10 +189,11 @@ export class HaConfigDevicePage extends LitElement { changedProps.has("entries") ) { this._diagnosticDownloadLinks = undefined; + this._deleteButtons = undefined; } if ( - this._diagnosticDownloadLinks || + (this._diagnosticDownloadLinks && this._deleteButtons) || !this.devices || !this.deviceId || !this.entries @@ -198,7 +202,9 @@ export class HaConfigDevicePage extends LitElement { } this._diagnosticDownloadLinks = Math.random(); + this._deleteButtons = []; // To prevent re-rendering if no delete buttons this._renderDiagnosticButtons(this._diagnosticDownloadLinks); + this._renderDeleteButtons(); } private async _renderDiagnosticButtons(requestId: number): Promise { @@ -263,6 +269,55 @@ export class HaConfigDevicePage extends LitElement { } } + private _renderDeleteButtons() { + const device = this._device(this.deviceId, this.devices); + + if (!device) { + return; + } + + const buttons: TemplateResult[] = []; + this._integrations(device, this.entries).forEach((entry) => { + if (entry.state !== "loaded" || !entry.supports_remove_device) { + return; + } + buttons.push(html` + + ${buttons.length > 1 + ? this.hass.localize( + `ui.panel.config.devices.delete_device_integration`, + { + integration: domainToName(this.hass.localize, entry.domain), + } + ) + : this.hass.localize(`ui.panel.config.devices.delete_device`)} + + `); + }); + + if (buttons.length > 0) { + this._deleteButtons = buttons; + } + } + + private async _confirmDeleteEntry(e: MouseEvent): Promise { + const entryId = (e.currentTarget as any).entryId; + + const confirmed = await showConfirmationDialog(this, { + text: this.hass.localize("ui.panel.config.devices.confirm_delete"), + }); + + if (!confirmed) { + return; + } + + await removeConfigEntryFromDevice(this.hass!, this.deviceId, entryId); + } + protected firstUpdated(changedProps) { super.firstUpdated(changedProps); loadDeviceRegistryDetailDialog(); @@ -375,6 +430,9 @@ export class HaConfigDevicePage extends LitElement { if (Array.isArray(this._diagnosticDownloadLinks)) { deviceActions.push(...this._diagnosticDownloadLinks); } + if (this._deleteButtons) { + deviceActions.push(...this._deleteButtons); + } return html`