diff --git a/src/data/script.ts b/src/data/script.ts index 942296cef8..6fb4fbb596 100644 --- a/src/data/script.ts +++ b/src/data/script.ts @@ -51,6 +51,7 @@ export const serviceActionStruct: Describe = assign( entity_id: optional(string()), target: optional(targetStruct), data: optional(object()), + response_variable: optional(string()), }) ); diff --git a/src/panels/config/automation/action/types/ha-automation-action-service.ts b/src/panels/config/automation/action/types/ha-automation-action-service.ts index af4a525406..0c403a13dd 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-service.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-service.ts @@ -1,4 +1,11 @@ -import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; +import { + css, + CSSResultGroup, + html, + LitElement, + nothing, + PropertyValues, +} from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { assert } from "superstruct"; @@ -21,7 +28,9 @@ export class HaServiceAction extends LitElement implements ActionElement { @property({ type: Boolean }) public narrow = false; - @state() private _action!: ServiceAction; + @state() private _action?: ServiceAction; + + @state() private _responseChecked = false; private _fields = memoizeOne( ( @@ -98,6 +107,12 @@ export class HaServiceAction extends LitElement implements ActionElement { } protected render() { + if (!this._action) { + return nothing; + } + const [domain, service] = this._action.service + ? this._action.service.split(".", 2) + : [undefined, undefined]; return html` + ${domain && service && this.hass.services[domain]?.[service]?.response + ? html` + ${this.hass.services[domain][service].response!.optional + ? html`` + : html`
`} + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.type.service.response_variable" + )} + + ${this.hass.services[domain][service].response!.optional + ? this.hass.localize( + "ui.panel.config.automation.editor.actions.type.service.has_optional_response" + ) + : this.hass.localize( + "ui.panel.config.automation.editor.actions.type.service.has_response" + )} + + +
` + : nothing} `; } @@ -114,6 +164,39 @@ export class HaServiceAction extends LitElement implements ActionElement { if (ev.detail.value === this._action) { ev.stopPropagation(); } + const value = { ...this.action, ...ev.detail.value }; + if ("response_variable" in this.action) { + const [domain, service] = this._action!.service + ? this._action!.service.split(".", 2) + : [undefined, undefined]; + if ( + domain && + service && + this.hass.services[domain]?.[service] && + !("response" in this.hass.services[domain][service]) + ) { + delete value.response_variable; + this._responseChecked = false; + } + } + fireEvent(this, "value-changed", { value }); + } + + private _responseVariableChanged(ev) { + const value = { ...this.action, response_variable: ev.target.value }; + if (!ev.target.value) { + delete value.response_variable; + } + fireEvent(this, "value-changed", { value }); + } + + private _responseCheckboxChanged(ev) { + this._responseChecked = ev.target.checked; + if (!this._responseChecked) { + const value = { ...this.action }; + delete value.response_variable; + fireEvent(this, "value-changed", { value }); + } } static get styles(): CSSResultGroup { @@ -122,6 +205,25 @@ export class HaServiceAction extends LitElement implements ActionElement { display: block; margin: 0 -16px; } + ha-settings-row { + margin: 0 -16px; + padding: var(--service-control-padding, 0 16px); + } + ha-settings-row { + --paper-time-input-justify-content: flex-end; + --settings-row-content-width: 100%; + --settings-row-prefix-display: contents; + border-top: var( + --service-control-items-border-top, + 1px solid var(--divider-color) + ); + } + ha-checkbox { + margin-left: -16px; + } + .checkbox-spacer { + width: 32px; + } `; } } diff --git a/src/translations/en.json b/src/translations/en.json index 6e9da65bba..7e081c3070 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2567,7 +2567,10 @@ "continue_on_error": "Continue on error", "type": { "service": { - "label": "Call service" + "label": "Call service", + "response_variable": "Response variable", + "has_optional_response": "This service can return a response, if you want to use the response, enter the name of a variable the response will be saved in", + "has_response": "This service returns a response, enter the name of a variable the response will be saved in" }, "play_media": { "label": "Play media"