diff --git a/src/components/entity/ha-entity-toggle.ts b/src/components/entity/ha-entity-toggle.ts index 6c5f757724..7243ad12f3 100644 --- a/src/components/entity/ha-entity-toggle.ts +++ b/src/components/entity/ha-entity-toggle.ts @@ -18,9 +18,12 @@ import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateName } from "../../common/entity/compute_state_name"; import "../ha-switch"; +import { UNAVAILABLE_STATES } from "../../data/entity"; const isOn = (stateObj?: HassEntity) => - stateObj !== undefined && !STATES_OFF.includes(stateObj.state); + stateObj !== undefined && + !STATES_OFF.includes(stateObj.state) && + !UNAVAILABLE_STATES.includes(stateObj.state); class HaEntityToggle extends LitElement { // hass is not a property so that we only re-render on stateObj changes @@ -40,12 +43,14 @@ class HaEntityToggle extends LitElement { @@ -58,6 +63,7 @@ class HaEntityToggle extends LitElement { this._isOn ? "off" : "on" }`} .checked=${this._isOn} + .disabled=${UNAVAILABLE_STATES.includes(this.stateObj.state)} @change=${this._toggleChanged} > `; diff --git a/src/components/ha-cover-controls.js b/src/components/ha-cover-controls.js index b669d23eb9..76990761e5 100644 --- a/src/components/ha-cover-controls.js +++ b/src/components/ha-cover-controls.js @@ -3,6 +3,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import CoverEntity from "../util/cover-model"; +import { UNAVAILABLE_STATES } from "../data/entity"; class HaCoverControls extends PolymerElement { static get template() { @@ -81,11 +82,17 @@ class HaCoverControls extends PolymerElement { } computeOpenDisabled(stateObj, entityObj) { + if (UNAVAILABLE_STATES.includes(stateObj.state)) { + return true; + } var assumedState = stateObj.attributes.assumed_state === true; return (entityObj.isFullyOpen || entityObj.isOpening) && !assumedState; } computeClosedDisabled(stateObj, entityObj) { + if (UNAVAILABLE_STATES.includes(stateObj.state)) { + return true; + } var assumedState = stateObj.attributes.assumed_state === true; return (entityObj.isFullyClosed || entityObj.isClosing) && !assumedState; } diff --git a/src/components/ha-cover-tilt-controls.js b/src/components/ha-cover-tilt-controls.js index 1852973d2d..b989af8659 100644 --- a/src/components/ha-cover-tilt-controls.js +++ b/src/components/ha-cover-tilt-controls.js @@ -4,6 +4,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import CoverEntity from "../util/cover-model"; +import { UNAVAILABLE_STATES } from "../data/entity"; class HaCoverTiltControls extends PolymerElement { static get template() { @@ -63,11 +64,17 @@ class HaCoverTiltControls extends PolymerElement { } computeOpenDisabled(stateObj, entityObj) { + if (UNAVAILABLE_STATES.includes(stateObj.state)) { + return true; + } var assumedState = stateObj.attributes.assumed_state === true; return entityObj.isFullyOpenTilt && !assumedState; } computeClosedDisabled(stateObj, entityObj) { + if (UNAVAILABLE_STATES.includes(stateObj.state)) { + return true; + } var assumedState = stateObj.attributes.assumed_state === true; return entityObj.isFullyClosedTilt && !assumedState; } diff --git a/src/data/entity.ts b/src/data/entity.ts index f4d78f3175..80f4e7c820 100644 --- a/src/data/entity.ts +++ b/src/data/entity.ts @@ -1,6 +1,8 @@ export const UNAVAILABLE = "unavailable"; export const UNKNOWN = "unknown"; +export const UNAVAILABLE_STATES = [UNAVAILABLE, UNKNOWN]; + export const ENTITY_COMPONENT_DOMAINS = [ "air_quality", "alarm_control_panel", diff --git a/src/panels/lovelace/cards/hui-entity-card.ts b/src/panels/lovelace/cards/hui-entity-card.ts index 6d0f2aa4f8..a1245e185b 100644 --- a/src/panels/lovelace/cards/hui-entity-card.ts +++ b/src/panels/lovelace/cards/hui-entity-card.ts @@ -30,7 +30,7 @@ import { actionHandler } from "../common/directives/action-handler-directive"; import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { findEntities } from "../common/find-entites"; import { createHeaderFooterElement } from "../create-element/create-header-footer-element"; -import { UNKNOWN, UNAVAILABLE } from "../../../data/entity"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; import { HuiErrorCard } from "./hui-error-card"; @customElement("hui-entity-card") @@ -105,7 +105,7 @@ export class HuiEntityCard extends LitElement implements LovelaceCard { const showUnit = this._config.attribute ? this._config.attribute in stateObj.attributes - : stateObj.state !== UNKNOWN && stateObj.state !== UNAVAILABLE; + : !UNAVAILABLE_STATES.includes(stateObj.state); return html` diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts index c892148259..f49fd30f58 100644 --- a/src/panels/lovelace/cards/hui-glance-card.ts +++ b/src/panels/lovelace/cards/hui-glance-card.ts @@ -30,7 +30,7 @@ import { hasAction } from "../common/has-action"; import { ActionHandlerEvent } from "../../../data/lovelace"; import { handleAction } from "../common/handle-action"; import { computeDomain } from "../../../common/entity/compute_domain"; -import { UNAVAILABLE, UNKNOWN } from "../../../data/entity"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; import { findEntities } from "../common/find-entites"; @customElement("hui-glance-card") @@ -263,8 +263,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
${computeDomain(entityConf.entity) === "sensor" && stateObj.attributes.device_class === "timestamp" && - stateObj.state !== UNAVAILABLE && - stateObj.state !== UNKNOWN + !UNAVAILABLE_STATES.includes(stateObj.state) ? html` - ${stateObj.state === UNAVAILABLE - ? html` - - ` - : ""}
-
- % -
+ ${UNAVAILABLE_STATES.includes(stateObj.state) + ? html` +
+ ${this.hass.localize(`state.default.${stateObj.state}`) || + stateObj.state} +
+ ` + : html` +
+ % +
+ `} ${this._config.name || computeStateName(stateObj)}
@@ -267,10 +269,6 @@ export class HuiLightCard extends LitElement implements LovelaceCard { display: block; } - hui-unavailable { - cursor: pointer; - } - ha-card { height: 100%; box-sizing: border-box; @@ -353,9 +351,6 @@ export class HuiLightCard extends LitElement implements LovelaceCard { transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -webkit-transition: opacity 0.5s ease-in-out; - cursor: pointer; - pointer-events: none; - padding-left: 0.5em; } .show_brightness { diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 9e60be8de2..bf3c250dab 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -30,7 +30,7 @@ import { stateIcon } from "../../../common/entity/state_icon"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { contrast } from "../common/color/contrast"; import { findEntities } from "../common/find-entites"; -import { UNAVAILABLE, UNKNOWN } from "../../../data/entity"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; import { SUPPORT_PAUSE, SUPPORT_TURN_ON, @@ -285,8 +285,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { const isOffState = state === "off"; const isUnavailable = - state === UNAVAILABLE || - state === UNKNOWN || + UNAVAILABLE_STATES.includes(state) || (state === "off" && !supportsFeature(stateObj, SUPPORT_TURN_ON)); const hasNoImage = !this._image; const controls = this._getControls(); @@ -501,7 +500,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { const state = stateObj.state; - if (state === UNAVAILABLE || state === UNKNOWN) { + if (UNAVAILABLE_STATES.includes(state)) { return undefined; } diff --git a/src/panels/lovelace/cards/hui-picture-entity-card.ts b/src/panels/lovelace/cards/hui-picture-entity-card.ts index f295f28d96..fbc17265e0 100644 --- a/src/panels/lovelace/cards/hui-picture-entity-card.ts +++ b/src/panels/lovelace/cards/hui-picture-entity-card.ts @@ -21,7 +21,7 @@ import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { HomeAssistant } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { UNAVAILABLE } from "../../../data/entity"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { PictureEntityCardConfig } from "./types"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; @@ -178,7 +178,7 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard { : undefined )} class=${classMap({ - clickable: stateObj.state !== UNAVAILABLE, + clickable: !UNAVAILABLE_STATES.includes(stateObj.state), })} > ${footer} diff --git a/src/panels/lovelace/cards/hui-thermostat-card.ts b/src/panels/lovelace/cards/hui-thermostat-card.ts index 5161d76fae..ebd51de5f9 100644 --- a/src/panels/lovelace/cards/hui-thermostat-card.ts +++ b/src/panels/lovelace/cards/hui-thermostat-card.ts @@ -15,7 +15,6 @@ import "@thomasloven/round-slider"; import "../../../components/ha-card"; import "../components/hui-warning"; -import "../components/hui-unavailable"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { computeStateName } from "../../../common/entity/compute_state_name"; @@ -35,7 +34,7 @@ import { import { HassEntity } from "home-assistant-js-websocket"; import { actionHandler } from "../common/directives/action-handler-directive"; import { findEntities } from "../common/find-entites"; -import { UNAVAILABLE } from "../../../data/entity"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; const modeIcons: { [mode in HvacMode]: string } = { auto: "hass:calendar-repeat", @@ -127,23 +126,22 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard { ? stateObj.attributes.temperature : stateObj.attributes.min_temp; - const slider = - stateObj.state === "unavailable" - ? html` - - ` - : html` - - `; + const slider = UNAVAILABLE_STATES.includes(stateObj.state) + ? html` + + ` + : html` + + `; const currentTemperature = !isNaN(stateObj.attributes.current_temperature) ? svg` @@ -224,14 +222,6 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard { [mode]: true, })} > - ${stateObj.state === UNAVAILABLE - ? html` - - ` - : ""} -
${this.text}
- `; - } - - static get styles(): CSSResult { - return css` - .disabled-overlay { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: var(--state-icon-unavailable-color); - opacity: 0.6; - z-index: 50; - } - - .disabled-overlay-text { - position: absolute; - top: 50%; - left: 50%; - font-size: 24px; - text-align: center; - color: var(--primary-text-color); - transform: translate(-50%, -50%); - -ms-transform: translate(-50%, -50%); - z-index: 50; - opacity: 0.7; - } - `; - } -} - -declare global { - interface HTMLElementTagNameMap { - "hui-unavailable": HuiUnavailable; - } -} diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 2e22f0232e..ed5b65e998 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -22,7 +22,7 @@ import { computeUsedEntities, calcUnusedEntities, } from "../../common/compute-unused-entities"; -import { UNKNOWN, UNAVAILABLE } from "../../../../data/entity"; +import { UNAVAILABLE_STATES } from "../../../../data/entity"; import { customCards, getCustomCardEntry, @@ -168,14 +168,12 @@ export class HuiCardPicker extends LitElement { this._usedEntities = [...usedEntities].filter( (eid) => this.hass!.states[eid] && - this.hass!.states[eid].state !== UNKNOWN && - this.hass!.states[eid].state !== UNAVAILABLE + !UNAVAILABLE_STATES.includes(this.hass!.states[eid].state) ); this._unusedEntities = [...unusedEntities].filter( (eid) => this.hass!.states[eid] && - this.hass!.states[eid].state !== UNKNOWN && - this.hass!.states[eid].state !== UNAVAILABLE + !UNAVAILABLE_STATES.includes(this.hass!.states[eid].state) ); this.requestUpdate(); diff --git a/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts index 7afbc34dd6..cab9fb9437 100644 --- a/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts @@ -19,6 +19,7 @@ import { HomeAssistant } from "../../../types"; import { LovelaceRow, EntityConfig } from "./types"; import { setInputDateTimeValue } from "../../../data/input_datetime"; import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; @customElement("hui-input-datetime-entity-row") class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { @@ -60,6 +61,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { ${stateObj.attributes.has_date ? html` - ` - : ""} @@ -149,10 +141,6 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow { handleAction(this, this.hass!, this._config!, ev.detail.action!); } - private _showMoreInfo() { - fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); - } - static get styles(): CSSResult { return css` :host { @@ -175,9 +163,6 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow { background: var(--divider-color); border-radius: 100%; } - hui-unavailable { - cursor: pointer; - } `; } diff --git a/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts index e8fa7eb863..7515f48499 100644 --- a/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts @@ -15,6 +15,7 @@ import { HomeAssistant } from "../../../types"; import { LovelaceRow, EntityConfig } from "./types"; import { setValue } from "../../../data/input_text"; import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; @customElement("hui-input-text-entity-row") class HuiInputTextEntityRow extends LitElement implements LovelaceRow { @@ -56,6 +57,7 @@ class HuiInputTextEntityRow extends LitElement implements LovelaceRow { - + ${stateObj.state === "locked" ? this.hass!.localize("ui.card.lock.unlock") : this.hass!.localize("ui.card.lock.lock")} diff --git a/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts b/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts index 7e096fbc88..bbd33c78ba 100644 --- a/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts @@ -17,6 +17,7 @@ import { HomeAssistant } from "../../../types"; import { LovelaceRow, ActionRowConfig } from "./types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { activateScene } from "../../../data/scene"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; @customElement("hui-scene-entity-row") class HuiSceneEntityRow extends LitElement implements LovelaceRow { @@ -56,7 +57,11 @@ class HuiSceneEntityRow extends LitElement implements LovelaceRow { return html` - + ${this._config.action_name || this.hass!.localize("ui.card.scene.activate")} 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 bc0dd5b468..d07ad64a58 100644 --- a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts @@ -16,6 +16,7 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { LovelaceRow, ActionRowConfig } from "./types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; @customElement("hui-script-entity-row") class HuiScriptEntityRow extends LitElement implements LovelaceRow { @@ -58,12 +59,17 @@ class HuiScriptEntityRow extends LitElement implements LovelaceRow { ${stateObj.attributes.can_cancel ? html` ` : html` - + ${this._config.action_name || this.hass!.localize("ui.card.script.execute")} diff --git a/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts index b166ba9d2b..56d2339fa1 100644 --- a/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts @@ -15,6 +15,7 @@ import { computeStateDisplay } from "../../../common/entity/compute_state_displa import { HomeAssistant } from "../../../types"; import { LovelaceRow, EntityConfig } from "./types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { UNAVAILABLE_STATES } from "../../../data/entity"; @customElement("hui-toggle-entity-row") class HuiToggleEntityRow extends LitElement implements LovelaceRow { @@ -54,7 +55,9 @@ class HuiToggleEntityRow extends LitElement implements LovelaceRow { return html` - ${stateObj.state === "on" || stateObj.state === "off" + ${stateObj.state === "on" || + stateObj.state === "off" || + UNAVAILABLE_STATES.includes(stateObj.state) ? html`
- ${stateObj.attributes.temperature} - ${getWeatherUnit(this.hass, "temperature")} + ${UNAVAILABLE_STATES.includes(stateObj.state) + ? this.hass.localize(`state.default.${stateObj.state}`) || + stateObj.state + : html` + ${stateObj.attributes.temperature} + ${getWeatherUnit(this.hass, "temperature")} + `}
- ${this._getSecondaryAttribute(stateObj)} + ${!UNAVAILABLE_STATES.includes(stateObj.state) + ? this._getSecondaryAttribute(stateObj) + : ""}