mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +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 "./ha-yaml-editor";
|
||||||
import type { HaYamlEditor } from "./ha-yaml-editor";
|
import type { HaYamlEditor } from "./ha-yaml-editor";
|
||||||
import "./ha-service-section-icon";
|
import "./ha-service-section-icon";
|
||||||
|
import { hasTemplate } from "../common/string/has-template";
|
||||||
|
|
||||||
const attributeFilter = (values: any[], attribute: any) => {
|
const attributeFilter = (values: any[], attribute: any) => {
|
||||||
if (typeof attribute === "object") {
|
if (typeof attribute === "object") {
|
||||||
@ -101,6 +102,8 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
||||||
|
|
||||||
|
private _stickySelector: Record<string, Selector> = {};
|
||||||
|
|
||||||
protected willUpdate(changedProperties: PropertyValues<this>) {
|
protected willUpdate(changedProperties: PropertyValues<this>) {
|
||||||
if (!this.hasUpdated) {
|
if (!this.hasUpdated) {
|
||||||
this.hass.loadBackendTranslation("services");
|
this.hass.loadBackendTranslation("services");
|
||||||
@ -590,7 +593,23 @@ export class HaServiceControl extends LitElement {
|
|||||||
return nothing;
|
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);
|
const showOptional = showOptionalToggle(dataField);
|
||||||
|
|
||||||
@ -693,6 +712,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
this._checkedKeys.delete(key);
|
this._checkedKeys.delete(key);
|
||||||
data = { ...this._value?.data };
|
data = { ...this._value?.data };
|
||||||
delete data[key];
|
delete data[key];
|
||||||
|
delete this._stickySelector[key];
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
fireEvent(this, "value-changed", {
|
fireEvent(this, "value-changed", {
|
||||||
@ -816,6 +836,10 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
private _serviceDataChanged(ev: CustomEvent) {
|
private _serviceDataChanged(ev: CustomEvent) {
|
||||||
ev.stopPropagation();
|
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 key = (ev.currentTarget as any).key;
|
||||||
const value = ev.detail.value;
|
const value = ev.detail.value;
|
||||||
if (
|
if (
|
||||||
@ -828,8 +852,13 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
const data = { ...this._value?.data, [key]: value };
|
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 data[key];
|
||||||
|
delete this._stickySelector[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
fireEvent(this, "value-changed", {
|
fireEvent(this, "value-changed", {
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import type { PropertyValues } from "lit";
|
import type { PropertyValues } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { assert } from "superstruct";
|
import { assert } from "superstruct";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
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 { hasTemplate } from "../../../../../common/string/has-template";
|
||||||
import "../../../../../components/ha-service-control";
|
import "../../../../../components/ha-service-control";
|
||||||
import type { ServiceAction } from "../../../../../data/script";
|
import type { ServiceAction } from "../../../../../data/script";
|
||||||
@ -27,26 +24,6 @@ export class HaServiceAction extends LitElement implements ActionElement {
|
|||||||
|
|
||||||
@state() private _responseChecked = false;
|
@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 {
|
public static get defaultConfig(): ServiceAction {
|
||||||
return { action: "", data: {} };
|
return { action: "", data: {} };
|
||||||
}
|
}
|
||||||
@ -62,23 +39,11 @@ export class HaServiceAction extends LitElement implements ActionElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields = this._fields(this.hass.services, this.action?.action).fields;
|
|
||||||
if (
|
if (
|
||||||
this.action &&
|
this.action &&
|
||||||
(Object.entries(this.action).some(
|
Object.entries(this.action).some(
|
||||||
([key, val]) => key !== "data" && hasTemplate(val)
|
([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(
|
fireEvent(
|
||||||
this,
|
this,
|
||||||
|
@ -528,26 +528,11 @@ class HaPanelDevAction extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _checkUiSupported() {
|
private _checkUiSupported() {
|
||||||
const fields = this._fields(
|
|
||||||
this.hass.services,
|
|
||||||
this._serviceData?.action
|
|
||||||
).fields;
|
|
||||||
if (
|
if (
|
||||||
this._serviceData &&
|
this._serviceData &&
|
||||||
(Object.entries(this._serviceData).some(
|
Object.entries(this._serviceData).some(
|
||||||
([key, val]) => key !== "data" && hasTemplate(val)
|
([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._yamlMode = true;
|
||||||
this._uiAvailable = false;
|
this._uiAvailable = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user