From 52870616993c9676476d7cbb1b2115cfaad370ec Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 28 Feb 2024 11:07:26 -0500 Subject: [PATCH] Update script more info (#19899) * Update script more info * Fixes * Update styling * remarks * Always show cancel button --------- Co-authored-by: Bram Kragten --- src/components/ha-control-button.ts | 4 +- .../components/ha-more-info-state-header.ts | 6 +- src/dialogs/more-info/const.ts | 3 +- .../more-info/controls/more-info-script.ts | 183 ++++++++++++------ src/translations/en.json | 8 +- 5 files changed, 138 insertions(+), 66 deletions(-) diff --git a/src/components/ha-control-button.ts b/src/components/ha-control-button.ts index 1eee1286e6..58ea4f4400 100644 --- a/src/components/ha-control-button.ts +++ b/src/components/ha-control-button.ts @@ -127,9 +127,11 @@ export class HaControlButton extends LitElement { opacity 180ms ease-in-out; opacity: var(--control-button-background-opacity); } - .button ::slotted(*) { + .button { transition: color 180ms ease-in-out; color: var(--control-button-icon-color); + } + .button ::slotted(*) { pointer-events: none; } .button:disabled { diff --git a/src/dialogs/more-info/components/ha-more-info-state-header.ts b/src/dialogs/more-info/components/ha-more-info-state-header.ts index 4697868390..9432eb46b1 100644 --- a/src/dialogs/more-info/components/ha-more-info-state-header.ts +++ b/src/dialogs/more-info/components/ha-more-info-state-header.ts @@ -16,6 +16,8 @@ export class HaMoreInfoStateHeader extends LitElement { @property({ attribute: false }) public stateOverride?: string; + @property({ attribute: false }) public changedOverride?: number; + @state() private _absoluteTime = false; private _localizeState(): TemplateResult | string { @@ -50,13 +52,13 @@ export class HaMoreInfoStateHeader extends LitElement { ? html` ` : html` `} diff --git a/src/dialogs/more-info/const.ts b/src/dialogs/more-info/const.ts index b9fe72039a..e558910779 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", "script"]; +export const DOMAINS_NO_INFO = ["camera", "configurator"]; /** * Entity domains that should be editable *if* they have an id present; * {@see shouldShowEditIcon}. @@ -26,6 +26,7 @@ export const DOMAINS_WITH_NEW_MORE_INFO = [ "light", "lock", "siren", + "script", "switch", "valve", "water_heater", diff --git a/src/dialogs/more-info/controls/more-info-script.ts b/src/dialogs/more-info/controls/more-info-script.ts index a2fc2b1186..c530f05cf5 100644 --- a/src/dialogs/more-info/controls/more-info-script.ts +++ b/src/dialogs/more-info/controls/more-info-script.ts @@ -1,3 +1,4 @@ +import { mdiPlay, mdiStop } from "@mdi/js"; import "@material/mwc-button"; import { HassEntity } from "home-assistant-js-websocket"; import { @@ -8,28 +9,54 @@ import { nothing, PropertyValues, } from "lit"; -import { customElement, property } from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import "../../../components/ha-relative-time"; import "../../../components/ha-service-control"; +import "../../../components/ha-control-button"; +import "../../../components/ha-control-button-group"; 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"; +import { listenMediaQuery } from "../../../common/dom/media_query"; +import "../components/ha-more-info-state-header"; @customElement("more-info-script") class MoreInfoScript extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property({ attribute: false }) public stateObj?: HassEntity; + @property({ attribute: false }) public stateObj?: ScriptEntity; - private _scriptData: Record = {}; + @state() private _scriptData: Record = {}; + + @state() private narrow = false; + + private _unsubMediaQuery?: () => void; + + public connectedCallback(): void { + super.connectedCallback(); + this._unsubMediaQuery = listenMediaQuery( + "(max-width: 870px)", + (matches) => { + this.narrow = matches; + } + ); + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + if (this._unsubMediaQuery) { + this._unsubMediaQuery(); + this._unsubMediaQuery = undefined; + } + } protected render() { if (!this.hass || !this.stateObj) { return nothing; } - const stateObj = this.stateObj as ScriptEntity; + const stateObj = this.stateObj; const fields = this.hass.services.script[computeObjectId(this.stateObj.entity_id)] @@ -37,64 +64,74 @@ class MoreInfoScript extends LitElement { const hasFields = fields && Object.keys(fields).length > 0; + const current = stateObj.attributes.current || 0; + const isQueued = stateObj.attributes.mode === "queued"; + const isParallel = stateObj.attributes.mode === "parallel"; + const hasQueue = isQueued && current > 1; + 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} + 0 + ? isParallel && current > 1 + ? this.hass.localize("ui.card.script.running_parallel", { + active: current, + }) + : this.hass.localize("ui.card.script.running_single") + : this.hass.localize("ui.card.script.idle")} + .changedOverride=${this.stateObj.attributes.last_triggered || 0} + > + +
+ ${hasQueue + ? html` + ${this.hass.localize("ui.card.script.running_queued", { + queued: current - 1, + })} + ` + : ""}
${hasFields ? html` - +
+
+ ${this.hass.localize("ui.card.script.run_script")} +
+ +
` : nothing} -
-
-
- ${this.hass.localize( - "ui.dialogs.more_info_control.script.last_triggered" - )}: -
- ${this.stateObj.attributes.last_triggered - ? html` - - ` - : this.hass.localize("ui.components.relative_time.never")} -
+ + + + ${(isQueued || isParallel) && current > 1 + ? this.hass.localize("ui.card.script.cancel_all") + : this.hass.localize("ui.card.script.cancel")} + + + + ${this.hass!.localize("ui.card.script.run")} + + `; } @@ -139,17 +176,41 @@ class MoreInfoScript extends LitElement { this._scriptData = { ...this._scriptData, ...ev.detail.value }; } + private _canRun() { + if ( + canRun(this.stateObj!) || + // Restart can also always runs. Just cancels other run. + this.stateObj!.attributes.mode === "restart" + ) { + return true; + } + return false; + } + static get styles(): CSSResultGroup { return css` - .flex { - display: flex; - justify-content: space-between; + .queue { + visibility: hidden; + color: var(--secondary-text-color); + text-align: center; + margin-bottom: 16px; + height: 21px; + } + .queue.has-queue { + visibility: visible; + } + .fields { + padding: 16px; + border: 1px solid var(--divider-color); + border-radius: 8px; margin-bottom: 16px; } - hr { - border-color: var(--divider-color); - border-bottom: none; - margin: 16px 0; + .fields .title { + font-weight: bold; + } + ha-control-button ha-svg-icon { + z-index: -1; + margin-right: 4px; } ha-service-control { --service-control-padding: 0; diff --git a/src/translations/en.json b/src/translations/en.json index 5c385a9e32..24f63e86a3 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -218,8 +218,14 @@ }, "script": { "run": "[%key:ui::card::service::run%]", + "running_single": "Running…", + "running_queued": "{queued} queued", + "running_parallel": "{active} Running…", "cancel": "Cancel", - "cancel_multiple": "Cancel {number}" + "cancel_multiple": "Cancel {number}", + "cancel_all": "Cancel all", + "idle": "Idle", + "run_script": "Run script" }, "service": { "run": "Run"