diff --git a/src/panels/config/automation/action/types/ha-automation-action-service.ts b/src/panels/config/automation/action/types/ha-automation-action-service.ts index e59c1800dd..af4a525406 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-service.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-service.ts @@ -1,7 +1,10 @@ import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; import { assert } from "superstruct"; import { fireEvent } from "../../../../../common/dom/fire_event"; +import { computeDomain } from "../../../../../common/entity/compute_domain"; +import { computeObjectId } from "../../../../../common/entity/compute_object_id"; import { hasTemplate } from "../../../../../common/string/has-template"; import "../../../../../components/ha-service-control"; import { ServiceAction, serviceActionStruct } from "../../../../../data/script"; @@ -20,6 +23,26 @@ export class HaServiceAction extends LitElement implements ActionElement { @state() private _action!: ServiceAction; + private _fields = memoizeOne( + ( + serviceDomains: HomeAssistant["services"], + domainService: string | undefined + ): { fields: any } => { + if (!domainService) { + return { fields: {} }; + } + const domain = computeDomain(domainService); + const service = computeObjectId(domainService); + if (!(domain in serviceDomains)) { + return { fields: {} }; + } + if (!(service in serviceDomains[domain])) { + return { fields: {} }; + } + return { fields: serviceDomains[domain][service].fields }; + } + ); + public static get defaultConfig() { return { service: "", data: {} }; } @@ -34,7 +57,28 @@ export class HaServiceAction extends LitElement implements ActionElement { fireEvent(this, "ui-mode-not-available", err); return; } - if (this.action && hasTemplate(this.action)) { + + const fields = this._fields( + this.hass.services, + this.action?.service + ).fields; + if ( + this.action && + (Object.entries(this.action).some( + ([key, val]) => key !== "data" && hasTemplate(val) + ) || + (this.action.data && + Object.entries(this.action.data).some(([key, val]) => { + const field = fields[key]; + if ( + field?.selector && + ("template" in field.selector || "object" in field.selector) + ) { + return false; + } + return hasTemplate(val); + }))) + ) { fireEvent( this, "ui-mode-not-available", diff --git a/src/panels/developer-tools/service/developer-tools-service.ts b/src/panels/developer-tools/service/developer-tools-service.ts index 8e45387ed2..a169b0fb27 100644 --- a/src/panels/developer-tools/service/developer-tools-service.ts +++ b/src/panels/developer-tools/service/developer-tools-service.ts @@ -346,7 +346,27 @@ class HaPanelDevService extends LitElement { } private _checkUiSupported() { - if (this._serviceData && hasTemplate(this._serviceData)) { + const fields = this._fields( + this.hass.services, + this._serviceData?.service + ).fields; + if ( + this._serviceData && + (Object.entries(this._serviceData).some( + ([key, val]) => key !== "data" && hasTemplate(val) + ) || + (this._serviceData.data && + Object.entries(this._serviceData.data).some(([key, val]) => { + const field = fields.find((f) => f.key === key); + if ( + field?.selector && + ("template" in field.selector || "object" in field.selector) + ) { + return false; + } + return hasTemplate(val); + }))) + ) { this._yamlMode = true; this._uiAvailable = false; } else {