diff --git a/src/common/const.ts b/src/common/const.ts index c7b2ac917f..8ed86c0614 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -226,6 +226,7 @@ export const DOMAINS_INPUT_ROW = [ "select", "switch", "text", + "time", "vacuum", ]; diff --git a/src/common/entity/compute_state_display.ts b/src/common/entity/compute_state_display.ts index e07f19fc20..662b58a541 100644 --- a/src/common/entity/compute_state_display.ts +++ b/src/common/entity/compute_state_display.ts @@ -117,7 +117,7 @@ export const computeStateDisplayFromEntityAttributes = ( const domain = computeDomain(entityId); - if (domain === "input_datetime") { + if (domain === "input_datetime" || domain === "time") { if (state !== undefined) { // If trying to display an explicit state, need to parse the explicit state to `Date` then format. // Attributes aren't available, we have to use `state`. diff --git a/src/data/time.ts b/src/data/time.ts new file mode 100644 index 0000000000..c2e9310633 --- /dev/null +++ b/src/data/time.ts @@ -0,0 +1,10 @@ +import { HomeAssistant } from "../types"; + +export const setTimeValue = ( + hass: HomeAssistant, + entityId: string, + time: string | undefined = undefined +) => { + const param = { entity_id: entityId, time: time }; + hass.callService(entityId.split(".", 1)[0], "set_value", param); +}; diff --git a/src/panels/lovelace/create-element/create-row-element.ts b/src/panels/lovelace/create-element/create-row-element.ts index 71f8a2359e..6852092e42 100644 --- a/src/panels/lovelace/create-element/create-row-element.ts +++ b/src/panels/lovelace/create-element/create-row-element.ts @@ -42,6 +42,7 @@ const LAZY_LOAD_TYPES = { "number-entity": () => import("../entity-rows/hui-number-entity-row"), "select-entity": () => import("../entity-rows/hui-select-entity-row"), "text-entity": () => import("../entity-rows/hui-text-entity-row"), + "time-entity": () => import("../entity-rows/hui-time-entity-row"), "timer-entity": () => import("../entity-rows/hui-timer-entity-row"), conditional: () => import("../special-rows/hui-conditional-row"), "weather-entity": () => import("../entity-rows/hui-weather-entity-row"), @@ -80,6 +81,7 @@ const DOMAIN_TO_ELEMENT_TYPE = { siren: "toggle", switch: "toggle", text: "text", + time: "time", timer: "timer", vacuum: "toggle", // Temporary. Once climate is rewritten, diff --git a/src/panels/lovelace/entity-rows/hui-time-entity-row.ts b/src/panels/lovelace/entity-rows/hui-time-entity-row.ts new file mode 100644 index 0000000000..1efee0fee9 --- /dev/null +++ b/src/panels/lovelace/entity-rows/hui-time-entity-row.ts @@ -0,0 +1,95 @@ +import { + css, + CSSResultGroup, + html, + LitElement, + nothing, + PropertyValues, + TemplateResult, +} from "lit"; +import { customElement, property, state } from "lit/decorators"; +import "../../../components/ha-date-input"; +import { isUnavailableState } from "../../../data/entity"; +import { setTimeValue } from "../../../data/time"; +import type { HomeAssistant } from "../../../types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; +import "../components/hui-generic-entity-row"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; +import type { EntityConfig, LovelaceRow } from "./types"; +import "../../../components/ha-time-input"; + +@customElement("hui-time-entity-row") +class HuiTimeEntityRow extends LitElement implements LovelaceRow { + @property({ attribute: false }) public hass?: HomeAssistant; + + @state() private _config?: EntityConfig; + + public setConfig(config: EntityConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + + protected render(): TemplateResult | typeof nothing { + if (!this._config || !this.hass) { + return nothing; + } + + const stateObj = this.hass.states[this._config.entity]; + + if (!stateObj) { + return html` + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + + `; + } + + return html` + + + + `; + } + + private _stopEventPropagation(ev: Event): void { + ev.stopPropagation(); + } + + private _timeChanged(ev: CustomEvent<{ value: string }>): void { + const stateObj = this.hass!.states[this._config!.entity]; + setTimeValue(this.hass!, stateObj.entity_id, ev.detail.value); + } + + static get styles(): CSSResultGroup { + return css` + ha-date-input + ha-time-input { + margin-left: 4px; + margin-inline-start: 4px; + margin-inline-end: initial; + direction: var(--direction); + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-time-entity-row": HuiTimeEntityRow; + } +}