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
.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;

View File

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

View File

@ -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`
<ha-icon-overflow-menu
.hass=${this.hass}
narrow
.items=${[
{
path: mdiInformationOutline,
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>
<ha-icon-button
.automation=${automation}
.label=${this.hass.localize("ui.common.overflow_menu")}
.path=${mdiDotsVertical}
@click=${this._showOverflowMenu}
></ha-icon-button>
`,
};
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>)[] {
return [
subscribeCategoryRegistry(
@ -689,6 +640,80 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
</ha-fab>
</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();
}
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<void> {
private async _toggle(ev): Promise<void> {
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,