mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Support templates in action target (#25656)
This commit is contained in:
parent
174d54396f
commit
2dfe5f50a6
@ -276,6 +276,16 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
private _getTargetedEntities = memoizeOne((target, value) => {
|
private _getTargetedEntities = memoizeOne((target, value) => {
|
||||||
const targetSelector = target ? { target } : { target: {} };
|
const targetSelector = target ? { target } : { target: {} };
|
||||||
|
if (
|
||||||
|
hasTemplate(value?.target) ||
|
||||||
|
hasTemplate(value?.data?.entity_id) ||
|
||||||
|
hasTemplate(value?.data?.device_id) ||
|
||||||
|
hasTemplate(value?.data?.area_id) ||
|
||||||
|
hasTemplate(value?.data?.floor_id) ||
|
||||||
|
hasTemplate(value?.data?.label_id)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const targetEntities =
|
const targetEntities =
|
||||||
ensureArray(
|
ensureArray(
|
||||||
value?.target?.entity_id || value?.data?.entity_id
|
value?.target?.entity_id || value?.data?.entity_id
|
||||||
@ -349,8 +359,11 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
private _filterField(
|
private _filterField(
|
||||||
filter: ExtHassService["fields"][number]["filter"],
|
filter: ExtHassService["fields"][number]["filter"],
|
||||||
targetEntities: string[]
|
targetEntities: string[] | null
|
||||||
) {
|
) {
|
||||||
|
if (targetEntities === null) {
|
||||||
|
return true; // Target is a template, show all fields
|
||||||
|
}
|
||||||
if (!targetEntities.length) {
|
if (!targetEntities.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -386,8 +399,21 @@ export class HaServiceControl extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _targetSelector = memoizeOne(
|
private _targetSelector = memoizeOne(
|
||||||
(targetSelector: TargetSelector | null | undefined) =>
|
(targetSelector: TargetSelector | null | undefined, value) => {
|
||||||
targetSelector ? { target: { ...targetSelector } } : { target: {} }
|
if (!value || (typeof value === "object" && !Object.keys(value).length)) {
|
||||||
|
delete this._stickySelector.target;
|
||||||
|
} else if (hasTemplate(value)) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this._stickySelector.target = { template: null };
|
||||||
|
} else {
|
||||||
|
this._stickySelector.target = { object: null };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this._stickySelector.target ??
|
||||||
|
(targetSelector ? { target: { ...targetSelector } } : { target: {} })
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
@ -482,7 +508,8 @@ export class HaServiceControl extends LitElement {
|
|||||||
><ha-selector
|
><ha-selector
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.selector=${this._targetSelector(
|
.selector=${this._targetSelector(
|
||||||
serviceData.target as TargetSelector
|
serviceData.target as TargetSelector,
|
||||||
|
this._value?.target
|
||||||
)}
|
)}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@value-changed=${this._targetChanged}
|
@value-changed=${this._targetChanged}
|
||||||
@ -575,7 +602,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
private _hasFilteredFields(
|
private _hasFilteredFields(
|
||||||
dataFields: ExtHassService["fields"],
|
dataFields: ExtHassService["fields"],
|
||||||
targetEntities: string[]
|
targetEntities: string[] | null
|
||||||
) {
|
) {
|
||||||
return dataFields.some(
|
return dataFields.some(
|
||||||
(dataField) =>
|
(dataField) =>
|
||||||
@ -588,7 +615,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
hasOptional: boolean,
|
hasOptional: boolean,
|
||||||
domain: string | undefined,
|
domain: string | undefined,
|
||||||
serviceName: string | undefined,
|
serviceName: string | undefined,
|
||||||
targetEntities: string[]
|
targetEntities: string[] | null
|
||||||
) => {
|
) => {
|
||||||
if (
|
if (
|
||||||
dataField.filter &&
|
dataField.filter &&
|
||||||
@ -822,6 +849,10 @@ export class HaServiceControl extends LitElement {
|
|||||||
|
|
||||||
private _targetChanged(ev: CustomEvent) {
|
private _targetChanged(ev: CustomEvent) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
if (ev.detail.isValid === false) {
|
||||||
|
// Don't clear an object selector that returns invalid YAML
|
||||||
|
return;
|
||||||
|
}
|
||||||
const newValue = ev.detail.value;
|
const newValue = ev.detail.value;
|
||||||
if (this._value?.target === newValue) {
|
if (this._value?.target === newValue) {
|
||||||
return;
|
return;
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
literal,
|
literal,
|
||||||
is,
|
is,
|
||||||
boolean,
|
boolean,
|
||||||
|
refine,
|
||||||
} from "superstruct";
|
} from "superstruct";
|
||||||
import { arrayLiteralIncludes } from "../common/array/literal-includes";
|
import { arrayLiteralIncludes } from "../common/array/literal-includes";
|
||||||
import { navigate } from "../common/navigate";
|
import { navigate } from "../common/navigate";
|
||||||
@ -49,13 +50,18 @@ export const targetStruct = object({
|
|||||||
label_id: optional(union([string(), array(string())])),
|
label_id: optional(union([string(), array(string())])),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const serviceActionStruct: Describe<ServiceAction> = assign(
|
export const serviceActionStruct: Describe<ServiceActionWithTemplate> = assign(
|
||||||
baseActionStruct,
|
baseActionStruct,
|
||||||
object({
|
object({
|
||||||
action: optional(string()),
|
action: optional(string()),
|
||||||
service_template: optional(string()),
|
service_template: optional(string()),
|
||||||
entity_id: optional(string()),
|
entity_id: optional(string()),
|
||||||
target: optional(targetStruct),
|
target: optional(
|
||||||
|
union([
|
||||||
|
targetStruct,
|
||||||
|
refine(string(), "has_template", (val) => hasTemplate(val)),
|
||||||
|
])
|
||||||
|
),
|
||||||
data: optional(object()),
|
data: optional(object()),
|
||||||
response_variable: optional(string()),
|
response_variable: optional(string()),
|
||||||
metadata: optional(object()),
|
metadata: optional(object()),
|
||||||
@ -132,6 +138,12 @@ export interface ServiceAction extends BaseAction {
|
|||||||
metadata?: Record<string, unknown>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ServiceActionWithTemplate = ServiceAction & {
|
||||||
|
target?: HassServiceTarget | string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type { ServiceActionWithTemplate };
|
||||||
|
|
||||||
export interface DeviceAction extends BaseAction {
|
export interface DeviceAction extends BaseAction {
|
||||||
type: string;
|
type: string;
|
||||||
device_id: string;
|
device_id: string;
|
||||||
|
@ -42,7 +42,7 @@ export class HaServiceAction extends LitElement implements ActionElement {
|
|||||||
if (
|
if (
|
||||||
this.action &&
|
this.action &&
|
||||||
Object.entries(this.action).some(
|
Object.entries(this.action).some(
|
||||||
([key, val]) => key !== "data" && hasTemplate(val)
|
([key, val]) => !["data", "target"].includes(key) && hasTemplate(val)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
fireEvent(
|
fireEvent(
|
||||||
|
@ -535,7 +535,7 @@ class HaPanelDevAction extends LitElement {
|
|||||||
if (
|
if (
|
||||||
this._serviceData &&
|
this._serviceData &&
|
||||||
Object.entries(this._serviceData).some(
|
Object.entries(this._serviceData).some(
|
||||||
([key, val]) => key !== "data" && hasTemplate(val)
|
([key, val]) => !["data", "target"].includes(key) && hasTemplate(val)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this._yamlMode = true;
|
this._yamlMode = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user