Add overflow menu to automation picker (#13569)

This commit is contained in:
Paul Bottein 2022-09-02 19:01:05 +02:00 committed by GitHub
parent ffad6f340f
commit ec257710ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 188 additions and 28 deletions

View File

@ -3,6 +3,8 @@ import { mdiDotsVertical } from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { haStyle } from "../resources/styles";
import { HomeAssistant } from "../types";
import "./ha-button-menu";
import "./ha-icon-button";
@ -16,6 +18,7 @@ export interface IconOverflowMenuItem {
disabled?: boolean;
tooltip?: string;
onClick: CallableFunction;
warning?: boolean;
}
@customElement("ha-icon-overflow-menu")
@ -49,9 +52,13 @@ export class HaIconOverflowMenu extends LitElement {
graphic="icon"
.disabled=${item.disabled}
@click=${item.action}
class=${classMap({ warning: Boolean(item.warning) })}
>
<div slot="graphic">
<ha-svg-icon .path=${item.path}></ha-svg-icon>
<ha-svg-icon
class=${classMap({ warning: Boolean(item.warning) })}
.path=${item.path}
></ha-svg-icon>
</div>
${item.label}
</mwc-list-item>
@ -81,7 +88,8 @@ export class HaIconOverflowMenu extends LitElement {
`;
}
protected _handleIconOverflowMenuOpened() {
protected _handleIconOverflowMenuOpened(e) {
e.stopPropagation();
// If this component is used inside a data table, the z-index of the row
// needs to be increased. Otherwise the ha-button-menu would be displayed
// underneath the next row in the table.
@ -99,12 +107,15 @@ export class HaIconOverflowMenu extends LitElement {
}
static get styles() {
return css`
:host {
display: flex;
justify-content: flex-end;
}
`;
return [
haStyle,
css`
:host {
display: flex;
justify-content: flex-end;
}
`,
];
}
}

View File

@ -1,4 +1,16 @@
import { mdiHelpCircle, mdiInformationOutline, mdiPlus } from "@mdi/js";
import {
mdiCancel,
mdiContentDuplicate,
mdiDelete,
mdiHelpCircle,
mdiInformationOutline,
mdiPlay,
mdiPlayCircleOutline,
mdiPlus,
mdiStopCircleOutline,
mdiTransitConnection,
} from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
@ -13,11 +25,22 @@ import type {
RowClickedEvent,
} from "../../../components/data-table/ha-data-table";
import "../../../components/ha-button-related-filter-menu";
import "../../../components/ha-chip";
import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
import "../../../components/ha-icon-overflow-menu";
import "../../../components/ha-svg-icon";
import type { AutomationEntity } from "../../../data/automation";
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
import {
AutomationEntity,
deleteAutomation,
getAutomationConfig,
showAutomationEditor,
triggerAutomationActions,
} from "../../../data/automation";
import {
showAlertDialog,
showConfirmationDialog,
} from "../../../dialogs/generic/show-dialog-box";
import "../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant, Route } from "../../../types";
@ -63,6 +86,7 @@ class HaAutomationPicker extends LitElement {
...automation,
name: computeStateName(automation),
last_triggered: automation.attributes.last_triggered || undefined,
disabled: automation.state === "off",
}));
}
);
@ -123,22 +147,105 @@ class HaAutomationPicker extends LitElement {
},
};
}
columns.disabled = this.narrow
? {
title: "",
template: (disabled: boolean) =>
disabled
? html`
<paper-tooltip animation-delay="0" position="left">
${this.hass.localize(
"ui.panel.config.automation.picker.disabled"
)}
</paper-tooltip>
<ha-svg-icon
.path=${mdiCancel}
style="color: var(--secondary-text-color)"
></ha-svg-icon>
`
: "",
}
: {
width: "20%",
title: "",
template: (disabled: boolean) =>
disabled
? html`
<ha-chip>
${this.hass.localize(
"ui.panel.config.automation.picker.disabled"
)}
</ha-chip>
`
: "",
};
columns.actions = {
title: "",
label: this.hass.localize(
"ui.panel.config.automation.picker.headers.actions"
),
type: "icon-button",
template: (_info, automation: any) => html`
<ha-icon-button
.automation=${automation}
.label=${this.hass.localize(
"ui.panel.config.automation.picker.headers.actions"
)}
.path=${mdiInformationOutline}
@click=${this._showInfo}
></ha-icon-button>
`,
width: this.narrow ? undefined : "10%",
type: "overflow-menu",
template: (_: string, automation: any) =>
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: 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),
},
{
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;
}
@ -210,12 +317,52 @@ class HaAutomationPicker extends LitElement {
this._filterValue = undefined;
}
private _showInfo(ev) {
ev.stopPropagation();
const automation = ev.currentTarget.automation;
private _showInfo(automation: any) {
fireEvent(this, "hass-more-info", { entityId: automation.entity_id });
}
private _runActions(automation: any) {
triggerAutomationActions(this.hass, automation.entity_id);
}
private _showTrace(automation: any) {
navigate(`/config/automation/trace/${automation.attributes.id}`);
}
private async _toggle(automation): Promise<void> {
const service = automation.state === "off" ? "turn_on" : "turn_off";
await this.hass.callService("automation", service, {
entity_id: automation.entity_id,
});
}
private async _deleteConfirm(automation) {
showConfirmationDialog(this, {
text: this.hass.localize(
"ui.panel.config.automation.picker.delete_confirm"
),
confirmText: this.hass!.localize("ui.common.delete"),
dismissText: this.hass!.localize("ui.common.cancel"),
confirm: () => this._delete(automation),
});
}
private async _delete(automation) {
await deleteAutomation(this.hass, automation.attributes.id);
}
private async duplicate(automation) {
const config = await getAutomationConfig(
this.hass,
automation.attributes.id
);
showAutomationEditor({
...config,
id: undefined,
alias: undefined,
});
}
private _showHelp() {
showAlertDialog(this, {
title: this.hass.localize("ui.panel.config.automation.caption"),

View File

@ -1793,6 +1793,7 @@
"delete": "Delete",
"delete_confirm": "Are you sure you want to delete this automation?",
"duplicate": "Duplicate",
"disabled": "Disabled",
"headers": {
"toggle": "Enable/disable",
"name": "Name",
@ -1822,6 +1823,7 @@
"run": "[%key:ui::panel::config::automation::editor::actions::run%]",
"rename": "[%key:ui::panel::config::automation::editor::triggers::rename%]",
"show_trace": "Traces",
"show_info": "Information",
"introduction": "Use automations to bring your home to life.",
"default_name": "New Automation",
"missing_name": "Cannot save automation without a name",