mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Support more templates in action visual editor (#25015)
* Support more templates in action visual editor * Make selector sticky * typing
This commit is contained in:
parent
fbeb457c25
commit
6d7a40368c
@ -38,6 +38,7 @@ import "./ha-settings-row";
|
||||
import "./ha-yaml-editor";
|
||||
import type { HaYamlEditor } from "./ha-yaml-editor";
|
||||
import "./ha-service-section-icon";
|
||||
import { hasTemplate } from "../common/string/has-template";
|
||||
|
||||
const attributeFilter = (values: any[], attribute: any) => {
|
||||
if (typeof attribute === "object") {
|
||||
@ -101,6 +102,8 @@ export class HaServiceControl extends LitElement {
|
||||
|
||||
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
||||
|
||||
private _stickySelector: Record<string, Selector> = {};
|
||||
|
||||
protected willUpdate(changedProperties: PropertyValues<this>) {
|
||||
if (!this.hasUpdated) {
|
||||
this.hass.loadBackendTranslation("services");
|
||||
@ -590,7 +593,23 @@ export class HaServiceControl extends LitElement {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const selector = dataField?.selector ?? { text: undefined };
|
||||
const fieldDataHasTemplate =
|
||||
this._value?.data && hasTemplate(this._value.data[dataField.key]);
|
||||
|
||||
const selector =
|
||||
fieldDataHasTemplate &&
|
||||
typeof this._value!.data![dataField.key] === "string"
|
||||
? { template: null }
|
||||
: fieldDataHasTemplate &&
|
||||
typeof this._value!.data![dataField.key] === "object"
|
||||
? { object: null }
|
||||
: (this._stickySelector[dataField.key] ??
|
||||
dataField?.selector ?? { text: null });
|
||||
|
||||
if (fieldDataHasTemplate) {
|
||||
// Hold this selector type until the field is cleared
|
||||
this._stickySelector[dataField.key] = selector;
|
||||
}
|
||||
|
||||
const showOptional = showOptionalToggle(dataField);
|
||||
|
||||
@ -693,6 +712,7 @@ export class HaServiceControl extends LitElement {
|
||||
this._checkedKeys.delete(key);
|
||||
data = { ...this._value?.data };
|
||||
delete data[key];
|
||||
delete this._stickySelector[key];
|
||||
}
|
||||
if (data) {
|
||||
fireEvent(this, "value-changed", {
|
||||
@ -816,6 +836,10 @@ export class HaServiceControl extends LitElement {
|
||||
|
||||
private _serviceDataChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
if (ev.detail.isValid === false) {
|
||||
// Don't clear an object selector that returns invalid YAML
|
||||
return;
|
||||
}
|
||||
const key = (ev.currentTarget as any).key;
|
||||
const value = ev.detail.value;
|
||||
if (
|
||||
@ -828,8 +852,13 @@ export class HaServiceControl extends LitElement {
|
||||
|
||||
const data = { ...this._value?.data, [key]: value };
|
||||
|
||||
if (value === "" || value === undefined) {
|
||||
if (
|
||||
value === "" ||
|
||||
value === undefined ||
|
||||
(typeof value === "object" && !Object.keys(value).length)
|
||||
) {
|
||||
delete data[key];
|
||||
delete this._stickySelector[key];
|
||||
}
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
|
@ -1,11 +1,8 @@
|
||||
import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } 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 type { ServiceAction } from "../../../../../data/script";
|
||||
@ -27,26 +24,6 @@ export class HaServiceAction extends LitElement implements ActionElement {
|
||||
|
||||
@state() private _responseChecked = false;
|
||||
|
||||
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(): ServiceAction {
|
||||
return { action: "", data: {} };
|
||||
}
|
||||
@ -62,23 +39,11 @@ export class HaServiceAction extends LitElement implements ActionElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const fields = this._fields(this.hass.services, this.action?.action).fields;
|
||||
if (
|
||||
this.action &&
|
||||
(Object.entries(this.action).some(
|
||||
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,
|
||||
|
@ -528,26 +528,11 @@ class HaPanelDevAction extends LitElement {
|
||||
}
|
||||
|
||||
private _checkUiSupported() {
|
||||
const fields = this._fields(
|
||||
this.hass.services,
|
||||
this._serviceData?.action
|
||||
).fields;
|
||||
if (
|
||||
this._serviceData &&
|
||||
(Object.entries(this._serviceData).some(
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user