diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.js b/src/panels/lovelace/entity-rows/hui-timer-entity-row.js deleted file mode 100644 index fbcfd143d5..0000000000 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.js +++ /dev/null @@ -1,98 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -import "../components/hui-generic-entity-row"; - -import timerTimeRemaining from "../../../common/entity/timer_time_remaining"; -import secondsToDuration from "../../../common/datetime/seconds_to_duration"; - -class HuiTimerEntityRow extends PolymerElement { - static get template() { - return html` - - ${this.timerControlTemplate} - - `; - } - - static get timerControlTemplate() { - return html` -
[[_computeDisplay(_stateObj, _timeRemaining)]]
- `; - } - - static get properties() { - return { - hass: Object, - _config: Object, - _stateObj: { - type: Object, - computed: "_computeStateObj(hass.states, _config.entity)", - observer: "_stateObjChanged", - }, - _timeRemaining: Number, - }; - } - - disconnectedCallback() { - super.disconnectedCallback(); - this._clearInterval(); - } - - _stateObjChanged(stateObj) { - if (stateObj) { - this._startInterval(stateObj); - } else { - this._clearInterval(); - } - } - - _clearInterval() { - if (this._updateRemaining) { - clearInterval(this._updateRemaining); - this._updateRemaining = null; - } - } - - _startInterval(stateObj) { - this._clearInterval(); - this._calculateRemaining(stateObj); - - if (stateObj.state === "active") { - this._updateRemaining = setInterval( - () => this._calculateRemaining(this._stateObj), - 1000 - ); - } - } - - _calculateRemaining(stateObj) { - this._timeRemaining = timerTimeRemaining(stateObj); - } - - _computeDisplay(stateObj, time) { - if (!stateObj) return null; - - if (stateObj.state === "idle" || time === 0) return stateObj.state; - - let display = secondsToDuration(time); - - if (stateObj.state === "paused") { - display += " (paused)"; - } - - return display; - } - - _computeStateObj(states, entityId) { - return states && entityId in states ? states[entityId] : null; - } - - setConfig(config) { - if (!config || !config.entity) { - throw new Error("Entity not configured."); - } - this._config = config; - } -} -customElements.define("hui-timer-entity-row", HuiTimerEntityRow); diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts new file mode 100644 index 0000000000..7e7383961d --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -0,0 +1,128 @@ +import { + html, + LitElement, + TemplateResult, + property, + PropertyValues, +} from "lit-element"; + +import "../components/hui-generic-entity-row"; +import "../components/hui-warning"; + +import timerTimeRemaining from "../../../common/entity/timer_time_remaining"; +import secondsToDuration from "../../../common/datetime/seconds_to_duration"; +import { HomeAssistant } from "../../../types"; +import { EntityConfig } from "./types"; +import { HassEntity } from "home-assistant-js-websocket"; + +class HuiTimerEntityRow extends LitElement { + @property() public hass?: HomeAssistant; + @property() private _config?: EntityConfig; + @property() private _timeRemaining?: number; + private _interval?: number; + + public setConfig(config: EntityConfig): void { + if (!config) { + throw new Error("Configuration error"); + } + this._config = config; + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + this._clearInterval(); + } + + protected render(): TemplateResult | void { + if (!this._config || !this.hass) { + return html``; + } + + const stateObj = this.hass.states[this._config.entity]; + + if (!stateObj) { + return html` + ${this.hass.localize( + "ui.panel.lovelace.warning.entity_not_found", + "entity", + this._config.entity + )} + `; + } + + return html` + +
${this._computeDisplay(stateObj)}
+
+ `; + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + + if (changedProps.has("hass")) { + const stateObj = this.hass!.states[this._config!.entity]; + const oldHass = changedProps.get("hass") as this["hass"]; + const oldStateObj = oldHass + ? oldHass.states[this._config!.entity] + : undefined; + + if (oldStateObj !== stateObj) { + this._startInterval(stateObj); + } else if (!stateObj) { + this._clearInterval(); + } + } + } + + private _clearInterval(): void { + if (this._interval) { + window.clearInterval(this._interval); + this._interval = undefined; + } + } + + private _startInterval(stateObj: HassEntity): void { + this._clearInterval(); + this._calculateRemaining(stateObj); + + if (stateObj.state === "active") { + this._interval = window.setInterval( + () => this._calculateRemaining(stateObj), + 1000 + ); + } + } + + private _calculateRemaining(stateObj: HassEntity): void { + this._timeRemaining = timerTimeRemaining(stateObj); + } + + private _computeDisplay(stateObj: HassEntity): string | null { + if (!stateObj) { + return null; + } + + if (stateObj.state === "idle" || this._timeRemaining === 0) { + return this.hass!.localize("state.timer." + stateObj.state); + } + + let display = secondsToDuration(this._timeRemaining || 0); + + if (stateObj.state === "paused") { + display += ` (${this.hass!.localize("state.timer.paused")})`; + } + + return display; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-timer-entity-row": HuiTimerEntityRow; + } +} + +customElements.define("hui-timer-entity-row", HuiTimerEntityRow); diff --git a/src/translations/en.json b/src/translations/en.json index 35207ed514..9797982c17 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -271,6 +271,11 @@ "off": "[%key:state::default::off%]", "on": "[%key:state::default::on%]" }, + "timer": { + "active": "active", + "idle": "idle", + "paused": "paused" + }, "vacuum": { "cleaning": "Cleaning", "docked": "Docked",