From af8659d8ed0ae212742cab99a22a3fcd44575ca6 Mon Sep 17 00:00:00 2001 From: Aidan Timson Date: Fri, 16 Jan 2026 11:23:56 +0000 Subject: [PATCH] Migrate automation/script dialogs to ha-wa-dialog (#29030) * Migrate dialog-automation-save to ha-wa-dialog * Migrate dialog-automation-mode to ha-wa-dialog * Migrate dialog-paste-replace to ha-wa-dialog * Migrate dialog-new-automation to ha-wa-dialog * Migrate ha-device-automation-dialog to ha-wa-dialog --- .../dialog-automation-mode.ts | 106 ++++++++--------- .../dialog-automation-save.ts | 111 +++++++++--------- .../automation/dialog-new-automation.ts | 49 ++++---- .../dialog-paste-replace.ts | 58 ++++----- .../ha-device-automation-dialog.ts | 27 +++-- 5 files changed, 179 insertions(+), 172 deletions(-) diff --git a/src/panels/config/automation/automation-mode-dialog/dialog-automation-mode.ts b/src/panels/config/automation/automation-mode-dialog/dialog-automation-mode.ts index f23e079687..9c98f57b71 100644 --- a/src/panels/config/automation/automation-mode-dialog/dialog-automation-mode.ts +++ b/src/panels/config/automation/automation-mode-dialog/dialog-automation-mode.ts @@ -1,16 +1,16 @@ -import { mdiClose, mdiHelpCircle } from "@mdi/js"; +import { mdiHelpCircle } from "@mdi/js"; import type { CSSResultGroup } from "lit"; import { LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; -import "../../../../components/ha-dialog-header"; +import "../../../../components/ha-wa-dialog"; +import "../../../../components/ha-dialog-footer"; import "../../../../components/ha-icon-button"; import "../../../../components/ha-md-list-item"; import "../../../../components/ha-md-list"; import "../../../../components/ha-radio"; import "../../../../components/ha-button"; import "../../../../components/ha-textfield"; -import "../../../../components/ha-dialog"; import { AUTOMATION_DEFAULT_MAX, @@ -27,16 +27,16 @@ import type { AutomationModeDialog } from "./show-dialog-automation-mode"; class DialogAutomationMode extends LitElement implements HassDialog { @property({ attribute: false }) public hass!: HomeAssistant; - @state() private _opened = false; + @state() private _open = false; - private _params!: AutomationModeDialog; + @state() private _params?: AutomationModeDialog; @state() private _newMode: (typeof MODES)[number] = AUTOMATION_DEFAULT_MODE; @state() private _newMax?: number; public showDialog(params: AutomationModeDialog): void { - this._opened = true; + this._open = true; this._params = params; this._newMode = params.config.mode || AUTOMATION_DEFAULT_MODE; this._newMax = isMaxMode(this._newMode) @@ -44,18 +44,21 @@ class DialogAutomationMode extends LitElement implements HassDialog { : undefined; } - public closeDialog() { - this._params.onClose(); - - if (this._opened) { - fireEvent(this, "dialog-closed", { dialog: this.localName }); - } - this._opened = false; + public closeDialog(): boolean { + this._open = false; return true; } + private _dialogClosed() { + if (this._params?.onClose) { + this._params.onClose(); + } + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + protected render() { - if (!this._opened) { + if (!this._params) { return nothing; } @@ -64,34 +67,25 @@ class DialogAutomationMode extends LitElement implements HassDialog { ); return html` - - + -
${title}
-
- - -
+ - ${this.hass.localize("ui.common.cancel")} - - - ${this.hass.localize("ui.panel.config.automation.editor.change_mode")} - -
+ + + ${this.hass.localize("ui.common.cancel")} + + + ${this.hass.localize( + "ui.panel.config.automation.editor.change_mode" + )} + + + `; } @@ -190,6 +188,9 @@ class DialogAutomationMode extends LitElement implements HassDialog { } private _save(): void { + if (!this._params) { + return; + } this._params.updateConfig({ ...this._params.config, mode: this._newMode, @@ -206,15 +207,12 @@ class DialogAutomationMode extends LitElement implements HassDialog { ha-textfield { display: block; } - ha-dialog { + ha-wa-dialog { --dialog-content-padding: 0; } .options { padding: 0 24px 24px 24px; } - ha-dialog-header a { - color: inherit; - } `, ]; } diff --git a/src/panels/config/automation/automation-save-dialog/dialog-automation-save.ts b/src/panels/config/automation/automation-save-dialog/dialog-automation-save.ts index b3152c04e3..30bbe60ae0 100644 --- a/src/panels/config/automation/automation-save-dialog/dialog-automation-save.ts +++ b/src/panels/config/automation/automation-save-dialog/dialog-automation-save.ts @@ -1,4 +1,4 @@ -import { mdiClose, mdiPlus } from "@mdi/js"; +import { mdiPlus } from "@mdi/js"; import { dump } from "js-yaml"; import type { CSSResultGroup } from "lit"; import { css, html, LitElement, nothing } from "lit"; @@ -8,6 +8,7 @@ import "../../../../components/chips/ha-assist-chip"; import "../../../../components/chips/ha-chip-set"; import "../../../../components/ha-alert"; import "../../../../components/ha-area-picker"; +import "../../../../components/ha-dialog-footer"; import "../../../../components/ha-domain-icon"; import "../../../../components/ha-expansion-panel"; import "../../../../components/ha-icon-picker"; @@ -17,6 +18,7 @@ import type { SuggestWithAIGenerateTask } from "../../../../components/ha-sugges import "../../../../components/ha-svg-icon"; import "../../../../components/ha-textarea"; import "../../../../components/ha-textfield"; +import "../../../../components/ha-wa-dialog"; import "../../category/ha-category-picker"; import { computeStateDomain } from "../../../../common/entity/compute_state_domain"; @@ -38,7 +40,7 @@ import type { class DialogAutomationSave extends LitElement implements HassDialog { @property({ attribute: false }) public hass!: HomeAssistant; - @state() private _opened = false; + @state() private _open = false; @state() private _error?: string; @@ -46,7 +48,7 @@ class DialogAutomationSave extends LitElement implements HassDialog { @state() private _entryUpdates!: EntityRegistryUpdate; - private _params!: SaveDialogParams; + @state() private _params?: SaveDialogParams; @state() private _newName?: string; @@ -55,7 +57,7 @@ class DialogAutomationSave extends LitElement implements HassDialog { private _newDescription?: string; public showDialog(params: SaveDialogParams): void { - this._opened = true; + this._open = true; this._params = params; this._newIcon = "icon" in params.config ? params.config.icon : undefined; this._newName = @@ -79,17 +81,18 @@ class DialogAutomationSave extends LitElement implements HassDialog { ].filter(Boolean); } - public closeDialog() { - this._params.onClose(); - - if (this._opened) { - fireEvent(this, "dialog-closed", { dialog: this.localName }); - } - this._opened = false; - this._visibleOptionals = []; + public closeDialog(): boolean { + this._open = false; return true; } + private _dialogClosed() { + this._params?.onClose(); + this._visibleOptionals = []; + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + protected _renderOptionalChip(id: string, label: string) { if (this._visibleOptionals.includes(id)) { return nothing; @@ -103,15 +106,15 @@ class DialogAutomationSave extends LitElement implements HassDialog { } protected _renderDiscard() { - if (!this._params.onDiscard) { + if (!this._params?.onDiscard) { return nothing; } return html` ${this.hass.localize("ui.common.dont_save")} @@ -119,13 +122,13 @@ class DialogAutomationSave extends LitElement implements HassDialog { } protected _renderInputs() { - if (this._params.hideInputs) { + if (!this._params || this._params.hideInputs) { return nothing; } return html` - - - ${this._params.title || title} - ${this._params.hideInputs - ? nothing - : html` `} - + ${this._params.hideInputs + ? nothing + : html` `} ${this._error ? html`${this.hass.localize( @@ -283,21 +277,25 @@ class DialogAutomationSave extends LitElement implements HassDialog { ${this._params.description ? html`

