Fix and optimize automation overflow (#20293)

* WIP fix and optimize automation overflow

* finish

* Prettier

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
Bram Kragten 2024-04-02 11:23:43 +02:00 committed by GitHub
parent 2e58d6656c
commit 4fb42d3545
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 133 additions and 89 deletions

View File

@ -627,9 +627,13 @@ export class HaDataTable extends LitElement {
ev ev
.composedPath() .composedPath()
.find((el) => .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; return;

View File

@ -556,7 +556,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
></ha-svg-icon ></ha-svg-icon
><ha-svg-icon slot="end" .path=${mdiPlus}></ha-svg-icon> ><ha-svg-icon slot="end" .path=${mdiPlus}></ha-svg-icon>
</ha-list-item-new> </ha-list-item-new>
<md-divider></md-divider>` <md-divider role="separator" tabindex="-1"></md-divider>`
: ""} : ""}
${repeat( ${repeat(
items, items,

View File

@ -1,5 +1,6 @@
import { consume } from "@lit-labs/context"; import { consume } from "@lit-labs/context";
import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import "@material/web/divider/divider";
import { import {
mdiChevronRight, mdiChevronRight,
mdiCog, mdiCog,
@ -30,7 +31,7 @@ import {
html, html,
nothing, nothing,
} from "lit"; } 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 { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { computeCssColor } from "../../../common/color/compute-color"; 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-filter-labels";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-icon-overflow-menu"; import "../../../components/ha-icon-overflow-menu";
import "../../../components/ha-menu";
import "../../../components/ha-menu-item"; import "../../../components/ha-menu-item";
import "../../../components/ha-sub-menu"; import "../../../components/ha-sub-menu";
import "../../../components/ha-svg-icon"; 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 { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
import { configSections } from "../ha-panel-config"; import { configSections } from "../ha-panel-config";
import { showNewAutomationDialog } from "./show-dialog-new-automation"; import { showNewAutomationDialog } from "./show-dialog-new-automation";
import type { HaMenu } from "../../../components/ha-menu";
type AutomationItem = AutomationEntity & { type AutomationItem = AutomationEntity & {
name: string; name: string;
@ -143,6 +146,10 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
@consume({ context: fullEntitiesContext, subscribe: true }) @consume({ context: fullEntitiesContext, subscribe: true })
_entityReg!: EntityRegistryEntry[]; _entityReg!: EntityRegistryEntry[];
@state() private _overflowAutomation?: AutomationItem;
@query("#overflow-menu") private _overflowMenu!: HaMenu;
private _automations = memoizeOne( private _automations = memoizeOne(
( (
automations: AutomationEntity[], automations: AutomationEntity[],
@ -291,89 +298,33 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
columns.actions = { columns.actions = {
title: "", title: "",
width: "64px", width: "64px",
type: "overflow-menu", type: "icon-button",
template: (automation) => html` template: (automation) => html`
<ha-icon-overflow-menu <ha-icon-button
.hass=${this.hass} .automation=${automation}
narrow .label=${this.hass.localize("ui.common.overflow_menu")}
.items=${[ .path=${mdiDotsVertical}
{ @click=${this._showOverflowMenu}
path: mdiInformationOutline, ></ha-icon-button>
label: this.hass.localize(
"ui.panel.config.automation.editor.show_info"
),
action: () => 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,
},
]}
>
</ha-icon-overflow-menu>
`, `,
}; };
return columns; 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<UnsubscribeFunc>)[] { protected hassSubscribe(): (UnsubscribeFunc | Promise<UnsubscribeFunc>)[] {
return [ return [
subscribeCategoryRegistry( subscribeCategoryRegistry(
@ -689,6 +640,80 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon> <ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
</ha-fab> </ha-fab>
</hass-tabs-subpage-data-table> </hass-tabs-subpage-data-table>
<ha-menu id="overflow-menu" positioning="fixed">
<ha-menu-item @click=${this._showInfo}>
<ha-svg-icon
.path=${mdiInformationOutline}
slot="start"
></ha-svg-icon>
<div slot="headline">
${this.hass.localize("ui.panel.config.automation.editor.show_info")}
</div>
</ha-menu-item>
<ha-menu-item @click=${this._showSettings}>
<ha-svg-icon .path=${mdiCog} slot="start"></ha-svg-icon>
<div slot="headline">
${this.hass.localize(
"ui.panel.config.automation.picker.show_settings"
)}
</div>
</ha-menu-item>
<ha-menu-item @click=${this._editCategory}>
<ha-svg-icon .path=${mdiTag} slot="start"></ha-svg-icon>
<div slot="headline">
${this.hass.localize(
`ui.panel.config.automation.picker.${this._overflowAutomation?.category ? "edit_category" : "assign_category"}`
)}
</div>
</ha-menu-item>
<ha-menu-item @click=${this._runActions}>
<ha-svg-icon .path=${mdiPlay} slot="start"></ha-svg-icon>
<div slot="headline">
${this.hass.localize("ui.panel.config.automation.editor.run")}
</div>
</ha-menu-item>
<ha-menu-item @click=${this._showTrace}>
<ha-svg-icon .path=${mdiTransitConnection} slot="start"></ha-svg-icon>
<div slot="headline">
${this.hass.localize(
"ui.panel.config.automation.editor.show_trace"
)}
</div>
</ha-menu-item>
<md-divider role="separator" tabindex="-1"></md-divider>
<ha-menu-item @click=${this._duplicate}>
<ha-svg-icon .path=${mdiContentDuplicate} slot="start"></ha-svg-icon>
<div slot="headline">
${this.hass.localize("ui.panel.config.automation.picker.duplicate")}
</div>
</ha-menu-item>
<ha-menu-item @click=${this._toggle}>
<ha-svg-icon
.path=${
this._overflowAutomation?.state === "off"
? mdiPlayCircleOutline
: mdiStopCircleOutline
}
slot="start"
></ha-svg-icon>
<div slot="headline">
${
this._overflowAutomation?.state === "off"
? this.hass.localize("ui.panel.config.automation.editor.enable")
: this.hass.localize(
"ui.panel.config.automation.editor.disable"
)
}
</div>
</ha-menu-item>
<ha-menu-item @click=${this._deleteConfirm} class="warning">
<ha-svg-icon .path=${mdiDelete} slot="start"></ha-svg-icon>
<div slot="headline">
${this.hass.localize("ui.panel.config.automation.picker.delete")}
</div>
</ha-menu-item>
</ha-menu>
`; `;
} }
@ -815,22 +840,29 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
this._applyFilters(); 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 }); 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", { fireEvent(this, "hass-more-info", {
entityId: automation.entity_id, entityId: automation.entity_id,
view: "settings", view: "settings",
}); });
} }
private _runActions(automation: any) { private _runActions(ev) {
const automation = ev.currentTarget.parentElement.anchorElement.automation;
triggerAutomationActions(this.hass, automation.entity_id); 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( const entityReg = this._entityReg.find(
(reg) => reg.entity_id === automation.entity_id (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) { if (!automation.attributes.id) {
showAlertDialog(this, { showAlertDialog(this, {
text: this.hass.localize( text: this.hass.localize(
@ -865,14 +899,18 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
); );
} }
private async _toggle(automation): Promise<void> { private async _toggle(ev): Promise<void> {
const automation = ev.currentTarget.parentElement.anchorElement.automation;
const service = automation.state === "off" ? "turn_on" : "turn_off"; const service = automation.state === "off" ? "turn_on" : "turn_off";
await this.hass.callService("automation", service, { await this.hass.callService("automation", service, {
entity_id: automation.entity_id, entity_id: automation.entity_id,
}); });
} }
private async _deleteConfirm(automation) { private async _deleteConfirm(ev) {
const automation = ev.currentTarget.parentElement.anchorElement.automation;
showConfirmationDialog(this, { showConfirmationDialog(this, {
title: this.hass.localize( title: this.hass.localize(
"ui.panel.config.automation.picker.delete_confirm_title" "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 { try {
const config = await fetchAutomationFileConfig( const config = await fetchAutomationFileConfig(
this.hass, this.hass,