diff --git a/src/panels/lovelace/editor/config-elements/elements/hui-service-button-element-editor.ts b/src/panels/lovelace/editor/config-elements/elements/hui-service-button-element-editor.ts
index 7f6afd193e..30110619fe 100644
--- a/src/panels/lovelace/editor/config-elements/elements/hui-service-button-element-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/elements/hui-service-button-element-editor.ts
@@ -1,32 +1,29 @@
-import { html, LitElement, nothing } from "lit";
+import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
+import memoizeOne from "memoize-one";
import { any, assert, literal, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../../common/dom/fire_event";
-import type { SchemaUnion } from "../../../../../components/ha-form/types";
-import type { HomeAssistant } from "../../../../../types";
import "../../../../../components/ha-form/ha-form";
-import { LovelacePictureElementEditor } from "../../../types";
+import type { SchemaUnion } from "../../../../../components/ha-form/types";
+import "../../../../../components/ha-service-control";
+import { ServiceAction } from "../../../../../data/script";
+import type { HomeAssistant } from "../../../../../types";
import { ServiceButtonElementConfig } from "../../../elements/types";
-// import { UiAction } from "../../components/hui-action-editor";
+import { LovelacePictureElementEditor } from "../../../types";
const serviceButtonElementConfigStruct = object({
type: literal("service-button"),
style: optional(any()),
title: optional(string()),
+ action: optional(string()),
service: optional(string()),
service_data: optional(any()),
+ data: optional(any()),
+ target: optional(any()),
});
const SCHEMA = [
{ name: "title", required: true, selector: { text: {} } },
- /* {
- name: "service",
- selector: {
- ui_action: { actions: ["call-service"] as UiAction[] },
- },
- }, */
- { name: "service", required: true, selector: { text: {} } },
- { name: "service_data", selector: { object: {} } },
{ name: "style", selector: { object: {} } },
] as const;
@@ -44,6 +41,14 @@ export class HuiServiceButtonElementEditor
this._config = config;
}
+ private _serviceData = memoizeOne(
+ (config: ServiceButtonElementConfig): ServiceAction => ({
+ action: config?.action ?? config?.service,
+ data: config?.data ?? config?.service_data,
+ target: config?.target,
+ })
+ );
+
protected render() {
if (!this.hass || !this._config) {
return nothing;
@@ -57,11 +62,41 @@ export class HuiServiceButtonElementEditor
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
>
+
`;
}
private _valueChanged(ev: CustomEvent): void {
- fireEvent(this, "config-changed", { config: ev.detail.value });
+ fireEvent(this, "config-changed", {
+ config: { ...this._config, ...ev.detail.value },
+ });
+ }
+
+ private _serviceDataChanged(ev: CustomEvent<{ value: ServiceAction }>): void {
+ const config: ServiceButtonElementConfig = {
+ ...this._config!,
+ action: ev.detail.value.action,
+ data: ev.detail.value.data,
+ target: ev.detail.value.target,
+ };
+
+ if ("service" in config) {
+ delete config.service;
+ }
+
+ if ("service_data" in config) {
+ delete config.service_data;
+ }
+
+ fireEvent(this, "config-changed", {
+ config,
+ });
}
private _computeLabelCallback = (schema: SchemaUnion) =>
@@ -70,6 +105,16 @@ export class HuiServiceButtonElementEditor
) ||
this.hass!.localize(`ui.panel.lovelace.editor.elements.${schema.name}`) ||
schema.name;
+
+ static get styles() {
+ return css`
+ ha-service-control {
+ display: block;
+ margin-top: 16px;
+ --service-control-padding: 0;
+ }
+ `;
+ }
}
declare global {
diff --git a/src/panels/lovelace/elements/hui-service-button-element.ts b/src/panels/lovelace/elements/hui-service-button-element.ts
index 6c7d3508e1..73bed5d415 100644
--- a/src/panels/lovelace/elements/hui-service-button-element.ts
+++ b/src/panels/lovelace/elements/hui-service-button-element.ts
@@ -26,18 +26,21 @@ export class HuiServiceButtonElement
private _service?: string;
public setConfig(config: ServiceButtonElementConfig): void {
- if (!config || !config.service) {
- throw Error("Service required");
+ if (!config || (!config.action && !config.service)) {
+ throw Error("Action required");
}
- [this._domain, this._service] = config.service.split(".", 2);
+ [this._domain, this._service] = (config.action ?? config.service)!.split(
+ ".",
+ 2
+ );
if (!this._domain) {
- throw Error("Service does not have a service domain");
+ throw Error("Action does not have a domain");
}
if (!this._service) {
- throw Error("Service does not have a service name");
+ throw Error("Action does not have a action name");
}
this._config = config;
@@ -49,7 +52,7 @@ export class HuiServiceButtonElement
}
const { entity_id, label_id, floor_id, device_id, area_id } =
- this._config.service_data ?? {};
+ this._config.service_data ?? this._config.data ?? {};
const updatedTarget = this._config.target ?? {
entity_id,
label_id,
@@ -65,8 +68,9 @@ export class HuiServiceButtonElement
.service=${this._service}
.data=${this._config.data ?? this._config.service_data}
.target=${updatedTarget}
- >${this._config.title}
+ ${this._config.title}
+
`;
}
diff --git a/src/panels/lovelace/elements/types.ts b/src/panels/lovelace/elements/types.ts
index 1b433b5bd9..fcd9a44865 100644
--- a/src/panels/lovelace/elements/types.ts
+++ b/src/panels/lovelace/elements/types.ts
@@ -59,9 +59,11 @@ export interface ImageElementConfig extends LovelaceElementConfigBase {
export interface ServiceButtonElementConfig extends LovelaceElementConfigBase {
title?: string;
+ /* @deprecated "service" is kept for backwards compatibility. Replaced by "action". */
service?: string;
+ action?: string;
target?: HassServiceTarget;
- // "service_data" is kept for backwards compatibility. Replaced by "data".
+ /* @deprecated "service_data" is kept for backwards compatibility. Replaced by "data". */
service_data?: Record;
data?: Record;
}
diff --git a/src/translations/en.json b/src/translations/en.json
index d706a8d066..804fad507d 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -5996,7 +5996,7 @@
"state-badge": "State badge",
"state-icon": "State icon",
"state-label": "State label",
- "service-button": "Service call button",
+ "service-button": "Perform action button",
"icon": "Icon",
"image": "Image",
"conditional": "Conditional"