Add for to UI for template trigger (#15534)

This commit is contained in:
karwosts 2023-02-21 08:27:56 -08:00 committed by GitHub
parent 4e841c4a06
commit d00467a39c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 53 deletions

View File

@ -146,6 +146,7 @@ export interface TimeTrigger extends BaseTrigger {
export interface TemplateTrigger extends BaseTrigger { export interface TemplateTrigger extends BaseTrigger {
platform: "template"; platform: "template";
value_template: string; value_template: string;
for?: string | number | ForDict;
} }
export interface EventTrigger extends BaseTrigger { export interface EventTrigger extends BaseTrigger {

View File

@ -3,7 +3,7 @@ import secondsToDuration from "../common/datetime/seconds_to_duration";
import { ensureArray } from "../common/array/ensure-array"; import { ensureArray } from "../common/array/ensure-array";
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
import type { HomeAssistant } from "../types"; import type { HomeAssistant } from "../types";
import { Condition, Trigger } from "./automation"; import { Condition, Trigger, ForDict } from "./automation";
import { import {
DeviceCondition, DeviceCondition,
DeviceTrigger, DeviceTrigger,
@ -12,6 +12,18 @@ import {
} from "./device_automation"; } from "./device_automation";
import { formatAttributeName } from "./entity_attributes"; import { formatAttributeName } from "./entity_attributes";
const describeDuration = (forTime: number | string | ForDict) => {
let duration: string | null;
if (typeof forTime === "number") {
duration = secondsToDuration(forTime);
} else if (typeof forTime === "string") {
duration = forTime;
} else {
duration = formatDuration(forTime);
}
return duration;
};
export const describeTrigger = ( export const describeTrigger = (
trigger: Trigger, trigger: Trigger,
hass: HomeAssistant, hass: HomeAssistant,
@ -73,14 +85,7 @@ export const describeTrigger = (
} }
if (trigger.for) { if (trigger.for) {
let duration: string | null; const duration = describeDuration(trigger.for);
if (typeof trigger.for === "number") {
duration = secondsToDuration(trigger.for);
} else if (typeof trigger.for === "string") {
duration = trigger.for;
} else {
duration = formatDuration(trigger.for);
}
if (duration) { if (duration) {
base += ` for ${duration}`; base += ` for ${duration}`;
} }
@ -156,15 +161,7 @@ export const describeTrigger = (
} }
if (trigger.for) { if (trigger.for) {
let duration: string | null; const duration = describeDuration(trigger.for);
if (typeof trigger.for === "number") {
duration = secondsToDuration(trigger.for);
} else if (typeof trigger.for === "string") {
duration = trigger.for;
} else {
duration = formatDuration(trigger.for);
}
if (duration) { if (duration) {
base += ` for ${duration}`; base += ` for ${duration}`;
} }
@ -319,7 +316,14 @@ export const describeTrigger = (
// Template Trigger // Template Trigger
if (trigger.platform === "template") { if (trigger.platform === "template") {
return "When a template triggers"; let base = "When a template triggers";
if (trigger.for) {
const duration = describeDuration(trigger.for);
if (duration) {
base += ` for ${duration}`;
}
}
return base;
} }
// Webhook Trigger // Webhook Trigger
@ -440,14 +444,7 @@ export const describeCondition = (
base += ` ${entity} is ${states}`; base += ` ${entity} is ${states}`;
if (condition.for) { if (condition.for) {
let duration: string | null; const duration = describeDuration(condition.for);
if (typeof condition.for === "number") {
duration = secondsToDuration(condition.for);
} else if (typeof condition.for === "string") {
duration = condition.for;
} else {
duration = formatDuration(condition.for);
}
if (duration) { if (duration) {
base += ` for ${duration}`; base += ` for ${duration}`;
} }

View File

@ -1,9 +1,18 @@
import "../../../../../components/ha-textarea"; import "../../../../../components/ha-textarea";
import { css, html, LitElement } from "lit"; import { html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import type { TemplateTrigger } from "../../../../../data/automation"; import type { TemplateTrigger } from "../../../../../data/automation";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { handleChangeEvent } from "../ha-automation-trigger-row"; import "../../../../../components/ha-form/ha-form";
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { hasTemplate } from "../../../../../common/string/has-template";
import type { SchemaUnion } from "../../../../../components/ha-form/types";
const SCHEMA = [
{ name: "value_template", required: true, selector: { template: {} } },
{ name: "for", selector: { duration: {} } },
] as const;
@customElement("ha-automation-trigger-template") @customElement("ha-automation-trigger-template")
export class HaTemplateTrigger extends LitElement { export class HaTemplateTrigger extends LitElement {
@ -17,39 +26,60 @@ export class HaTemplateTrigger extends LitElement {
return { value_template: "" }; return { value_template: "" };
} }
public willUpdate(changedProperties: PropertyValues) {
if (!changedProperties.has("trigger")) {
return;
}
// Check for templates in trigger. If found, revert to YAML mode.
if (this.trigger && hasTemplate(this.trigger.for)) {
fireEvent(
this,
"ui-mode-not-available",
Error(this.hass.localize("ui.errors.config.no_template_editor_support"))
);
}
}
protected render() { protected render() {
const { value_template } = this.trigger; const trgFor = createDurationData(this.trigger.for);
const data = {
...this.trigger,
for: trgFor,
};
return html` return html`
<p> <ha-form
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.template.value_template"
)}
*
</p>
<ha-code-editor
.name=${"value_template"}
mode="jinja2"
.hass=${this.hass} .hass=${this.hass}
.value=${value_template} .data=${data}
.readOnly=${this.disabled} .schema=${SCHEMA}
autocomplete-entities
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
dir="ltr" .computeLabel=${this._computeLabelCallback}
></ha-code-editor> .disabled=${this.disabled}
></ha-form>
`; `;
} }
private _valueChanged(ev: CustomEvent): void { private _valueChanged(ev: CustomEvent): void {
handleChangeEvent(this, ev); ev.stopPropagation();
const newTrigger = ev.detail.value;
if (
newTrigger.for &&
Object.values(newTrigger.for).every((value) => value === 0)
) {
delete newTrigger.for;
}
fireEvent(this, "value-changed", { value: newTrigger });
} }
static get styles() { private _computeLabelCallback = (
return css` schema: SchemaUnion<typeof SCHEMA>
p { ): string =>
margin-top: 0; this.hass.localize(
} `ui.panel.config.automation.editor.triggers.type.template.${schema.name}`
`; );
}
} }
declare global { declare global {

View File

@ -2129,7 +2129,8 @@
}, },
"template": { "template": {
"label": "Template", "label": "Template",
"value_template": "Value template" "value_template": "Value template",
"for": "For"
}, },
"time": { "time": {
"type_value": "Fixed time", "type_value": "Fixed time",