From 4fb42d3545a37d1868d6e1a36a48f6d13efc9342 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Apr 2024 11:23:43 +0200 Subject: [PATCH] Fix and optimize automation overflow (#20293) * WIP fix and optimize automation overflow * finish * Prettier --------- Co-authored-by: Paul Bottein --- src/components/data-table/ha-data-table.ts | 10 +- .../add-automation-element-dialog.ts | 2 +- .../config/automation/ha-automation-picker.ts | 210 +++++++++++------- 3 files changed, 133 insertions(+), 89 deletions(-) diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index e514526c3b..e0f7c8894e 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -627,9 +627,13 @@ export class HaDataTable extends LitElement { ev .composedPath() .find((el) => - ["ha-checkbox", "mwc-button", "ha-button", "ha-assist-chip"].includes( - (el as HTMLElement).localName - ) + [ + "ha-checkbox", + "mwc-button", + "ha-button", + "ha-icon-button", + "ha-assist-chip", + ].includes((el as HTMLElement).localName) ) ) { return; diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 3222c1b1e2..09fcf360a1 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -556,7 +556,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { > - ` + ` : ""} ${repeat( items, diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index c53a786621..b5208b944e 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -1,5 +1,6 @@ import { consume } from "@lit-labs/context"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; +import "@material/web/divider/divider"; import { mdiChevronRight, mdiCog, @@ -30,7 +31,7 @@ import { html, nothing, } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { computeCssColor } from "../../../common/color/compute-color"; @@ -58,6 +59,7 @@ import "../../../components/ha-filter-floor-areas"; import "../../../components/ha-filter-labels"; import "../../../components/ha-icon-button"; import "../../../components/ha-icon-overflow-menu"; +import "../../../components/ha-menu"; import "../../../components/ha-menu-item"; import "../../../components/ha-sub-menu"; import "../../../components/ha-svg-icon"; @@ -99,6 +101,7 @@ import { turnOnOffEntity } from "../../lovelace/common/entity/turn-on-off-entity import { showAssignCategoryDialog } from "../category/show-dialog-assign-category"; import { configSections } from "../ha-panel-config"; import { showNewAutomationDialog } from "./show-dialog-new-automation"; +import type { HaMenu } from "../../../components/ha-menu"; type AutomationItem = AutomationEntity & { name: string; @@ -143,6 +146,10 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { @consume({ context: fullEntitiesContext, subscribe: true }) _entityReg!: EntityRegistryEntry[]; + @state() private _overflowAutomation?: AutomationItem; + + @query("#overflow-menu") private _overflowMenu!: HaMenu; + private _automations = memoizeOne( ( automations: AutomationEntity[], @@ -291,89 +298,33 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { columns.actions = { title: "", width: "64px", - type: "overflow-menu", + type: "icon-button", template: (automation) => html` - this._showInfo(automation), - }, - { - path: mdiCog, - label: this.hass.localize( - "ui.panel.config.automation.picker.show_settings" - ), - action: () => this._showSettings(automation), - }, - { - path: mdiTag, - label: this.hass.localize( - `ui.panel.config.automation.picker.${automation.category ? "edit_category" : "assign_category"}` - ), - action: () => this._editCategory(automation), - }, - { - path: mdiPlay, - label: this.hass.localize( - "ui.panel.config.automation.editor.run" - ), - action: () => this._runActions(automation), - }, - { - path: mdiTransitConnection, - label: this.hass.localize( - "ui.panel.config.automation.editor.show_trace" - ), - action: () => this._showTrace(automation), - }, - { - divider: true, - }, - { - path: mdiContentDuplicate, - label: this.hass.localize( - "ui.panel.config.automation.picker.duplicate" - ), - action: () => this.duplicate(automation), - }, - { - path: - automation.state === "off" - ? mdiPlayCircleOutline - : mdiStopCircleOutline, - label: - automation.state === "off" - ? this.hass.localize( - "ui.panel.config.automation.editor.enable" - ) - : this.hass.localize( - "ui.panel.config.automation.editor.disable" - ), - action: () => this._toggle(automation), - }, - { - label: this.hass.localize( - "ui.panel.config.automation.picker.delete" - ), - path: mdiDelete, - action: () => this._deleteConfirm(automation), - warning: true, - }, - ]} - > - + `, }; return columns; } ); + private _showOverflowMenu = (ev) => { + if ( + this._overflowMenu.open && + ev.target === this._overflowMenu.anchorElement + ) { + this._overflowMenu.close(); + return; + } + this._overflowAutomation = ev.target.automation; + this._overflowMenu.anchorElement = ev.target; + this._overflowMenu.show(); + }; + protected hassSubscribe(): (UnsubscribeFunc | Promise)[] { return [ subscribeCategoryRegistry( @@ -689,6 +640,80 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { + + + +
+ ${this.hass.localize("ui.panel.config.automation.editor.show_info")} +
+
+ + + +
+ ${this.hass.localize( + "ui.panel.config.automation.picker.show_settings" + )} +
+
+ + +
+ ${this.hass.localize( + `ui.panel.config.automation.picker.${this._overflowAutomation?.category ? "edit_category" : "assign_category"}` + )} +
+
+ + +
+ ${this.hass.localize("ui.panel.config.automation.editor.run")} +
+
+ + +
+ ${this.hass.localize( + "ui.panel.config.automation.editor.show_trace" + )} +
+
+ + + +
+ ${this.hass.localize("ui.panel.config.automation.picker.duplicate")} +
+
+ + +
+ ${ + this._overflowAutomation?.state === "off" + ? this.hass.localize("ui.panel.config.automation.editor.enable") + : this.hass.localize( + "ui.panel.config.automation.editor.disable" + ) + } +
+
+ + +
+ ${this.hass.localize("ui.panel.config.automation.picker.delete")} +
+
+
`; } @@ -815,22 +840,29 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { this._applyFilters(); } - private _showInfo(automation: any) { + private _showInfo(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; fireEvent(this, "hass-more-info", { entityId: automation.entity_id }); } - private _showSettings(automation: any) { + private _showSettings(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + fireEvent(this, "hass-more-info", { entityId: automation.entity_id, view: "settings", }); } - private _runActions(automation: any) { + private _runActions(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + triggerAutomationActions(this.hass, automation.entity_id); } - private _editCategory(automation: any) { + private _editCategory(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + const entityReg = this._entityReg.find( (reg) => reg.entity_id === automation.entity_id ); @@ -851,7 +883,9 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { }); } - private _showTrace(automation: any) { + private _showTrace(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + if (!automation.attributes.id) { showAlertDialog(this, { text: this.hass.localize( @@ -865,14 +899,18 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { ); } - private async _toggle(automation): Promise { + private async _toggle(ev): Promise { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + const service = automation.state === "off" ? "turn_on" : "turn_off"; await this.hass.callService("automation", service, { entity_id: automation.entity_id, }); } - private async _deleteConfirm(automation) { + private async _deleteConfirm(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + showConfirmationDialog(this, { title: this.hass.localize( "ui.panel.config.automation.picker.delete_confirm_title" @@ -906,7 +944,9 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { } } - private async duplicate(automation) { + private async _duplicate(ev) { + const automation = ev.currentTarget.parentElement.anchorElement.automation; + try { const config = await fetchAutomationFileConfig( this.hass,