mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
An alias editor and overflow menu for choose options (#18183)
This commit is contained in:
parent
62d21bea4f
commit
c3a9682861
@ -1,19 +1,41 @@
|
|||||||
import { consume } from "@lit-labs/context";
|
import { consume } from "@lit-labs/context";
|
||||||
import type { SortableEvent } from "sortablejs";
|
import type { SortableEvent } from "sortablejs";
|
||||||
import { mdiDelete, mdiPlus, mdiArrowUp, mdiArrowDown, mdiDrag } from "@mdi/js";
|
import {
|
||||||
|
mdiDotsVertical,
|
||||||
|
mdiRenameBox,
|
||||||
|
mdiSort,
|
||||||
|
mdiContentDuplicate,
|
||||||
|
mdiDelete,
|
||||||
|
mdiPlus,
|
||||||
|
mdiArrowUp,
|
||||||
|
mdiArrowDown,
|
||||||
|
mdiDrag,
|
||||||
|
} from "@mdi/js";
|
||||||
|
import deepClone from "deep-clone-simple";
|
||||||
import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit";
|
import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { repeat } from "lit/directives/repeat";
|
import { repeat } from "lit/directives/repeat";
|
||||||
|
import type { ActionDetail } from "@material/mwc-list";
|
||||||
import {
|
import {
|
||||||
loadSortable,
|
loadSortable,
|
||||||
SortableInstance,
|
SortableInstance,
|
||||||
} from "../../../../../resources/sortable.ondemand";
|
} from "../../../../../resources/sortable.ondemand";
|
||||||
import { ensureArray } from "../../../../../common/array/ensure-array";
|
import { ensureArray } from "../../../../../common/array/ensure-array";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import { capitalizeFirstLetter } from "../../../../../common/string/capitalize-first-letter";
|
||||||
import "../../../../../components/ha-button";
|
import "../../../../../components/ha-button";
|
||||||
import "../../../../../components/ha-icon-button";
|
import "../../../../../components/ha-icon-button";
|
||||||
|
import "../../../../../components/ha-button-menu";
|
||||||
import { Condition } from "../../../../../data/automation";
|
import { Condition } from "../../../../../data/automation";
|
||||||
import { Action, ChooseAction } from "../../../../../data/script";
|
import {
|
||||||
|
Action,
|
||||||
|
ChooseAction,
|
||||||
|
ChooseActionChoice,
|
||||||
|
} from "../../../../../data/script";
|
||||||
|
import {
|
||||||
|
showConfirmationDialog,
|
||||||
|
showPromptDialog,
|
||||||
|
} from "../../../../../dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../../../resources/styles";
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import { ActionElement } from "../ha-automation-action-row";
|
import { ActionElement } from "../ha-automation-action-row";
|
||||||
@ -22,6 +44,8 @@ import { fullEntitiesContext } from "../../../../../data/context";
|
|||||||
import { EntityRegistryEntry } from "../../../../../data/entity_registry";
|
import { EntityRegistryEntry } from "../../../../../data/entity_registry";
|
||||||
import { sortableStyles } from "../../../../../resources/ha-sortable-style";
|
import { sortableStyles } from "../../../../../resources/ha-sortable-style";
|
||||||
|
|
||||||
|
const preventDefault = (ev) => ev.preventDefault();
|
||||||
|
|
||||||
@customElement("ha-automation-action-choose")
|
@customElement("ha-automation-action-choose")
|
||||||
export class HaChooseAction extends LitElement implements ActionElement {
|
export class HaChooseAction extends LitElement implements ActionElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@ -53,13 +77,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
this._expandedStates[ev.target!.index] = ev.detail.expanded;
|
this._expandedStates[ev.target!.index] = ev.detail.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getDescription(option, idx: number) {
|
private _getDescription(option) {
|
||||||
if (option.alias) {
|
|
||||||
return option.alias;
|
|
||||||
}
|
|
||||||
if (this._expandedStates[idx]) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
const conditions = ensureArray(option.conditions);
|
const conditions = ensureArray(option.conditions);
|
||||||
if (!conditions || conditions.length === 0) {
|
if (!conditions || conditions.length === 0) {
|
||||||
return this.hass.localize(
|
return this.hass.localize(
|
||||||
@ -103,7 +121,10 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
"number",
|
"number",
|
||||||
idx + 1
|
idx + 1
|
||||||
)}:
|
)}:
|
||||||
${this._getDescription(option, idx)}
|
${option.alias ||
|
||||||
|
(this._expandedStates[idx]
|
||||||
|
? ""
|
||||||
|
: this._getDescription(option))}
|
||||||
</h3>
|
</h3>
|
||||||
${this.reOrderMode
|
${this.reOrderMode
|
||||||
? html`
|
? html`
|
||||||
@ -133,16 +154,71 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<ha-icon-button
|
<ha-button-menu
|
||||||
slot="icons"
|
slot="icons"
|
||||||
.idx=${idx}
|
.idx=${idx}
|
||||||
|
@action=${this._handleAction}
|
||||||
|
@click=${preventDefault}
|
||||||
|
fixed
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
slot="trigger"
|
||||||
|
.label=${this.hass.localize("ui.common.menu")}
|
||||||
|
.path=${mdiDotsVertical}
|
||||||
|
></ha-icon-button>
|
||||||
|
<mwc-list-item
|
||||||
|
graphic="icon"
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@click=${this._removeOption}
|
>
|
||||||
.label=${this.hass.localize(
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.rename"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiRenameBox}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</mwc-list-item>
|
||||||
|
<mwc-list-item
|
||||||
|
graphic="icon"
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.re_order"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiSort}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</mwc-list-item>
|
||||||
|
|
||||||
|
<mwc-list-item
|
||||||
|
graphic="icon"
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.duplicate"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiContentDuplicate}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</mwc-list-item>
|
||||||
|
|
||||||
|
<mwc-list-item
|
||||||
|
class="warning"
|
||||||
|
graphic="icon"
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.actions.type.choose.remove_option"
|
"ui.panel.config.automation.editor.actions.type.choose.remove_option"
|
||||||
)}
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
class="warning"
|
||||||
|
slot="graphic"
|
||||||
.path=${mdiDelete}
|
.path=${mdiDelete}
|
||||||
></ha-icon-button>
|
></ha-svg-icon>
|
||||||
|
</mwc-list-item>
|
||||||
|
</ha-button-menu>
|
||||||
`}
|
`}
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<h4>
|
<h4>
|
||||||
@ -220,6 +296,58 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _handleAction(ev: CustomEvent<ActionDetail>) {
|
||||||
|
switch (ev.detail.index) {
|
||||||
|
case 0:
|
||||||
|
await this._renameAction(ev);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
fireEvent(this, "re-order");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this._duplicateOption(ev);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
this._removeOption(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _renameAction(ev: CustomEvent<ActionDetail>): Promise<void> {
|
||||||
|
const index = (ev.target as any).idx;
|
||||||
|
const choose = this.action.choose
|
||||||
|
? [...ensureArray(this.action.choose)]
|
||||||
|
: [];
|
||||||
|
const choice = choose[index];
|
||||||
|
const alias = await showPromptDialog(this, {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.type.choose.change_alias"
|
||||||
|
),
|
||||||
|
inputLabel: this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.type.choose.alias"
|
||||||
|
),
|
||||||
|
inputType: "string",
|
||||||
|
placeholder: capitalizeFirstLetter(this._getDescription(choice)),
|
||||||
|
defaultValue: choice.alias,
|
||||||
|
confirmText: this.hass.localize("ui.common.submit"),
|
||||||
|
});
|
||||||
|
if (alias !== null) {
|
||||||
|
if (alias === "") {
|
||||||
|
delete choose[index].alias;
|
||||||
|
} else {
|
||||||
|
choose[index].alias = alias;
|
||||||
|
}
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: { ...this.action, choose },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _duplicateOption(ev) {
|
||||||
|
const index = (ev.target as any).idx;
|
||||||
|
this._addOption(deepClone(ensureArray(this.action.choose)[index]));
|
||||||
|
}
|
||||||
|
|
||||||
protected firstUpdated() {
|
protected firstUpdated() {
|
||||||
ensureArray(this.action.choose).forEach(() =>
|
ensureArray(this.action.choose).forEach(() =>
|
||||||
this._expandedStates.push(false)
|
this._expandedStates.push(false)
|
||||||
@ -274,11 +402,11 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addOption() {
|
private _addOption(opt?: ChooseActionChoice) {
|
||||||
const choose = this.action.choose
|
const choose = this.action.choose
|
||||||
? [...ensureArray(this.action.choose)]
|
? [...ensureArray(this.action.choose)]
|
||||||
: [];
|
: [];
|
||||||
choose.push({ conditions: [], sequence: [] });
|
choose.push(opt ?? { conditions: [], sequence: [] });
|
||||||
fireEvent(this, "value-changed", {
|
fireEvent(this, "value-changed", {
|
||||||
value: { ...this.action, choose },
|
value: { ...this.action, choose },
|
||||||
});
|
});
|
||||||
@ -317,7 +445,18 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _removeOption(ev: CustomEvent) {
|
private _removeOption(ev: CustomEvent) {
|
||||||
const index = (ev.currentTarget as any).idx;
|
const index = (ev.target as any).idx;
|
||||||
|
showConfirmationDialog(this, {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.type.choose.delete_confirm_title"
|
||||||
|
),
|
||||||
|
text: this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.delete_confirm_text"
|
||||||
|
),
|
||||||
|
dismissText: this.hass.localize("ui.common.cancel"),
|
||||||
|
confirmText: this.hass.localize("ui.common.delete"),
|
||||||
|
destructive: true,
|
||||||
|
confirm: () => {
|
||||||
const choose = this.action.choose
|
const choose = this.action.choose
|
||||||
? [...ensureArray(this.action.choose)]
|
? [...ensureArray(this.action.choose)]
|
||||||
: [];
|
: [];
|
||||||
@ -326,6 +465,8 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
|||||||
fireEvent(this, "value-changed", {
|
fireEvent(this, "value-changed", {
|
||||||
value: { ...this.action, choose },
|
value: { ...this.action, choose },
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _defaultChanged(ev: CustomEvent) {
|
private _defaultChanged(ev: CustomEvent) {
|
||||||
|
@ -2825,6 +2825,9 @@
|
|||||||
"option": "Option {number}",
|
"option": "Option {number}",
|
||||||
"add_option": "Add option",
|
"add_option": "Add option",
|
||||||
"remove_option": "Remove option",
|
"remove_option": "Remove option",
|
||||||
|
"change_alias": "Rename option",
|
||||||
|
"alias": "Option name",
|
||||||
|
"delete_confirm_title": "Remove option?",
|
||||||
"option_description_additional": " {numberOfAdditionalConditions, plural,\n one {and 1 more condition}\n other {and {numberOfAdditionalConditions} more conditions}}",
|
"option_description_additional": " {numberOfAdditionalConditions, plural,\n one {and 1 more condition}\n other {and {numberOfAdditionalConditions} more conditions}}",
|
||||||
"conditions": "Conditions",
|
"conditions": "Conditions",
|
||||||
"no_conditions": "[%key:ui::panel::config::devices::automation::conditions::no_conditions%]",
|
"no_conditions": "[%key:ui::panel::config::devices::automation::conditions::no_conditions%]",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user