diff --git a/pyproject.toml b/pyproject.toml index 6267bdc101..afea7e45d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20231208.1" +version = "20231208.2" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" diff --git a/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts index 5b13039385..4477359e1d 100644 --- a/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts @@ -1,11 +1,15 @@ +import { mdiThermostat } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; +import { stopPropagation } from "../../../common/dom/stop_propagation"; import { computeDomain } from "../../../common/entity/compute_domain"; import { stateColorCss } from "../../../common/entity/state_color"; import "../../../components/ha-control-select"; +import "../../../components/ha-control-select-menu"; import type { ControlSelectOption } from "../../../components/ha-control-select"; +import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu"; import { ClimateEntity, compareClimateHvacModes, @@ -35,6 +39,9 @@ class HuiClimateHvacModesCardFeature @state() _currentHvacMode?: HvacMode; + @query("ha-control-select-menu", true) + private _haSelect?: HaControlSelectMenu; + static getStubConfig( _, stateObj?: HassEntity @@ -66,8 +73,23 @@ class HuiClimateHvacModesCardFeature } } + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (this._haSelect && changedProps.has("hass")) { + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; + if ( + this.hass && + this.hass.formatEntityAttributeValue !== + oldHass?.formatEntityAttributeValue + ) { + this._haSelect.layoutOptions(); + } + } + } + private async _valueChanged(ev: CustomEvent) { - const mode = (ev.detail as any).value as HvacMode; + const mode = + (ev.detail as any).value ?? ((ev.target as any).value as HvacMode); if (mode === this.stateObj!.state) return; @@ -111,6 +133,37 @@ class HuiClimateHvacModesCardFeature path: computeHvacModeIcon(mode), })); + if (this._config.style === "dropdown") { + return html` +
+ + + ${options.map( + (option) => html` + + + ${option.label} + + ` + )} + +
+ `; + } + return html`
1 + ? [ + { + type: "climate-hvac-modes", + hvac_modes: states[entityId]?.attributes?.hvac_modes, + }, + ] + : undefined, }; cards.push(cardConfig); } else if (domain === "humidifier") { diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts index a9dcdb3084..7f01de6102 100644 --- a/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts @@ -4,6 +4,7 @@ import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; import type { FormatEntityStateFunc } from "../../../../common/translations/entity-state"; +import type { LocalizeFunc } from "../../../../common/translations/localize"; import "../../../../components/ha-form/ha-form"; import type { SchemaUnion } from "../../../../components/ha-form/types"; import { HVAC_MODES } from "../../../../data/climate"; @@ -30,8 +31,27 @@ export class HuiClimateHvacModesCardFeatureEditor } private _schema = memoizeOne( - (formatEntityState: FormatEntityStateFunc, stateObj?: HassEntity) => + ( + localize: LocalizeFunc, + formatEntityState: FormatEntityStateFunc, + stateObj?: HassEntity + ) => [ + { + name: "style", + selector: { + select: { + multiple: false, + mode: "list", + options: ["dropdown", "icons"].map((mode) => ({ + value: mode, + label: localize( + `ui.panel.lovelace.editor.features.types.climate-preset-modes.style_list.${mode}` + ), + })), + }, + }, + }, { name: "hvac_modes", selector: { @@ -59,12 +79,22 @@ export class HuiClimateHvacModesCardFeatureEditor ? this.hass.states[this.context?.entity_id] : undefined; - const schema = this._schema(this.hass.formatEntityState, stateObj); + const data: ClimateHvacModesCardFeatureConfig = { + style: "icons", + hvac_modes: [], + ...this._config, + }; + + const schema = this._schema( + this.hass.localize, + this.hass.formatEntityState, + stateObj + ); return html` { switch (schema.name) { case "hvac_modes": + case "style": return this.hass!.localize( `ui.panel.lovelace.editor.features.types.climate-hvac-modes.${schema.name}` ); default: - return this.hass!.localize( - `ui.panel.lovelace.editor.card.generic.${schema.name}` - ); + return ""; } }; } diff --git a/src/panels/todo/ha-panel-todo.ts b/src/panels/todo/ha-panel-todo.ts index 345df4010c..ba03971c12 100644 --- a/src/panels/todo/ha-panel-todo.ts +++ b/src/panels/todo/ha-panel-todo.ts @@ -46,7 +46,10 @@ import { HuiErrorCard } from "../lovelace/cards/hui-error-card"; import { createCardElement } from "../lovelace/create-element/create-card-element"; import { LovelaceCard } from "../lovelace/types"; import { navigate } from "../../common/navigate"; -import { createSearchParam } from "../../common/url/search-params"; +import { + createSearchParam, + extractSearchParam, +} from "../../common/url/search-params"; import { constructUrlCurrentPath } from "../../common/url/construct-url"; @customElement("ha-panel-todo") @@ -105,18 +108,21 @@ class PanelTodo extends LitElement { if (!this.hasUpdated) { this.hass.loadFragmentTranslation("lovelace"); + + const urlEntityId = extractSearchParam("entity_id"); + if (urlEntityId) { + this._entityId = urlEntityId; + } else { + if (this._entityId && !(this._entityId in this.hass.states)) { + this._entityId = undefined; + } + if (!this._entityId) { + this._entityId = getTodoLists(this.hass)[0]?.entity_id; + } + } } - if (!this.hasUpdated && !this._entityId) { - this._entityId = getTodoLists(this.hass)[0]?.entity_id; - } else if (!this.hasUpdated) { - this._setupTodoElement(); - } - } - - protected updated(changedProperties: PropertyValues): void { - super.updated(changedProperties); - if (changedProperties.has("_entityId")) { + if (changedProperties.has("_entityId") || !this.hasUpdated) { this._setupTodoElement(); } diff --git a/src/state-control/climate/ha-state-control-climate-humidity.ts b/src/state-control/climate/ha-state-control-climate-humidity.ts index be27b7bdb6..9918db1044 100644 --- a/src/state-control/climate/ha-state-control-climate-humidity.ts +++ b/src/state-control/climate/ha-state-control-climate-humidity.ts @@ -97,6 +97,12 @@ export class HaStateControlClimateHumidity extends LitElement { `; } + if (!this._targetHumidity) { + return html` +

${this.hass.formatEntityState(this.stateObj)}

+ `; + } + return html`

${this.hass.localize("ui.card.climate.humidity_target")} diff --git a/src/state-control/climate/ha-state-control-climate-temperature.ts b/src/state-control/climate/ha-state-control-climate-temperature.ts index 755b0ce6ab..0975b1bd99 100644 --- a/src/state-control/climate/ha-state-control-climate-temperature.ts +++ b/src/state-control/climate/ha-state-control-climate-temperature.ts @@ -164,14 +164,17 @@ export class HaStateControlClimateTemperature extends LitElement { } if ( - !supportsFeature( + (!supportsFeature( this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE - ) && - !supportsFeature( + ) || + this._targetTemperature.value === null) && + (!supportsFeature( this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE_RANGE - ) + ) || + this._targetTemperature.low === null || + this._targetTemperature.high === null) ) { return html`

${this.hass.formatEntityState(this.stateObj)}

diff --git a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts index 9f9bf92605..648753ab66 100644 --- a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts +++ b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts @@ -110,7 +110,9 @@ export class HaStateControlHumidifierHumidity extends LitElement {

${action && action !== "off" && action !== "idle" ? actionLabel - : this.hass.localize("ui.card.humidifier.target")} + : this._targetHumidity + ? this.hass.localize("ui.card.humidifier.target") + : this.hass.formatEntityState(this.stateObj)}

`; } diff --git a/src/state-control/water_heater/ha-state-control-water_heater-temperature.ts b/src/state-control/water_heater/ha-state-control-water_heater-temperature.ts index bbcd5cdaad..4e52499618 100644 --- a/src/state-control/water_heater/ha-state-control-water_heater-temperature.ts +++ b/src/state-control/water_heater/ha-state-control-water_heater-temperature.ts @@ -107,7 +107,8 @@ export class HaStateControlWaterHeaterTemperature extends LitElement { !supportsFeature( this.stateObj, WaterHeaterEntityFeature.TARGET_TEMPERATURE - ) + ) || + !this._targetTemperature ) { return html`

${this.hass.formatEntityState(this.stateObj)}

diff --git a/src/translations/en.json b/src/translations/en.json index 41ed918e23..af46f7f134 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -5280,7 +5280,12 @@ }, "climate-hvac-modes": { "label": "Climate HVAC modes", - "hvac_modes": "HVAC modes" + "hvac_modes": "HVAC modes", + "style": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style%]", + "style_list": { + "dropdown": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style_list::dropdown%]", + "icons": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style_list::icons%]" + } }, "climate-preset-modes": { "label": "Climate preset modes",