diff --git a/demo/src/stubs/config_entries.ts b/demo/src/stubs/config_entries.ts index 01a6da133e72..7891d08db5c7 100644 --- a/demo/src/stubs/config_entries.ts +++ b/demo/src/stubs/config_entries.ts @@ -10,6 +10,7 @@ export const mockConfigEntries = (hass: MockHomeAssistant) => { supports_options: false, supports_remove_device: false, supports_unload: true, + supports_reconfigure: true, pref_disable_new_entities: false, pref_disable_polling: false, disabled_by: null, diff --git a/gallery/src/pages/misc/integration-card.ts b/gallery/src/pages/misc/integration-card.ts index ad0e1f2bca38..c2b2f2c24d93 100644 --- a/gallery/src/pages/misc/integration-card.ts +++ b/gallery/src/pages/misc/integration-card.ts @@ -31,6 +31,7 @@ const createConfigEntry = ( supports_options: false, supports_remove_device: false, supports_unload: true, + supports_reconfigure: true, disabled_by: null, pref_disable_new_entities: false, pref_disable_polling: false, diff --git a/src/data/config_entries.ts b/src/data/config_entries.ts index f4c4cea7ca54..ab3d7480fd1d 100644 --- a/src/data/config_entries.ts +++ b/src/data/config_entries.ts @@ -18,6 +18,7 @@ export interface ConfigEntry { supports_options: boolean; supports_remove_device: boolean; supports_unload: boolean; + supports_reconfigure: boolean; pref_disable_new_entities: boolean; pref_disable_polling: boolean; disabled_by: "user" | null; diff --git a/src/data/config_flow.ts b/src/data/config_flow.ts index 27a2926a0d8c..5c58cf789cf4 100644 --- a/src/data/config_flow.ts +++ b/src/data/config_flow.ts @@ -26,13 +26,18 @@ const HEADERS = { "HA-Frontend-Base": `${location.protocol}//${location.host}`, }; -export const createConfigFlow = (hass: HomeAssistant, handler: string) => +export const createConfigFlow = ( + hass: HomeAssistant, + handler: string, + entry_id?: string +) => hass.callApi( "POST", "config/config_entries/flow", { handler, show_advanced_options: Boolean(hass.userData?.showAdvanced), + entry_id, }, HEADERS ); diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index 9ccc58184015..869dc50e1857 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -23,7 +23,7 @@ export const showConfigFlowDialog = ( loadDevicesAndAreas: true, createFlow: async (hass, handler) => { const [step] = await Promise.all([ - createConfigFlow(hass, handler), + createConfigFlow(hass, handler, dialogParams.entryId), hass.loadFragmentTranslation("config"), hass.loadBackendTranslation("config", handler), hass.loadBackendTranslation("selector", handler), diff --git a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts index 5dbd48e7b364..3594188455c0 100644 --- a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts @@ -139,6 +139,7 @@ export interface DataEntryFlowDialogParams { }) => void; flowConfig: FlowConfig; showAdvanced?: boolean; + entryId?: string; dialogParentElement?: HTMLElement; } diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index 10e3fcd85fba..b53f46e855fb 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -23,6 +23,7 @@ import { mdiRenameBox, mdiShapeOutline, mdiStopCircleOutline, + mdiWrench, } from "@mdi/js"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { @@ -806,6 +807,19 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { ` : ""} + ${!item.disabled_by && + item.supports_reconfigure && + item.source !== "system" + ? html` + ${this.hass.localize( + "ui.panel.config.integrations.config_entry.reconfigure" + )} + + ` + : ""} ): void { + if (!shouldHandleRequestSelectedEvent(ev)) { + return; + } + this._reconfigureIntegration( + ((ev.target as HTMLElement).closest(".config_entry") as any).configEntry + ); + } + private _handleDelete(ev: CustomEvent): void { if (!shouldHandleRequestSelectedEvent(ev)) { return; @@ -1259,6 +1282,15 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { }); } + private async _reconfigureIntegration(configEntry: ConfigEntry) { + showConfigFlowDialog(this, { + startFlowHandler: configEntry.domain, + showAdvanced: this.hass.userData?.showAdvanced, + manifest: await fetchIntegrationManifest(this.hass, configEntry.domain), + entryId: configEntry.entry_id, + }); + } + private async _editEntryName(configEntry: ConfigEntry) { const newName = await showPromptDialog(this, { title: this.hass.localize("ui.panel.config.integrations.rename_dialog"), diff --git a/src/translations/en.json b/src/translations/en.json index 972c6753f50b..5c88e72e7de3 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3921,6 +3921,7 @@ "delete_confirm_title": "Delete {title}?", "delete_confirm_text": "Its devices and entities will be permanently deleted.", "enable_debug_logging": "Enable debug logging", + "reconfigure": "Reconfigure", "reload": "Reload", "restart_confirm": "Restart Home Assistant to finish removing this integration", "reload_confirm": "The integration was reloaded",