From 0dc56d79830533b46c56392c18f7a2a32512fab3 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 17 Feb 2022 16:46:08 +0100 Subject: [PATCH 01/10] Add support for removing config entry from a device --- src/data/config_entries.ts | 1 + src/data/device_registry.ts | 11 +++ .../config/devices/ha-config-device-page.ts | 70 ++++++++++++++++++- src/translations/en.json | 2 + 4 files changed, 83 insertions(+), 1 deletion(-) 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..69cdb6b974 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 5e966278e8..999b7aebdd 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 = [".."]; this._renderDiagnosticButtons(this._diagnosticDownloadLinks); + this._renderDeleteButtons(); } private async _renderDiagnosticButtons(requestId: number): Promise { @@ -263,6 +269,65 @@ export class HaConfigDevicePage extends LitElement { } } + private _renderDeleteButtons() { + console.log("Hello!") + const device = this._device(this.deviceId, this.devices); + + if (!device) { + return; + } + + let buttons = this._integrations(device, this.entries).map((entry) => { + console.log("Hello!") + console.log(entry.supports_remove_device) + if (entry.state !== "loaded" || !entry.supports_remove_device) { + return false; + } + return { + entry_id: entry.entry_id, + domain: entry.domain, + }; + }); + + buttons = buttons.filter(Boolean); + + if (buttons.length > 0) { + this._deleteButtons = ( + buttons as { entry_id: string; domain: string }[] + ).map( + (button) => html` + + ${buttons.length > 1 + ? this.hass.localize( + `ui.panel.config.devices.delete_device_integration`, + { + integration: domainToName( + this.hass.localize, + button.domain + ), + } + ) + : this.hass.localize( + `ui.panel.config.devices.delete_device` + )} + + ` + ); + } + } + + private async _confirmDeleteEntry(): Promise { + const confirmed = await showConfirmationDialog(this, { + text: this.hass.localize("ui.panel.config.devices.confirm_delete"), + }); + + if (!confirmed) { + return; + } + + await removeConfigEntryFromDevice(this.hass!, this.deviceId, "blabla"); + } + protected firstUpdated(changedProps) { super.firstUpdated(changedProps); loadDeviceRegistryDetailDialog(); @@ -375,6 +440,9 @@ export class HaConfigDevicePage extends LitElement { if (Array.isArray(this._diagnosticDownloadLinks)) { deviceActions.push(...this._diagnosticDownloadLinks); } + if (Array.isArray(this._deleteButtons)) { + deviceActions.push(...this._deleteButtons); + } return html` Date: Thu, 17 Feb 2022 17:12:17 +0100 Subject: [PATCH 02/10] Tweak --- .../config/devices/ha-config-device-page.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 999b7aebdd..15da420e06 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -270,16 +270,13 @@ export class HaConfigDevicePage extends LitElement { } private _renderDeleteButtons() { - console.log("Hello!") const device = this._device(this.deviceId, this.devices); if (!device) { return; } - let buttons = this._integrations(device, this.entries).map((entry) => { - console.log("Hello!") - console.log(entry.supports_remove_device) + let buttons = this._integrations(device, this.entries).map((entry) => { if (entry.state !== "loaded" || !entry.supports_remove_device) { return false; } @@ -296,7 +293,11 @@ export class HaConfigDevicePage extends LitElement { buttons as { entry_id: string; domain: string }[] ).map( (button) => html` - + ${buttons.length > 1 ? this.hass.localize( `ui.panel.config.devices.delete_device_integration`, @@ -307,16 +308,16 @@ export class HaConfigDevicePage extends LitElement { ), } ) - : this.hass.localize( - `ui.panel.config.devices.delete_device` - )} + : this.hass.localize(`ui.panel.config.devices.delete_device`)} ` ); } } - private async _confirmDeleteEntry(): Promise { + private async _confirmDeleteEntry(e: MouseEvent): Promise { + const entry_id = (e.currentTarget! as HTMLElement).getAttribute("entry_id") + const confirmed = await showConfirmationDialog(this, { text: this.hass.localize("ui.panel.config.devices.confirm_delete"), }); @@ -325,7 +326,7 @@ export class HaConfigDevicePage extends LitElement { return; } - await removeConfigEntryFromDevice(this.hass!, this.deviceId, "blabla"); + await removeConfigEntryFromDevice(this.hass!, this.deviceId, entry_id); } protected firstUpdated(changedProps) { From 0abafff4c91782dd786700f4f59d1c8ad4b8e084 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Feb 2022 08:26:37 +0100 Subject: [PATCH 03/10] Fix lint error --- gallery/src/pages/misc/integration-card.ts | 1 + 1 file changed, 1 insertion(+) 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, From 8f5c9295d3bb723778fafcb34b9c873918b35f5f Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Feb 2022 08:48:53 +0100 Subject: [PATCH 04/10] Tweak --- src/panels/config/devices/ha-config-device-page.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 15da420e06..46b8a161ed 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -202,7 +202,7 @@ export class HaConfigDevicePage extends LitElement { } this._diagnosticDownloadLinks = Math.random(); - this._deleteButtons = [".."]; + this._deleteButtons = []; // To prevent re-rendering if no delete buttons this._renderDiagnosticButtons(this._diagnosticDownloadLinks); this._renderDeleteButtons(); } @@ -316,7 +316,7 @@ export class HaConfigDevicePage extends LitElement { } private async _confirmDeleteEntry(e: MouseEvent): Promise { - const entry_id = (e.currentTarget! as HTMLElement).getAttribute("entry_id") + const entry_id = (e.currentTarget! as HTMLElement).getAttribute("entry_id"); const confirmed = await showConfirmationDialog(this, { text: this.hass.localize("ui.panel.config.devices.confirm_delete"), @@ -326,7 +326,7 @@ export class HaConfigDevicePage extends LitElement { return; } - await removeConfigEntryFromDevice(this.hass!, this.deviceId, entry_id); + await removeConfigEntryFromDevice(this.hass!, this.deviceId, entry_id!); } protected firstUpdated(changedProps) { From 246724c59e51ee80220dffb8e48ea6ff9c04da96 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Feb 2022 09:13:18 +0100 Subject: [PATCH 05/10] Prettier --- src/data/device_registry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts index 69cdb6b974..64e29d3a20 100644 --- a/src/data/device_registry.ts +++ b/src/data/device_registry.ts @@ -80,7 +80,7 @@ export const updateDeviceRegistryEntry = ( export const removeConfigEntryFromDevice = ( hass: HomeAssistant, deviceId: string, - configEntryId: string, + configEntryId: string ) => hass.callWS({ type: "config/device_registry/remove_config_entry", From 4f6a241817da8e55240013b78ed3ed637fcf7884 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Fri, 18 Feb 2022 15:57:57 +0100 Subject: [PATCH 06/10] Apply suggestions from code review Co-authored-by: Bram Kragten --- .../config/devices/ha-config-device-page.ts | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 46b8a161ed..8b52379f08 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -276,26 +276,14 @@ export class HaConfigDevicePage extends LitElement { return; } - let buttons = this._integrations(device, this.entries).map((entry) => { + const buttons = this._integrations(device, this.entries).forEach((entry) => { if (entry.state !== "loaded" || !entry.supports_remove_device) { - return false; + return; } - return { - entry_id: entry.entry_id, - domain: entry.domain, - }; - }); - - buttons = buttons.filter(Boolean); - - if (buttons.length > 0) { - this._deleteButtons = ( - buttons as { entry_id: string; domain: string }[] - ).map( - (button) => html` + buttons.push(html` ${buttons.length > 1 @@ -304,19 +292,22 @@ export class HaConfigDevicePage extends LitElement { { integration: domainToName( this.hass.localize, - button.domain + 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 entry_id = (e.currentTarget! as HTMLElement).getAttribute("entry_id"); + const entryId = (e.currentTarget as any). entryId; const confirmed = await showConfirmationDialog(this, { text: this.hass.localize("ui.panel.config.devices.confirm_delete"), @@ -326,7 +317,7 @@ export class HaConfigDevicePage extends LitElement { return; } - await removeConfigEntryFromDevice(this.hass!, this.deviceId, entry_id!); + await removeConfigEntryFromDevice(this.hass!, this.deviceId, entryId); } protected firstUpdated(changedProps) { From 26689a0a855a21f24b981da63e7d720a1cd687fe Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Fri, 18 Feb 2022 16:21:11 +0100 Subject: [PATCH 07/10] Update src/panels/config/devices/ha-config-device-page.ts Co-authored-by: Bram Kragten --- src/panels/config/devices/ha-config-device-page.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 8b52379f08..7e94b312b4 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -276,7 +276,8 @@ export class HaConfigDevicePage extends LitElement { return; } - const buttons = this._integrations(device, this.entries).forEach((entry) => { + const buttons = []; + this._integrations(device, this.entries).forEach((entry) => { if (entry.state !== "loaded" || !entry.supports_remove_device) { return; } From fe8a1152c465698082ee9fdbc30c57ca7bfafd5d Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Feb 2022 16:36:15 +0100 Subject: [PATCH 08/10] Correct typing --- src/panels/config/devices/ha-config-device-page.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 7e94b312b4..d18fd3e5d4 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -276,7 +276,7 @@ export class HaConfigDevicePage extends LitElement { return; } - const buttons = []; + const buttons: TemplateResult[] = []; this._integrations(device, this.entries).forEach((entry) => { if (entry.state !== "loaded" || !entry.supports_remove_device) { return; From b29563a254de7367cc29093464a596ef14cef1a8 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Feb 2022 16:41:18 +0100 Subject: [PATCH 09/10] Prettier --- .../config/devices/ha-config-device-page.ts | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index d18fd3e5d4..6d56220da3 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -282,24 +282,21 @@ export class HaConfigDevicePage extends LitElement { 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`)} - - `); + + ${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) { @@ -308,7 +305,7 @@ export class HaConfigDevicePage extends LitElement { } private async _confirmDeleteEntry(e: MouseEvent): Promise { - const entryId = (e.currentTarget as any). entryId; + const entryId = (e.currentTarget as any).entryId; const confirmed = await showConfirmationDialog(this, { text: this.hass.localize("ui.panel.config.devices.confirm_delete"), From bc6ef7780c5e9a9d6300b2b6424f1e8d9618a4a3 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Feb 2022 16:49:23 +0100 Subject: [PATCH 10/10] Remove useless Array.isArray check --- src/panels/config/devices/ha-config-device-page.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 6d56220da3..ee2bdddda9 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -430,7 +430,7 @@ export class HaConfigDevicePage extends LitElement { if (Array.isArray(this._diagnosticDownloadLinks)) { deviceActions.push(...this._diagnosticDownloadLinks); } - if (Array.isArray(this._deleteButtons)) { + if (this._deleteButtons) { deviceActions.push(...this._deleteButtons); }