From 07d37dd89f25dae045ce21856db243276a8a8b3a Mon Sep 17 00:00:00 2001
From: karwosts <32912880+karwosts@users.noreply.github.com>
Date: Tue, 20 Jun 2023 23:50:01 -0700
Subject: [PATCH] Handle multiple triggers in trigger condition UI (#16983)
---
.../ha-selector/ha-selector-select.ts | 34 ++++----
.../types/ha-automation-condition-trigger.ts | 81 ++++++++++++-------
2 files changed, 72 insertions(+), 43 deletions(-)
diff --git a/src/components/ha-selector/ha-selector-select.ts b/src/components/ha-selector/ha-selector-select.ts
index f4b07b55aa..e8bd3ac4b4 100644
--- a/src/components/ha-selector/ha-selector-select.ts
+++ b/src/components/ha-selector/ha-selector-select.ts
@@ -4,6 +4,7 @@ import { css, html, LitElement } from "lit";
import { customElement, property, query } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import { stopPropagation } from "../../common/dom/stop_propagation";
+import { ensureArray } from "../../common/array/ensure-array";
import type { SelectOption, SelectSelector } from "../../data/selector";
import type { HomeAssistant } from "../../types";
import "../ha-checkbox";
@@ -40,7 +41,7 @@ export class HaSelectSelector extends LitElement {
protected render() {
const options =
- this.selector.select?.options.map((option) =>
+ this.selector.select?.options?.map((option) =>
typeof option === "object"
? (option as SelectOption)
: ({ value: option, label: option } as SelectOption)
@@ -77,7 +78,8 @@ export class HaSelectSelector extends LitElement {
${this._renderHelper()}
`;
}
-
+ const value =
+ !this.value || this.value === "" ? [] : ensureArray(this.value);
return html`
${this.label}
@@ -85,7 +87,7 @@ export class HaSelectSelector extends LitElement {
(item: SelectOption) => html`
!option.disabled && !value?.includes(option.value)
@@ -231,19 +233,19 @@ export class HaSelectSelector extends LitElement {
const value: string = ev.target.value;
const checked = ev.target.checked;
+ const oldValue =
+ !this.value || this.value === "" ? [] : ensureArray(this.value);
+
if (checked) {
- if (!this.value) {
- newValue = [value];
- } else if (this.value.includes(value)) {
+ if (oldValue.includes(value)) {
return;
- } else {
- newValue = [...this.value, value];
}
+ newValue = [...oldValue, value];
} else {
- if (!this.value?.includes(value)) {
+ if (!oldValue?.includes(value)) {
return;
}
- newValue = (this.value as string[]).filter((v) => v !== value);
+ newValue = oldValue.filter((v) => v !== value);
}
fireEvent(this, "value-changed", {
@@ -252,7 +254,7 @@ export class HaSelectSelector extends LitElement {
}
private async _removeItem(ev) {
- const value: string[] = [...(this.value! as string[])];
+ const value: string[] = [...ensureArray(this.value!)];
value.splice(ev.target.idx, 1);
fireEvent(this, "value-changed", {
@@ -277,7 +279,10 @@ export class HaSelectSelector extends LitElement {
return;
}
- if (newValue !== undefined && this.value?.includes(newValue)) {
+ const currentValue =
+ !this.value || this.value === "" ? [] : ensureArray(this.value);
+
+ if (newValue !== undefined && currentValue.includes(newValue)) {
return;
}
@@ -286,9 +291,6 @@ export class HaSelectSelector extends LitElement {
this.comboBox.setInputValue("");
}, 0);
- const currentValue =
- !this.value || this.value === "" ? [] : (this.value as string[]);
-
fireEvent(this, "value-changed", {
value: [...currentValue, newValue],
});
diff --git a/src/panels/config/automation/condition/types/ha-automation-condition-trigger.ts b/src/panels/config/automation/condition/types/ha-automation-condition-trigger.ts
index 3eb72d48d2..8935668618 100644
--- a/src/panels/config/automation/condition/types/ha-automation-condition-trigger.ts
+++ b/src/panels/config/automation/condition/types/ha-automation-condition-trigger.ts
@@ -1,9 +1,11 @@
import "@material/mwc-list/mwc-list-item";
+import memoizeOne from "memoize-one";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { ensureArray } from "../../../../../common/array/ensure-array";
+import type { SchemaUnion } from "../../../../../components/ha-form/types";
import "../../../../../components/ha-select";
import type {
AutomationConfig,
@@ -30,6 +32,22 @@ export class HaTriggerCondition extends LitElement {
};
}
+ private _schema = memoizeOne(
+ (triggers: Trigger[]) =>
+ [
+ {
+ name: "id",
+ selector: {
+ select: {
+ multiple: true,
+ options: triggers.map((trigger) => trigger.id!),
+ },
+ },
+ required: true,
+ },
+ ] as const
+ );
+
connectedCallback() {
super.connectedCallback();
const details = { callback: (config) => this._automationUpdated(config) };
@@ -45,30 +63,33 @@ export class HaTriggerCondition extends LitElement {
}
protected render() {
- const { id } = this.condition;
-
if (!this._triggers.length) {
return this.hass.localize(
"ui.panel.config.automation.editor.conditions.type.trigger.no_triggers"
);
}
- return html`
- ${this._triggers.map(
- (trigger) =>
- html`
- ${trigger.id}
- `
- )}
- `;
+
+ const schema = this._schema(this._triggers);
+
+ return html`
+
+ `;
}
+ private _computeLabelCallback = (
+ schema: SchemaUnion>
+ ): string =>
+ this.hass.localize(
+ `ui.panel.config.automation.editor.conditions.type.trigger.${schema.name}`
+ );
+
private _automationUpdated(config?: AutomationConfig) {
const seenIds = new Set();
this._triggers = config?.trigger
@@ -78,18 +99,24 @@ export class HaTriggerCondition extends LitElement {
: [];
}
- private _triggerPicked(ev) {
+ private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation();
- if (!ev.target.value) {
- return;
+ const newValue = ev.detail.value;
+
+ if (typeof newValue.id === "string") {
+ if (!this._triggers.some((trigger) => trigger.id === newValue.id)) {
+ newValue.id = "";
+ }
+ } else if (Array.isArray(newValue.id)) {
+ newValue.id = newValue.id.filter((id) =>
+ this._triggers.some((trigger) => trigger.id === id)
+ );
+ if (!newValue.id.length) {
+ newValue.id = "";
+ }
}
- const newTrigger = ev.target.value;
- if (this.condition.id === newTrigger) {
- return;
- }
- fireEvent(this, "value-changed", {
- value: { ...this.condition, id: newTrigger },
- });
+
+ fireEvent(this, "value-changed", { value: newValue });
}
}