${this._params.description}

` : nothing} - ${this._renderInputs()} ${this._renderDiscard()} - -
- + ${this._renderInputs()} + + ${this._renderDiscard()} + ${this.hass.localize("ui.common.cancel")} - + ${this.hass.localize( this._params.config.alias && !this._params.onDiscard ? "ui.panel.config.automation.editor.rename" : "ui.common.save" )} -
- + + `; } @@ -331,7 +329,7 @@ class DialogAutomationSave extends LitElement implements HassDialog { } private _handleDiscard() { - this._params.onDiscard?.(); + this._params?.onDiscard?.(); this.closeDialog(); } @@ -350,6 +348,10 @@ class DialogAutomationSave extends LitElement implements HassDialog { } private _generateTask = async (): Promise => { + if (!this._params) { + throw new Error("Dialog params not set"); + } + const [labels, entities, categories] = await this._getSuggestData(); const inspirations: string[] = []; @@ -514,6 +516,10 @@ ${dump(this._params.config)} } private async _save(): Promise { + if (!this._params) { + return; + } + if (!this._newName) { this._error = "Name is required"; return; @@ -548,17 +554,10 @@ ${dump(this._params.config)} haStyle, haStyleDialog, css` - ha-dialog { + ha-wa-dialog { --dialog-content-padding: 0 24px 24px 24px; } - @media all and (min-width: 500px) { - ha-dialog { - --mdc-dialog-min-width: min(500px, 95vw); - --mdc-dialog-max-width: min(500px, 95vw); - } - } - ha-textfield, ha-textarea, ha-icon-picker, diff --git a/src/panels/config/automation/dialog-new-automation.ts b/src/panels/config/automation/dialog-new-automation.ts index 096784cad4..037b015480 100644 --- a/src/panels/config/automation/dialog-new-automation.ts +++ b/src/panels/config/automation/dialog-new-automation.ts @@ -12,8 +12,8 @@ import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { stringCompare } from "../../../common/string/compare"; -import { createCloseHeading } from "../../../components/ha-dialog"; import "../../../components/ha-icon-next"; +import "../../../components/ha-wa-dialog"; import "../../../components/ha-list"; import "../../../components/ha-list-item"; import "../../../components/ha-tip"; @@ -29,7 +29,6 @@ import { getBlueprintSourceType, } from "../../../data/blueprint"; import { showScriptEditor } from "../../../data/script"; -import type { HassDialog } from "../../../dialogs/make-dialog-manager"; import { mdiHomeAssistant } from "../../../resources/home-assistant-logo-svg"; import { haStyle, haStyleDialog } from "../../../resources/styles"; import type { HomeAssistant } from "../../../types"; @@ -43,17 +42,20 @@ const SOURCE_TYPE_ICONS: Record = { }; @customElement("ha-dialog-new-automation") -class DialogNewAutomation extends LitElement implements HassDialog { +class DialogNewAutomation extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @state() private _opened = false; + @state() private _open = false; + + @state() private _params?: NewAutomationDialogParams; @state() private _mode: BlueprintDomain = "automation"; @state() public blueprints?: Blueprints; public showDialog(params: NewAutomationDialogParams): void { - this._opened = true; + this._params = params; + this._open = true; this._mode = params?.mode || "automation"; fetchBlueprints(this.hass!, this._mode).then((blueprints) => { @@ -61,12 +63,14 @@ class DialogNewAutomation extends LitElement implements HassDialog { }); } - public closeDialog() { - if (this._opened) { - fireEvent(this, "dialog-closed", { dialog: this.localName }); - } - this._opened = false; - return true; + public closeDialog(): void { + this._open = false; + } + + private _dialogClosed(): void { + this._params = undefined; + this.blueprints = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); } private _processedBlueprints = memoizeOne((blueprints?: Blueprints) => { @@ -90,21 +94,20 @@ class DialogNewAutomation extends LitElement implements HassDialog { }); protected render() { - if (!this._opened) { + if (!this._params) { return nothing; } const processedBlueprints = this._processedBlueprints(this.blueprints); return html` - `} - + `; } @@ -229,13 +232,13 @@ class DialogNewAutomation extends LitElement implements HassDialog { haStyle, haStyleDialog, css` - ha-dialog { + ha-wa-dialog { --dialog-content-padding: 0; --mdc-dialog-max-height: 60vh; --mdc-dialog-max-height: 60dvh; } @media all and (min-width: 550px) { - ha-dialog { + ha-wa-dialog { --mdc-dialog-min-width: 500px; } } diff --git a/src/panels/config/automation/paste-replace-dialog/dialog-paste-replace.ts b/src/panels/config/automation/paste-replace-dialog/dialog-paste-replace.ts index dcbbd29d16..49718379ff 100644 --- a/src/panels/config/automation/paste-replace-dialog/dialog-paste-replace.ts +++ b/src/panels/config/automation/paste-replace-dialog/dialog-paste-replace.ts @@ -2,48 +2,48 @@ import { css, type CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; -import { createCloseHeading } from "../../../../components/ha-dialog"; +import "../../../../components/ha-dialog-footer"; +import "../../../../components/ha-wa-dialog"; import "../../../../components/ha-yaml-editor"; -import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; + import { haStyle, haStyleDialog } from "../../../../resources/styles"; import type { HomeAssistant } from "../../../../types"; import type { PasteReplaceDialogParams } from "./show-dialog-paste-replace"; @customElement("ha-dialog-paste-replace") -class DialogPasteReplace extends LitElement implements HassDialog { +class DialogPasteReplace extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @state() private _opened = false; + @state() private _open = false; @state() private _params!: PasteReplaceDialogParams; public showDialog(params: PasteReplaceDialogParams): void { - this._opened = true; + this._open = true; this._params = params; } - public closeDialog() { - if (this._opened) { - fireEvent(this, "dialog-closed", { dialog: this.localName }); - } - this._opened = false; - return true; + public closeDialog(): void { + this._open = false; + } + + private _dialogClosed() { + this._params = undefined!; + fireEvent(this, "dialog-closed", { dialog: this.localName }); } public render() { - if (!this._opened) { + if (!this._params) { return nothing; } return html` -

@@ -58,15 +58,19 @@ class DialogPasteReplace extends LitElement implements HassDialog { read-only > -

- + + ${this.hass.localize("ui.common.append")} - + ${this.hass.localize("ui.common.replace")} -
-
+ + `; } @@ -90,10 +94,6 @@ class DialogPasteReplace extends LitElement implements HassDialog { font-size: inherit; font-weight: inherit; } - div[slot="primaryAction"] { - display: flex; - gap: var(--ha-space-2); - } `, ]; } diff --git a/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts b/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts index 72dc04ddd8..0e904b5e1d 100644 --- a/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts +++ b/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts @@ -9,10 +9,10 @@ import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; import { shouldHandleRequestSelectedEvent } from "../../../../common/mwc/handle-request-selected-event"; -import { createCloseHeading } from "../../../../components/ha-dialog"; import "../../../../components/ha-icon-next"; import "../../../../components/ha-list"; import "../../../../components/ha-list-item"; +import "../../../../components/ha-wa-dialog"; import type { AutomationConfig } from "../../../../data/automation"; import { showAutomationEditor } from "../../../../data/automation"; import type { @@ -44,12 +44,19 @@ export class DialogDeviceAutomation extends LitElement { @state() private _params?: DeviceAutomationDialogParams; + @state() private _open = false; + public async showDialog(params: DeviceAutomationDialogParams): Promise { this._params = params; + this._open = true; await this.updateComplete; } public closeDialog(): void { + this._open = false; + } + + private _dialogClosed(): void { this._params = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -136,18 +143,18 @@ export class DialogDeviceAutomation extends LitElement { }); return html` - ${this._triggers.length ? html` @@ -245,7 +252,7 @@ export class DialogDeviceAutomation extends LitElement { - + `; } @@ -254,12 +261,12 @@ export class DialogDeviceAutomation extends LitElement { haStyle, haStyleDialog, css` - ha-dialog { + ha-wa-dialog { --dialog-content-padding: 0; --mdc-dialog-max-height: 60vh; } @media all and (min-width: 550px) { - ha-dialog { + ha-wa-dialog { --mdc-dialog-min-width: 500px; } }