mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add some Trigger Descriptions (#13460)
Co-authored-by: Franck Nijhof <git@frenck.dev> Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
5ce81232b5
commit
807bb10199
@ -1,25 +1,56 @@
|
||||
import { dump } from "js-yaml";
|
||||
import { html, css, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { css, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/ha-yaml-editor";
|
||||
import { Trigger } from "../../../../src/data/automation";
|
||||
import { describeTrigger } from "../../../../src/data/automation_i18n";
|
||||
import { getEntity } from "../../../../src/fake_data/entity";
|
||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
|
||||
const ENTITIES = [
|
||||
getEntity("light", "kitchen", "on", {
|
||||
friendly_name: "Kitchen Light",
|
||||
}),
|
||||
getEntity("person", "person", "", {
|
||||
friendly_name: "Person",
|
||||
}),
|
||||
getEntity("zone", "home", "", {
|
||||
friendly_name: "Home",
|
||||
}),
|
||||
];
|
||||
|
||||
const triggers = [
|
||||
{ platform: "state" },
|
||||
{ platform: "state", entity_id: "light.kitchen", from: "off", to: "on" },
|
||||
{ platform: "mqtt" },
|
||||
{ platform: "geo_location" },
|
||||
{ platform: "homeassistant" },
|
||||
{ platform: "numeric_state" },
|
||||
{ platform: "sun" },
|
||||
{
|
||||
platform: "geo_location",
|
||||
source: "test_source",
|
||||
zone: "zone.home",
|
||||
event: "enter",
|
||||
},
|
||||
{ platform: "homeassistant", event: "start" },
|
||||
{
|
||||
platform: "numeric_state",
|
||||
entity_id: "light.kitchen",
|
||||
attribute: "brightness",
|
||||
below: 80,
|
||||
above: 20,
|
||||
},
|
||||
{ platform: "sun", event: "sunset" },
|
||||
{ platform: "time_pattern" },
|
||||
{ platform: "webhook" },
|
||||
{ platform: "zone" },
|
||||
{
|
||||
platform: "zone",
|
||||
entity_id: "person.person",
|
||||
zone: "zone.home",
|
||||
event: "enter",
|
||||
},
|
||||
{ platform: "tag" },
|
||||
{ platform: "time" },
|
||||
{ platform: "time", at: "15:32" },
|
||||
{ platform: "template" },
|
||||
{ platform: "event" },
|
||||
{ platform: "event", event_type: "homeassistant_started" },
|
||||
];
|
||||
|
||||
const initialTrigger: Trigger = {
|
||||
@ -29,14 +60,22 @@ const initialTrigger: Trigger = {
|
||||
|
||||
@customElement("demo-automation-describe-trigger")
|
||||
export class DemoAutomationDescribeTrigger extends LitElement {
|
||||
@property({ attribute: false }) hass!: HomeAssistant;
|
||||
|
||||
@state() _trigger = initialTrigger;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.hass) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-card header="Triggers">
|
||||
<div class="trigger">
|
||||
<span>
|
||||
${this._trigger ? describeTrigger(this._trigger) : "<invalid YAML>"}
|
||||
${this._trigger
|
||||
? describeTrigger(this._trigger, this.hass)
|
||||
: "<invalid YAML>"}
|
||||
</span>
|
||||
<ha-yaml-editor
|
||||
label="Trigger Config"
|
||||
@ -47,7 +86,7 @@ export class DemoAutomationDescribeTrigger extends LitElement {
|
||||
${triggers.map(
|
||||
(conf) => html`
|
||||
<div class="trigger">
|
||||
<span>${describeTrigger(conf as any)}</span>
|
||||
<span>${describeTrigger(conf as any, this.hass)}</span>
|
||||
<pre>${dump(conf)}</pre>
|
||||
</div>
|
||||
`
|
||||
@ -56,6 +95,13 @@ export class DemoAutomationDescribeTrigger extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
const hass = provideHass(this);
|
||||
hass.updateTranslations(null, "en");
|
||||
hass.addEntities(ENTITIES);
|
||||
}
|
||||
|
||||
private _dataChanged(ev: CustomEvent): void {
|
||||
ev.stopPropagation();
|
||||
this._trigger = ev.detail.isValid ? ev.detail.value : undefined;
|
||||
|
@ -2,11 +2,296 @@ import secondsToDuration from "../common/datetime/seconds_to_duration";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import { Condition, Trigger } from "./automation";
|
||||
import { formatAttributeName } from "./entity_attributes";
|
||||
|
||||
export const describeTrigger = (trigger: Trigger, ignoreAlias = false) => {
|
||||
export const describeTrigger = (
|
||||
trigger: Trigger,
|
||||
hass: HomeAssistant,
|
||||
ignoreAlias = false
|
||||
) => {
|
||||
if (trigger.alias && !ignoreAlias) {
|
||||
return trigger.alias;
|
||||
}
|
||||
|
||||
// Event Trigger
|
||||
if (trigger.platform === "event" && trigger.event_type) {
|
||||
let eventTypes = "";
|
||||
|
||||
if (Array.isArray(trigger.event_type)) {
|
||||
for (const [index, state] of trigger.event_type.entries()) {
|
||||
eventTypes += `${index > 0 ? "," : ""} ${
|
||||
trigger.event_type.length > 1 &&
|
||||
index === trigger.event_type.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${state}`;
|
||||
}
|
||||
} else {
|
||||
eventTypes = trigger.event_type.toString();
|
||||
}
|
||||
|
||||
return `When ${eventTypes} event is fired`;
|
||||
}
|
||||
|
||||
// Home Assistant Trigger
|
||||
if (trigger.platform === "homeassistant" && trigger.event) {
|
||||
return `When Home Assistant is ${
|
||||
trigger.event === "start" ? "started" : "shutdown"
|
||||
}`;
|
||||
}
|
||||
|
||||
// Numeric State Trigger
|
||||
if (trigger.platform === "numeric_state" && trigger.entity_id) {
|
||||
let base = "When";
|
||||
const stateObj = hass.states[trigger.entity_id];
|
||||
const entity = stateObj ? computeStateName(stateObj) : trigger.entity_id;
|
||||
|
||||
if (trigger.attribute) {
|
||||
base += ` ${formatAttributeName(trigger.attribute)} from`;
|
||||
}
|
||||
|
||||
base += ` ${entity} is`;
|
||||
|
||||
if ("above" in trigger) {
|
||||
base += ` above ${trigger.above}`;
|
||||
}
|
||||
|
||||
if ("below" in trigger && "above" in trigger) {
|
||||
base += " and";
|
||||
}
|
||||
|
||||
if ("below" in trigger) {
|
||||
base += ` below ${trigger.below}`;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
// State Trigger
|
||||
if (trigger.platform === "state" && trigger.entity_id) {
|
||||
let base = "When";
|
||||
let entities = "";
|
||||
|
||||
const states = hass.states;
|
||||
|
||||
if (trigger.attribute) {
|
||||
base += ` ${formatAttributeName(trigger.attribute)} from`;
|
||||
}
|
||||
|
||||
if (Array.isArray(trigger.entity_id)) {
|
||||
for (const [index, entity] of trigger.entity_id.entries()) {
|
||||
if (states[entity]) {
|
||||
entities += `${index > 0 ? "," : ""} ${
|
||||
trigger.entity_id.length > 1 &&
|
||||
index === trigger.entity_id.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${computeStateName(states[entity]) || entity}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
entities = states[trigger.entity_id]
|
||||
? computeStateName(states[trigger.entity_id])
|
||||
: trigger.entity_id;
|
||||
}
|
||||
|
||||
base += ` ${entities} changes`;
|
||||
|
||||
if (trigger.from) {
|
||||
let from = "";
|
||||
if (Array.isArray(trigger.from)) {
|
||||
for (const [index, state] of trigger.from.entries()) {
|
||||
from += `${index > 0 ? "," : ""} ${
|
||||
trigger.from.length > 1 && index === trigger.from.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${state}`;
|
||||
}
|
||||
} else {
|
||||
from = trigger.from.toString();
|
||||
}
|
||||
base += ` from ${from}`;
|
||||
}
|
||||
|
||||
if (trigger.to) {
|
||||
let to = "";
|
||||
if (Array.isArray(trigger.to)) {
|
||||
for (const [index, state] of trigger.to.entries()) {
|
||||
to += `${index > 0 ? "," : ""} ${
|
||||
trigger.to.length > 1 && index === trigger.to.length - 1 ? "or" : ""
|
||||
} ${state}`;
|
||||
}
|
||||
} else if (trigger.to) {
|
||||
to = trigger.to.toString();
|
||||
}
|
||||
|
||||
base += ` to ${to}`;
|
||||
}
|
||||
|
||||
if ("for" in trigger) {
|
||||
let duration: string;
|
||||
if (typeof trigger.for === "number") {
|
||||
duration = `for ${secondsToDuration(trigger.for)!}`;
|
||||
} else if (typeof trigger.for === "string") {
|
||||
duration = `for ${trigger.for}`;
|
||||
} else {
|
||||
duration = `for ${JSON.stringify(trigger.for)}`;
|
||||
}
|
||||
|
||||
base += ` for ${duration}`;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
// Sun Trigger
|
||||
if (trigger.platform === "sun" && trigger.event) {
|
||||
let base = `When the sun ${trigger.event === "sunset" ? "sets" : "rises"}`;
|
||||
|
||||
if (trigger.offset) {
|
||||
let duration = "";
|
||||
|
||||
if (trigger.offset) {
|
||||
if (typeof trigger.offset === "number") {
|
||||
duration = ` offset by ${secondsToDuration(trigger.offset)!}`;
|
||||
} else if (typeof trigger.offset === "string") {
|
||||
duration = ` offset by ${trigger.offset}`;
|
||||
} else {
|
||||
duration = ` offset by ${JSON.stringify(trigger.offset)}`;
|
||||
}
|
||||
}
|
||||
base += duration;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
// Tag Trigger
|
||||
if (trigger.platform === "tag") {
|
||||
return "When a tag is scanned";
|
||||
}
|
||||
|
||||
// Time Trigger
|
||||
if (trigger.platform === "time" && trigger.at) {
|
||||
const at = trigger.at.includes(".")
|
||||
? hass.states[trigger.at] || trigger.at
|
||||
: trigger.at;
|
||||
|
||||
return `When the time is equal to ${at}`;
|
||||
}
|
||||
|
||||
// Time Patter Trigger
|
||||
if (trigger.platform === "time_pattern") {
|
||||
return "Time pattern trigger";
|
||||
}
|
||||
|
||||
// Zone Trigger
|
||||
if (trigger.platform === "zone" && trigger.entity_id && trigger.zone) {
|
||||
let entities = "";
|
||||
let zones = "";
|
||||
let zonesPlural = false;
|
||||
|
||||
const states = hass.states;
|
||||
|
||||
if (Array.isArray(trigger.entity_id)) {
|
||||
for (const [index, entity] of trigger.entity_id.entries()) {
|
||||
if (states[entity]) {
|
||||
entities += `${index > 0 ? "," : ""} ${
|
||||
trigger.entity_id.length > 1 &&
|
||||
index === trigger.entity_id.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${computeStateName(states[entity]) || entity}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
entities = states[trigger.entity_id]
|
||||
? computeStateName(states[trigger.entity_id])
|
||||
: trigger.entity_id;
|
||||
}
|
||||
|
||||
if (Array.isArray(trigger.zone)) {
|
||||
if (trigger.zone.length > 1) {
|
||||
zonesPlural = true;
|
||||
}
|
||||
|
||||
for (const [index, zone] of trigger.zone.entries()) {
|
||||
if (states[zone]) {
|
||||
zones += `${index > 0 ? "," : ""} ${
|
||||
trigger.zone.length > 1 && index === trigger.zone.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${computeStateName(states[zone]) || zone}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zones = states[trigger.zone]
|
||||
? computeStateName(states[trigger.zone])
|
||||
: trigger.zone;
|
||||
}
|
||||
|
||||
return `When ${entities} ${trigger.event}s ${zones} ${
|
||||
zonesPlural ? "zones" : "zone"
|
||||
}`;
|
||||
}
|
||||
|
||||
// Geo Location Trigger
|
||||
if (trigger.platform === "geo_location" && trigger.source && trigger.zone) {
|
||||
let sources = "";
|
||||
let zones = "";
|
||||
let zonesPlural = false;
|
||||
const states = hass.states;
|
||||
|
||||
if (Array.isArray(trigger.source)) {
|
||||
for (const [index, source] of trigger.source.entries()) {
|
||||
sources += `${index > 0 ? "," : ""} ${
|
||||
trigger.source.length > 1 && index === trigger.source.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${source}`;
|
||||
}
|
||||
} else {
|
||||
sources = trigger.source;
|
||||
}
|
||||
|
||||
if (Array.isArray(trigger.zone)) {
|
||||
if (trigger.zone.length > 1) {
|
||||
zonesPlural = true;
|
||||
}
|
||||
|
||||
for (const [index, zone] of trigger.zone.entries()) {
|
||||
if (states[zone]) {
|
||||
zones += `${index > 0 ? "," : ""} ${
|
||||
trigger.zone.length > 1 && index === trigger.zone.length - 1
|
||||
? "or"
|
||||
: ""
|
||||
} ${computeStateName(states[zone]) || zone}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zones = states[trigger.zone]
|
||||
? computeStateName(states[trigger.zone])
|
||||
: trigger.zone;
|
||||
}
|
||||
|
||||
return `When ${sources} ${trigger.event}s ${zones} ${
|
||||
zonesPlural ? "zones" : "zone"
|
||||
}`;
|
||||
}
|
||||
// MQTT Trigger
|
||||
if (trigger.platform === "mqtt") {
|
||||
return "When a MQTT payload has been received";
|
||||
}
|
||||
|
||||
// Template Trigger
|
||||
if (trigger.platform === "template") {
|
||||
return "When a template triggers";
|
||||
}
|
||||
|
||||
// Webhook Trigger
|
||||
if (trigger.platform === "webhook") {
|
||||
return "When a Webhook payload has been received";
|
||||
}
|
||||
return `${trigger.platform || "Unknown"} trigger`;
|
||||
};
|
||||
|
||||
|
@ -142,7 +142,7 @@ export const describeAction = <T extends ActionType>(
|
||||
if (actionType === "wait_for_trigger") {
|
||||
const config = action as WaitForTriggerAction;
|
||||
return `Wait for ${ensureArray(config.wait_for_trigger)
|
||||
.map((trigger) => describeTrigger(trigger))
|
||||
.map((trigger) => describeTrigger(trigger, hass))
|
||||
.join(", ")}`;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ import { customElement, property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
|
||||
import { handleStructError } from "../../../../common/structs/handle-errors";
|
||||
import { debounce } from "../../../../common/util/debounce";
|
||||
import "../../../../components/ha-alert";
|
||||
@ -23,9 +24,10 @@ import "../../../../components/ha-button-menu";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-expansion-panel";
|
||||
import "../../../../components/ha-icon-button";
|
||||
import { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
||||
import "../../../../components/ha-textfield";
|
||||
import { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
||||
import { subscribeTrigger, Trigger } from "../../../../data/automation";
|
||||
import { describeTrigger } from "../../../../data/automation_i18n";
|
||||
import { validateConfig } from "../../../../data/config";
|
||||
import {
|
||||
showAlertDialog,
|
||||
@ -49,8 +51,6 @@ import "./types/ha-automation-trigger-time";
|
||||
import "./types/ha-automation-trigger-time_pattern";
|
||||
import "./types/ha-automation-trigger-webhook";
|
||||
import "./types/ha-automation-trigger-zone";
|
||||
import { describeTrigger } from "../../../../data/automation_i18n";
|
||||
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
|
||||
|
||||
export interface TriggerElement extends LitElement {
|
||||
trigger: Trigger;
|
||||
@ -121,7 +121,9 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
|
||||
<ha-expansion-panel
|
||||
leftChevron
|
||||
.header=${capitalizeFirstLetter(describeTrigger(this.trigger))}
|
||||
.header=${capitalizeFirstLetter(
|
||||
describeTrigger(this.trigger, this.hass)
|
||||
)}
|
||||
>
|
||||
<ha-button-menu
|
||||
slot="icons"
|
||||
@ -485,7 +487,9 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
"ui.panel.config.automation.editor.triggers.alias"
|
||||
),
|
||||
inputType: "string",
|
||||
placeholder: capitalizeFirstLetter(describeTrigger(this.trigger, true)),
|
||||
placeholder: capitalizeFirstLetter(
|
||||
describeTrigger(this.trigger, this.hass, true)
|
||||
),
|
||||
defaultValue: this.trigger.alias,
|
||||
confirmText: this.hass.localize("ui.common.submit"),
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user