Change yaml config of UI service call actions (#21508)

This commit is contained in:
Bram Kragten 2024-07-31 14:34:43 +02:00 committed by GitHub
parent 0a095c6f21
commit a88a7c5236
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 71 additions and 32 deletions

View File

@ -287,11 +287,11 @@ const CONFIGS = [
config: `
- type: entities
entities:
- type: call-service
- type: perform-action
icon: mdi:power
name: Bed light
action_name: Toggle light
service: light.toggle
action: light.toggle
data:
entity_id: light.bed_light
- type: section

View File

@ -5,10 +5,12 @@ export interface ToggleActionConfig extends BaseActionConfig {
}
export interface CallServiceActionConfig extends BaseActionConfig {
action: "call-service";
service: string;
action: "call-service" | "perform-action";
/** @deprecated "service" is kept for backwards compatibility. Replaced by "perform_action". */
service?: string;
perform_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<string, unknown>;
data?: Record<string, unknown>;
}

View File

@ -302,7 +302,9 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
state_color: this._config.state_color,
...(entityConf as EntityConfig),
} as EntityConfig)
: entityConf
: entityConf.type === "perform-action"
? { ...entityConf, type: "call-service" }
: entityConf
);
if (this._hass) {
element.hass = this._hass;

View File

@ -66,6 +66,8 @@ export interface EntitiesCardEntityConfig extends EntityConfig {
| "tilt-position"
| "brightness";
action_name?: string;
action?: string;
/** @deprecated use "action" instead */
service?: string;
// "service_data" is kept for backwards compatibility. Replaced by "data".
service_data?: Record<string, unknown>;

View File

@ -56,8 +56,12 @@ export const handleAction = async (
forwardHaptic("warning");
let serviceName;
if (actionConfig.action === "call-service") {
const [domain, service] = actionConfig.service.split(".", 2);
if (
actionConfig.action === "call-service" ||
actionConfig.action === "perform-action"
) {
const [domain, service] = (actionConfig.perform_action ||
actionConfig.service)!.split(".", 2);
const serviceDomains = hass.services;
if (domain in serviceDomains && service in serviceDomains[domain]) {
await hass.loadBackendTranslation("title");
@ -145,15 +149,17 @@ export const handleAction = async (
}
break;
}
case "perform-action":
case "call-service": {
if (!actionConfig.service) {
if (!actionConfig.perform_action && !actionConfig.service) {
showToast(node, {
message: hass.localize("ui.panel.lovelace.cards.actions.no_action"),
});
forwardHaptic("failure");
return;
}
const [domain, service] = actionConfig.service.split(".", 2);
const [domain, service] = (actionConfig.perform_action ||
actionConfig.service)!.split(".", 2);
hass.callService(
domain,
service,

View File

@ -33,7 +33,7 @@ const DEFAULT_ACTIONS: UiAction[] = [
"toggle",
"navigate",
"url",
"call-service",
"perform-action",
"assist",
"none",
];
@ -98,7 +98,7 @@ export class HuiActionEditor extends LitElement {
get _service(): string {
const config = this.config as CallServiceActionConfig;
return config?.service || "";
return config?.perform_action || config?.service || "";
}
private _serviceAction = memoizeOne(
@ -127,13 +127,19 @@ export class HuiActionEditor extends LitElement {
const actions = this.actions ?? DEFAULT_ACTIONS;
let action = this.config?.action || "default";
if (action === "call-service") {
action = "perform-action";
}
return html`
<div class="dropdown">
<ha-select
.label=${this.label}
.configValue=${"action"}
@selected=${this._actionPicked}
.value=${this.config?.action ?? "default"}
.value=${action}
@closed=${stopPropagation}
fixedMenuPosition
naturalMenuWidt
@ -149,10 +155,10 @@ export class HuiActionEditor extends LitElement {
: nothing}
</mwc-list-item>
${actions.map(
(action) => html`
<mwc-list-item .value=${action}>
(actn) => html`
<mwc-list-item .value=${actn}>
${this.hass!.localize(
`ui.panel.lovelace.editor.action-editor.actions.${action}`
`ui.panel.lovelace.editor.action-editor.actions.${actn}`
)}
</mwc-list-item>
`
@ -188,7 +194,8 @@ export class HuiActionEditor extends LitElement {
></ha-textfield>
`
: nothing}
${this.config?.action === "call-service"
${this.config?.action === "call-service" ||
this.config?.action === "perform-action"
? html`
<ha-service-control
.hass=${this.hass}
@ -234,8 +241,8 @@ export class HuiActionEditor extends LitElement {
data = { url_path: this._url_path };
break;
}
case "call-service": {
data = { service: this._service };
case "perform-action": {
data = { perform_action: this._service };
break;
}
case "navigate": {
@ -285,7 +292,7 @@ export class HuiActionEditor extends LitElement {
ev.stopPropagation();
const value = {
...this.config!,
service: ev.detail.value.service || "",
perform_action: ev.detail.value.service || "",
data: ev.detail.value.data,
target: ev.detail.value.target || {},
};
@ -296,6 +303,9 @@ export class HuiActionEditor extends LitElement {
if ("service_data" in value) {
delete value.service_data;
}
if ("service" in value) {
delete value.service;
}
fireEvent(this, "value-changed", { value });
}

View File

@ -67,9 +67,10 @@ const castEntitiesRowConfigStruct = object({
});
const callServiceEntitiesRowConfigStruct = object({
type: literal("call-service"),
type: enums(["call-service", "perform-action"]),
name: string(),
service: string(),
service: optional(string()),
action: optional(string()),
icon: optional(string()),
action_name: optional(string()),
// "service_data" is kept for backwards compatibility. Replaced by "data".
@ -149,6 +150,7 @@ const entitiesRowConfigStruct = dynamic<any>((value) => {
case "buttons": {
return buttonsEntitiesRowConfigStruct;
}
case "perform-action":
case "call-service": {
return callServiceEntitiesRowConfigStruct;
}

View File

@ -13,6 +13,10 @@ export class HuiRowElementEditor extends HuiElementEditor<LovelaceRowConfig> {
return GENERIC_ROW_TYPE;
}
if (this.value?.type === "perform-action") {
return "call-service";
}
return this.value?.type;
}

View File

@ -31,8 +31,9 @@ const actionConfigStructUrl = object({
});
const actionConfigStructService = object({
action: literal("call-service"),
service: string(),
action: enums(["call-service", "perform-action"]),
service: optional(string()),
perform_action: optional(string()),
service_data: optional(object()),
data: optional(object()),
target: optional(
@ -64,6 +65,7 @@ export const actionConfigStructType = object({
"toggle",
"more-info",
"call-service",
"perform-action",
"url",
"navigate",
"assist",
@ -77,6 +79,9 @@ export const actionConfigStruct = dynamic<any>((value) => {
case "call-service": {
return actionConfigStructService;
}
case "perform-action": {
return actionConfigStructService;
}
case "navigate": {
return actionConfigStructNavigate;
}

View File

@ -41,8 +41,12 @@ export interface TextConfig {
text: string;
}
export interface CallServiceConfig extends EntityConfig {
type: "call-service";
service: string;
type: "call-service" | "perform-action";
/** @deprecated use "action" instead */
service?: string;
action: string;
data?: Record<string, any>;
/** @deprecated use "data" instead */
service_data?: Record<string, any>;
action_name?: string;
}

View File

@ -15,15 +15,16 @@ export class HuiCallServiceRow extends HuiButtonRow {
throw new Error("No name specified");
}
if (!callServiceConfig.service) {
throw new Error("No service specified");
if (!callServiceConfig.action && !callServiceConfig.service) {
throw new Error("No action specified");
}
super.setConfig({
tap_action: {
action: "call-service",
service: callServiceConfig.service,
data: callServiceConfig.service_data,
action: "perform-action",
perform_action: (callServiceConfig.action ||
callServiceConfig.service)!,
data: callServiceConfig.data || callServiceConfig.service_data,
},
...callServiceConfig,
type: "button",

View File

@ -5672,7 +5672,7 @@
"pipeline_id": "Assistant",
"actions": {
"default_action": "Default",
"call-service": "Perform action",
"perform-action": "Perform action",
"more-info": "More info",
"toggle": "Toggle",
"navigate": "Navigate",
@ -5787,6 +5787,7 @@
"entity_row": {
"divider": "Divider",
"call-service": "Perform action",
"perform-action": "Perform action",
"section": "Section",
"weblink": "Web link",
"attribute": "Attribute",