diff --git a/src/components/ha-service-control.ts b/src/components/ha-service-control.ts index 57c3e2b3ba..778216f792 100644 --- a/src/components/ha-service-control.ts +++ b/src/components/ha-service-control.ts @@ -93,6 +93,8 @@ export class HaServiceControl extends LitElement { @property({ type: Boolean, reflect: true }) public hidePicker = false; + @property({ type: Boolean }) public hideDescription = false; + @state() private _value!: this["value"]; @state() private _checkedKeys = new Set(); @@ -373,7 +375,8 @@ export class HaServiceControl extends LitElement { )) || serviceData?.description; - return html`${this.hidePicker + return html` + ${this.hidePicker ? nothing : html``} -
- ${description ? html`

${description}

` : ""} - ${this._manifest - ? html` - - ` - : ""} -
+ ${this.hideDescription + ? nothing + : html` +
+ ${description ? html`

${description}

` : ""} + ${this._manifest + ? html` + + ` + : nothing} +
+ `} ${serviceData && "target" in serviceData ? html` ${hasOptional @@ -517,7 +524,8 @@ export class HaServiceControl extends LitElement { > ` : ""; - })}`; + })} + `; } private _localizeValueCallback = (key: string) => { diff --git a/src/dialogs/more-info/const.ts b/src/dialogs/more-info/const.ts index 65375a6f6d..b9fe72039a 100644 --- a/src/dialogs/more-info/const.ts +++ b/src/dialogs/more-info/const.ts @@ -5,7 +5,7 @@ import { computeGroupDomain, GroupEntity } from "../../data/group"; import { CONTINUOUS_DOMAINS } from "../../data/logbook"; import { HomeAssistant } from "../../types"; -export const DOMAINS_NO_INFO = ["camera", "configurator"]; +export const DOMAINS_NO_INFO = ["camera", "configurator", "script"]; /** * Entity domains that should be editable *if* they have an id present; * {@see shouldShowEditIcon}. diff --git a/src/dialogs/more-info/controls/more-info-script.ts b/src/dialogs/more-info/controls/more-info-script.ts index c53da01be1..aed21e711e 100644 --- a/src/dialogs/more-info/controls/more-info-script.ts +++ b/src/dialogs/more-info/controls/more-info-script.ts @@ -1,8 +1,21 @@ +import "@material/mwc-button"; import { HassEntity } from "home-assistant-js-websocket"; -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { + css, + CSSResultGroup, + html, + LitElement, + nothing, + PropertyValues, +} from "lit"; import { customElement, property } from "lit/decorators"; import "../../../components/ha-relative-time"; +import "../../../components/ha-service-control"; +import "../../../components/entity/state-info"; import { HomeAssistant } from "../../../types"; +import { canRun, ScriptEntity } from "../../../data/script"; +import { isUnavailableState } from "../../../data/entity"; +import { computeObjectId } from "../../../common/entity/compute_object_id"; @customElement("more-info-script") class MoreInfoScript extends LitElement { @@ -10,12 +23,61 @@ class MoreInfoScript extends LitElement { @property({ attribute: false }) public stateObj?: HassEntity; + private _scriptData: Record = {}; + protected render() { if (!this.hass || !this.stateObj) { return nothing; } + const stateObj = this.stateObj as ScriptEntity; + + const fields = + this.hass.services.script[computeObjectId(this.stateObj.entity_id)] + ?.fields; + + const hasFields = fields && Object.keys(fields).length > 0; return html` +
+ + ${stateObj.state === "on" + ? html` + ${stateObj.attributes.mode !== "single" && + (stateObj.attributes.current || 0) > 0 + ? this.hass.localize("ui.card.script.cancel_multiple", { + number: stateObj.attributes.current, + }) + : this.hass.localize("ui.card.script.cancel")} + ` + : nothing} + ${stateObj.state === "off" || stateObj.attributes.max + ? html` + ${this.hass!.localize("ui.card.script.run")} + ` + : nothing} +
+ + ${hasFields + ? html` + + ` + : nothing} +
@@ -36,17 +98,63 @@ class MoreInfoScript extends LitElement { `; } + protected override willUpdate(changedProperties: PropertyValues): void { + super.willUpdate(changedProperties); + + if (!changedProperties.has("stateObj")) { + return; + } + + const oldState = changedProperties.get("stateObj") as + | HassEntity + | undefined; + const newState = this.stateObj; + + if (newState && (!oldState || oldState.entity_id !== newState.entity_id)) { + this._scriptData = { service: newState.entity_id, data: {} }; + } + } + + private _cancelScript(ev: Event) { + ev.stopPropagation(); + this._callService("turn_off"); + } + + private async _runScript(ev: Event) { + ev.stopPropagation(); + this.hass.callService( + "script", + computeObjectId(this.stateObj!.entity_id), + this._scriptData + ); + } + + private _callService(service: string): void { + this.hass.callService("script", service, { + entity_id: this.stateObj!.entity_id, + }); + } + + private _scriptDataChanged(ev: CustomEvent): void { + this._scriptData = { ...this._scriptData, ...ev.detail.value }; + } + static get styles(): CSSResultGroup { return css` .flex { display: flex; justify-content: space-between; + margin-bottom: 16px; } hr { border-color: var(--divider-color); border-bottom: none; margin: 16px 0; } + ha-service-control { + --service-control-padding: 0; + --service-control-items-border-top: none; + } `; } } diff --git a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts index 6fa20512ea..1147d405b4 100644 --- a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts @@ -15,6 +15,8 @@ import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import { ActionRowConfig, LovelaceRow } from "./types"; +import { computeObjectId } from "../../../common/entity/compute_object_id"; +import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog"; @customElement("hui-script-entity-row") class HuiScriptEntityRow extends LitElement implements LovelaceRow { @@ -92,7 +94,15 @@ class HuiScriptEntityRow extends LitElement implements LovelaceRow { private _runScript(ev): void { ev.stopPropagation(); - this._callService("turn_on"); + + const fields = + this.hass!.services.script[computeObjectId(this._config!.entity)]?.fields; + + if (fields && Object.keys(fields).length > 0) { + showMoreInfoDialog(this, { entityId: this._config!.entity }); + } else { + this._callService("turn_on"); + } } private _callService(service: string): void { diff --git a/src/state-summary/state-card-script.ts b/src/state-summary/state-card-script.ts index f8014684e7..fc375d8d25 100644 --- a/src/state-summary/state-card-script.ts +++ b/src/state-summary/state-card-script.ts @@ -8,6 +8,8 @@ import { isUnavailableState } from "../data/entity"; import { canRun, ScriptEntity } from "../data/script"; import { haStyle } from "../resources/styles"; import { HomeAssistant } from "../types"; +import { computeObjectId } from "../common/entity/compute_object_id"; +import { showMoreInfoDialog } from "../dialogs/more-info/show-ha-more-info-dialog"; @customElement("state-card-script") class StateCardScript extends LitElement { @@ -56,7 +58,16 @@ class StateCardScript extends LitElement { private _runScript(ev: Event) { ev.stopPropagation(); - this._callService("turn_on"); + + const fields = + this.hass!.services.script[computeObjectId(this.stateObj.entity_id)] + ?.fields; + + if (fields && Object.keys(fields).length > 0) { + showMoreInfoDialog(this, { entityId: this.stateObj.entity_id }); + } else { + this._callService("turn_on"); + } } private _callService(service: string): void {